Skip to content

Commit 1a9c8cc

Browse files
committed
auto merge of #11156 : luqmana/rust/trait-object-coercion, r=pcwalton
This ports over @pcwalton's old pull that bitrotted (#5597). Fixes #10039. r? @pcwalton / @nikomatsakis
2 parents cc1b93e + 981c6b1 commit 1a9c8cc

21 files changed

+604
-144
lines changed

src/libextra/enum_set.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
//! This module defines a container which uses an efficient bit mask
1414
//! representation to hold C-like enum variants.
1515
16-
#[deriving(Clone, Eq, IterBytes, ToStr)]
16+
#[deriving(Clone, Eq, IterBytes, ToStr, Encodable, Decodable)]
1717
/// A specialized Set implementation to use enum types.
1818
pub struct EnumSet<E> {
1919
// We must maintain the invariant that no bits are set

src/librustc/metadata/tydecode.rs

+6
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,12 @@ pub fn parse_trait_ref_data(data: &[u8], crate_num: ast::CrateNum, pos: uint, tc
129129
parse_trait_ref(&mut st, conv)
130130
}
131131

132+
pub fn parse_substs_data(data: &[u8], crate_num: ast::CrateNum, pos: uint, tcx: ty::ctxt,
133+
conv: conv_did) -> ty::substs {
134+
let mut st = parse_state_from_data(data, crate_num, pos, tcx);
135+
parse_substs(&mut st, conv)
136+
}
137+
132138
fn parse_sigil(st: &mut PState) -> ast::Sigil {
133139
match next(st) {
134140
'@' => ast::ManagedSigil,

src/librustc/metadata/tyencode.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ fn enc_opt<T>(w: &mut MemWriter, t: Option<T>, enc_f: |&mut MemWriter, T|) {
140140
}
141141
}
142142

143-
fn enc_substs(w: &mut MemWriter, cx: @ctxt, substs: &ty::substs) {
143+
pub fn enc_substs(w: &mut MemWriter, cx: @ctxt, substs: &ty::substs) {
144144
enc_region_substs(w, cx, &substs.regions);
145145
enc_opt(w, substs.self_ty, |w, t| enc_ty(w, cx, t));
146146
mywrite!(w, "[");

src/librustc/middle/astencode.rs

+102-12
Original file line numberDiff line numberDiff line change
@@ -450,15 +450,13 @@ impl tr for ast::Def {
450450
// ______________________________________________________________________
451451
// Encoding and decoding of adjustment information
452452

453-
impl tr for ty::AutoAdjustment {
454-
fn tr(&self, xcx: @ExtendedDecodeContext) -> ty::AutoAdjustment {
455-
match *self {
456-
ty::AutoAddEnv(r, s) => ty::AutoAddEnv(r.tr(xcx), s),
457-
ty::AutoDerefRef(ref adr) => {
458-
ty::AutoDerefRef(ty::AutoDerefRef {
459-
autoderefs: adr.autoderefs,
460-
autoref: adr.autoref.map(|ar| ar.tr(xcx)),
461-
})
453+
impl tr for ty::AutoDerefRef {
454+
fn tr(&self, xcx: @ExtendedDecodeContext) -> ty::AutoDerefRef {
455+
ty::AutoDerefRef {
456+
autoderefs: self.autoderefs,
457+
autoref: match self.autoref {
458+
Some(ref autoref) => Some(autoref.tr(xcx)),
459+
None => None
462460
}
463461
}
464462
}
@@ -786,6 +784,8 @@ trait ebml_writer_helpers {
786784
fn emit_tpbt(&mut self,
787785
ecx: &e::EncodeContext,
788786
tpbt: ty::ty_param_bounds_and_ty);
787+
fn emit_substs(&mut self, ecx: &e::EncodeContext, substs: &ty::substs);
788+
fn emit_auto_adjustment(&mut self, ecx: &e::EncodeContext, adj: &ty::AutoAdjustment);
789789
}
790790

791791
impl<'a> ebml_writer_helpers for writer::Encoder<'a> {
@@ -833,6 +833,40 @@ impl<'a> ebml_writer_helpers for writer::Encoder<'a> {
833833
})
834834
})
835835
}
836+
837+
fn emit_substs(&mut self, ecx: &e::EncodeContext, substs: &ty::substs) {
838+
self.emit_opaque(|this| tyencode::enc_substs(this.writer, ecx.ty_str_ctxt(), substs))
839+
}
840+
841+
fn emit_auto_adjustment(&mut self, ecx: &e::EncodeContext, adj: &ty::AutoAdjustment) {
842+
self.emit_enum("AutoAdjustment", |this| {
843+
match *adj {
844+
ty::AutoAddEnv(region, sigil) => {
845+
this.emit_enum_variant("AutoAddEnv", 0, 2, |this| {
846+
this.emit_enum_variant_arg(0, |this| region.encode(this));
847+
this.emit_enum_variant_arg(1, |this| sigil.encode(this));
848+
});
849+
}
850+
851+
ty::AutoDerefRef(ref auto_deref_ref) => {
852+
this.emit_enum_variant("AutoDerefRef", 1, 1, |this| {
853+
this.emit_enum_variant_arg(0, |this| auto_deref_ref.encode(this));
854+
});
855+
}
856+
857+
ty::AutoObject(sigil, region, m, b, def_id, ref substs) => {
858+
this.emit_enum_variant("AutoObject", 2, 6, |this| {
859+
this.emit_enum_variant_arg(0, |this| sigil.encode(this));
860+
this.emit_enum_variant_arg(1, |this| region.encode(this));
861+
this.emit_enum_variant_arg(2, |this| m.encode(this));
862+
this.emit_enum_variant_arg(3, |this| b.encode(this));
863+
this.emit_enum_variant_arg(4, |this| def_id.encode(this));
864+
this.emit_enum_variant_arg(5, |this| this.emit_substs(ecx, substs));
865+
});
866+
}
867+
}
868+
});
869+
}
836870
}
837871

838872
trait write_tag_and_id {
@@ -1023,7 +1057,7 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext,
10231057
ebml_w.tag(c::tag_table_adjustments, |ebml_w| {
10241058
ebml_w.id(id);
10251059
ebml_w.tag(c::tag_table_val, |ebml_w| {
1026-
(**adj).encode(ebml_w)
1060+
ebml_w.emit_auto_adjustment(ecx, **adj);
10271061
})
10281062
})
10291063
}
@@ -1064,6 +1098,8 @@ trait ebml_decoder_decoder_helpers {
10641098
-> ty::TypeParameterDef;
10651099
fn read_ty_param_bounds_and_ty(&mut self, xcx: @ExtendedDecodeContext)
10661100
-> ty::ty_param_bounds_and_ty;
1101+
fn read_substs(&mut self, xcx: @ExtendedDecodeContext) -> ty::substs;
1102+
fn read_auto_adjustment(&mut self, xcx: @ExtendedDecodeContext) -> ty::AutoAdjustment;
10671103
fn convert_def_id(&mut self,
10681104
xcx: @ExtendedDecodeContext,
10691105
source: DefIdSource,
@@ -1172,6 +1208,61 @@ impl<'a> ebml_decoder_decoder_helpers for reader::Decoder<'a> {
11721208
})
11731209
}
11741210

1211+
fn read_substs(&mut self, xcx: @ExtendedDecodeContext) -> ty::substs {
1212+
self.read_opaque(|this, doc| {
1213+
tydecode::parse_substs_data(doc.data,
1214+
xcx.dcx.cdata.cnum,
1215+
doc.start,
1216+
xcx.dcx.tcx,
1217+
|s, a| this.convert_def_id(xcx, s, a))
1218+
})
1219+
}
1220+
1221+
fn read_auto_adjustment(&mut self, xcx: @ExtendedDecodeContext) -> ty::AutoAdjustment {
1222+
self.read_enum("AutoAdjustment", |this| {
1223+
let variants = ["AutoAddEnv", "AutoDerefRef", "AutoObject"];
1224+
this.read_enum_variant(variants, |this, i| {
1225+
match i {
1226+
0 => {
1227+
let region: ty::Region =
1228+
this.read_enum_variant_arg(0, |this| Decodable::decode(this));
1229+
let sigil: ast::Sigil =
1230+
this.read_enum_variant_arg(1, |this| Decodable::decode(this));
1231+
1232+
ty:: AutoAddEnv(region.tr(xcx), sigil)
1233+
}
1234+
1 => {
1235+
let auto_deref_ref: ty::AutoDerefRef =
1236+
this.read_enum_variant_arg(0, |this| Decodable::decode(this));
1237+
1238+
ty::AutoDerefRef(auto_deref_ref.tr(xcx))
1239+
}
1240+
2 => {
1241+
let sigil: ast::Sigil =
1242+
this.read_enum_variant_arg(0, |this| Decodable::decode(this));
1243+
let region: Option<ty::Region> =
1244+
this.read_enum_variant_arg(1, |this| Decodable::decode(this));
1245+
let m: ast::Mutability =
1246+
this.read_enum_variant_arg(2, |this| Decodable::decode(this));
1247+
let b: ty::BuiltinBounds =
1248+
this.read_enum_variant_arg(3, |this| Decodable::decode(this));
1249+
let def_id: ast::DefId =
1250+
this.read_enum_variant_arg(4, |this| Decodable::decode(this));
1251+
let substs = this.read_enum_variant_arg(5, |this| this.read_substs(xcx));
1252+
1253+
let region = match region {
1254+
Some(r) => Some(r.tr(xcx)),
1255+
None => None
1256+
};
1257+
1258+
ty::AutoObject(sigil, region, m, b, def_id.tr(xcx), substs)
1259+
}
1260+
_ => fail!("bad enum variant for ty::AutoAdjustment")
1261+
}
1262+
})
1263+
})
1264+
}
1265+
11751266
fn convert_def_id(&mut self,
11761267
xcx: @ExtendedDecodeContext,
11771268
source: tydecode::DefIdSource,
@@ -1289,8 +1380,7 @@ fn decode_side_tables(xcx: @ExtendedDecodeContext,
12891380
vtable_map.get().insert(id, vtable_res);
12901381
}
12911382
c::tag_table_adjustments => {
1292-
let adj: @ty::AutoAdjustment = @Decodable::decode(val_dsr);
1293-
adj.tr(xcx);
1383+
let adj: @ty::AutoAdjustment = @val_dsr.read_auto_adjustment(xcx);
12941384
let mut adjustments = dcx.tcx
12951385
.adjustments
12961386
.borrow_mut();

src/librustc/middle/borrowck/gather_loans/mod.rs

+4
Original file line numberDiff line numberDiff line change
@@ -419,6 +419,10 @@ impl<'a> GatherLoanCtxt<'a> {
419419
ty::AutoUnsafe(_) => {}
420420
}
421421
}
422+
423+
ty::AutoObject(..) => {
424+
// XXX: Handle @Trait to &Trait casts here?
425+
}
422426
}
423427
}
424428

src/librustc/middle/borrowck/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -490,7 +490,7 @@ impl BorrowckCtxt {
490490
adj: @ty::AutoAdjustment)
491491
-> mc::cmt {
492492
match *adj {
493-
ty::AutoAddEnv(..) => {
493+
ty::AutoAddEnv(..) | ty::AutoObject(..) => {
494494
// no autoderefs
495495
mc::cat_expr_unadjusted(self.tcx, self.method_map, expr)
496496
}

src/librustc/middle/kind.rs

+30-14
Original file line numberDiff line numberDiff line change
@@ -311,14 +311,9 @@ pub fn check_expr(cx: &mut Context, e: @Expr) {
311311
let _ = check_durable(cx.tcx, interior_type, interior.span);
312312
}
313313
ExprCast(source, _) => {
314-
check_cast_for_escaping_regions(cx, source, e);
315-
match ty::get(ty::expr_ty(cx.tcx, e)).sty {
316-
ty::ty_trait(_, _, _, _, bounds) => {
317-
let source_ty = ty::expr_ty(cx.tcx, source);
318-
check_trait_cast_bounds(cx, e.span, source_ty, bounds)
319-
}
320-
_ => { }
321-
}
314+
let source_ty = ty::expr_ty(cx.tcx, source);
315+
let target_ty = ty::expr_ty(cx.tcx, e);
316+
check_trait_cast(cx, source_ty, target_ty, source.span);
322317
}
323318
ExprRepeat(element, count_expr, _) => {
324319
let count = ty::eval_repeat_count(&cx.tcx, count_expr);
@@ -330,9 +325,31 @@ pub fn check_expr(cx: &mut Context, e: @Expr) {
330325
}
331326
_ => {}
332327
}
328+
329+
// Search for auto-adjustments to find trait coercions.
330+
let adjustments = cx.tcx.adjustments.borrow();
331+
match adjustments.get().find(&e.id) {
332+
Some(&@ty::AutoObject(..)) => {
333+
let source_ty = ty::expr_ty(cx.tcx, e);
334+
let target_ty = ty::expr_ty_adjusted(cx.tcx, e);
335+
check_trait_cast(cx, source_ty, target_ty, e.span);
336+
}
337+
Some(&@ty::AutoAddEnv(..)) | Some(&@ty::AutoDerefRef(..)) | None => {}
338+
}
339+
333340
visit::walk_expr(cx, e, ());
334341
}
335342

343+
fn check_trait_cast(cx: &mut Context, source_ty: ty::t, target_ty: ty::t, span: Span) {
344+
check_cast_for_escaping_regions(cx, source_ty, target_ty, span);
345+
match ty::get(target_ty).sty {
346+
ty::ty_trait(_, _, _, _, bounds) => {
347+
check_trait_cast_bounds(cx, span, source_ty, bounds);
348+
}
349+
_ => {}
350+
}
351+
}
352+
336353
fn check_ty(cx: &mut Context, aty: &Ty) {
337354
match aty.node {
338355
ty_path(_, _, id) => {
@@ -510,12 +527,12 @@ pub fn check_durable(tcx: ty::ctxt, ty: ty::t, sp: Span) -> bool {
510527
/// FIXME(#5723)---This code should probably move into regionck.
511528
pub fn check_cast_for_escaping_regions(
512529
cx: &Context,
513-
source: &Expr,
514-
target: &Expr)
530+
source_ty: ty::t,
531+
target_ty: ty::t,
532+
source_span: Span)
515533
{
516534
// Determine what type we are casting to; if it is not an trait, then no
517535
// worries.
518-
let target_ty = ty::expr_ty(cx.tcx, target);
519536
match ty::get(target_ty).sty {
520537
ty::ty_trait(..) => {}
521538
_ => { return; }
@@ -545,7 +562,6 @@ pub fn check_cast_for_escaping_regions(
545562
// Assuming the trait instance can escape, then ensure that each parameter
546563
// either appears in the trait type or is sendable.
547564
let target_params = ty::param_tys_in_type(target_ty);
548-
let source_ty = ty::expr_ty(cx.tcx, source);
549565
ty::walk_regions_and_ty(
550566
cx.tcx,
551567
source_ty,
@@ -555,7 +571,7 @@ pub fn check_cast_for_escaping_regions(
555571
//
556572
// if !target_regions.iter().any(|t_r| is_subregion_of(cx, *t_r, r)) {
557573
// cx.tcx.sess.span_err(
558-
// source.span,
574+
// source_span,
559575
// format!("source contains borrowed pointer with lifetime \
560576
// not found in the target type `{}`",
561577
// ty_to_str(cx.tcx, target_ty)));
@@ -570,7 +586,7 @@ pub fn check_cast_for_escaping_regions(
570586
if target_params.iter().any(|x| x == &source_param) {
571587
/* case (2) */
572588
} else {
573-
check_durable(cx.tcx, ty, source.span); /* case (3) */
589+
check_durable(cx.tcx, ty, source_span); /* case (3) */
574590
}
575591
}
576592
_ => {}

src/librustc/middle/mem_categorization.rs

+7
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,13 @@ impl mem_categorization_ctxt {
347347
self.cat_expr_unadjusted(expr)
348348
}
349349

350+
Some(&@ty::AutoObject(..)) => {
351+
// Implicity casts a concrete object to trait object
352+
// Result is an rvalue
353+
let expr_ty = ty::expr_ty_adjusted(self.tcx, expr);
354+
self.cat_rvalue_node(expr, expr_ty)
355+
}
356+
350357
Some(&@ty::AutoAddEnv(..)) => {
351358
// Convert a bare fn to a closure by adding NULL env.
352359
// Result is an rvalue.

src/librustc/middle/trans/consts.rs

+3
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,9 @@ pub fn const_expr(cx: @CrateContext, e: &ast::Expr) -> (ValueRef, bool) {
199199
cx.sess.span_bug(e.span, format!("unexpected static function: \
200200
region {:?} sigil {:?}", *r, *s))
201201
}
202+
Some(@ty::AutoObject(..)) => {
203+
cx.sess.span_unimpl(e.span, "unimplemented const coercion to trait object");
204+
}
202205
Some(@ty::AutoDerefRef(ref adj)) => {
203206
let mut ty = ety;
204207
let mut maybe_ptr = None;

src/librustc/middle/trans/expr.rs

+24-3
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ use middle::trans::inline;
139139
use middle::trans::tvec;
140140
use middle::trans::type_of;
141141
use middle::ty::struct_fields;
142-
use middle::ty::{AutoBorrowObj, AutoDerefRef, AutoAddEnv, AutoUnsafe};
142+
use middle::ty::{AutoBorrowObj, AutoDerefRef, AutoAddEnv, AutoObject, AutoUnsafe};
143143
use middle::ty::{AutoPtr, AutoBorrowVec, AutoBorrowVecRef, AutoBorrowFn};
144144
use middle::ty;
145145
use util::common::indenter;
@@ -228,6 +228,23 @@ pub fn trans_to_datum(bcx: @Block, expr: &ast::Expr) -> DatumBlock {
228228
}
229229
};
230230
}
231+
AutoObject(ref sigil, ref region, _, _, _, _) => {
232+
233+
let adjusted_ty = ty::expr_ty_adjusted(bcx.tcx(), expr);
234+
let scratch = scratch_datum(bcx, adjusted_ty, "__adjust", false);
235+
236+
let trait_store = match *sigil {
237+
ast::BorrowedSigil => ty::RegionTraitStore(region.expect("expected valid region")),
238+
ast::OwnedSigil => ty::UniqTraitStore,
239+
ast::ManagedSigil => ty::BoxTraitStore
240+
};
241+
242+
bcx = meth::trans_trait_cast(bcx, expr, expr.id, SaveIn(scratch.val),
243+
trait_store, false /* no adjustments */);
244+
245+
datum = scratch.to_appropriate_datum(bcx);
246+
datum.add_clean(bcx);
247+
}
231248
}
232249
debug!("after adjustments, datum={}", datum.to_str(bcx.ccx()));
233250
return DatumBlock {bcx: bcx, datum: datum};
@@ -432,6 +449,10 @@ pub fn trans_into(bcx: @Block, expr: &ast::Expr, dest: Dest) -> @Block {
432449
};
433450
}
434451

452+
trans_into_unadjusted(bcx, expr, dest)
453+
}
454+
455+
pub fn trans_into_unadjusted(bcx: @Block, expr: &ast::Expr, dest: Dest) -> @Block {
435456
let ty = expr_ty(bcx, expr);
436457

437458
debug!("trans_into_unadjusted(expr={}, dest={})",
@@ -778,8 +799,8 @@ fn trans_rvalue_dps_unadjusted(bcx: @Block, expr: &ast::Expr,
778799
ast::ExprCast(val, _) => {
779800
match ty::get(node_id_type(bcx, expr.id)).sty {
780801
ty::ty_trait(_, _, store, _, _) => {
781-
return meth::trans_trait_cast(bcx, val, expr.id, dest,
782-
store);
802+
return meth::trans_trait_cast(bcx, val, expr.id,
803+
dest, store, true /* adjustments */);
783804
}
784805
_ => {
785806
bcx.tcx().sess.span_bug(expr.span,

0 commit comments

Comments
 (0)