Skip to content

Commit 1abed7b

Browse files
committed
Implement .use keyword as an alias of clone
1 parent cd4591b commit 1abed7b

File tree

42 files changed

+348
-32
lines changed

Some content is hidden

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

42 files changed

+348
-32
lines changed

compiler/rustc_ast/src/ast.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1357,6 +1357,7 @@ impl Expr {
13571357
// Never need parens
13581358
ExprKind::Array(_)
13591359
| ExprKind::Await(..)
1360+
| ExprKind::Use(..)
13601361
| ExprKind::Block(..)
13611362
| ExprKind::Call(..)
13621363
| ExprKind::ConstBlock(_)
@@ -1536,6 +1537,8 @@ pub enum ExprKind {
15361537
Gen(CaptureBy, P<Block>, GenBlockKind, Span),
15371538
/// An await expression (`my_future.await`). Span is of await keyword.
15381539
Await(P<Expr>, Span),
1540+
/// A use expression (`x.use`). Span is of use keyword.
1541+
Use(P<Expr>, Span),
15391542

15401543
/// A try block (`try { ... }`).
15411544
TryBlock(P<Block>),

compiler/rustc_ast/src/mut_visit.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1713,6 +1713,10 @@ pub fn walk_expr<T: MutVisitor>(vis: &mut T, Expr { kind, id, span, attrs, token
17131713
vis.visit_expr(expr);
17141714
vis.visit_span(await_kw_span);
17151715
}
1716+
ExprKind::Use(expr, use_kw_span) => {
1717+
vis.visit_expr(expr);
1718+
vis.visit_span(use_kw_span);
1719+
}
17161720
ExprKind::Assign(el, er, span) => {
17171721
vis.visit_expr(el);
17181722
vis.visit_expr(er);

compiler/rustc_ast/src/util/classify.rs

Lines changed: 2 additions & 0 deletions
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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1175,6 +1175,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) -> V
11751175
}
11761176
ExprKind::Gen(_capt, body, _kind, _decl_span) => try_visit!(visitor.visit_block(body)),
11771177
ExprKind::Await(expr, _span) => try_visit!(visitor.visit_expr(expr)),
1178+
ExprKind::Use(expr, _span) => try_visit!(visitor.visit_expr(expr)),
11781179
ExprKind::Assign(lhs, rhs, _span) => {
11791180
try_visit!(visitor.visit_expr(lhs));
11801181
try_visit!(visitor.visit_expr(rhs));

compiler/rustc_ast_lowering/messages.ftl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ ast_lowering_default_field_in_tuple = default fields are not supported in tuple
5959
ast_lowering_does_not_support_modifiers =
6060
the `{$class_name}` register class does not support template modifiers
6161
62+
ast_lowering_ergonomic_clones = ergonomic clones is experimental
63+
6264
ast_lowering_extra_double_dot =
6365
`..` can only be used once per {$ctx} pattern
6466
.label = can only be used once per {$ctx} pattern

compiler/rustc_ast_lowering/src/expr.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,18 @@ impl<'hir> LoweringContext<'_, 'hir> {
229229
},
230230
),
231231
ExprKind::Await(expr, await_kw_span) => self.lower_expr_await(*await_kw_span, expr),
232+
ExprKind::Use(expr, use_kw_span) => {
233+
if !self.tcx.features().ergonomic_clones() {
234+
rustc_session::parse::feature_err(
235+
&self.tcx.sess,
236+
sym::ergonomic_clones,
237+
*use_kw_span,
238+
fluent_generated::ast_lowering_ergonomic_clones,
239+
)
240+
.emit();
241+
}
242+
self.lower_expr_use(*use_kw_span, expr)
243+
}
232244
ExprKind::Closure(box Closure {
233245
binder,
234246
capture_clause,
@@ -1033,6 +1045,17 @@ impl<'hir> LoweringContext<'_, 'hir> {
10331045
)
10341046
}
10351047

1048+
/// Desugar `<expr>.use` into:
1049+
/// ```ignore (pseudo-rust)
1050+
/// <expr>.clone()
1051+
/// ```
1052+
fn lower_expr_use(&mut self, use_kw_span: Span, expr: &Expr) -> hir::ExprKind<'hir> {
1053+
let expr = self.lower_expr(expr);
1054+
let span = self.mark_span_with_reason(DesugaringKind::Use, use_kw_span, None);
1055+
1056+
hir::ExprKind::Use(expr, span)
1057+
}
1058+
10361059
fn lower_expr_closure(
10371060
&mut self,
10381061
binder: &ClosureBinder,

compiler/rustc_ast_passes/messages.ftl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,9 @@ ast_passes_inherent_cannot_be = inherent impls cannot be {$annotation}
154154
.type = inherent impl for this type
155155
.only_trait = only trait implementations may be annotated with {$annotation}
156156
157+
ast_passes_invalid_use_feature_disabled = Invalid `.use` with ergonomic_clones disabled
158+
.note = enable ergonomic_clones feature
159+
157160
ast_passes_item_invalid_safety = items outside of `unsafe extern {"{ }"}` cannot be declared with `safe` safety qualifier
158161
.suggestion = remove safe from this item
159162

compiler/rustc_ast_passes/src/ast_validation.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -812,6 +812,21 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
812812
self.walk_ty(ty)
813813
}
814814

