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,

0 commit comments

Comments
 (0)