Introduce move expressions (move($expr)) #155023
Introduce move expressions (move($expr)) #155023TaKO8Ki wants to merge 9 commits intorust-lang:mainfrom
move($expr)) #155023Conversation
move($expr)) move($expr))
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
replace TODO with FIXME
|
Some changes occurred in src/tools/clippy cc @rust-lang/clippy The parser was modified, potentially altering the grammar of (stable) Rust cc @fmease Some changes occurred in src/tools/rustfmt cc @rust-lang/rustfmt |
| @@ -0,0 +1,12 @@ | |||
| error[E0658]: `move(expr)` syntax is experimental | |||
There was a problem hiding this comment.
I think it'd be nice to test more of the edge cases around move vs move(...). Something like this:
let x: bool = true;
let y: bool = true;
let a = move(x) || y; // this should be an error: move(x) outside of closurelet x: bool = true;
let y: bool = true;
let a = || move(x) || y; // this should successfully parselet x: bool = true;
let y: bool = true;
let a = move[x] || y; // this should errorlet x: bool = true;
let y: bool = true;
let a = move || move(x) || y; // this should successfully parseTrying to think what else might come up. That's all I can think of right now.
| use crate::errors::{InvalidLegacyConstGenericArg, UseConstGenericArg, YieldInClosure}; | ||
| use crate::{AllowReturnTypeNotation, FnDeclKind, ImplTraitPosition, TryBlockScope}; | ||
|
|
||
| struct MoveExprOccurrence<'a> { |
There was a problem hiding this comment.
comment please -- what is this struct for? what are the roles of its fields?
| expr: &'a Expr, | ||
| } | ||
|
|
||
| struct MoveExprCollector<'a> { |
There was a problem hiding this comment.
comment please: what does this struct do?
There was a problem hiding this comment.
my preference is to have comments that walk through an example, e.g.,
// Given an expression like this
//
// ```
// || move(foo.bar).clone()
// ```
//
// this will pass walk the AST for the closure and collect `move(foo.bar)` expressions into the vector.|
|
||
| impl<'a> Visitor<'a> for MoveExprCollector<'a> { | ||
| fn visit_expr(&mut self, expr: &'a Expr) { | ||
| match &expr.kind { |
There was a problem hiding this comment.
...then here you can refer back to the example...
// If this is `move` expression (`move(foo.bar)` in the example above) push its id into the vector.
// Else recurse.or something lik ethat.
| expr: inner, | ||
| }); | ||
| } | ||
| ExprKind::Closure(..) | ExprKind::Gen(..) | ExprKind::ConstBlock(..) => {} |
There was a problem hiding this comment.
Worth calling this behavior out too: does not recurse into nested closures or const blocks. What about things like...
|| {
fn bar() {
move(x)
}
}...I guess that'd be an error, but still, seems like we should stop recursing at items.
| pub explicit_captures: &'hir [ExplicitCapture], | ||
| } | ||
|
|
||
| #[derive(Debug, Clone, Copy, HashStable_Generic)] |
There was a problem hiding this comment.
comment, what does this struct represent in terms of Rust source code/
| fn main() { | ||
| let s = String::from("hello"); | ||
| let c = || { | ||
| let t = move(s); |
There was a problem hiding this comment.
add a test with more than one move
|
|
||
| let _ = euv::ExprUseVisitor::new(&closure_fcx, &mut delegate).consume_body(body); | ||
|
|
||
| let explicit_captures = match self.tcx.hir_node(closure_hir_id).expect_expr().kind { |
There was a problem hiding this comment.
this paragraph merits a comment
There was a problem hiding this comment.
(...continuing previous store...) so we make it stronger here
| @@ -210,6 +210,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { | |||
|
|
|||
| let _ = euv::ExprUseVisitor::new(&closure_fcx, &mut delegate).consume_body(body); | |||
There was a problem hiding this comment.
pre-existing, but this process ought to have a better comment showing the overall flow.
From what I see here, at the end of this phase, we'll have inferred uses based on the actual actions taken in the closure. But that is not strong enough for move($).clone(), which would introduce a variable $m that is only used by-ref, and we want it to capture $m by value.
| }; | ||
| for capture in explicit_captures { | ||
| let place = closure_fcx.place_for_root_variable(closure_def_id, capture.var_hir_id); | ||
| delegate.capture_information.push(( |
There was a problem hiding this comment.
I have to refresh my memory, I kinda remember there were methods on delegate for like "this place was moved" and so forth-- we are skipping those and directly writing this data structure, is there a helper method we could invoke instead?
|
☔ The latest upstream changes (presumably #155380) made this pull request unmergeable. Please resolve the merge conflicts. |
This is an experimental first version of move expressions.
This first version implements it just in plain closures. A support for coroutine closures will be added in follow up pull requests.
RFC: will be added later
Tracking issue: #155050
Project goal:
r? @nikomatsakis