815+
fn visit_expr(&mut self, expr: &'a Expr) {
816+
if let ExprKind::Use(_, span) = expr.kind {
817+
if !self.features.ergonomic_clones() {
818+
self.sess
819+
.create_feature_err(
820+
errors::InvalidUseFeatureDisabled { span },
821+
sym::ergonomic_clones,
822+
)
823+
.emit();
824+
}
825+
}
826+
827+
visit::walk_expr(self, expr);
828+
}
829+
815830
fn visit_item(&mut self, item: &'a Item) {
816831
if item.attrs.iter().any(|attr| attr.is_proc_macro_attr()) {
817832
self.has_proc_macro_decls = true;

compiler/rustc_ast_passes/src/errors.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,14 @@ pub(crate) struct InvalidSafetyOnBareFn {
230230
pub span: Span,
231231
}
232232

233+
#[derive(Diagnostic)]
234+
#[diag(ast_passes_invalid_use_feature_disabled)]
235+
#[note]
236+
pub(crate) struct InvalidUseFeatureDisabled {
237+
#[primary_span]
238+
pub span: Span,
239+
}
240+
233241
#[derive(Diagnostic)]
234242
#[diag(ast_passes_unsafe_static)]
235243
pub(crate) struct UnsafeStatic {

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -571,6 +571,14 @@ impl<'a> State<'a> {
571571
);
572572
self.word(".await");
573573
}
574+
ast::ExprKind::Use(expr, _) => {
575+
self.print_expr_cond_paren(
576+
expr,
577+
expr.precedence() < ExprPrecedence::Unambiguous,
578+
fixup,
579+
);
580+
self.word(".use");
581+
}
574582
ast::ExprKind::Assign(lhs, rhs, _) => {
575583
self.print_expr_cond_paren(
576584
lhs,

compiler/rustc_builtin_macros/src/assert/context.rs

Lines changed: 1 addition & 0 deletions
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_hir/src/hir.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1988,6 +1988,7 @@ impl Expr<'_> {
19881988
| ExprKind::Tup(_)
19891989
| ExprKind::Type(..)
19901990
| ExprKind::UnsafeBinderCast(..)
1991+
| ExprKind::Use(..)
19911992
| ExprKind::Err(_) => ExprPrecedence::Unambiguous,
19921993

19931994
ExprKind::DropTemps(ref expr, ..) => expr.precedence(),
@@ -2034,6 +2035,7 @@ impl Expr<'_> {
20342035
ExprKind::Path(QPath::TypeRelative(..))
20352036
| ExprKind::Call(..)
20362037
| ExprKind::MethodCall(..)
2038+
| ExprKind::Use(..)
20372039
| ExprKind::Struct(..)
20382040
| ExprKind::Tup(..)
20392041
| ExprKind::If(..)
@@ -2095,7 +2097,9 @@ impl Expr<'_> {
20952097

20962098
pub fn can_have_side_effects(&self) -> bool {
20972099
match self.peel_drop_temps().kind {
2098-
ExprKind::Path(_) | ExprKind::Lit(_) | ExprKind::OffsetOf(..) => false,
2100+
ExprKind::Path(_) | ExprKind::Lit(_) | ExprKind::OffsetOf(..) | ExprKind::Use(..) => {
2101+
false
2102+
}
20992103
ExprKind::Type(base, _)
21002104
| ExprKind::Unary(_, base)
21012105
| ExprKind::Field(base, _)
@@ -2318,6 +2322,8 @@ pub enum ExprKind<'hir> {
23182322
///
23192323
/// [`type_dependent_def_id`]: ../../rustc_middle/ty/struct.TypeckResults.html#method.type_dependent_def_id
23202324
MethodCall(&'hir PathSegment<'hir>, &'hir Expr<'hir>, &'hir [Expr<'hir>], Span),
2325+
/// An use expression (e.g., `var.use`).
2326+
Use(&'hir Expr<'hir>, Span),
23212327
/// A tuple (e.g., `(a, b, c, d)`).
23222328
Tup(&'hir [Expr<'hir>]),
23232329
/// A binary operation (e.g., `a + b`, `a * b`).

compiler/rustc_hir/src/intravisit.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -764,6 +764,9 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>)
764764
try_visit!(visitor.visit_expr(receiver));
765765
walk_list!(visitor, visit_expr, arguments);
766766
}
767+
ExprKind::Use(expr, _) => {
768+
try_visit!(visitor.visit_expr(expr));
769+
}
767770
ExprKind::Binary(_, ref left_expression, ref right_expression) => {
768771
try_visit!(visitor.visit_expr(left_expression));
769772
try_visit!(visitor.visit_expr(right_expression));

compiler/rustc_hir_pretty/src/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1461,6 +1461,10 @@ impl<'a> State<'a> {
14611461
hir::ExprKind::MethodCall(segment, receiver, args, _) => {
14621462
self.print_expr_method_call(segment, receiver, args);
14631463
}
1464+
hir::ExprKind::Use(expr, _) => {
1465+
self.print_expr(expr);
1466+
self.word(".use");
1467+
}
14641468
hir::ExprKind::Binary(op, lhs, rhs) => {
14651469
self.print_expr_binary(op, lhs, rhs);
14661470
}

compiler/rustc_hir_typeck/src/expr.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
359359
// Any expression child of these expressions constitute reads.
360360
ExprKind::Array(_)
361361
| ExprKind::Call(_, _)
362+
| ExprKind::Use(_, _)
362363
| ExprKind::MethodCall(_, _, _, _)
363364
| ExprKind::Tup(_)
364365
| ExprKind::Binary(_, _, _)
@@ -546,6 +547,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
546547
ExprKind::Closure(closure) => self.check_expr_closure(closure, expr.span, expected),
547548
ExprKind::Block(body, _) => self.check_expr_block(body, expected),
548549
ExprKind::Call(callee, args) => self.check_expr_call(expr, callee, args, expected),
550+
ExprKind::Use(used_expr, _) => self.check_expr_use(used_expr, expected),
549551
ExprKind::MethodCall(segment, receiver, args, _) => {
550552
self.check_expr_method_call(expr, segment, receiver, args, expected)
551553
}
@@ -1614,6 +1616,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
16141616
)
16151617
}
16161618

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

compiler/rustc_hir_typeck/src/expr_use_visitor.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,10 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
367367
self.consume_exprs(args)?;
368368
}
369369

370+
hir::ExprKind::Use(expr, _) => {
371+
self.consume_expr(expr)?;
372+
}
373+
370374
hir::ExprKind::MethodCall(.., receiver, args, _) => {
371375
// callee.m(args)
372376
self.consume_expr(receiver)?;
@@ -1371,6 +1375,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
13711375

13721376
hir::ExprKind::AddrOf(..)
13731377
| hir::ExprKind::Call(..)
1378+
| hir::ExprKind::Use(..)
13741379
| hir::ExprKind::Assign(..)
13751380
| hir::ExprKind::AssignOp(..)
13761381
| hir::ExprKind::Closure { .. }

compiler/rustc_lint/src/dangling.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,10 @@ fn is_temporary_rvalue(expr: &Expr<'_>) -> bool {
159159
ExprKind::Path(..) => false,
160160

161161
// Calls return rvalues.
162-
ExprKind::Call(..) | ExprKind::MethodCall(..) | ExprKind::Binary(..) => true,
162+
ExprKind::Call(..)
163+
| ExprKind::MethodCall(..)
164+
| ExprKind::Use(..)
165+
| ExprKind::Binary(..) => true,
163166

164167
// Inner blocks are rvalues.
165168
ExprKind::If(..) | ExprKind::Loop(..) | ExprKind::Match(..) | ExprKind::Block(..) => true,

compiler/rustc_lint/src/if_let_rescope.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,10 @@ impl<'tcx, 'a> Visitor<'tcx> for FindSignificantDropper<'tcx, 'a> {
415415
}
416416
ControlFlow::Continue(())
417417
}
418+
hir::ExprKind::Use(expr, _) => {
419+
self.visit_expr(expr)?;
420+
ControlFlow::Continue(())
421+
}
418422
hir::ExprKind::Index(left, right, _) | hir::ExprKind::Binary(_, left, right) => {
419423
self.visit_expr(left)?;
420424
self.visit_expr(right)

compiler/rustc_middle/src/thir.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,14 @@ pub enum ExprKind<'tcx> {
319319
/// (e.g. `foo(a, b)` in `x.foo(a, b)`).
320320
fn_span: Span,
321321
},
322+
/// A use expression `x.use`.
323+
ByUse {
324+
/// The expression on which use is applied.
325+
expr: ExprId,
326+
/// The span of use, without the dot and receiver
327+
/// (e.g. `use` in `x.use`).
328+
span: Span,
329+
},
322330
/// A *non-overloaded* dereference.
323331
Deref {
324332
arg: ExprId,

compiler/rustc_middle/src/thir/visit.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,9 @@ pub fn walk_expr<'thir, 'tcx: 'thir, V: Visitor<'thir, 'tcx>>(
6060
visitor.visit_expr(&visitor.thir()[arg]);
6161
}
6262
}
63+
ByUse { expr, span: _ } => {
64+
visitor.visit_expr(&visitor.thir()[expr]);
65+
}
6366
Deref { arg } => visitor.visit_expr(&visitor.thir()[arg]),
6467
Binary { lhs, rhs, op: _ } | LogicalOp { lhs, rhs, op: _ } => {
6568
visitor.visit_expr(&visitor.thir()[lhs]);

compiler/rustc_mir_build/src/builder/expr/as_place.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -560,7 +560,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
560560
| ExprKind::OffsetOf { .. }
561561
| ExprKind::Yield { .. }
562562
| ExprKind::ThreadLocalRef(_)
563-
| ExprKind::Call { .. } => {
563+
| ExprKind::Call { .. }
564+
| ExprKind::ByUse { .. } => {
564565
// these are not places, so we need to make a temporary.
565566
debug_assert!(!matches!(Category::of(&expr.kind), Some(Category::Place)));
566567
let temp =

compiler/rustc_mir_build/src/builder/expr/as_rvalue.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -550,6 +550,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
550550
);
551551
block.and(Rvalue::Use(operand))
552552
}
553+
554+
ExprKind::ByUse { expr, span: _ } => {
555+
let operand = unpack!(
556+
block =
557+
this.as_operand(block, scope, expr, LocalInfo::Boring, NeedsTemporary::No,)
558+
);
559+
block.and(Rvalue::Use(operand))
560+
}
553561
}
554562
}
555563

compiler/rustc_mir_build/src/builder/expr/category.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ impl Category {
5454
| ExprKind::RawBorrow { .. }
5555
| ExprKind::Yield { .. }
5656
| ExprKind::Call { .. }
57+
| ExprKind::ByUse { .. }
5758
| ExprKind::InlineAsm { .. } => Some(Category::Rvalue(RvalueFunc::Into)),
5859

5960
ExprKind::Array { .. }

0 commit comments

Comments
 (0)