Skip to content

Commit

Permalink
Fix codegen breaking aliasing rules for functions with sret results
Browse files Browse the repository at this point in the history
This reverts commit a0ec902 "Avoid
unnecessary temporary on assignments".

Leaving out the temporary for the functions return value can lead to a
situation that conflicts with rust's aliasing rules.

Given this:

````rust
fn func(f: &mut Foo) -> Foo { /* ... */ }

fn bar() {
    let mut foo = Foo { /* ... */ };

    foo = func(&mut foo);
}
````

We effectively get two mutable references to the same variable `foo` at
the same time. One for the parameter `f`, and one for the hidden
out-pointer. So we can't just `trans_into` the destination directly, but
must use `trans` to get a new temporary slot from which the result can
be copied.
  • Loading branch information
dotdash committed Oct 23, 2014
1 parent 2130f22 commit 70fe20a
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 2 deletions.
4 changes: 2 additions & 2 deletions src/librustc/middle/trans/expr.rs
Expand Up @@ -940,6 +940,7 @@ fn trans_rvalue_stmt_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
controlflow::trans_loop(bcx, expr.id, &**body)
}
ast::ExprAssign(ref dst, ref src) => {
let src_datum = unpack_datum!(bcx, trans(bcx, &**src));
let dst_datum = unpack_datum!(bcx, trans_to_lvalue(bcx, &**dst, "assign"));

if ty::type_needs_drop(bcx.tcx(), dst_datum.ty) {
Expand All @@ -960,7 +961,6 @@ fn trans_rvalue_stmt_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
// We could avoid this intermediary with some analysis
// to determine whether `dst` may possibly own `src`.
debuginfo::set_source_location(bcx.fcx, expr.id, expr.span);
let src_datum = unpack_datum!(bcx, trans(bcx, &**src));
let src_datum = unpack_datum!(
bcx, src_datum.to_rvalue_datum(bcx, "ExprAssign"));
bcx = glue::drop_ty(bcx,
Expand All @@ -969,7 +969,7 @@ fn trans_rvalue_stmt_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
Some(NodeInfo { id: expr.id, span: expr.span }));
src_datum.store_to(bcx, dst_datum.val)
} else {
trans_into(bcx, &**src, SaveIn(dst_datum.to_llref()))
src_datum.store_to(bcx, dst_datum.val)
}
}
ast::ExprAssignOp(op, ref dst, ref src) => {
Expand Down
30 changes: 30 additions & 0 deletions src/test/run-pass/out-pointer-aliasing.rs
@@ -0,0 +1,30 @@
// 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.

pub struct Foo {
f1: int,
_f2: int,
}

#[inline(never)]
pub fn foo(f: &mut Foo) -> Foo {
let ret = *f;
f.f1 = 0;
ret
}

pub fn main() {
let mut f = Foo {
f1: 8,
_f2: 9,
};
f = foo(&mut f);
assert_eq!(f.f1, 8);
}

0 comments on commit 70fe20a

Please sign in to comment.