Skip to content

Commit bfb93ef

Browse files
committed
Drive unsizing coercions using just the target pointer type.
1 parent 352a63c commit bfb93ef

File tree

13 files changed

+201
-320
lines changed

13 files changed

+201
-320
lines changed

src/librustc/middle/astencode.rs

Lines changed: 4 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -844,8 +844,6 @@ trait rbml_writer_helpers<'tcx> {
844844
fn emit_autoref<'a>(&mut self, autoref: &ty::AutoRef<'tcx>);
845845
fn emit_auto_deref_ref<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>,
846846
auto_deref_ref: &ty::AutoDerefRef<'tcx>);
847-
fn emit_auto_unsize<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>,
848-
unsize: &ty::AutoUnsize<'tcx>);
849847
}
850848

851849
impl<'a, 'tcx> rbml_writer_helpers<'tcx> for Encoder<'a> {
@@ -1067,29 +1065,14 @@ impl<'a, 'tcx> rbml_writer_helpers<'tcx> for Encoder<'a> {
10671065
this.emit_option(|this| {
10681066
match auto_deref_ref.unsize {
10691067
None => this.emit_option_none(),
1070-
Some(ref uk) => this.emit_option_some(|this| Ok(this.emit_auto_unsize(ecx, uk))),
1068+
Some(target) => this.emit_option_some(|this| {
1069+
Ok(this.emit_ty(ecx, target))
1070+
})
10711071
}
10721072
})
10731073
})
10741074
});
10751075
}
1076-
1077-
fn emit_auto_unsize<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>,
1078-
unsize: &ty::AutoUnsize<'tcx>) {
1079-
use serialize::Encoder;
1080-
1081-
self.emit_struct("AutoUnsize", 3, |this| {
1082-
this.emit_struct_field("leaf_source", 0, |this| {
1083-
Ok(this.emit_ty(ecx, unsize.leaf_source))
1084-
});
1085-
this.emit_struct_field("leaf_target", 1, |this| {
1086-
Ok(this.emit_ty(ecx, unsize.leaf_target))
1087-
});
1088-
this.emit_struct_field("target", 2, |this| {
1089-
Ok(this.emit_ty(ecx, unsize.target))
1090-
})
1091-
});
1092-
}
10931076
}
10941077

