Skip to content

Commit f5a143f

Browse files
authored
Rollup merge of #134797 - spastorino:ergonomic-ref-counting-1, r=nikomatsakis
Ergonomic ref counting This is an experimental first version of ergonomic ref counting. This first version implements most of the RFC but doesn't implement any of the optimizations. This was left for following iterations. RFC: rust-lang/rfcs#3680 Tracking issue: #132290 Project goal: rust-lang/rust-project-goals#107 r? ```@nikomatsakis```
2 parents 03eb454 + d2bde63 commit f5a143f

File tree

119 files changed

+1401
-79
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

119 files changed

+1401
-79
lines changed

compiler/rustc_ast/src/ast.rs

+13-1
Original file line numberDiff line numberDiff line change
@@ -1399,6 +1399,7 @@ impl Expr {
13991399
// Never need parens
14001400
ExprKind::Array(_)
14011401
| ExprKind::Await(..)
1402+
| ExprKind::Use(..)
14021403
| ExprKind::Block(..)
14031404
| ExprKind::Call(..)
14041405
| ExprKind::ConstBlock(_)
@@ -1588,6 +1589,8 @@ pub enum ExprKind {
15881589
Gen(CaptureBy, P<Block>, GenBlockKind, Span),
15891590
/// An await expression (`my_future.await`). Span is of await keyword.
15901591
Await(P<Expr>, Span),
1592+
/// A use expression (`x.use`). Span is of use keyword.
1593+
Use(P<Expr>, Span),
15911594

15921595
/// A try block (`try { ... }`).
15931596
TryBlock(P<Block>),
@@ -1757,8 +1760,17 @@ pub enum CaptureBy {
17571760
/// The span of the `move` keyword.
17581761
move_kw: Span,
17591762
},
1760-
/// `move` keyword was not specified.
1763+
/// `move` or `use` keywords were not specified.
17611764
Ref,
1765+
/// `use |x| y + x`.
1766+
///
1767+
/// Note that if you have a regular closure like `|| x.use`, this will *not* result
1768+
/// in a `Use` capture. Instead, the `ExprUseVisitor` will look at the type
1769+
/// of `x` and treat `x.use` as either a copy/clone/move as appropriate.
1770+
Use {
1771+
/// The span of the `use` keyword.
1772+
use_kw: Span,
1773+
},
17621774
}
17631775

17641776
/// Closure lifetime binder, `for<'a, 'b>` in `for<'a, 'b> |_: &'a (), _: &'b ()|`.

compiler/rustc_ast/src/mut_visit.rs

+7
Original file line numberDiff line numberDiff line change
@@ -1745,6 +1745,10 @@ pub fn walk_expr<T: MutVisitor>(vis: &mut T, Expr { kind, id, span, attrs, token
17451745
vis.visit_expr(expr);
17461746
vis.visit_span(await_kw_span);
17471747
}
1748+
ExprKind::Use(expr, use_kw_span) => {
1749+
vis.visit_expr(expr);
1750+
vis.visit_span(use_kw_span);
1751+
}
17481752
ExprKind::Assign(el, er, span) => {
17491753
vis.visit_expr(el);
17501754
vis.visit_expr(er);
@@ -1895,6 +1899,9 @@ fn walk_capture_by<T: MutVisitor>(vis: &mut T, capture_by: &mut CaptureBy) {
18951899
CaptureBy::Value { move_kw } => {
18961900
vis.visit_span(move_kw);
18971901
}
1902+
CaptureBy::Use { use_kw } => {
1903+
vis.visit_span(use_kw);
1904+
}
18981905
}
18991906
}
19001907

compiler/rustc_ast/src/util/classify.rs

+2
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ pub fn leading_labeled_expr(mut expr: &ast::Expr) -> bool {
108108
Assign(e, _, _)
109109
| AssignOp(_, e, _)
110110
| Await(e, _)
111+
| Use(e, _)
111112
| Binary(_, e, _)
112113
| Call(e, _)
113114
| Cast(e, _)
@@ -224,6 +225,7 @@ pub fn expr_trailing_brace(mut expr: &ast::Expr) -> Option<TrailingBrace<'_>> {
224225
| Lit(_)
225226
| Type(_, _)
226227
| Await(_, _)
228+
| Use(_, _)
227229
| Field(_, _)
228230
| Index(_, _, _)
229231
| Underscore

compiler/rustc_ast/src/visit.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1211,6 +1211,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) -> V
12111211
}
12121212
ExprKind::Gen(_capt, body, _kind, _decl_span) => try_visit!(visitor.visit_block(body)),
12131213
ExprKind::Await(expr, _span) => try_visit!(visitor.visit_expr(expr)),
1214+
ExprKind::Use(expr, _span) => try_visit!(visitor.visit_expr(expr)),
12141215
ExprKind::Assign(lhs, rhs, _span) => {
12151216
try_visit!(visitor.visit_expr(lhs));
12161217
try_visit!(visitor.visit_expr(rhs));

compiler/rustc_ast_lowering/src/expr.rs

+5
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
207207
},
208208
),
209209
ExprKind::Await(expr, await_kw_span) => self.lower_expr_await(*await_kw_span, expr),
210+
ExprKind::Use(expr, use_kw_span) => self.lower_expr_use(*use_kw_span, expr),
210211
ExprKind::Closure(box Closure {
211212
binder,
212213
capture_clause,
@@ -1067,6 +1068,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
10671068
)
10681069
}
10691070

