Skip to content

Commit d80a62d

Browse files
committed
Fix soundness hole in struct with expressions.
Fixes rust-lang#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)
1 parent 60a669a commit d80a62d

File tree

3 files changed

+34
-2
lines changed

3 files changed

+34
-2
lines changed

src/librustc/middle/cfg/construct.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -448,8 +448,8 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
448448
}
449449

450450
ast::ExprStruct(_, ref fields, ref base) => {
451-
let base_exit = self.opt_expr(base, pred);
452-
self.straightline(expr, base_exit, fields.iter().map(|f| &*f.expr))
451+
let field_cfg = self.straightline(expr, pred, fields.iter().map(|f| &*f.expr));
452+
self.opt_expr(base, field_cfg)
453453
}
454454

455455
ast::ExprRepeat(ref elem, ref count) => {

src/librustc/middle/expr_use_visitor.rs

+4
Original file line numberDiff line numberDiff line change
@@ -672,6 +672,10 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,TYPER> {
672672
}
673673
}
674674

675+
// walk the with expression so that complex expressions
676+
// are properly handled.
677+
self.walk_expr(with_expr);
678+
675679
fn contains_field_named(field: &ty::field,
676680
fields: &Vec<ast::Field>)
677681
-> bool
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
struct Mine{
12+
test: String,
13+
other_val: int
14+
}
15+
16+
impl Mine{
17+
fn make_string_bar(mut self) -> Mine{
18+
self.test = "Bar".to_string();
19+
self
20+
}
21+
}
22+
23+
fn main(){
24+
let start = Mine{test:"Foo".to_string(), other_val:0};
25+
let end = Mine{other_val:1, ..start.make_string_bar()};
26+
println!("{}", start.test); //~ ERROR use of moved value: `start.test`
27+
}
28+

0 commit comments

Comments
 (0)