Skip to content

Commit 05c5164

Browse files
committed
Implement .use keyword as an alias of clone
1 parent 0cf8dbc commit 05c5164

File tree

36 files changed

+247
-24
lines changed

36 files changed

+247
-24
lines changed

compiler/rustc_ast/src/ast.rs

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

compiler/rustc_ast/src/mut_visit.rs

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

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_pretty/src/pprust/state/expr.rs

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

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
@@ -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_pretty/src/lib.rs

+4
Original file line numberDiff line numberDiff line change
@@ -1544,6 +1544,10 @@ impl<'a> State<'a> {
15441544
hir::ExprKind::MethodCall(segment, receiver, args, _) => {
15451545
self.print_expr_method_call(segment, receiver, args);
15461546
}
1547+
hir::ExprKind::Use(expr, _) => {
1548+
self.print_expr(expr);
1549+
self.word(".use");
1550+
}
15471551
hir::ExprKind::Binary(op, lhs, rhs) => {
15481552
self.print_expr_binary(op, lhs, rhs);
15491553
}

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>,

compiler/rustc_hir_typeck/src/expr_use_visitor.rs

+5
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,10 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
366366
self.consume_exprs(args)?;
367367
}
368368

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

13871391
hir::ExprKind::AddrOf(..)
13881392
| hir::ExprKind::Call(..)
1393+
| hir::ExprKind::Use(..)
13891394
| hir::ExprKind::Assign(..)
13901395
| hir::ExprKind::AssignOp(..)
13911396
| 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_middle/src/thir.rs

+8
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,14 @@ pub enum ExprKind<'tcx> {
312312
/// (e.g. `foo(a, b)` in `x.foo(a, b)`).
313313
fn_span: Span,
314314
},
315+
/// A use expression `x.use`.
316+
ByUse {
317+
/// The expression on which use is applied.
318+
expr: ExprId,
319+
/// The span of use, without the dot and receiver
320+
/// (e.g. `use` in `x.use`).
321+
span: Span,
322+
},
315323
/// A *non-overloaded* dereference.
316324
Deref {
317325
arg: ExprId,

compiler/rustc_middle/src/thir/visit.rs

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

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

+1
Original file line numberDiff line numberDiff line change
@@ -582,6 +582,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
582582
| ExprKind::Yield { .. }
583583
| ExprKind::ThreadLocalRef(_)
584584
| ExprKind::Call { .. }
585+
| ExprKind::ByUse { .. }
585586
| ExprKind::WrapUnsafeBinder { .. } => {
586587
// these are not places, so we need to make a temporary.
587588
debug_assert!(!matches!(Category::of(&expr.kind), Some(Category::Place)));

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

+8
Original file line numberDiff line numberDiff line change
@@ -572,6 +572,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
572572
);
573573
block.and(Rvalue::Use(operand))
574574
}
575+
576+
ExprKind::ByUse { expr, span: _ } => {
577+
let operand = unpack!(
578+
block =
579+
this.as_operand(block, scope, expr, LocalInfo::Boring, NeedsTemporary::No)
580+
);
581+
block.and(Rvalue::Use(operand))
582+
}
575583
}
576584
}
577585

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

