about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2014-11-07 07:16:33 +0000
committerbors <bors@rust-lang.org>2014-11-07 07:16:33 +0000
commita0a7ab461283322215f0343cd2b5e66fc19a7bd5 (patch)
treeca291c865de18e4fb591399ad43169360f0640ee
parentb03a2755193cd756583bcf5831cf4545d75ecb8a (diff)
parentd80a62d84bc9fbc9ae7c8bd300bf5416249b51f7 (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.rs4
-rw-r--r--src/librustc/middle/expr_use_visitor.rs4
-rw-r--r--src/test/compile-fail/walk-struct-literal-with.rs28
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`
+}
+