diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index c50d23ff592e8..8cf39d14763b3 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -345,9 +345,12 @@ impl mem_categorization_ctxt { match **adjustment { ty::AutoObject(..) => { // Implicity casts a concrete object to trait object - // Result is an rvalue + // so just patch up the type let expr_ty = ty::expr_ty_adjusted(self.tcx, expr); - self.cat_rvalue_node(expr, expr_ty) + @cmt_ { + ty: expr_ty, + ..*self.cat_expr_unadjusted(expr) + } } ty::AutoAddEnv(..) => { diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs index ae9aa461bc7f8..8d3b953af1829 100644 --- a/src/librustc/middle/trans/expr.rs +++ b/src/librustc/middle/trans/expr.rs @@ -229,19 +229,12 @@ pub fn trans_to_datum<'a>(bcx: &'a Block<'a>, expr: &ast::Expr) } }; } - AutoObject(ref sigil, ref region, _, _, _, _) => { + AutoObject(..) => { let adjusted_ty = ty::expr_ty_adjusted(bcx.tcx(), expr); let scratch = scratch_datum(bcx, adjusted_ty, "__adjust", false); - let trait_store = match *sigil { - ast::BorrowedSigil => ty::RegionTraitStore(region.expect("expected valid region")), - ast::OwnedSigil => ty::UniqTraitStore, - ast::ManagedSigil => ty::BoxTraitStore - }; - - bcx = meth::trans_trait_cast(bcx, expr, expr.id, SaveIn(scratch.val), - trait_store, false /* no adjustments */); + bcx = meth::trans_trait_cast(bcx, expr, expr.id, SaveIn(scratch.val), Some(datum)); datum = scratch.to_appropriate_datum(bcx); datum.add_clean(bcx); @@ -834,9 +827,9 @@ fn trans_rvalue_dps_unadjusted<'a>( } ast::ExprCast(val, _) => { match ty::get(node_id_type(bcx, expr.id)).sty { - ty::ty_trait(_, _, store, _, _) => { + ty::ty_trait(..) => { return meth::trans_trait_cast(bcx, val, expr.id, - dest, store, true /* adjustments */); + dest, None); } _ => { bcx.tcx().sess.span_bug(expr.span, diff --git a/src/librustc/middle/trans/meth.rs b/src/librustc/middle/trans/meth.rs index 7bf278fe8d812..f8aef90838118 100644 --- a/src/librustc/middle/trans/meth.rs +++ b/src/librustc/middle/trans/meth.rs @@ -637,22 +637,14 @@ pub fn trans_trait_cast<'a>( val: &ast::Expr, id: ast::NodeId, dest: expr::Dest, - _store: ty::TraitStore, - do_adjustments: bool) + obj: Option) -> &'a Block<'a> { let mut bcx = bcx; let _icx = push_ctxt("impl::trans_cast"); - // Pick the right trans function - let trans_into = if do_adjustments { - expr::trans_into - } else { - expr::trans_into_unadjusted - }; - let lldest = match dest { Ignore => { - return trans_into(bcx, val, Ignore); + return expr::trans_into(bcx, val, Ignore); } SaveIn(dest) => dest }; @@ -667,7 +659,12 @@ pub fn trans_trait_cast<'a>( llboxdest = PointerCast(bcx, llboxdest, type_of(bcx.ccx(), v_ty).ptr_to()); - bcx = trans_into(bcx, val, SaveIn(llboxdest)); + bcx = match obj { + Some(datum) => { + datum.store_to_dest(bcx, SaveIn(llboxdest)) + } + None => expr::trans_into(bcx, val, SaveIn(llboxdest)) + }; // Store the vtable into the pair or triple. // This is structured a bit funny because of dynamic borrow failures. diff --git a/src/test/compile-fail/use-after-move-implicity-coerced-object.rs b/src/test/compile-fail/use-after-move-implicity-coerced-object.rs new file mode 100644 index 0000000000000..bef6165d120a5 --- /dev/null +++ b/src/test/compile-fail/use-after-move-implicity-coerced-object.rs @@ -0,0 +1,37 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +struct Number { + n: i64 +} + +impl ToStr for Number { + fn to_str(&self) -> ~str { + self.n.to_str() + } +} + +struct List { + list: ~[~ToStr] +} + +impl List { + fn push(&mut self, n: ~ToStr) { + self.list.push(n); + } +} + +fn main() { + let n = ~Number { n: 42 }; + let mut l = ~List { list: ~[] }; + l.push(n); + //^~ NOTE: `n` moved here because it has type `~Number`, which is non-copyable (perhaps you meant to use clone()?) + let x = n.to_str(); //~ ERROR: use of moved value: `n` +} diff --git a/src/test/run-pass/trait-coercion.rs b/src/test/run-pass/trait-coercion.rs index 7ee11b5d6e93f..365831eda83df 100644 --- a/src/test/run-pass/trait-coercion.rs +++ b/src/test/run-pass/trait-coercion.rs @@ -10,6 +10,8 @@ #[feature(managed_boxes)]; +use std::io; + trait Trait { fn f(&self); } @@ -29,6 +31,10 @@ fn f(x: @Trait) { x.f(); } +fn foo(mut a: ~Writer) { + a.write(bytes!("Hello\n")); +} + pub fn main() { let a = Struct { x: 1, y: 2 }; let b: @Trait = @a; @@ -38,5 +44,8 @@ pub fn main() { let d: &Trait = &a; d.f(); f(@a); + + let out = io::stdout(); + foo(~out); }