+1
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ impl Category {
5656
| ExprKind::RawBorrow { .. }
5757
| ExprKind::Yield { .. }
5858
| ExprKind::Call { .. }
59+
| ExprKind::ByUse { .. }
5960
| ExprKind::InlineAsm { .. } => Some(Category::Rvalue(RvalueFunc::Into)),
6061

6162
ExprKind::Array { .. }

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

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

@@ -289,6 +291,38 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
289291
this.diverge_from(block);
290292
success.unit()
291293
}
294+
ExprKind::ByUse { expr, span } => {
295+
let place = unpack!(block = this.as_place(block, expr));
296+
let ty = place.ty(&this.local_decls, this.tcx).ty;
297+
298+
// Convert `expr.use` to a call like `Clone::clone(&expr)`
299+
let success = this.cfg.start_new_block();
300+
let clone_trait = this.tcx.require_lang_item(LangItem::Clone, None);
301+
let clone_fn = this.tcx.associated_item_def_ids(clone_trait)[0];
302+
let func = Operand::function_handle(this.tcx, clone_fn, [ty.into()], expr_span);
303+
let ref_ty = Ty::new_imm_ref(this.tcx, this.tcx.lifetimes.re_erased, ty);
304+
let ref_place = this.temp(ref_ty, span);
305+
this.cfg.push_assign(
306+
block,
307+
source_info,
308+
ref_place,
309+
Rvalue::Ref(this.tcx.lifetimes.re_erased, BorrowKind::Shared, place),
310+
);
311+
this.cfg.terminate(
312+
block,
313+
source_info,
314+
TerminatorKind::Call {
315+
func,
316+
args: [Spanned { node: Operand::Move(ref_place), span: DUMMY_SP }].into(),
317+
destination,
318+
target: Some(success),
319+
unwind: UnwindAction::Unreachable,
320+
call_source: CallSource::Misc,
321+
fn_span: expr_span,
322+
},
323+
);
324+
success.unit()
325+
}
292326
ExprKind::Use { source } => this.expr_into_dest(destination, block, source),
293327
ExprKind::Borrow { arg, borrow_kind } => {
294328
// 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
@@ -451,6 +451,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
451451
| ExprKind::Tuple { .. }
452452
| ExprKind::Unary { .. }
453453
| ExprKind::Call { .. }
454+
| ExprKind::ByUse { .. }
454455
| ExprKind::Assign { .. }
455456
| ExprKind::AssignOp { .. }
456457
| ExprKind::Break { .. }

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

+4
Original file line numberDiff line numberDiff line change
@@ -464,6 +464,10 @@ impl<'tcx> ThirBuildCx<'tcx> {
464464
}
465465
}
466466

467+
hir::ExprKind::Use(expr, span) => {
468+
ExprKind::ByUse { expr: self.mirror_expr(expr), span }
469+
}
470+
467471
hir::ExprKind::AddrOf(hir::BorrowKind::Ref, mutbl, arg) => {
468472
ExprKind::Borrow { borrow_kind: mutbl.to_borrow_kind(), arg: self.mirror_expr(arg) }
469473
}

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
@@ -246,6 +246,13 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> {
246246

247247
print_indented!(self, "}", depth_lvl);
248248
}
249+
ByUse { expr, span } => {
250+
print_indented!(self, "ByUse {", depth_lvl);
251+
print_indented!(self, "expr:", depth_lvl + 1);
252+
self.print_expr(*expr, depth_lvl + 2);
253+
print_indented!(self, format!("span: {:?}", span), depth_lvl + 1);
254+
print_indented!(self, "}", depth_lvl);
255+
}
249256
Deref { arg } => {
250257
print_indented!(self, "Deref {", depth_lvl);
251258
self.print_expr(*arg, depth_lvl + 1);

compiler/rustc_parse/messages.ftl

+3
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,9 @@ 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, try removing the parentheses
353+
351354
parse_incorrect_visibility_restriction = incorrect visibility restriction
352355
.help = some possible visibility restrictions are:
353356
`pub(crate)`: visible only on the current crate

compiler/rustc_parse/src/errors.rs

+13
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,19 @@ pub(crate) struct IncorrectUseOfAwait {
106106
pub span: Span,
107107
}
108108

109+
#[derive(Diagnostic)]
110+
#[diag(parse_incorrect_use_of_use)]
111+
pub(crate) struct IncorrectUseOfUse {
112+
#[primary_span]
113+
#[suggestion(
114+
parse_parentheses_suggestion,
115+
style = "verbose",
116+
code = "",
117+
applicability = "machine-applicable"
118+
)]
119+
pub span: Span,
120+
}
121+
109122
#[derive(Subdiagnostic)]
110123
#[multipart_suggestion(
111124
parse_incorrect_use_of_await_postfix_suggestion,

0 commit comments

Comments
 (0)