Implement .use keyword as an alias of clone
This commit is contained in:
parent
0cf8dbc96c
commit
05c516446a
36 changed files with 247 additions and 24 deletions
|
@ -1399,6 +1399,7 @@ impl Expr {
|
||||||
// Never need parens
|
// Never need parens
|
||||||
ExprKind::Array(_)
|
ExprKind::Array(_)
|
||||||
| ExprKind::Await(..)
|
| ExprKind::Await(..)
|
||||||
|
| ExprKind::Use(..)
|
||||||
| ExprKind::Block(..)
|
| ExprKind::Block(..)
|
||||||
| ExprKind::Call(..)
|
| ExprKind::Call(..)
|
||||||
| ExprKind::ConstBlock(_)
|
| ExprKind::ConstBlock(_)
|
||||||
|
@ -1588,6 +1589,8 @@ pub enum ExprKind {
|
||||||
Gen(CaptureBy, P<Block>, GenBlockKind, Span),
|
Gen(CaptureBy, P<Block>, GenBlockKind, Span),
|
||||||
/// An await expression (`my_future.await`). Span is of await keyword.
|
/// An await expression (`my_future.await`). Span is of await keyword.
|
||||||
Await(P<Expr>, Span),
|
Await(P<Expr>, Span),
|
||||||
|
/// A use expression (`x.use`). Span is of use keyword.
|
||||||
|
Use(P<Expr>, Span),
|
||||||
|
|
||||||
/// A try block (`try { ... }`).
|
/// A try block (`try { ... }`).
|
||||||
TryBlock(P<Block>),
|
TryBlock(P<Block>),
|
||||||
|
|
|
@ -1745,6 +1745,10 @@ pub fn walk_expr<T: MutVisitor>(vis: &mut T, Expr { kind, id, span, attrs, token
|
||||||
vis.visit_expr(expr);
|
vis.visit_expr(expr);
|
||||||
vis.visit_span(await_kw_span);
|
vis.visit_span(await_kw_span);
|
||||||
}
|
}
|
||||||
|
ExprKind::Use(expr, use_kw_span) => {
|
||||||
|
vis.visit_expr(expr);
|
||||||
|
vis.visit_span(use_kw_span);
|
||||||
|
}
|
||||||
ExprKind::Assign(el, er, span) => {
|
ExprKind::Assign(el, er, span) => {
|
||||||
vis.visit_expr(el);
|
vis.visit_expr(el);
|
||||||
vis.visit_expr(er);
|
vis.visit_expr(er);
|
||||||
|
|
|
@ -108,6 +108,7 @@ pub fn leading_labeled_expr(mut expr: &ast::Expr) -> bool {
|
||||||
Assign(e, _, _)
|
Assign(e, _, _)
|
||||||
| AssignOp(_, e, _)
|
| AssignOp(_, e, _)
|
||||||
| Await(e, _)
|
| Await(e, _)
|
||||||
|
| Use(e, _)
|
||||||
| Binary(_, e, _)
|
| Binary(_, e, _)
|
||||||
| Call(e, _)
|
| Call(e, _)
|
||||||
| Cast(e, _)
|
| Cast(e, _)
|
||||||
|
@ -224,6 +225,7 @@ pub fn expr_trailing_brace(mut expr: &ast::Expr) -> Option<TrailingBrace<'_>> {
|
||||||
| Lit(_)
|
| Lit(_)
|
||||||
| Type(_, _)
|
| Type(_, _)
|
||||||
| Await(_, _)
|
| Await(_, _)
|
||||||
|
| Use(_, _)
|
||||||
| Field(_, _)
|
| Field(_, _)
|
||||||
| Index(_, _, _)
|
| Index(_, _, _)
|
||||||
| Underscore
|
| Underscore
|
||||||
|
|
|
@ -1211,6 +1211,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) -> V
|
||||||
}
|
}
|
||||||
ExprKind::Gen(_capt, body, _kind, _decl_span) => try_visit!(visitor.visit_block(body)),
|
ExprKind::Gen(_capt, body, _kind, _decl_span) => try_visit!(visitor.visit_block(body)),
|
||||||
ExprKind::Await(expr, _span) => try_visit!(visitor.visit_expr(expr)),
|
ExprKind::Await(expr, _span) => try_visit!(visitor.visit_expr(expr)),
|
||||||
|
ExprKind::Use(expr, _span) => try_visit!(visitor.visit_expr(expr)),
|
||||||
ExprKind::Assign(lhs, rhs, _span) => {
|
ExprKind::Assign(lhs, rhs, _span) => {
|
||||||
try_visit!(visitor.visit_expr(lhs));
|
try_visit!(visitor.visit_expr(lhs));
|
||||||
try_visit!(visitor.visit_expr(rhs));
|
try_visit!(visitor.visit_expr(rhs));
|
||||||
|
|
|
@ -207,6 +207,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
ExprKind::Await(expr, await_kw_span) => self.lower_expr_await(*await_kw_span, expr),
|
ExprKind::Await(expr, await_kw_span) => self.lower_expr_await(*await_kw_span, expr),
|
||||||
|
ExprKind::Use(expr, use_kw_span) => self.lower_expr_use(*use_kw_span, expr),
|
||||||
ExprKind::Closure(box Closure {
|
ExprKind::Closure(box Closure {
|
||||||
binder,
|
binder,
|
||||||
capture_clause,
|
capture_clause,
|
||||||
|
@ -1067,6 +1068,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn lower_expr_use(&mut self, use_kw_span: Span, expr: &Expr) -> hir::ExprKind<'hir> {
|
||||||
|
hir::ExprKind::Use(self.lower_expr(expr), use_kw_span)
|
||||||
|
}
|
||||||
|
|
||||||
fn lower_expr_closure(
|
fn lower_expr_closure(
|
||||||
&mut self,
|
&mut self,
|
||||||
binder: &ClosureBinder,
|
binder: &ClosureBinder,
|
||||||
|
|
|
@ -574,6 +574,14 @@ impl<'a> State<'a> {
|
||||||
);
|
);
|
||||||
self.word(".await");
|
self.word(".await");
|
||||||
}
|
}
|
||||||
|
ast::ExprKind::Use(expr, _) => {
|
||||||
|
self.print_expr_cond_paren(
|
||||||
|
expr,
|
||||||
|
expr.precedence() < ExprPrecedence::Unambiguous,
|
||||||
|
fixup,
|
||||||
|
);
|
||||||
|
self.word(".use");
|
||||||
|
}
|
||||||
ast::ExprKind::Assign(lhs, rhs, _) => {
|
ast::ExprKind::Assign(lhs, rhs, _) => {
|
||||||
self.print_expr_cond_paren(
|
self.print_expr_cond_paren(
|
||||||
lhs,
|
lhs,
|
||||||
|
|
|
@ -297,6 +297,7 @@ impl<'cx, 'a> Context<'cx, 'a> {
|
||||||
| ExprKind::AssignOp(_, _, _)
|
| ExprKind::AssignOp(_, _, _)
|
||||||
| ExprKind::Gen(_, _, _, _)
|
| ExprKind::Gen(_, _, _, _)
|
||||||
| ExprKind::Await(_, _)
|
| ExprKind::Await(_, _)
|
||||||
|
| ExprKind::Use(_, _)
|
||||||
| ExprKind::Block(_, _)
|
| ExprKind::Block(_, _)
|
||||||
| ExprKind::Break(_, _)
|
| ExprKind::Break(_, _)
|
||||||
| ExprKind::Closure(_)
|
| ExprKind::Closure(_)
|
||||||
|
|
|
@ -2166,6 +2166,7 @@ impl Expr<'_> {
|
||||||
| ExprKind::Tup(_)
|
| ExprKind::Tup(_)
|
||||||
| ExprKind::Type(..)
|
| ExprKind::Type(..)
|
||||||
| ExprKind::UnsafeBinderCast(..)
|
| ExprKind::UnsafeBinderCast(..)
|
||||||
|
| ExprKind::Use(..)
|
||||||
| ExprKind::Err(_) => ExprPrecedence::Unambiguous,
|
| ExprKind::Err(_) => ExprPrecedence::Unambiguous,
|
||||||
|
|
||||||
ExprKind::DropTemps(expr, ..) => expr.precedence(),
|
ExprKind::DropTemps(expr, ..) => expr.precedence(),
|
||||||
|
@ -2212,6 +2213,7 @@ impl Expr<'_> {
|
||||||
ExprKind::Path(QPath::TypeRelative(..))
|
ExprKind::Path(QPath::TypeRelative(..))
|
||||||
| ExprKind::Call(..)
|
| ExprKind::Call(..)
|
||||||
| ExprKind::MethodCall(..)
|
| ExprKind::MethodCall(..)
|
||||||
|
| ExprKind::Use(..)
|
||||||
| ExprKind::Struct(..)
|
| ExprKind::Struct(..)
|
||||||
| ExprKind::Tup(..)
|
| ExprKind::Tup(..)
|
||||||
| ExprKind::If(..)
|
| ExprKind::If(..)
|
||||||
|
@ -2285,7 +2287,9 @@ impl Expr<'_> {
|
||||||
|
|
||||||
pub fn can_have_side_effects(&self) -> bool {
|
pub fn can_have_side_effects(&self) -> bool {
|
||||||
match self.peel_drop_temps().kind {
|
match self.peel_drop_temps().kind {
|
||||||
ExprKind::Path(_) | ExprKind::Lit(_) | ExprKind::OffsetOf(..) => false,
|
ExprKind::Path(_) | ExprKind::Lit(_) | ExprKind::OffsetOf(..) | ExprKind::Use(..) => {
|
||||||
|
false
|
||||||
|
}
|
||||||
ExprKind::Type(base, _)
|
ExprKind::Type(base, _)
|
||||||
| ExprKind::Unary(_, base)
|
| ExprKind::Unary(_, base)
|
||||||
| ExprKind::Field(base, _)
|
| ExprKind::Field(base, _)
|
||||||
|
@ -2547,6 +2551,8 @@ pub enum ExprKind<'hir> {
|
||||||
///
|
///
|
||||||
/// [`type_dependent_def_id`]: ../../rustc_middle/ty/struct.TypeckResults.html#method.type_dependent_def_id
|
/// [`type_dependent_def_id`]: ../../rustc_middle/ty/struct.TypeckResults.html#method.type_dependent_def_id
|
||||||
MethodCall(&'hir PathSegment<'hir>, &'hir Expr<'hir>, &'hir [Expr<'hir>], Span),
|
MethodCall(&'hir PathSegment<'hir>, &'hir Expr<'hir>, &'hir [Expr<'hir>], Span),
|
||||||
|
/// An use expression (e.g., `var.use`).
|
||||||
|
Use(&'hir Expr<'hir>, Span),
|
||||||
/// A tuple (e.g., `(a, b, c, d)`).
|
/// A tuple (e.g., `(a, b, c, d)`).
|
||||||
Tup(&'hir [Expr<'hir>]),
|
Tup(&'hir [Expr<'hir>]),
|
||||||
/// A binary operation (e.g., `a + b`, `a * b`).
|
/// A binary operation (e.g., `a + b`, `a * b`).
|
||||||
|
|
|
@ -821,6 +821,9 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>)
|
||||||
try_visit!(visitor.visit_expr(receiver));
|
try_visit!(visitor.visit_expr(receiver));
|
||||||
walk_list!(visitor, visit_expr, arguments);
|
walk_list!(visitor, visit_expr, arguments);
|
||||||
}
|
}
|
||||||
|
ExprKind::Use(expr, _) => {
|
||||||
|
try_visit!(visitor.visit_expr(expr));
|
||||||
|
}
|
||||||
ExprKind::Binary(_, ref left_expression, ref right_expression) => {
|
ExprKind::Binary(_, ref left_expression, ref right_expression) => {
|
||||||
try_visit!(visitor.visit_expr(left_expression));
|
try_visit!(visitor.visit_expr(left_expression));
|
||||||
try_visit!(visitor.visit_expr(right_expression));
|
try_visit!(visitor.visit_expr(right_expression));
|
||||||
|
|
|
@ -1544,6 +1544,10 @@ impl<'a> State<'a> {
|
||||||
hir::ExprKind::MethodCall(segment, receiver, args, _) => {
|
hir::ExprKind::MethodCall(segment, receiver, args, _) => {
|
||||||
self.print_expr_method_call(segment, receiver, args);
|
self.print_expr_method_call(segment, receiver, args);
|
||||||
}
|
}
|
||||||
|
hir::ExprKind::Use(expr, _) => {
|
||||||
|
self.print_expr(expr);
|
||||||
|
self.word(".use");
|
||||||
|
}
|
||||||
hir::ExprKind::Binary(op, lhs, rhs) => {
|
hir::ExprKind::Binary(op, lhs, rhs) => {
|
||||||
self.print_expr_binary(op, lhs, rhs);
|
self.print_expr_binary(op, lhs, rhs);
|
||||||
}
|
}
|
||||||
|
|
|
@ -362,6 +362,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
// Any expression child of these expressions constitute reads.
|
// Any expression child of these expressions constitute reads.
|
||||||
ExprKind::Array(_)
|
ExprKind::Array(_)
|
||||||
| ExprKind::Call(_, _)
|
| ExprKind::Call(_, _)
|
||||||
|
| ExprKind::Use(_, _)
|
||||||
| ExprKind::MethodCall(_, _, _, _)
|
| ExprKind::MethodCall(_, _, _, _)
|
||||||
| ExprKind::Tup(_)
|
| ExprKind::Tup(_)
|
||||||
| ExprKind::Binary(_, _, _)
|
| ExprKind::Binary(_, _, _)
|
||||||
|
@ -552,6 +553,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
ExprKind::Closure(closure) => self.check_expr_closure(closure, expr.span, expected),
|
ExprKind::Closure(closure) => self.check_expr_closure(closure, expr.span, expected),
|
||||||
ExprKind::Block(body, _) => self.check_expr_block(body, expected),
|
ExprKind::Block(body, _) => self.check_expr_block(body, expected),
|
||||||
ExprKind::Call(callee, args) => self.check_expr_call(expr, callee, args, expected),
|
ExprKind::Call(callee, args) => self.check_expr_call(expr, callee, args, expected),
|
||||||
|
ExprKind::Use(used_expr, _) => self.check_expr_use(used_expr, expected),
|
||||||
ExprKind::MethodCall(segment, receiver, args, _) => {
|
ExprKind::MethodCall(segment, receiver, args, _) => {
|
||||||
self.check_expr_method_call(expr, segment, receiver, args, expected)
|
self.check_expr_method_call(expr, segment, receiver, args, expected)
|
||||||
}
|
}
|
||||||
|
@ -1616,6 +1618,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Checks use `x.use`.
|
||||||
|
fn check_expr_use(
|
||||||
|
&self,
|
||||||
|
used_expr: &'tcx hir::Expr<'tcx>,
|
||||||
|
expected: Expectation<'tcx>,
|
||||||
|
) -> Ty<'tcx> {
|
||||||
|
self.check_expr_with_expectation(used_expr, expected)
|
||||||
|
}
|
||||||
|
|
||||||
fn check_expr_cast(
|
fn check_expr_cast(
|
||||||
&self,
|
&self,
|
||||||
e: &'tcx hir::Expr<'tcx>,
|
e: &'tcx hir::Expr<'tcx>,
|
||||||
|
|
|
@ -366,6 +366,10 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
|
||||||
self.consume_exprs(args)?;
|
self.consume_exprs(args)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hir::ExprKind::Use(expr, _) => {
|
||||||
|
self.consume_expr(expr)?;
|
||||||
|
}
|
||||||
|
|
||||||
hir::ExprKind::MethodCall(.., receiver, args, _) => {
|
hir::ExprKind::MethodCall(.., receiver, args, _) => {
|
||||||
// callee.m(args)
|
// callee.m(args)
|
||||||
self.consume_expr(receiver)?;
|
self.consume_expr(receiver)?;
|
||||||
|
@ -1386,6 +1390,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
|
||||||
|
|
||||||
hir::ExprKind::AddrOf(..)
|
hir::ExprKind::AddrOf(..)
|
||||||
| hir::ExprKind::Call(..)
|
| hir::ExprKind::Call(..)
|
||||||
|
| hir::ExprKind::Use(..)
|
||||||
| hir::ExprKind::Assign(..)
|
| hir::ExprKind::Assign(..)
|
||||||
| hir::ExprKind::AssignOp(..)
|
| hir::ExprKind::AssignOp(..)
|
||||||
| hir::ExprKind::Closure { .. }
|
| hir::ExprKind::Closure { .. }
|
||||||
|
|
|
@ -159,7 +159,10 @@ fn is_temporary_rvalue(expr: &Expr<'_>) -> bool {
|
||||||
ExprKind::Path(..) => false,
|
ExprKind::Path(..) => false,
|
||||||
|
|
||||||
// Calls return rvalues.
|
// Calls return rvalues.
|
||||||
ExprKind::Call(..) | ExprKind::MethodCall(..) | ExprKind::Binary(..) => true,
|
ExprKind::Call(..)
|
||||||
|
| ExprKind::MethodCall(..)
|
||||||
|
| ExprKind::Use(..)
|
||||||
|
| ExprKind::Binary(..) => true,
|
||||||
|
|
||||||
// Inner blocks are rvalues.
|
// Inner blocks are rvalues.
|
||||||
ExprKind::If(..) | ExprKind::Loop(..) | ExprKind::Match(..) | ExprKind::Block(..) => true,
|
ExprKind::If(..) | ExprKind::Loop(..) | ExprKind::Match(..) | ExprKind::Block(..) => true,
|
||||||
|
|
|
@ -312,6 +312,14 @@ pub enum ExprKind<'tcx> {
|
||||||
/// (e.g. `foo(a, b)` in `x.foo(a, b)`).
|
/// (e.g. `foo(a, b)` in `x.foo(a, b)`).
|
||||||
fn_span: Span,
|
fn_span: Span,
|
||||||
},
|
},
|
||||||
|
/// A use expression `x.use`.
|
||||||
|
ByUse {
|
||||||
|
/// The expression on which use is applied.
|
||||||
|
expr: ExprId,
|
||||||
|
/// The span of use, without the dot and receiver
|
||||||
|
/// (e.g. `use` in `x.use`).
|
||||||
|
span: Span,
|
||||||
|
},
|
||||||
/// A *non-overloaded* dereference.
|
/// A *non-overloaded* dereference.
|
||||||
Deref {
|
Deref {
|
||||||
arg: ExprId,
|
arg: ExprId,
|
||||||
|
|
|
@ -59,6 +59,9 @@ pub fn walk_expr<'thir, 'tcx: 'thir, V: Visitor<'thir, 'tcx>>(
|
||||||
visitor.visit_expr(&visitor.thir()[arg]);
|
visitor.visit_expr(&visitor.thir()[arg]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ByUse { expr, span: _ } => {
|
||||||
|
visitor.visit_expr(&visitor.thir()[expr]);
|
||||||
|
}
|
||||||
Deref { arg } => visitor.visit_expr(&visitor.thir()[arg]),
|
Deref { arg } => visitor.visit_expr(&visitor.thir()[arg]),
|
||||||
Binary { lhs, rhs, op: _ } | LogicalOp { lhs, rhs, op: _ } => {
|
Binary { lhs, rhs, op: _ } | LogicalOp { lhs, rhs, op: _ } => {
|
||||||
visitor.visit_expr(&visitor.thir()[lhs]);
|
visitor.visit_expr(&visitor.thir()[lhs]);
|
||||||
|
|
|
@ -582,6 +582,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
| ExprKind::Yield { .. }
|
| ExprKind::Yield { .. }
|
||||||
| ExprKind::ThreadLocalRef(_)
|
| ExprKind::ThreadLocalRef(_)
|
||||||
| ExprKind::Call { .. }
|
| ExprKind::Call { .. }
|
||||||
|
| ExprKind::ByUse { .. }
|
||||||
| ExprKind::WrapUnsafeBinder { .. } => {
|
| ExprKind::WrapUnsafeBinder { .. } => {
|
||||||
// these are not places, so we need to make a temporary.
|
// these are not places, so we need to make a temporary.
|
||||||
debug_assert!(!matches!(Category::of(&expr.kind), Some(Category::Place)));
|
debug_assert!(!matches!(Category::of(&expr.kind), Some(Category::Place)));
|
||||||
|
|
|
@ -572,6 +572,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
);
|
);
|
||||||
block.and(Rvalue::Use(operand))
|
block.and(Rvalue::Use(operand))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ExprKind::ByUse { expr, span: _ } => {
|
||||||
|
let operand = unpack!(
|
||||||
|
block =
|
||||||
|
this.as_operand(block, scope, expr, LocalInfo::Boring, NeedsTemporary::No)
|
||||||
|
);
|
||||||
|
block.and(Rvalue::Use(operand))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -56,6 +56,7 @@ impl Category {
|
||||||
| ExprKind::RawBorrow { .. }
|
| ExprKind::RawBorrow { .. }
|
||||||
| ExprKind::Yield { .. }
|
| ExprKind::Yield { .. }
|
||||||
| ExprKind::Call { .. }
|
| ExprKind::Call { .. }
|
||||||
|
| ExprKind::ByUse { .. }
|
||||||
| ExprKind::InlineAsm { .. } => Some(Category::Rvalue(RvalueFunc::Into)),
|
| ExprKind::InlineAsm { .. } => Some(Category::Rvalue(RvalueFunc::Into)),
|
||||||
|
|
||||||
ExprKind::Array { .. }
|
ExprKind::Array { .. }
|
||||||
|
|
|
@ -4,10 +4,12 @@ use rustc_ast::{AsmMacro, InlineAsmOptions};
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_data_structures::stack::ensure_sufficient_stack;
|
use rustc_data_structures::stack::ensure_sufficient_stack;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
|
use rustc_hir::lang_items::LangItem;
|
||||||
use rustc_middle::mir::*;
|
use rustc_middle::mir::*;
|
||||||
use rustc_middle::span_bug;
|
use rustc_middle::span_bug;
|
||||||
use rustc_middle::thir::*;
|
use rustc_middle::thir::*;
|
||||||
use rustc_middle::ty::CanonicalUserTypeAnnotation;
|
use rustc_middle::ty::{CanonicalUserTypeAnnotation, Ty};
|
||||||
|
use rustc_span::DUMMY_SP;
|
||||||
use rustc_span::source_map::Spanned;
|
use rustc_span::source_map::Spanned;
|
||||||
use tracing::{debug, instrument};
|
use tracing::{debug, instrument};
|
||||||
|
|
||||||
|
@ -289,6 +291,38 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
this.diverge_from(block);
|
this.diverge_from(block);
|
||||||
success.unit()
|
success.unit()
|
||||||
}
|
}
|
||||||
|
ExprKind::ByUse { expr, span } => {
|
||||||
|
let place = unpack!(block = this.as_place(block, expr));
|
||||||
|
let ty = place.ty(&this.local_decls, this.tcx).ty;
|
||||||
|
|
||||||
|
// Convert `expr.use` to a call like `Clone::clone(&expr)`
|
||||||
|
let success = this.cfg.start_new_block();
|
||||||
|
let clone_trait = this.tcx.require_lang_item(LangItem::Clone, None);
|
||||||
|
let clone_fn = this.tcx.associated_item_def_ids(clone_trait)[0];
|
||||||
|
let func = Operand::function_handle(this.tcx, clone_fn, [ty.into()], expr_span);
|
||||||
|
let ref_ty = Ty::new_imm_ref(this.tcx, this.tcx.lifetimes.re_erased, ty);
|
||||||
|
let ref_place = this.temp(ref_ty, span);
|
||||||
|
this.cfg.push_assign(
|
||||||
|
block,
|
||||||
|
source_info,
|
||||||
|
ref_place,
|
||||||
|
Rvalue::Ref(this.tcx.lifetimes.re_erased, BorrowKind::Shared, place),
|
||||||
|
);
|
||||||
|
this.cfg.terminate(
|
||||||
|
block,
|
||||||
|
source_info,
|
||||||
|
TerminatorKind::Call {
|
||||||
|
func,
|
||||||
|
args: [Spanned { node: Operand::Move(ref_place), span: DUMMY_SP }].into(),
|
||||||
|
destination,
|
||||||
|
target: Some(success),
|
||||||
|
unwind: UnwindAction::Unreachable,
|
||||||
|
call_source: CallSource::Misc,
|
||||||
|
fn_span: expr_span,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
success.unit()
|
||||||
|
}
|
||||||
ExprKind::Use { source } => this.expr_into_dest(destination, block, source),
|
ExprKind::Use { source } => this.expr_into_dest(destination, block, source),
|
||||||
ExprKind::Borrow { arg, borrow_kind } => {
|
ExprKind::Borrow { arg, borrow_kind } => {
|
||||||
// We don't do this in `as_rvalue` because we use `as_place`
|
// We don't do this in `as_rvalue` because we use `as_place`
|
||||||
|
|
|
@ -451,6 +451,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
|
||||||
| ExprKind::Tuple { .. }
|
| ExprKind::Tuple { .. }
|
||||||
| ExprKind::Unary { .. }
|
| ExprKind::Unary { .. }
|
||||||
| ExprKind::Call { .. }
|
| ExprKind::Call { .. }
|
||||||
|
| ExprKind::ByUse { .. }
|
||||||
| ExprKind::Assign { .. }
|
| ExprKind::Assign { .. }
|
||||||
| ExprKind::AssignOp { .. }
|
| ExprKind::AssignOp { .. }
|
||||||
| ExprKind::Break { .. }
|
| ExprKind::Break { .. }
|
||||||
|
|
|
@ -464,6 +464,10 @@ impl<'tcx> ThirBuildCx<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hir::ExprKind::Use(expr, span) => {
|
||||||
|
ExprKind::ByUse { expr: self.mirror_expr(expr), span }
|
||||||
|
}
|
||||||
|
|
||||||
hir::ExprKind::AddrOf(hir::BorrowKind::Ref, mutbl, arg) => {
|
hir::ExprKind::AddrOf(hir::BorrowKind::Ref, mutbl, arg) => {
|
||||||
ExprKind::Borrow { borrow_kind: mutbl.to_borrow_kind(), arg: self.mirror_expr(arg) }
|
ExprKind::Borrow { borrow_kind: mutbl.to_borrow_kind(), arg: self.mirror_expr(arg) }
|
||||||
}
|
}
|
||||||
|
|
|
@ -345,6 +345,7 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
|
||||||
| Borrow { .. }
|
| Borrow { .. }
|
||||||
| Box { .. }
|
| Box { .. }
|
||||||
| Call { .. }
|
| Call { .. }
|
||||||
|
| ByUse { .. }
|
||||||
| Closure { .. }
|
| Closure { .. }
|
||||||
| ConstBlock { .. }
|
| ConstBlock { .. }
|
||||||
| ConstParam { .. }
|
| ConstParam { .. }
|
||||||
|
|
|
@ -246,6 +246,13 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> {
|
||||||
|
|
||||||
print_indented!(self, "}", depth_lvl);
|
print_indented!(self, "}", depth_lvl);
|
||||||
}
|
}
|
||||||
|
ByUse { expr, span } => {
|
||||||
|
print_indented!(self, "ByUse {", depth_lvl);
|
||||||
|
print_indented!(self, "expr:", depth_lvl + 1);
|
||||||
|
self.print_expr(*expr, depth_lvl + 2);
|
||||||
|
print_indented!(self, format!("span: {:?}", span), depth_lvl + 1);
|
||||||
|
print_indented!(self, "}", depth_lvl);
|
||||||
|
}
|
||||||
Deref { arg } => {
|
Deref { arg } => {
|
||||||
print_indented!(self, "Deref {", depth_lvl);
|
print_indented!(self, "Deref {", depth_lvl);
|
||||||
self.print_expr(*arg, depth_lvl + 1);
|
self.print_expr(*arg, depth_lvl + 1);
|
||||||
|
|
|
@ -348,6 +348,9 @@ parse_incorrect_use_of_await = incorrect use of `await`
|
||||||
|
|
||||||
parse_incorrect_use_of_await_postfix_suggestion = `await` is a postfix operation
|
parse_incorrect_use_of_await_postfix_suggestion = `await` is a postfix operation
|
||||||
|
|
||||||
|
parse_incorrect_use_of_use = incorrect use of `use`
|
||||||
|
.parentheses_suggestion = `use` is not a method call, try removing the parentheses
|
||||||
|
|
||||||
parse_incorrect_visibility_restriction = incorrect visibility restriction
|
parse_incorrect_visibility_restriction = incorrect visibility restriction
|
||||||
.help = some possible visibility restrictions are:
|
.help = some possible visibility restrictions are:
|
||||||
`pub(crate)`: visible only on the current crate
|
`pub(crate)`: visible only on the current crate
|
||||||
|
|
|
@ -106,6 +106,19 @@ pub(crate) struct IncorrectUseOfAwait {
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(parse_incorrect_use_of_use)]
|
||||||
|
pub(crate) struct IncorrectUseOfUse {
|
||||||
|
#[primary_span]
|
||||||
|
#[suggestion(
|
||||||
|
parse_parentheses_suggestion,
|
||||||
|
style = "verbose",
|
||||||
|
code = "",
|
||||||
|
applicability = "machine-applicable"
|
||||||
|
)]
|
||||||
|
pub span: Span,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Subdiagnostic)]
|
#[derive(Subdiagnostic)]
|
||||||
#[multipart_suggestion(
|
#[multipart_suggestion(
|
||||||
parse_incorrect_use_of_await_postfix_suggestion,
|
parse_incorrect_use_of_await_postfix_suggestion,
|
||||||
|
|
|
@ -38,8 +38,8 @@ use crate::errors::{
|
||||||
DoubleColonInBound, ExpectedIdentifier, ExpectedSemi, ExpectedSemiSugg,
|
DoubleColonInBound, ExpectedIdentifier, ExpectedSemi, ExpectedSemiSugg,
|
||||||
GenericParamsWithoutAngleBrackets, GenericParamsWithoutAngleBracketsSugg,
|
GenericParamsWithoutAngleBrackets, GenericParamsWithoutAngleBracketsSugg,
|
||||||
HelpIdentifierStartsWithNumber, HelpUseLatestEdition, InInTypo, IncorrectAwait,
|
HelpIdentifierStartsWithNumber, HelpUseLatestEdition, InInTypo, IncorrectAwait,
|
||||||
IncorrectSemicolon, IncorrectUseOfAwait, PatternMethodParamWithoutBody, QuestionMarkInType,
|
IncorrectSemicolon, IncorrectUseOfAwait, IncorrectUseOfUse, PatternMethodParamWithoutBody,
|
||||||
QuestionMarkInTypeSugg, SelfParamNotFirst, StructLiteralBodyWithoutPath,
|
QuestionMarkInType, QuestionMarkInTypeSugg, SelfParamNotFirst, StructLiteralBodyWithoutPath,
|
||||||
StructLiteralBodyWithoutPathSugg, StructLiteralNeedingParens, StructLiteralNeedingParensSugg,
|
StructLiteralBodyWithoutPathSugg, StructLiteralNeedingParens, StructLiteralNeedingParensSugg,
|
||||||
SuggAddMissingLetStmt, SuggEscapeIdentifier, SuggRemoveComma, TernaryOperator,
|
SuggAddMissingLetStmt, SuggEscapeIdentifier, SuggRemoveComma, TernaryOperator,
|
||||||
UnexpectedConstInGenericParam, UnexpectedConstParamDeclaration,
|
UnexpectedConstInGenericParam, UnexpectedConstParamDeclaration,
|
||||||
|
@ -1991,7 +1991,7 @@ impl<'a> Parser<'a> {
|
||||||
self.parse_expr()
|
self.parse_expr()
|
||||||
}
|
}
|
||||||
.map_err(|mut err| {
|
.map_err(|mut err| {
|
||||||
err.span_label(await_sp, "while parsing this incorrect await expression");
|
err.span_label(await_sp, format!("while parsing this incorrect await expression"));
|
||||||
err
|
err
|
||||||
})?;
|
})?;
|
||||||
Ok((expr.span, expr, is_question))
|
Ok((expr.span, expr, is_question))
|
||||||
|
@ -2030,6 +2030,21 @@ impl<'a> Parser<'a> {
|
||||||
self.dcx().emit_err(IncorrectUseOfAwait { span });
|
self.dcx().emit_err(IncorrectUseOfAwait { span });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
///
|
||||||
|
/// If encountering `x.use()`, consumes and emits an error.
|
||||||
|
pub(super) fn recover_from_use(&mut self) {
|
||||||
|
if self.token == token::OpenDelim(Delimiter::Parenthesis)
|
||||||
|
&& self.look_ahead(1, |t| t == &token::CloseDelim(Delimiter::Parenthesis))
|
||||||
|
{
|
||||||
|
// var.use()
|
||||||
|
let lo = self.token.span;
|
||||||
|
self.bump(); // (
|
||||||
|
let span = lo.to(self.token.span);
|
||||||
|
self.bump(); // )
|
||||||
|
|
||||||
|
self.dcx().emit_err(IncorrectUseOfUse { span });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(super) fn try_macro_suggestion(&mut self) -> PResult<'a, P<Expr>> {
|
pub(super) fn try_macro_suggestion(&mut self) -> PResult<'a, P<Expr>> {
|
||||||
let is_try = self.token.is_keyword(kw::Try);
|
let is_try = self.token.is_keyword(kw::Try);
|
||||||
|
|
|
@ -778,6 +778,7 @@ impl<'a> Parser<'a> {
|
||||||
ExprKind::MethodCall(_) => "a method call",
|
ExprKind::MethodCall(_) => "a method call",
|
||||||
ExprKind::Call(_, _) => "a function call",
|
ExprKind::Call(_, _) => "a function call",
|
||||||
ExprKind::Await(_, _) => "`.await`",
|
ExprKind::Await(_, _) => "`.await`",
|
||||||
|
ExprKind::Use(_, _) => "`.use`",
|
||||||
ExprKind::Match(_, _, MatchKind::Postfix) => "a postfix match",
|
ExprKind::Match(_, _, MatchKind::Postfix) => "a postfix match",
|
||||||
ExprKind::Err(_) => return Ok(with_postfix),
|
ExprKind::Err(_) => return Ok(with_postfix),
|
||||||
_ => unreachable!("parse_dot_or_call_expr_with_ shouldn't produce this"),
|
_ => unreachable!("parse_dot_or_call_expr_with_ shouldn't produce this"),
|
||||||
|
@ -1296,6 +1297,12 @@ impl<'a> Parser<'a> {
|
||||||
return Ok(self.mk_await_expr(self_arg, lo));
|
return Ok(self.mk_await_expr(self_arg, lo));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if self.eat_keyword(exp!(Use)) {
|
||||||
|
let use_span = self.prev_token.span;
|
||||||
|
self.psess.gated_spans.gate(sym::ergonomic_clones, use_span);
|
||||||
|
return Ok(self.mk_use_expr(self_arg, lo));
|
||||||
|
}
|
||||||
|
|
||||||
// Post-fix match
|
// Post-fix match
|
||||||
if self.eat_keyword(exp!(Match)) {
|
if self.eat_keyword(exp!(Match)) {
|
||||||
let match_span = self.prev_token.span;
|
let match_span = self.prev_token.span;
|
||||||
|
@ -3818,6 +3825,13 @@ impl<'a> Parser<'a> {
|
||||||
await_expr
|
await_expr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn mk_use_expr(&mut self, self_arg: P<Expr>, lo: Span) -> P<Expr> {
|
||||||
|
let span = lo.to(self.prev_token.span);
|
||||||
|
let use_expr = self.mk_expr(span, ExprKind::Use(self_arg, self.prev_token.span));
|
||||||
|
self.recover_from_use();
|
||||||
|
use_expr
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn mk_expr_with_attrs(&self, span: Span, kind: ExprKind, attrs: AttrVec) -> P<Expr> {
|
pub(crate) fn mk_expr_with_attrs(&self, span: Span, kind: ExprKind, attrs: AttrVec) -> P<Expr> {
|
||||||
P(Expr { kind, span, attrs, id: DUMMY_NODE_ID, tokens: None })
|
P(Expr { kind, span, attrs, id: DUMMY_NODE_ID, tokens: None })
|
||||||
}
|
}
|
||||||
|
@ -3966,6 +3980,7 @@ impl MutVisitor for CondChecker<'_> {
|
||||||
}
|
}
|
||||||
ExprKind::Unary(_, _)
|
ExprKind::Unary(_, _)
|
||||||
| ExprKind::Await(_, _)
|
| ExprKind::Await(_, _)
|
||||||
|
| ExprKind::Use(_, _)
|
||||||
| ExprKind::AssignOp(_, _, _)
|
| ExprKind::AssignOp(_, _, _)
|
||||||
| ExprKind::Range(_, _, _)
|
| ExprKind::Range(_, _, _)
|
||||||
| ExprKind::Try(_)
|
| ExprKind::Try(_)
|
||||||
|
|
|
@ -328,6 +328,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
|
||||||
Array,
|
Array,
|
||||||
Call,
|
Call,
|
||||||
MethodCall,
|
MethodCall,
|
||||||
|
Use,
|
||||||
Tup,
|
Tup,
|
||||||
Binary,
|
Binary,
|
||||||
Unary,
|
Unary,
|
||||||
|
@ -626,7 +627,7 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> {
|
||||||
(self, e, e.kind, None, ast, Expr, ExprKind),
|
(self, e, e.kind, None, ast, Expr, ExprKind),
|
||||||
[
|
[
|
||||||
Array, ConstBlock, Call, MethodCall, Tup, Binary, Unary, Lit, Cast, Type, Let,
|
Array, ConstBlock, Call, MethodCall, Tup, Binary, Unary, Lit, Cast, Type, Let,
|
||||||
If, While, ForLoop, Loop, Match, Closure, Block, Await, TryBlock, Assign,
|
If, While, ForLoop, Loop, Match, Closure, Block, Await, Use, TryBlock, Assign,
|
||||||
AssignOp, Field, Index, Range, Underscore, Path, AddrOf, Break, Continue, Ret,
|
AssignOp, Field, Index, Range, Underscore, Path, AddrOf, Break, Continue, Ret,
|
||||||
InlineAsm, FormatArgs, OffsetOf, MacCall, Struct, Repeat, Paren, Try, Yield, Yeet,
|
InlineAsm, FormatArgs, OffsetOf, MacCall, Struct, Repeat, Paren, Try, Yield, Yeet,
|
||||||
Become, IncludedBytes, Gen, UnsafeBinderCast, Err, Dummy
|
Become, IncludedBytes, Gen, UnsafeBinderCast, Err, Dummy
|
||||||
|
|
|
@ -426,6 +426,7 @@ impl<'tcx> Visitor<'tcx> for IrMaps<'tcx> {
|
||||||
| hir::ExprKind::Array(..)
|
| hir::ExprKind::Array(..)
|
||||||
| hir::ExprKind::Call(..)
|
| hir::ExprKind::Call(..)
|
||||||
| hir::ExprKind::MethodCall(..)
|
| hir::ExprKind::MethodCall(..)
|
||||||
|
| hir::ExprKind::Use(..)
|
||||||
| hir::ExprKind::Tup(..)
|
| hir::ExprKind::Tup(..)
|
||||||
| hir::ExprKind::Binary(..)
|
| hir::ExprKind::Binary(..)
|
||||||
| hir::ExprKind::AddrOf(..)
|
| hir::ExprKind::AddrOf(..)
|
||||||
|
@ -1031,6 +1032,11 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
|
||||||
self.propagate_through_expr(receiver, succ)
|
self.propagate_through_expr(receiver, succ)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hir::ExprKind::Use(expr, _) => {
|
||||||
|
let succ = self.check_is_ty_uninhabited(expr, succ);
|
||||||
|
self.propagate_through_expr(expr, succ)
|
||||||
|
}
|
||||||
|
|
||||||
hir::ExprKind::Tup(exprs) => self.propagate_through_exprs(exprs, succ),
|
hir::ExprKind::Tup(exprs) => self.propagate_through_exprs(exprs, succ),
|
||||||
|
|
||||||
hir::ExprKind::Binary(op, ref l, ref r) if op.node.is_lazy() => {
|
hir::ExprKind::Binary(op, ref l, ref r) if op.node.is_lazy() => {
|
||||||
|
@ -1418,6 +1424,7 @@ fn check_expr<'tcx>(this: &mut Liveness<'_, 'tcx>, expr: &'tcx Expr<'tcx>) {
|
||||||
// no correctness conditions related to liveness
|
// no correctness conditions related to liveness
|
||||||
hir::ExprKind::Call(..)
|
hir::ExprKind::Call(..)
|
||||||
| hir::ExprKind::MethodCall(..)
|
| hir::ExprKind::MethodCall(..)
|
||||||
|
| hir::ExprKind::Use(..)
|
||||||
| hir::ExprKind::Match(..)
|
| hir::ExprKind::Match(..)
|
||||||
| hir::ExprKind::Loop(..)
|
| hir::ExprKind::Loop(..)
|
||||||
| hir::ExprKind::Index(..)
|
| hir::ExprKind::Index(..)
|
||||||
|
|
|
@ -182,6 +182,7 @@ impl CheckInlineAssembly {
|
||||||
| ExprKind::Array(..)
|
| ExprKind::Array(..)
|
||||||
| ExprKind::Call(..)
|
| ExprKind::Call(..)
|
||||||
| ExprKind::MethodCall(..)
|
| ExprKind::MethodCall(..)
|
||||||
|
| ExprKind::Use(..)
|
||||||
| ExprKind::Tup(..)
|
| ExprKind::Tup(..)
|
||||||
| ExprKind::Binary(..)
|
| ExprKind::Binary(..)
|
||||||
| ExprKind::Unary(..)
|
| ExprKind::Unary(..)
|
||||||
|
|
|
@ -14,6 +14,8 @@ ty_utils_borrow_not_supported = borrowing is not supported in generic constants
|
||||||
|
|
||||||
ty_utils_box_not_supported = allocations are not allowed in generic constants
|
ty_utils_box_not_supported = allocations are not allowed in generic constants
|
||||||
|
|
||||||
|
ty_utils_by_use_not_supported = .use is not allowed in generic constants
|
||||||
|
|
||||||
ty_utils_closure_and_return_not_supported = closures and function keywords are not supported in generic constants
|
ty_utils_closure_and_return_not_supported = closures and function keywords are not supported in generic constants
|
||||||
|
|
||||||
ty_utils_const_block_not_supported = const blocks are not supported in generic constants
|
ty_utils_const_block_not_supported = const blocks are not supported in generic constants
|
||||||
|
|
|
@ -230,7 +230,9 @@ fn recurse_build<'tcx>(
|
||||||
error(GenericConstantTooComplexSub::LoopNotSupported(node.span))?
|
error(GenericConstantTooComplexSub::LoopNotSupported(node.span))?
|
||||||
}
|
}
|
||||||
ExprKind::Box { .. } => error(GenericConstantTooComplexSub::BoxNotSupported(node.span))?,
|
ExprKind::Box { .. } => error(GenericConstantTooComplexSub::BoxNotSupported(node.span))?,
|
||||||
|
ExprKind::ByUse { .. } => {
|
||||||
|
error(GenericConstantTooComplexSub::ByUseNotSupported(node.span))?
|
||||||
|
}
|
||||||
ExprKind::Unary { .. } => unreachable!(),
|
ExprKind::Unary { .. } => unreachable!(),
|
||||||
// we handle valid unary/binary ops above
|
// we handle valid unary/binary ops above
|
||||||
ExprKind::Binary { .. } => {
|
ExprKind::Binary { .. } => {
|
||||||
|
@ -317,6 +319,7 @@ impl<'a, 'tcx> IsThirPolymorphic<'a, 'tcx> {
|
||||||
| thir::ExprKind::Box { .. }
|
| thir::ExprKind::Box { .. }
|
||||||
| thir::ExprKind::If { .. }
|
| thir::ExprKind::If { .. }
|
||||||
| thir::ExprKind::Call { .. }
|
| thir::ExprKind::Call { .. }
|
||||||
|
| thir::ExprKind::ByUse { .. }
|
||||||
| thir::ExprKind::Deref { .. }
|
| thir::ExprKind::Deref { .. }
|
||||||
| thir::ExprKind::Binary { .. }
|
| thir::ExprKind::Binary { .. }
|
||||||
| thir::ExprKind::LogicalOp { .. }
|
| thir::ExprKind::LogicalOp { .. }
|
||||||
|
|
|
@ -55,6 +55,8 @@ pub(crate) enum GenericConstantTooComplexSub {
|
||||||
BoxNotSupported(#[primary_span] Span),
|
BoxNotSupported(#[primary_span] Span),
|
||||||
#[label(ty_utils_binary_not_supported)]
|
#[label(ty_utils_binary_not_supported)]
|
||||||
BinaryNotSupported(#[primary_span] Span),
|
BinaryNotSupported(#[primary_span] Span),
|
||||||
|
#[label(ty_utils_by_use_not_supported)]
|
||||||
|
ByUseNotSupported(#[primary_span] Span),
|
||||||
#[label(ty_utils_logical_op_not_supported)]
|
#[label(ty_utils_logical_op_not_supported)]
|
||||||
LogicalOpNotSupported(#[primary_span] Span),
|
LogicalOpNotSupported(#[primary_span] Span),
|
||||||
#[label(ty_utils_assign_not_supported)]
|
#[label(ty_utils_assign_not_supported)]
|
||||||
|
|
14
tests/ui/ergonomic-clones/dotuse.rs
Normal file
14
tests/ui/ergonomic-clones/dotuse.rs
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
//@ check-pass
|
||||||
|
|
||||||
|
#![feature(ergonomic_clones)]
|
||||||
|
|
||||||
|
fn basic_test(x: i32) -> i32 {
|
||||||
|
x.use.use.abs()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn do_not_move_test(x: String) -> String {
|
||||||
|
let s = x.use;
|
||||||
|
x
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -1,18 +1,18 @@
|
||||||
fn ergonomic_clone(x: i32) -> i32 {
|
fn ergonomic_clone(x: i32) -> i32 {
|
||||||
x.use
|
x.use
|
||||||
//~^ ERROR expected identifier, found keyword `use`
|
//~^ ERROR `.use` calls are experimental [E0658]
|
||||||
//~| ERROR `i32` is a primitive type and therefore doesn't have fields [E0610]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ergonomic_closure_clone() {
|
fn ergonomic_closure_clone() {
|
||||||
let s1 = String::from("hi!");
|
let s1 = String::from("hi!");
|
||||||
|
|
||||||
let s2 = use || {
|
let s2 = use || {
|
||||||
//~^ ERROR expected expression, found keyword `use`
|
//~^ ERROR incorrect use of `use`
|
||||||
s1
|
s1
|
||||||
};
|
};
|
||||||
|
|
||||||
let s3 = use || {
|
let s3 = use || {
|
||||||
|
//~^ ERROR incorrect use of `use`
|
||||||
s1
|
s1
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,26 +1,49 @@
|
||||||
error: expected identifier, found keyword `use`
|
error: incorrect use of `use`
|
||||||
--> $DIR/feature-gate-ergonomic-clones.rs:2:7
|
--> $DIR/feature-gate-ergonomic-clones.rs:9:14
|
||||||
|
|
|
|
||||||
LL | x.use
|
LL | let s2 = use || {
|
||||||
| ^^^ expected identifier, found keyword
|
| ______________^
|
||||||
|
LL | |
|
||||||
|
LL | | s1
|
||||||
|
LL | | };
|
||||||
|
| |_____^
|
||||||
|
|
|
|
||||||
help: escape `use` to use it as an identifier
|
help: `use` is a postfix operation
|
||||||
|
|
|
||||||
|
LL ~ let s2 = || {
|
||||||
|
LL |
|
||||||
|
LL | s1
|
||||||
|
LL ~ }.use;
|
||||||
|
|
|
|
||||||
LL | x.r#use
|
|
||||||
| ++
|
|
||||||
|
|
||||||
error: expected expression, found keyword `use`
|
error: incorrect use of `use`
|
||||||
--> $DIR/feature-gate-ergonomic-clones.rs:10:14
|
--> $DIR/feature-gate-ergonomic-clones.rs:14:14
|
||||||
|
|
|
||||||
|
LL | let s3 = use || {
|
||||||
|
| ______________^
|
||||||
|
LL | |
|
||||||
|
LL | | s1
|
||||||
|
LL | | };
|
||||||
|
| |_____^
|
||||||
|
|
|
||||||
|
help: `use` is a postfix operation
|
||||||
|
|
|
||||||
|
LL ~ let s3 = || {
|
||||||
|
LL |
|
||||||
|
LL | s1
|
||||||
|
LL ~ }.use;
|
||||||
|
|
|
|
||||||
LL | let s2 = use || {
|
|
||||||
| ^^^ expected expression
|
|
||||||
|
|
||||||
error[E0610]: `i32` is a primitive type and therefore doesn't have fields
|
error[E0658]: `.use` calls are experimental
|
||||||
--> $DIR/feature-gate-ergonomic-clones.rs:2:7
|
--> $DIR/feature-gate-ergonomic-clones.rs:2:7
|
||||||
|
|
|
|
||||||
LL | x.use
|
LL | x.use
|
||||||
| ^^^
|
| ^^^
|
||||||
|
|
|
||||||
|
= note: see issue #132290 <https://github.com/rust-lang/rust/issues/132290> for more information
|
||||||
|
= help: add `#![feature(ergonomic_clones)]` to the crate attributes to enable
|
||||||
|
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||||
|
|
||||||
error: aborting due to 3 previous errors
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0610`.
|
For more information about this error, try `rustc --explain E0658`.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue