Skip to content

Commit 9fd5694

Browse files
committed
Implement .use keyword as an alias of clone
1 parent 91fcfa1 commit 9fd5694

File tree

38 files changed

+331
-33
lines changed

38 files changed

+331
-33
lines changed

compiler/rustc_ast/src/ast.rs

+3
Original file line numberDiff line numberDiff line change
@@ -1348,6 +1348,7 @@ impl Expr {
13481348
// Never need parens
13491349
ExprKind::Array(_)
13501350
| ExprKind::Await(..)
1351+
| ExprKind::Use(..)
13511352
| ExprKind::Block(..)
13521353
| ExprKind::Call(..)
13531354
| ExprKind::ConstBlock(_)
@@ -1528,6 +1529,8 @@ pub enum ExprKind {
15281529
Gen(CaptureBy, P<Block>, GenBlockKind, Span),
15291530
/// An await expression (`my_future.await`). Span is of await keyword.
15301531
Await(P<Expr>, Span),
1532+
/// A use expression (`x.use`). Span is of use keyword.
1533+
Use(P<Expr>, Span),
15311534

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

compiler/rustc_ast/src/mut_visit.rs

+4
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

+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
@@ -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/src/expr.rs

+12
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,7 @@ 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) => self.lower_expr_use(*use_kw_span, expr),
232233
ExprKind::Closure(box Closure {
233234
binder,
234235
capture_clause,
@@ -1033,6 +1034,17 @@ impl<'hir> LoweringContext<'_, 'hir> {
10331034
)
10341035
}
10351036

1037+
/// Desugar `<expr>.use` into:
1038+
/// ```ignore (pseudo-rust)
1039+
/// <expr>.clone()
1040+
/// ```
1041+
fn lower_expr_use(&mut self, use_kw_span: Span, expr: &Expr) -> hir::ExprKind<'hir> {
1042+
let expr = self.lower_expr(expr);
1043+
let span = self.mark_span_with_reason(DesugaringKind::Use, use_kw_span, None);
1044+
1045+
hir::ExprKind::Use(expr, span)
1046+
}
1047+
10361048
fn lower_expr_closure(
10371049
&mut self,
10381050
binder: &ClosureBinder,

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

+8
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

+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_hir/src/hir.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -1993,6 +1993,7 @@ impl Expr<'_> {
19931993
| ExprKind::Tup(_)
19941994
| ExprKind::Type(..)
19951995
| ExprKind::UnsafeBinderCast(..)
1996+
| ExprKind::Use(..)
19961997
| ExprKind::Err(_) => ExprPrecedence::Unambiguous,
19971998

19981999
ExprKind::DropTemps(expr, ..) => expr.precedence(),
@@ -2039,6 +2040,7 @@ impl Expr<'_> {
20392040
ExprKind::Path(QPath::TypeRelative(..))
20402041
| ExprKind::Call(..)
20412042
| ExprKind::MethodCall(..)
2043+
| ExprKind::Use(..)
20422044
| ExprKind::Struct(..)
20432045
| ExprKind::Tup(..)
20442046
| ExprKind::If(..)
@@ -2100,7 +2102,9 @@ impl Expr<'_> {
21002102

21012103
pub fn can_have_side_effects(&self) -> bool {
21022104
match self.peel_drop_temps().kind {
2103-
ExprKind::Path(_) | ExprKind::Lit(_) | ExprKind::OffsetOf(..) => false,
2105+
ExprKind::Path(_) | ExprKind::Lit(_) | ExprKind::OffsetOf(..) | ExprKind::Use(..) => {
2106+
false
2107+
}
21042108
ExprKind::Type(base, _)
21052109
| ExprKind::Unary(_, base)
21062110
| ExprKind::Field(base, _)
@@ -2323,6 +2327,8 @@ pub enum ExprKind<'hir> {
23232327
///
23242328
/// [`type_dependent_def_id`]: ../../rustc_middle/ty/struct.TypeckResults.html#method.type_dependent_def_id
23252329
MethodCall(&'hir PathSegment<'hir>, &'hir Expr<'hir>, &'hir [Expr<'hir>], Span),
2330+
/// An use expression (e.g., `var.use`).
2331+
Use(&'hir Expr<'hir>, Span),
23262332
/// A tuple (e.g., `(a, b, c, d)`).
23272333
Tup(&'hir [Expr<'hir>]),
23282334
/// A binary operation (e.g., `a + b`, `a * b`).

compiler/rustc_hir/src/intravisit.rs

+3
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

+4
Original file line numberDiff line numberDiff line change
@@ -1463,6 +1463,10 @@ impl<'a> State<'a> {
14631463
hir::ExprKind::MethodCall(segment, receiver, args, _) => {
14641464
self.print_expr_method_call(segment, receiver, args);
14651465
}
1466+
hir::ExprKind::Use(expr, _) => {
1467+
self.print_expr(expr);
1468+
self.word(".use");
1469+
}
14661470
hir::ExprKind::Binary(op, lhs, rhs) => {
14671471
self.print_expr_binary(op, lhs, rhs);
14681472
}

compiler/rustc_hir_typeck/src/expr.rs

+11
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

+5
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

+4-1
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

+4
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

+8
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

+3
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

+2-1
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

+8
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

+1
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 { .. }

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

+30-1
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,12 @@ use rustc_ast::{AsmMacro, InlineAsmOptions};
44
use rustc_data_structures::fx::FxHashMap;
55
use rustc_data_structures::stack::ensure_sufficient_stack;
66
use rustc_hir as hir;
7+
use rustc_hir::lang_items::LangItem;
78
use rustc_middle::mir::*;
89
use rustc_middle::span_bug;
910
use rustc_middle::thir::*;
10-
use rustc_middle::ty::CanonicalUserTypeAnnotation;
11+
use rustc_middle::ty::{CanonicalUserTypeAnnotation, Ty};
12+
use rustc_span::DUMMY_SP;
1113
use rustc_span::source_map::Spanned;
1214
use tracing::{debug, instrument};
1315

@@ -281,6 +283,33 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
281283
this.diverge_from(block);
282284
success.unit()
283285
}
286+
ExprKind::ByUse { expr, span } => {
287+
let place = unpack!(block = this.as_place(block, expr));
288+
let ty = place.ty(&this.local_decls, this.tcx).ty;
289+
290+
let success = this.cfg.start_new_block();
291+
let clone_trait = this.tcx.require_lang_item(LangItem::Clone, None);
292+
let clone_fn = this.tcx.associated_item_def_ids(clone_trait)[0];
293+
let func = Operand::function_handle(this.tcx, clone_fn, [ty.into()], expr_span);
294+
let ref_ty = Ty::new_imm_ref(this.tcx, this.tcx.lifetimes.re_erased, ty);
295+
let ref_place = this.temp(ref_ty, span);
296+
this.cfg.push_assign(
297+
block,
298+
source_info,
299+
ref_place,
300+
Rvalue::Ref(this.tcx.lifetimes.re_erased, BorrowKind::Shared, place),
301+
);
302+
this.cfg.terminate(block, source_info, TerminatorKind::Call {
303+
func,
304+
args: [Spanned { node: Operand::Move(ref_place), span: DUMMY_SP }].into(),
305+
destination,
306+
target: Some(success),
307+
unwind: UnwindAction::Unreachable,
308+
call_source: CallSource::Misc,
309+
fn_span: expr_span,
310+
});
311+
success.unit()
312+
}
284313
ExprKind::Use { source } => this.expr_into_dest(destination, block, source),
285314
ExprKind::Borrow { arg, borrow_kind } => {
286315
// We don't do this in `as_rvalue` because we use `as_place`

compiler/rustc_mir_build/src/check_unsafety.rs

+1
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
446446
| ExprKind::Tuple { .. }
447447
| ExprKind::Unary { .. }
448448
| ExprKind::Call { .. }
449+
| ExprKind::ByUse { .. }
449450
| ExprKind::Assign { .. }
450451
| ExprKind::AssignOp { .. }
451452
| ExprKind::Break { .. }

compiler/rustc_mir_build/src/thir/cx/expr.rs

+4
Original file line numberDiff line numberDiff line change
@@ -487,6 +487,10 @@ impl<'tcx> Cx<'tcx> {
487487
}
488488
}
489489

490+
hir::ExprKind::Use(expr, span) => {
491+
ExprKind::ByUse { expr: self.mirror_expr(expr), span }
492+
}
493+
490494
hir::ExprKind::AddrOf(hir::BorrowKind::Ref, mutbl, arg) => {
491495
ExprKind::Borrow { borrow_kind: mutbl.to_borrow_kind(), arg: self.mirror_expr(arg) }
492496
}

compiler/rustc_mir_build/src/thir/pattern/check_match.rs

+1
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,7 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
345345
| Borrow { .. }
346346
| Box { .. }
347347
| Call { .. }
348+
| ByUse { .. }
348349
| Closure { .. }
349350
| ConstBlock { .. }
350351
| ConstParam { .. }

compiler/rustc_mir_build/src/thir/print.rs

+7
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,13 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> {
244244

245245
print_indented!(self, "}", depth_lvl);
246246
}
247+
ByUse { expr, span } => {
248+
print_indented!(self, "ByUse {", depth_lvl);
249+
print_indented!(self, "expr:", depth_lvl + 1);
250+
self.print_expr(*expr, depth_lvl + 2);
251+
print_indented!(self, format!("span: {:?}", span), depth_lvl + 1);
252+
print_indented!(self, "}", depth_lvl);
253+
}
247254
Deref { arg } => {
248255
print_indented!(self, "Deref {", depth_lvl);
249256
self.print_expr(*arg, depth_lvl + 1);

compiler/rustc_parse/messages.ftl

+5
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,11 @@ parse_incorrect_use_of_await = incorrect use of `await`
348348
349349
parse_incorrect_use_of_await_postfix_suggestion = `await` is a postfix operation
350350
351+
parse_incorrect_use_of_use = incorrect use of `use`
352+
.parentheses_suggestion = `use` is not a method call, remove the parentheses
353+
354+
parse_incorrect_use_of_use_postfix_suggestion = `use` is a postfix operation
355+
351356
parse_incorrect_visibility_restriction = incorrect visibility restriction
352357
.help = some possible visibility restrictions are:
353358
`pub(crate)`: visible only on the current crate

0 commit comments

Comments
 (0)