1071+
fn lower_expr_use(&mut self, use_kw_span: Span, expr: &Expr) -> hir::ExprKind<'hir> {
1072+
hir::ExprKind::Use(self.lower_expr(expr), use_kw_span)
1073+
}
1074+
10701075
fn lower_expr_closure(
10711076
&mut self,
10721077
binder: &ClosureBinder,

compiler/rustc_ast_passes/src/feature_gate.rs

+1
Original file line numberDiff line numberDiff line change
@@ -489,6 +489,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
489489
gate_all!(dyn_star, "`dyn*` trait objects are experimental");
490490
gate_all!(const_closures, "const closures are experimental");
491491
gate_all!(builtin_syntax, "`builtin #` syntax is unstable");
492+
gate_all!(ergonomic_clones, "ergonomic clones are experimental");
492493
gate_all!(explicit_tail_calls, "`become` expression is experimental");
493494
gate_all!(generic_const_items, "generic const items are experimental");
494495
gate_all!(guard_patterns, "guard patterns are experimental", "consider using match arm guards");

compiler/rustc_ast_pretty/src/pprust/state/expr.rs

+9
Original file line numberDiff line numberDiff line change
@@ -574,6 +574,14 @@ impl<'a> State<'a> {
574574
);
575575
self.word(".await");
576576
}
577+
ast::ExprKind::Use(expr, _) => {
578+
self.print_expr_cond_paren(
579+
expr,
580+
expr.precedence() < ExprPrecedence::Unambiguous,
581+
fixup,
582+
);
583+
self.word(".use");
584+
}
577585
ast::ExprKind::Assign(lhs, rhs, _) => {
578586
self.print_expr_cond_paren(
579587
lhs,
@@ -885,6 +893,7 @@ impl<'a> State<'a> {
885893
fn print_capture_clause(&mut self, capture_clause: ast::CaptureBy) {
886894
match capture_clause {
887895
ast::CaptureBy::Value { .. } => self.word_space("move"),
896+
ast::CaptureBy::Use { .. } => self.word_space("use"),
888897
ast::CaptureBy::Ref => {}
889898
}
890899
}

compiler/rustc_borrowck/src/borrowck_errors.rs

+1
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,7 @@ impl<'infcx, 'tcx> crate::MirBorrowckCtxt<'_, 'infcx, 'tcx> {
403403
.expect_closure();
404404
let span = match capture_clause {
405405
rustc_hir::CaptureBy::Value { move_kw } => move_kw.shrink_to_lo(),
406+
rustc_hir::CaptureBy::Use { use_kw } => use_kw.shrink_to_lo(),
406407
rustc_hir::CaptureBy::Ref => fn_decl_span.shrink_to_lo(),
407408
};
408409
diag.span_suggestion_verbose(

compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -823,7 +823,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
823823
) => {
824824
capture_reason = format!("mutable borrow of `{upvar}`");
825825
}
826-
ty::UpvarCapture::ByValue => {
826+
ty::UpvarCapture::ByValue | ty::UpvarCapture::ByUse => {
827827
capture_reason = format!("possible mutation of `{upvar}`");
828828
}
829829
_ => bug!("upvar `{upvar}` borrowed, but not mutably"),

compiler/rustc_borrowck/src/lib.rs

+13-7
Original file line numberDiff line numberDiff line change
@@ -1490,14 +1490,20 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
14901490
let stmt = &bbd.statements[loc.statement_index];
14911491
debug!("temporary assigned in: stmt={:?}", stmt);
14921492

1493-
if let StatementKind::Assign(box (_, Rvalue::Ref(_, _, source))) = stmt.kind
1494-
{
1495-
propagate_closure_used_mut_place(self, source);
1496-
} else {
1497-
bug!(
1498-
"closures should only capture user variables \
1493+
match stmt.kind {
1494+
StatementKind::Assign(box (
1495+
_,
1496+
Rvalue::Ref(_, _, source)
1497+
| Rvalue::Use(Operand::Copy(source) | Operand::Move(source)),
1498+
)) => {
1499+
propagate_closure_used_mut_place(self, source);
1500+
}
1501+
_ => {
1502+
bug!(
1503+
"closures should only capture user variables \
14991504
or references to user variables"
1500-
);
1505+
);
1506+
}
15011507
}
15021508
}
15031509
_ => propagate_closure_used_mut_place(self, place),

compiler/rustc_builtin_macros/src/assert/context.rs

+1
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,7 @@ impl<'cx, 'a> Context<'cx, 'a> {
297297
| ExprKind::AssignOp(_, _, _)
298298
| ExprKind::Gen(_, _, _, _)
299299
| ExprKind::Await(_, _)
300+
| ExprKind::Use(_, _)
300301
| ExprKind::Block(_, _)
301302
| ExprKind::Break(_, _)
302303
| ExprKind::Closure(_)

compiler/rustc_feature/src/unstable.rs

+2
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,8 @@ declare_features! (
474474
(unstable, doc_masked, "1.21.0", Some(44027)),
475475
/// Allows `dyn* Trait` objects.
476476
(incomplete, dyn_star, "1.65.0", Some(102425)),
477+
/// Allows the .use postfix syntax `x.use` and use closures `use |x| { ... }`
478+
(incomplete, ergonomic_clones, "CURRENT_RUSTC_VERSION", Some(132290)),
477479
/// Allows exhaustive pattern matching on types that contain uninhabited types.
478480
(unstable, exhaustive_patterns, "1.13.0", Some(51085)),
479481
/// Allows explicit tail calls via `become` expression.

compiler/rustc_hir/src/hir.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -2166,6 +2166,7 @@ impl Expr<'_> {
21662166
| ExprKind::Tup(_)
21672167
| ExprKind::Type(..)
21682168
| ExprKind::UnsafeBinderCast(..)
2169+
| ExprKind::Use(..)
21692170
| ExprKind::Err(_) => ExprPrecedence::Unambiguous,
21702171

21712172
ExprKind::DropTemps(expr, ..) => expr.precedence(),
@@ -2212,6 +2213,7 @@ impl Expr<'_> {
22122213
ExprKind::Path(QPath::TypeRelative(..))
22132214
| ExprKind::Call(..)
22142215
| ExprKind::MethodCall(..)
2216+
| ExprKind::Use(..)
22152217
| ExprKind::Struct(..)
22162218
| ExprKind::Tup(..)
22172219
| ExprKind::If(..)
@@ -2285,7 +2287,9 @@ impl Expr<'_> {
22852287

22862288
pub fn can_have_side_effects(&self) -> bool {
22872289
match self.peel_drop_temps().kind {
2288-
ExprKind::Path(_) | ExprKind::Lit(_) | ExprKind::OffsetOf(..) => false,
2290+
ExprKind::Path(_) | ExprKind::Lit(_) | ExprKind::OffsetOf(..) | ExprKind::Use(..) => {
2291+
false
2292+
}
22892293
ExprKind::Type(base, _)
22902294
| ExprKind::Unary(_, base)
22912295
| ExprKind::Field(base, _)
@@ -2547,6 +2551,8 @@ pub enum ExprKind<'hir> {
25472551
///
25482552
/// [`type_dependent_def_id`]: ../../rustc_middle/ty/struct.TypeckResults.html#method.type_dependent_def_id
25492553
MethodCall(&'hir PathSegment<'hir>, &'hir Expr<'hir>, &'hir [Expr<'hir>], Span),
2554+
/// An use expression (e.g., `var.use`).
2555+
Use(&'hir Expr<'hir>, Span),
25502556
/// A tuple (e.g., `(a, b, c, d)`).
25512557
Tup(&'hir [Expr<'hir>]),
25522558
/// A binary operation (e.g., `a + b`, `a * b`).

compiler/rustc_hir/src/intravisit.rs

+3
Original file line numberDiff line numberDiff line change
@@ -821,6 +821,9 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>)
821821
try_visit!(visitor.visit_expr(receiver));
822822
walk_list!(visitor, visit_expr, arguments);
823823
}
824+
ExprKind::Use(expr, _) => {
825+
try_visit!(visitor.visit_expr(expr));
826+
}
824827
ExprKind::Binary(_, ref left_expression, ref right_expression) => {
825828
try_visit!(visitor.visit_expr(left_expression));
826829
try_visit!(visitor.visit_expr(right_expression));

compiler/rustc_hir/src/lang_items.rs

+1
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@ language_item_table! {
171171
Copy, sym::copy, copy_trait, Target::Trait, GenericRequirement::Exact(0);
172172
Clone, sym::clone, clone_trait, Target::Trait, GenericRequirement::None;
173173
CloneFn, sym::clone_fn, clone_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
174+
UseCloned, sym::use_cloned, use_cloned_trait, Target::Trait, GenericRequirement::None;
174175
Sync, sym::sync, sync_trait, Target::Trait, GenericRequirement::Exact(0);
175176
DiscriminantKind, sym::discriminant_kind, discriminant_kind_trait, Target::Trait, GenericRequirement::None;
176177
/// The associated item of the `DiscriminantKind` trait.

compiler/rustc_hir_pretty/src/lib.rs

+5
Original file line numberDiff line numberDiff line change
@@ -1470,6 +1470,10 @@ impl<'a> State<'a> {
14701470
hir::ExprKind::MethodCall(segment, receiver, args, _) => {
14711471
self.print_expr_method_call(segment, receiver, args);
14721472
}
1473+
hir::ExprKind::Use(expr, _) => {
1474+
self.print_expr(expr);
1475+
self.word(".use");
1476+
}
14731477
hir::ExprKind::Binary(op, lhs, rhs) => {
14741478
self.print_expr_binary(op, lhs, rhs);
14751479
}
@@ -2220,6 +2224,7 @@ impl<'a> State<'a> {
22202224
fn print_capture_clause(&mut self, capture_clause: hir::CaptureBy) {
22212225
match capture_clause {
22222226
hir::CaptureBy::Value { .. } => self.word_space("move"),
2227+
hir::CaptureBy::Use { .. } => self.word_space("use"),
22232228
hir::CaptureBy::Ref => {}
22242229
}
22252230
}

compiler/rustc_hir_typeck/src/expr.rs

+11
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
362362
// Any expression child of these expressions constitute reads.
363363
ExprKind::Array(_)
364364
| ExprKind::Call(_, _)
365+
| ExprKind::Use(_, _)
365366
| ExprKind::MethodCall(_, _, _, _)
366367
| ExprKind::Tup(_)
367368
| ExprKind::Binary(_, _, _)
@@ -552,6 +553,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
552553
ExprKind::Closure(closure) => self.check_expr_closure(closure, expr.span, expected),
553554
ExprKind::Block(body, _) => self.check_expr_block(body, expected),
554555
ExprKind::Call(callee, args) => self.check_expr_call(expr, callee, args, expected),
556+
ExprKind::Use(used_expr, _) => self.check_expr_use(used_expr, expected),
555557
ExprKind::MethodCall(segment, receiver, args, _) => {
556558
self.check_expr_method_call(expr, segment, receiver, args, expected)
557559
}
@@ -1616,6 +1618,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
16161618
)
16171619
}
16181620

1621+
/// Checks use `x.use`.
1622+
fn check_expr_use(
1623+
&self,
1624+
used_expr: &'tcx hir::Expr<'tcx>,
1625+
expected: Expectation<'tcx>,
1626+
) -> Ty<'tcx> {
1627+
self.check_expr_with_expectation(used_expr, expected)
1628+
}
1629+
16191630
fn check_expr_cast(
16201631
&self,
16211632
e: &'tcx hir::Expr<'tcx>,

0 commit comments

Comments
 (0)