10951078
trait write_tag_and_id {
@@ -1304,8 +1287,6 @@ trait rbml_decoder_decoder_helpers<'tcx> {
13041287
-> ty::AutoDerefRef<'tcx>;
13051288
fn read_autoref<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
13061289
-> ty::AutoRef<'tcx>;
1307-
fn read_auto_unsize<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
1308-
-> ty::AutoUnsize<'tcx>;
13091290
fn convert_def_id(&mut self,
13101291
dcx: &DecodeContext,
13111292
source: DefIdSource,
@@ -1614,7 +1595,7 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> {
16141595
unsize: this.read_struct_field("unsize", 2, |this| {
16151596
this.read_option(|this, b| {
16161597
if b {
1617-
Ok(Some(this.read_auto_unsize(dcx)))
1598+
Ok(Some(this.read_ty(dcx)))
16181599
} else {
16191600
Ok(None)
16201601
}
@@ -1650,23 +1631,6 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> {
16501631
}).unwrap()
16511632
}
16521633

1653-
fn read_auto_unsize<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
1654-
-> ty::AutoUnsize<'tcx> {
1655-
self.read_struct("AutoUnsize", 3, |this| {
1656-
Ok(ty::AutoUnsize {
1657-
leaf_source: this.read_struct_field("leaf_source", 0, |this| {
1658-
Ok(this.read_ty(dcx))
1659-
}).unwrap(),
1660-
leaf_target: this.read_struct_field("leaf_target", 1, |this| {
1661-
Ok(this.read_ty(dcx))
1662-
}).unwrap(),
1663-
target: this.read_struct_field("target", 2, |this| {
1664-
Ok(this.read_ty(dcx))
1665-
}).unwrap()
1666-
})
1667-
}).unwrap()
1668-
}
1669-
16701634
fn read_closure_kind<'b, 'c>(&mut self, _dcx: &DecodeContext<'b, 'c, 'tcx>)
16711635
-> ty::ClosureKind
16721636
{

src/librustc/middle/ty.rs

Lines changed: 45 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -284,17 +284,6 @@ pub enum AutoAdjustment<'tcx> {
284284
AdjustDerefRef(AutoDerefRef<'tcx>),
285285
}
286286

287-
// In the case of `&Struct<[T; N]>` -> `&Struct<[T]>`, the types are:
288-
// * leaf_source: `[T; N]`
289-
// * leaf_target: `[T]`
290-
// * target: `&Struct<[T]>`
291-
#[derive(Copy, Clone, Debug)]
292-
pub struct AutoUnsize<'tcx> {
293-
pub leaf_source: Ty<'tcx>,
294-
pub leaf_target: Ty<'tcx>,
295-
pub target: Ty<'tcx>
296-
}
297-
298287
#[derive(Copy, Clone, Debug)]
299288
pub struct AutoDerefRef<'tcx> {
300289
/// Apply a number of dereferences, producing an lvalue.
@@ -304,7 +293,8 @@ pub struct AutoDerefRef<'tcx> {
304293
pub autoref: Option<AutoRef<'tcx>>,
305294

306295
/// Unsize a pointer/reference value, e.g. &[T; n] to &[T].
307-
pub unsize: Option<AutoUnsize<'tcx>>,
296+
/// The stored type is the target pointer type.
297+
pub unsize: Option<Ty<'tcx>>,
308298
}
309299

310300
#[derive(Copy, Clone, PartialEq, Debug)]
@@ -4490,8 +4480,8 @@ pub fn adjust_ty<'tcx, F>(cx: &ctxt<'tcx>,
44904480
}
44914481
}
44924482

4493-
if let Some(ref unsize) = adj.unsize {
4494-
unsize.target
4483+
if let Some(target) = adj.unsize {
4484+
target
44954485
} else {
44964486
adjust_ty_for_autoref(cx, adjusted_ty, adj.autoref)
44974487
}
@@ -5557,6 +5547,47 @@ pub fn tup_fields<'tcx>(v: &[Ty<'tcx>]) -> Vec<field<'tcx>> {
55575547
}).collect()
55585548
}
55595549

5550+
/// Returns the deeply last field of nested structures, or the same type,
5551+
/// if not a structure at all. Corresponds to the only possible unsized
5552+
/// field, and its type can be used to determine unsizing strategy.
5553+
pub fn struct_tail<'tcx>(cx: &ctxt<'tcx>, mut ty: Ty<'tcx>) -> Ty<'tcx> {
5554+
while let ty_struct(def_id, substs) = ty.sty {
5555+
match struct_fields(cx, def_id, substs).last() {
5556+
Some(f) => ty = f.mt.ty,
5557+
None => break
5558+
}
5559+
}
5560+
ty
5561+
}
5562+
5563+
/// Same as applying struct_tail on `source` and `target`, but only
5564+
/// keeps going as long as the two types are instances of the same
5565+
/// structure definitions.
5566+
/// For `(Foo<Foo<T>>, Foo<Trait>)`, the result will be `(Foo<T>, Trait)`,
5567+
/// whereas struct_tail produces `T`, and `Trait`, respectively.
5568+
pub fn struct_lockstep_tails<'tcx>(cx: &ctxt<'tcx>,
5569+
source: Ty<'tcx>,
5570+
target: Ty<'tcx>)
5571+
-> (Ty<'tcx>, Ty<'tcx>) {
5572+
let (mut a, mut b) = (source, target);
5573+
while let (&ty_struct(a_did, a_substs), &ty_struct(b_did, b_substs)) = (&a.sty, &b.sty) {
5574+
if a_did != b_did {
5575+
continue;
5576+
}
5577+
if let Some(a_f) = struct_fields(cx, a_did, a_substs).last() {
5578+
if let Some(b_f) = struct_fields(cx, b_did, b_substs).last() {
5579+
a = a_f.mt.ty;
5580+
b = b_f.mt.ty;
5581+
} else {
5582+
break;
5583+
}
5584+
} else {
5585+
break;
5586+
}
5587+
}
5588+
(a, b)
5589+
}
5590+
55605591
#[derive(Copy, Clone)]
55615592
pub struct ClosureUpvar<'tcx> {
55625593
pub def: def::Def,
@@ -6699,15 +6730,6 @@ impl<'tcx> Repr<'tcx> for AutoAdjustment<'tcx> {
66996730
}
67006731
}
67016732

6702-
impl<'tcx> Repr<'tcx> for AutoUnsize<'tcx> {
6703-
fn repr(&self, tcx: &ctxt<'tcx>) -> String {
6704-
format!("unsize({} => {}) => {}",
6705-
self.leaf_source.repr(tcx),
6706-
self.leaf_target.repr(tcx),
6707-
self.target.repr(tcx))
6708-
}
6709-
}
6710-
67116733
impl<'tcx> Repr<'tcx> for AutoDerefRef<'tcx> {
67126734
fn repr(&self, tcx: &ctxt<'tcx>) -> String {
67136735
format!("AutoDerefRef({}, unsize={}, {})",
@@ -7138,14 +7160,6 @@ impl<'tcx> HasProjectionTypes for BareFnTy<'tcx> {
71387160
}
71397161
}
71407162

7141-
impl<'tcx> HasProjectionTypes for AutoUnsize<'tcx> {
7142-
fn has_projection_types(&self) -> bool {
7143-
self.leaf_source.has_projection_types() ||
7144-
self.leaf_target.has_projection_types() ||
7145-
self.target.has_projection_types()
7146-
}
7147-
}
7148-
71497163
pub trait ReferencesError {
71507164
fn references_error(&self) -> bool;
71517165
}

src/librustc/middle/ty_fold.rs

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -467,16 +467,6 @@ impl<'tcx> TypeFoldable<'tcx> for ty::InstantiatedPredicates<'tcx> {
467467
}
468468
}
469469

470-
impl<'tcx> TypeFoldable<'tcx> for ty::AutoUnsize<'tcx> {
471-
fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::AutoUnsize<'tcx> {
472-
ty::AutoUnsize {
473-
leaf_source: self.leaf_source.fold_with(folder),
474-
leaf_target: self.leaf_target.fold_with(folder),
475-
target: self.target.fold_with(folder)
476-
}
477-
}
478-
}
479-
480470
impl<'tcx,O> TypeFoldable<'tcx> for traits::Obligation<'tcx,O>
481471
where O : TypeFoldable<'tcx>
482472
{

src/librustc_trans/trans/common.rs

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -146,33 +146,6 @@ pub fn type_is_fat_ptr<'tcx>(cx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
146146
}
147147
}
148148

149-
// Return the smallest part of `ty` which is unsized. Fails if `ty` is sized.
150-
// 'Smallest' here means component of the static representation of the type; not
151-
// the size of an object at runtime.
152-
pub fn unsized_part_of_type<'tcx>(cx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
153-
match ty.sty {
154-
ty::ty_str | ty::ty_trait(..) | ty::ty_vec(..) => ty,
155-
ty::ty_struct(def_id, substs) => {
156-
let unsized_fields: Vec<_> =
157-
ty::struct_fields(cx, def_id, substs)
158-
.iter()
159-
.map(|f| f.mt.ty)
160-
.filter(|ty| !type_is_sized(cx, *ty))
161-
.collect();
162-
163-
// Exactly one of the fields must be unsized.
164-
assert!(unsized_fields.len() == 1);
165-
166-
unsized_part_of_type(cx, unsized_fields[0])
167-
}
168-
_ => {
169-
assert!(type_is_sized(cx, ty),
170-
"unsized_part_of_type failed even though ty is unsized");
171-
panic!("called unsized_part_of_type with sized ty");
172-
}
173-
}
174-
}
175-
176149
// Some things don't need cleanups during unwinding because the
177150
// task can free them all at once later. Currently only things
178151
// that only contain scalars and shared boxes can avoid unwind

src/librustc_trans/trans/consts.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -277,10 +277,10 @@ pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
277277
ety_adjusted = dt;
278278
}
279279

280-
if let Some(ref unsize) = adj.unsize {
281-
let unsize = monomorphize::apply_param_substs(cx.tcx(),
280+
if let Some(target) = adj.unsize {
281+
let target = monomorphize::apply_param_substs(cx.tcx(),
282282
param_substs,
283-
unsize);
283+
&target);
284284

285285
let pointee_ty = ty::deref(ty, true)
286286
.expect("consts: unsizing got non-pointer type").ty;
@@ -297,11 +297,12 @@ pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
297297
(llconst, None)
298298
};
299299

300-
let unsized_ty = ty::deref(unsize.target, true)
300+
let unsized_ty = ty::deref(target, true)
301301
.expect("consts: unsizing got non-pointer target type").ty;
302302
let ptr_ty = type_of::in_memory_type_of(cx, unsized_ty).ptr_to();
303303
let base = ptrcast(base, ptr_ty);
304-
let info = expr::unsized_info(cx, &unsize, old_info, param_substs);
304+
let info = expr::unsized_info(cx, pointee_ty, unsized_ty,
305+
old_info, param_substs);
305306

306307
let prev_const = cx.const_unsized().borrow_mut()
307308
.insert(base, llconst);

src/librustc_trans/trans/expr.rs

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -292,16 +292,17 @@ pub fn copy_fat_ptr(bcx: Block, src_ptr: ValueRef, dst_ptr: ValueRef) {
292292
/// Retrieve the information we are losing (making dynamic) in an unsizing
293293
/// adjustment.
294294
///
295-
/// The `unadjusted_val` argument is a bit funny. It is intended
296-
/// for use in an upcast, where the new vtable for an object will
297-
/// be drived from the old one. Hence it is a pointer to the fat
298-
/// pointer.
295+
/// The `old_info` argument is a bit funny. It is intended for use
296+
/// in an upcast, where the new vtable for an object will be drived
297+
/// from the old one.
299298
pub fn unsized_info<'ccx, 'tcx>(ccx: &CrateContext<'ccx, 'tcx>,
300-
unsize: &ty::AutoUnsize<'tcx>,
299+
source: Ty<'tcx>,
300+
target: Ty<'tcx>,
301301
old_info: Option<ValueRef>,
302302
param_substs: &'tcx subst::Substs<'tcx>)
303303
-> ValueRef {
304-
match (&unsize.leaf_source.sty, &unsize.leaf_target.sty) {
304+
let (source, target) = ty::struct_lockstep_tails(ccx.tcx(), source, target);
305+
match (&source.sty, &target.sty) {
305306
(&ty::ty_vec(_, Some(len)), &ty::ty_vec(_, None)) => C_uint(ccx, len),
306307
(&ty::ty_trait(_), &ty::ty_trait(_)) => {
307308
// For now, upcasts are limited to changes in marker
@@ -311,15 +312,16 @@ pub fn unsized_info<'ccx, 'tcx>(ccx: &CrateContext<'ccx, 'tcx>,
311312
}
312313
(_, &ty::ty_trait(box ty::TyTrait { ref principal, .. })) => {
313314
// Note that we preserve binding levels here:
314-
let substs = principal.0.substs.with_self_ty(unsize.leaf_source).erase_regions();
315+
let substs = principal.0.substs.with_self_ty(source).erase_regions();
315316
let substs = ccx.tcx().mk_substs(substs);
316317
let trait_ref = ty::Binder(Rc::new(ty::TraitRef { def_id: principal.def_id(),
317318
substs: substs }));
318319
consts::ptrcast(meth::get_vtable(ccx, trait_ref, param_substs),
319320
Type::vtable_ptr(ccx))
320321
}
321-
_ => ccx.sess().bug(&format!("unsized_info: invalid unsizing {}",
322-
unsize.repr(ccx.tcx())))
322+
_ => ccx.sess().bug(&format!("unsized_info: invalid unsizing {} -> {}",
323+
source.repr(ccx.tcx()),
324+
target.repr(ccx.tcx())))
323325
}
324326
}
325327

@@ -386,8 +388,9 @@ fn apply_adjustments<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
386388
datum = unpack_datum!(bcx, apply_autoref(bcx, expr, datum));
387389
}
388390

389-
if let Some(ref unsize) = adj.unsize {
390-
datum = unpack_datum!(bcx, unsize_pointer(bcx, datum, unsize));
391+
if let Some(target) = adj.unsize {
392+
datum = unpack_datum!(bcx, unsize_pointer(bcx, datum,
393+
bcx.monomorphize(&target)));
391394
}
392395
}
393396
}
@@ -412,11 +415,10 @@ fn apply_adjustments<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
412415

413416
fn unsize_pointer<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
414417
datum: Datum<'tcx, Expr>,
415-
unsize: &ty::AutoUnsize<'tcx>)
418+
target: Ty<'tcx>)
416419
-> DatumBlock<'blk, 'tcx, Expr> {
417420
let mut bcx = bcx;
418-
let unsize = bcx.monomorphize(unsize);
419-
let unsized_ty = ty::deref(unsize.target, true)
421+
let unsized_ty = ty::deref(target, true)
420422
.expect("expr::unsize got non-pointer target type").ty;
421423
debug!("unsize_lvalue(unsized_ty={})", unsized_ty.repr(bcx.tcx()));
422424

@@ -442,20 +444,21 @@ fn apply_adjustments<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
442444
(datum.val, None)
443445
};
444446

445-
let info = unsized_info(bcx.ccx(), &unsize, old_info, bcx.fcx.param_substs);
447+
let info = unsized_info(bcx.ccx(), pointee_ty, unsized_ty,
448+
old_info, bcx.fcx.param_substs);
446449

447450
// Compute the base pointer. This doesn't change the pointer value,
448451
// but merely its type.
449452
let ptr_ty = type_of::in_memory_type_of(bcx.ccx(), unsized_ty).ptr_to();
450453
let base = PointerCast(bcx, base, ptr_ty);
451454

452-
let llty = type_of::type_of(bcx.ccx(), unsize.target);
455+
let llty = type_of::type_of(bcx.ccx(), target);
453456
// HACK(eddyb) get around issues with lifetime intrinsics.
454457
let scratch = alloca_no_lifetime(bcx, llty, "__fat_ptr");
455458
Store(bcx, base, get_dataptr(bcx, scratch));
456459
Store(bcx, info, get_len(bcx, scratch));
457460

458-
DatumBlock::new(bcx, Datum::new(scratch, unsize.target,
461+
DatumBlock::new(bcx, Datum::new(scratch, target,
459462
RvalueExpr(Rvalue::new(ByRef))))
460463
}
461464
}

src/librustc_trans/trans/type_of.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -358,14 +358,14 @@ pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) ->
358358
cx.tn().find_type("str_slice").unwrap()
359359
} else {
360360
let ptr_ty = in_memory_type_of(cx, ty).ptr_to();
361-
let unsized_part = unsized_part_of_type(cx.tcx(), ty);
361+
let unsized_part = ty::struct_tail(cx.tcx(), ty);
362362
let info_ty = match unsized_part.sty {
363363
ty::ty_str | ty::ty_vec(..) => {
364364
Type::uint_from_ty(cx, ast::TyUs(false))
365365
}
366366
ty::ty_trait(_) => Type::vtable_ptr(cx),
367367
_ => panic!("Unexpected type returned from \
368-
unsized_part_of_type: {} for ty={}",
368+
struct_tail: {} for ty={}",
369369
unsized_part.repr(cx.tcx()), ty.repr(cx.tcx()))
370370
};
371371
Type::struct_(cx, &[ptr_ty, info_ty], false)

0 commit comments

Comments
 (0)