auto merge of #11525 : luqmana/rust/trait-coercions, r=pcwalton

Fixes 2 annoying issues with implicit trait object coercion: #11481 & #11197.
This commit is contained in:
bors 2014-01-13 19:01:52 -08:00
commit b11c3e3829
5 changed files with 63 additions and 24 deletions

View file

@ -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(..) => {

View file

@ -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,

View file

@ -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<Datum>)
-> &'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.

View file

@ -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 <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 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`
}

View file

@ -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);
}