mirror of
https://github.com/rust-lang/rust.git
synced 2026-05-16 04:55:22 +03:00
add move(expr) syntax
This commit is contained in:
@@ -1594,6 +1594,7 @@ fn prefix_attrs_precedence(attrs: &AttrVec) -> ExprPrecedence {
|
||||
// need parens sometimes. E.g. we can print `(let _ = a) && b` as `let _ = a && b`
|
||||
// but we need to print `(let _ = a) < b` as-is with parens.
|
||||
| ExprKind::Let(..)
|
||||
| ExprKind::Move(..)
|
||||
| ExprKind::Unary(..) => ExprPrecedence::Prefix,
|
||||
|
||||
// Need parens if and only if there are prefix attributes.
|
||||
@@ -1763,6 +1764,8 @@ pub enum ExprKind {
|
||||
Binary(BinOp, Box<Expr>, Box<Expr>),
|
||||
/// A unary operation (e.g., `!x`, `*x`).
|
||||
Unary(UnOp, Box<Expr>),
|
||||
/// A `move(expr)` expression.
|
||||
Move(Box<Expr>, Span),
|
||||
/// A literal (e.g., `1`, `"foo"`).
|
||||
Lit(token::Lit),
|
||||
/// A cast (e.g., `foo as f64`).
|
||||
|
||||
@@ -108,6 +108,7 @@ pub fn leading_labeled_expr(mut expr: &ast::Expr) -> bool {
|
||||
Assign(e, _, _)
|
||||
| AssignOp(_, e, _)
|
||||
| Await(e, _)
|
||||
| Move(e, _)
|
||||
| Use(e, _)
|
||||
| Binary(_, e, _)
|
||||
| Call(e, _)
|
||||
@@ -183,6 +184,7 @@ pub fn expr_trailing_brace(mut expr: &ast::Expr) -> Option<TrailingBrace<'_>> {
|
||||
| Ret(Some(e))
|
||||
| Unary(_, e)
|
||||
| Yeet(Some(e))
|
||||
| Move(e, _)
|
||||
| Become(e) => {
|
||||
expr = e;
|
||||
}
|
||||
|
||||
@@ -1024,7 +1024,9 @@ pub fn walk_fn<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, kind: FnKind<$($lt)?
|
||||
visit_visitable!($($mut)? vis, block, opt_label),
|
||||
ExprKind::Gen(capt, body, kind, decl_span) =>
|
||||
visit_visitable!($($mut)? vis, capt, body, kind, decl_span),
|
||||
ExprKind::Await(expr, span) | ExprKind::Use(expr, span) =>
|
||||
ExprKind::Await(expr, span)
|
||||
| ExprKind::Move(expr, span)
|
||||
| ExprKind::Use(expr, span) =>
|
||||
visit_visitable!($($mut)? vis, expr, span),
|
||||
ExprKind::Assign(lhs, rhs, span) =>
|
||||
visit_visitable!($($mut)? vis, lhs, rhs, span),
|
||||
|
||||
@@ -136,6 +136,13 @@ pub(crate) struct ClosureCannotBeStatic {
|
||||
pub fn_decl_span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag("`move(expr)` is only supported in plain closures")]
|
||||
pub(crate) struct MoveExprOnlyInPlainClosures {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag("functional record updates are not allowed in destructuring assignments")]
|
||||
pub(crate) struct FunctionalRecordUpdateDestructuringAssignment {
|
||||
|
||||
@@ -19,8 +19,8 @@
|
||||
use super::errors::{
|
||||
AsyncCoroutinesNotSupported, AwaitOnlyInAsyncFnAndBlocks, ClosureCannotBeStatic,
|
||||
CoroutineTooManyParameters, FunctionalRecordUpdateDestructuringAssignment,
|
||||
InclusiveRangeWithNoEnd, MatchArmWithNoBody, NeverPatternWithBody, NeverPatternWithGuard,
|
||||
UnderscoreExprLhsAssign,
|
||||
InclusiveRangeWithNoEnd, MatchArmWithNoBody, MoveExprOnlyInPlainClosures, NeverPatternWithBody,
|
||||
NeverPatternWithGuard, UnderscoreExprLhsAssign,
|
||||
};
|
||||
use super::{
|
||||
GenericArgsMode, ImplTraitContext, LoweringContext, ParamMode, ResolverAstLoweringExt,
|
||||
@@ -211,6 +211,18 @@ pub(super) fn lower_expr_mut(&mut self, e: &Expr) -> hir::Expr<'hir> {
|
||||
},
|
||||
),
|
||||
ExprKind::Await(expr, await_kw_span) => self.lower_expr_await(*await_kw_span, expr),
|
||||
ExprKind::Move(_, move_kw_span) => {
|
||||
if !self.tcx.features().move_expr() {
|
||||
return self.expr_err(
|
||||
*move_kw_span,
|
||||
self.dcx().span_delayed_bug(*move_kw_span, "invalid move(expr)"),
|
||||
);
|
||||
}
|
||||
self.dcx().emit_err(MoveExprOnlyInPlainClosures { span: *move_kw_span });
|
||||
hir::ExprKind::Err(
|
||||
self.dcx().span_delayed_bug(*move_kw_span, "invalid move(expr)"),
|
||||
)
|
||||
}
|
||||
ExprKind::Use(expr, use_kw_span) => self.lower_expr_use(*use_kw_span, expr),
|
||||
ExprKind::Closure(Closure {
|
||||
binder,
|
||||
|
||||
@@ -352,6 +352,9 @@ fn visit_expr(&mut self, e: &'a ast::Expr) {
|
||||
}
|
||||
_ => (),
|
||||
},
|
||||
ast::ExprKind::Move(_, move_kw_span) => {
|
||||
gate!(&self, move_expr, move_kw_span, "`move(expr)` syntax is experimental");
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
visit::walk_expr(self, e)
|
||||
|
||||
@@ -630,6 +630,11 @@ pub(super) fn print_expr_outer_attr_style(
|
||||
);
|
||||
self.word(".await");
|
||||
}
|
||||
ast::ExprKind::Move(expr, _) => {
|
||||
self.word("move(");
|
||||
self.print_expr(expr, FixupContext::default());
|
||||
self.word(")");
|
||||
}
|
||||
ast::ExprKind::Use(expr, _) => {
|
||||
self.print_expr_cond_paren(
|
||||
expr,
|
||||
|
||||
@@ -248,6 +248,9 @@ fn manage_cond_expr(&mut self, expr: &mut Box<Expr>) {
|
||||
self.manage_cond_expr(arg);
|
||||
}
|
||||
}
|
||||
ExprKind::Move(local_expr, _) => {
|
||||
self.manage_cond_expr(local_expr);
|
||||
}
|
||||
ExprKind::Path(_, Path { segments, .. }) if let [path_segment] = &segments[..] => {
|
||||
let path_ident = path_segment.ident;
|
||||
self.manage_initial_capture(expr, path_ident);
|
||||
|
||||
@@ -564,6 +564,12 @@ macro_rules! make_it {
|
||||
token::Ident(..) if this.token.is_keyword(kw::Box) => {
|
||||
make_it!(this, attrs, |this, _| this.parse_expr_box(lo))
|
||||
}
|
||||
token::Ident(..)
|
||||
if this.token.is_keyword(kw::Move)
|
||||
&& this.look_ahead(1, |t| *t == token::OpenParen) =>
|
||||
{
|
||||
make_it!(this, attrs, |this, _| this.parse_expr_move(lo))
|
||||
}
|
||||
token::Ident(..) if this.may_recover() && this.is_mistaken_not_ident_negation() => {
|
||||
make_it!(this, attrs, |this, _| this.recover_not_expr(lo))
|
||||
}
|
||||
@@ -607,6 +613,16 @@ fn parse_expr_box(&mut self, box_kw: Span) -> PResult<'a, (Span, ExprKind)> {
|
||||
Ok((span, ExprKind::Err(guar)))
|
||||
}
|
||||
|
||||
fn parse_expr_move(&mut self, move_kw: Span) -> PResult<'a, (Span, ExprKind)> {
|
||||
self.bump();
|
||||
self.psess.gated_spans.gate(sym::move_expr, move_kw);
|
||||
self.expect(exp!(OpenParen))?;
|
||||
let expr = self.parse_expr()?;
|
||||
self.expect(exp!(CloseParen))?;
|
||||
let span = move_kw.to(self.prev_token.span);
|
||||
Ok((span, ExprKind::Move(expr, move_kw)))
|
||||
}
|
||||
|
||||
fn is_mistaken_not_ident_negation(&self) -> bool {
|
||||
let token_cannot_continue_expr = |t: &Token| match t.uninterpolate().kind {
|
||||
// These tokens can start an expression after `!`, but
|
||||
@@ -4387,6 +4403,7 @@ fn find_let_some(expr: &Expr) -> Option<&Expr> {
|
||||
}
|
||||
ExprKind::Unary(_, _)
|
||||
| ExprKind::Await(_, _)
|
||||
| ExprKind::Move(_, _)
|
||||
| ExprKind::Use(_, _)
|
||||
| ExprKind::AssignOp(_, _, _)
|
||||
| ExprKind::Range(_, _, _)
|
||||
|
||||
@@ -657,7 +657,7 @@ fn visit_expr(&mut self, e: &'v ast::Expr) {
|
||||
(self, e, e.kind, None, ast, Expr, ExprKind),
|
||||
[
|
||||
Array, ConstBlock, Call, MethodCall, Tup, Binary, Unary, Lit, Cast, Type, Let,
|
||||
If, While, ForLoop, Loop, Match, Closure, Block, Await, Use, TryBlock, Assign,
|
||||
If, While, ForLoop, Loop, Match, Closure, Block, Await, Move, Use, TryBlock, Assign,
|
||||
AssignOp, Field, Index, Range, Underscore, Path, AddrOf, Break, Continue, Ret,
|
||||
InlineAsm, FormatArgs, OffsetOf, MacCall, Struct, Repeat, Paren, Try, Yield, Yeet,
|
||||
Become, IncludedBytes, Gen, UnsafeBinderCast, Err, Dummy
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
fn main() {
|
||||
let _ = || move(2);
|
||||
//~^ ERROR `move(expr)` syntax is experimental
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
error[E0658]: `move(expr)` syntax is experimental
|
||||
--> $DIR/feature-gate-move_expr.rs:2:16
|
||||
|
|
||||
LL | let _ = || move(2);
|
||||
| ^^^^
|
||||
|
|
||||
= help: add `#![feature(move_expr)]` 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 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
||||
@@ -3,6 +3,7 @@
|
||||
//@ compile-flags: --test
|
||||
|
||||
#![allow(incomplete_features)]
|
||||
#![allow(unused_features)]
|
||||
#![feature(auto_traits)]
|
||||
#![feature(box_patterns)]
|
||||
#![feature(const_block_items)]
|
||||
@@ -11,6 +12,7 @@
|
||||
#![feature(decl_macro)]
|
||||
#![feature(macro_guard_matcher)]
|
||||
#![feature(more_qualified_paths)]
|
||||
#![feature(move_expr)]
|
||||
#![feature(never_patterns)]
|
||||
#![feature(specialization)]
|
||||
#![feature(trait_alias)]
|
||||
@@ -110,6 +112,7 @@ fn test_expr() {
|
||||
c1!(expr, [ *expr ], "*expr");
|
||||
c1!(expr, [ !expr ], "!expr");
|
||||
c1!(expr, [ -expr ], "-expr");
|
||||
c1!(expr, [ move(expr) ], "move(expr)");
|
||||
|
||||
// ExprKind::Lit
|
||||
c1!(expr, [ 'x' ], "'x'");
|
||||
|
||||
Reference in New Issue
Block a user