diff options
| author | bors <bors@rust-lang.org> | 2014-11-07 07:16:33 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2014-11-07 07:16:33 +0000 |
| commit | a0a7ab461283322215f0343cd2b5e66fc19a7bd5 (patch) | |
| tree | ca291c865de18e4fb591399ad43169360f0640ee | |
| parent | b03a2755193cd756583bcf5831cf4545d75ecb8a (diff) | |
| parent | d80a62d84bc9fbc9ae7c8bd300bf5416249b51f7 (diff) | |
auto merge of #18672 : brandonson/rust/functional-update-walk, r=nikomatsakis
Fixes #18567. `Struct{x:foo, .. with_expr}` did not walk `with_expr`, which allowed
using moved variables in some cases. The CFG for structs also built up with
`with_expr` happening before the fields, which is now reversed. (Fields are now
before the `with_expr` in the CFG)
| -rw-r--r-- | src/librustc/middle/cfg/construct.rs | 4 | ||||
| -rw-r--r-- | src/librustc/middle/expr_use_visitor.rs | 4 | ||||
| -rw-r--r-- | src/test/compile-fail/walk-struct-literal-with.rs | 28 |
3 files changed, 34 insertions, 2 deletions
diff --git a/src/librustc/middle/cfg/construct.rs b/src/librustc/middle/cfg/construct.rs index 1e38250ceb3..092ea3dfb38 100644 --- a/src/librustc/middle/cfg/construct.rs +++ b/src/librustc/middle/cfg/construct.rs @@ -448,8 +448,8 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { } ast::ExprStruct(_, ref fields, ref base) => { - let base_exit = self.opt_expr(base, pred); - self.straightline(expr, base_exit, fields.iter().map(|f| &*f.expr)) + let field_cfg = self.straightline(expr, pred, fields.iter().map(|f| &*f.expr)); + self.opt_expr(base, field_cfg) } ast::ExprRepeat(ref elem, ref count) => { diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index d12b612b033..95ebdd8214e 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -672,6 +672,10 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,TYPER> { } } + // walk the with expression so that complex expressions + // are properly handled. + self.walk_expr(with_expr); + fn contains_field_named(field: &ty::field, fields: &Vec<ast::Field>) -> bool diff --git a/src/test/compile-fail/walk-struct-literal-with.rs b/src/test/compile-fail/walk-struct-literal-with.rs new file mode 100644 index 00000000000..bb3b310a68f --- /dev/null +++ b/src/test/compile-fail/walk-struct-literal-with.rs @@ -0,0 +1,28 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +struct Mine{ + test: String, + other_val: int +} + +impl Mine{ + fn make_string_bar(mut self) -> Mine{ + self.test = "Bar".to_string(); + self + } +} + +fn main(){ + let start = Mine{test:"Foo".to_string(), other_val:0}; + let end = Mine{other_val:1, ..start.make_string_bar()}; + println!("{}", start.test); //~ ERROR use of moved value: `start.test` +} + |
