Skip to content

Commit b11c3e3

Browse files
committed
auto merge of #11525 : luqmana/rust/trait-coercions, r=pcwalton
Fixes 2 annoying issues with implicit trait object coercion: #11481 & #11197.
2 parents ab66f76 + d42e758 commit b11c3e3

File tree

5 files changed

+63
-24
lines changed

5 files changed

+63
-24
lines changed

src/librustc/middle/mem_categorization.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -345,9 +345,12 @@ impl mem_categorization_ctxt {
345345
match **adjustment {
346346
ty::AutoObject(..) => {
347347
// Implicity casts a concrete object to trait object
348-
// Result is an rvalue
348+
// so just patch up the type
349349
let expr_ty = ty::expr_ty_adjusted(self.tcx, expr);
350-
self.cat_rvalue_node(expr, expr_ty)
350+
@cmt_ {
351+
ty: expr_ty,
352+
..*self.cat_expr_unadjusted(expr)
353+
}
351354
}
352355

353356
ty::AutoAddEnv(..) => {

src/librustc/middle/trans/expr.rs

+4-11
Original file line numberDiff line numberDiff line change
@@ -229,19 +229,12 @@ pub fn trans_to_datum<'a>(bcx: &'a Block<'a>, expr: &ast::Expr)
229229
}
230230
};
231231
}
232-
AutoObject(ref sigil, ref region, _, _, _, _) => {
232+
AutoObject(..) => {
233233

234234
let adjusted_ty = ty::expr_ty_adjusted(bcx.tcx(), expr);
235235
let scratch = scratch_datum(bcx, adjusted_ty, "__adjust", false);
236236

237-
let trait_store = match *sigil {
238-
ast::BorrowedSigil => ty::RegionTraitStore(region.expect("expected valid region")),
239-
ast::OwnedSigil => ty::UniqTraitStore,
240-
ast::ManagedSigil => ty::BoxTraitStore
241-
};
242-
243-
bcx = meth::trans_trait_cast(bcx, expr, expr.id, SaveIn(scratch.val),
244-
trait_store, false /* no adjustments */);
237+
bcx = meth::trans_trait_cast(bcx, expr, expr.id, SaveIn(scratch.val), Some(datum));
245238

246239
datum = scratch.to_appropriate_datum(bcx);
247240
datum.add_clean(bcx);
@@ -834,9 +827,9 @@ fn trans_rvalue_dps_unadjusted<'a>(
834827
}
835828
ast::ExprCast(val, _) => {
836829
match ty::get(node_id_type(bcx, expr.id)).sty {
837-
ty::ty_trait(_, _, store, _, _) => {
830+
ty::ty_trait(..) => {
838831
return meth::trans_trait_cast(bcx, val, expr.id,
839-
dest, store, true /* adjustments */);
832+
dest, None);
840833
}
841834
_ => {
842835
bcx.tcx().sess.span_bug(expr.span,

src/librustc/middle/trans/meth.rs

+8-11
Original file line numberDiff line numberDiff line change
@@ -637,22 +637,14 @@ pub fn trans_trait_cast<'a>(
637637
val: &ast::Expr,
638638
id: ast::NodeId,
639639
dest: expr::Dest,
640-
_store: ty::TraitStore,
641-
do_adjustments: bool)
640+
obj: Option<Datum>)
642641
-> &'a Block<'a> {
643642
let mut bcx = bcx;
644643
let _icx = push_ctxt("impl::trans_cast");
645644

646-
// Pick the right trans function
647-
let trans_into = if do_adjustments {
648-
expr::trans_into
649-
} else {
650-
expr::trans_into_unadjusted
651-
};
652-
653645
let lldest = match dest {
654646
Ignore => {
655-
return trans_into(bcx, val, Ignore);
647+
return expr::trans_into(bcx, val, Ignore);
656648
}
657649
SaveIn(dest) => dest
658650
};
@@ -667,7 +659,12 @@ pub fn trans_trait_cast<'a>(
667659
llboxdest = PointerCast(bcx,
668660
llboxdest,
669661
type_of(bcx.ccx(), v_ty).ptr_to());
670-
bcx = trans_into(bcx, val, SaveIn(llboxdest));
662+
bcx = match obj {
663+
Some(datum) => {
664+
datum.store_to_dest(bcx, SaveIn(llboxdest))
665+
}
666+
None => expr::trans_into(bcx, val, SaveIn(llboxdest))
667+
};
671668

672669
// Store the vtable into the pair or triple.
673670
// This is structured a bit funny because of dynamic borrow failures.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
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 Number {
12+
n: i64
13+
}
14+
15+
impl ToStr for Number {
16+
fn to_str(&self) -> ~str {
17+
self.n.to_str()
18+
}
19+
}
20+
21+
struct List {
22+
list: ~[~ToStr]
23+
}
24+
25+
impl List {
26+
fn push(&mut self, n: ~ToStr) {
27+
self.list.push(n);
28+
}
29+
}
30+
31+
fn main() {
32+
let n = ~Number { n: 42 };
33+
let mut l = ~List { list: ~[] };
34+
l.push(n);
35+
//^~ NOTE: `n` moved here because it has type `~Number`, which is non-copyable (perhaps you meant to use clone()?)
36+
let x = n.to_str(); //~ ERROR: use of moved value: `n`
37+
}

src/test/run-pass/trait-coercion.rs

+9
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010

1111
#[feature(managed_boxes)];
1212

13+
use std::io;
14+
1315
trait Trait {
1416
fn f(&self);
1517
}
@@ -29,6 +31,10 @@ fn f(x: @Trait) {
2931
x.f();
3032
}
3133

34+
fn foo(mut a: ~Writer) {
35+
a.write(bytes!("Hello\n"));
36+
}
37+
3238
pub fn main() {
3339
let a = Struct { x: 1, y: 2 };
3440
let b: @Trait = @a;
@@ -38,5 +44,8 @@ pub fn main() {
3844
let d: &Trait = &a;
3945
d.f();
4046
f(@a);
47+
48+
let out = io::stdout();
49+
foo(~out);
4150
}
4251

0 commit comments

Comments
 (0)