Skip to content

Commit 5f5ed62

Browse files
committed
Remove subtyping for object types and replace with an *upcast* coercion.
This upcast coercion currently preserves the vtable for the object, but eventually it can be used to create a derived vtable. The upcast coercion is not introduced into method dispatch; see comment on #18737 for information about why. Fixes #18737.
1 parent bde09ee commit 5f5ed62

File tree

18 files changed

+187
-101
lines changed

18 files changed

+187
-101
lines changed

Diff for: src/liballoc/boxed.rs

+10-1
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,7 @@ pub trait BoxAny {
241241
/// Returns the boxed value if it is of type `T`, or
242242
/// `Err(Self)` if it isn't.
243243
#[stable(feature = "rust1", since = "1.0.0")]
244-
fn downcast<T: 'static>(self) -> Result<Box<T>, Self>;
244+
fn downcast<T: 'static>(self) -> Result<Box<T>, Box<Any>>;
245245
}
246246

247247
#[stable(feature = "rust1", since = "1.0.0")]
@@ -264,6 +264,15 @@ impl BoxAny for Box<Any> {
264264
}
265265
}
266266

267+
#[cfg(not(stage0))]
268+
#[stable(feature = "rust1", since = "1.0.0")]
269+
impl BoxAny for Box<Any+Send> {
270+
#[inline]
271+
fn downcast<T: 'static>(self) -> Result<Box<T>, Box<Any>> {
272+
<Box<Any>>::downcast(self)
273+
}
274+
}
275+
267276
#[stable(feature = "rust1", since = "1.0.0")]
268277
impl<T: fmt::Display + ?Sized> fmt::Display for Box<T> {
269278
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {

Diff for: src/libcore/any.rs

+26
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@
7171
7272
#![stable(feature = "rust1", since = "1.0.0")]
7373

74+
use marker::Send;
7475
use mem::transmute;
7576
use option::Option::{self, Some, None};
7677
use raw::TraitObject;
@@ -154,6 +155,31 @@ impl Any {
154155
}
155156
}
156157

158+
#[cfg(not(stage0))]
159+
impl Any+Send {
160+
/// Forwards to the method defined on the type `Any`.
161+
#[stable(feature = "rust1", since = "1.0.0")]
162+
#[inline]
163+
pub fn is<T: 'static>(&self) -> bool {
164+
Any::is::<T>(self)
165+
}
166+
167+
/// Forwards to the method defined on the type `Any`.
168+
#[stable(feature = "rust1", since = "1.0.0")]
169+
#[inline]
170+
pub fn downcast_ref<T: 'static>(&self) -> Option<&T> {
171+
Any::downcast_ref::<T>(self)
172+
}
173+
174+
/// Forwards to the method defined on the type `Any`.
175+
#[stable(feature = "rust1", since = "1.0.0")]
176+
#[inline]
177+
pub fn downcast_mut<T: 'static>(&mut self) -> Option<&mut T> {
178+
Any::downcast_mut::<T>(self)
179+
}
180+
}
181+
182+
157183
///////////////////////////////////////////////////////////////////////////////
158184
// TypeID and its methods
159185
///////////////////////////////////////////////////////////////////////////////

Diff for: src/librustc/middle/astencode.rs

+11-1
Original file line numberDiff line numberDiff line change
@@ -1102,6 +1102,11 @@ impl<'a, 'tcx> rbml_writer_helpers<'tcx> for Encoder<'a> {
11021102
this.emit_enum_variant_arg(1, |this| Ok(this.emit_ty(ecx, self_ty)))
11031103
})
11041104
}
1105+
ty::UnsizeUpcast(target_ty) => {
1106+
this.emit_enum_variant("UnsizeUpcast", 3, 1, |this| {
1107+
this.emit_enum_variant_arg(0, |this| Ok(this.emit_ty(ecx, target_ty)))
1108+
})
1109+
}
11051110
}
11061111
});
11071112
}
@@ -1707,7 +1712,7 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> {
17071712
fn read_unsize_kind<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
17081713
-> ty::UnsizeKind<'tcx> {
17091714
self.read_enum("UnsizeKind", |this| {
1710-
let variants = &["UnsizeLength", "UnsizeStruct", "UnsizeVtable"];
1715+
let variants = &["UnsizeLength", "UnsizeStruct", "UnsizeVtable", "UnsizeUpcast"];
17111716
this.read_enum_variant(variants, |this, i| {
17121717
Ok(match i {
17131718
0 => {
@@ -1741,6 +1746,11 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> {
17411746
this.read_enum_variant_arg(1, |this| Ok(this.read_ty(dcx))).unwrap();
17421747
ty::UnsizeVtable(ty_trait, self_ty)
17431748
}
1749+
3 => {
1750+
let target_ty =
1751+
this.read_enum_variant_arg(0, |this| Ok(this.read_ty(dcx))).unwrap();
1752+
ty::UnsizeUpcast(target_ty)
1753+
}
17441754
_ => panic!("bad enum variant for ty::UnsizeKind")
17451755
})
17461756
})

Diff for: src/librustc/middle/infer/combine.rs

+12-3
Original file line numberDiff line numberDiff line change
@@ -314,9 +314,18 @@ pub trait Combine<'tcx> : Sized {
314314
}
315315

316316
fn builtin_bounds(&self,
317-
a: ty::BuiltinBounds,
318-
b: ty::BuiltinBounds)
319-
-> cres<'tcx, ty::BuiltinBounds>;
317+
a: BuiltinBounds,
318+
b: BuiltinBounds)
319+
-> cres<'tcx, BuiltinBounds>
320+
{
321+
// Two sets of builtin bounds are only relatable if they are
322+
// precisely the same (but see the coercion code).
323+
if a != b {
324+
Err(ty::terr_builtin_bounds(expected_found(self, a, b)))
325+
} else {
326+
Ok(a)
327+
}
328+
}
320329

321330
fn trait_refs(&self,
322331
a: &ty::TraitRef<'tcx>,

Diff for: src/librustc/middle/infer/equate.rs

-18
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
use middle::ty::{BuiltinBounds};
1211
use middle::ty::{self, Ty};
1312
use middle::ty::TyVar;
1413
use middle::infer::combine::*;
@@ -73,23 +72,6 @@ impl<'f, 'tcx> Combine<'tcx> for Equate<'f, 'tcx> {
7372
}
7473
}
7574

76-
fn builtin_bounds(&self,
77-
a: BuiltinBounds,
78-
b: BuiltinBounds)
79-
-> cres<'tcx, BuiltinBounds>
80-
{
81-
// More bounds is a subtype of fewer bounds.
82-
//
83-
// e.g., fn:Copy() <: fn(), because the former is a function
84-
// that only closes over copyable things, but the latter is
85-
// any function at all.
86-
if a != b {
87-
Err(ty::terr_builtin_bounds(expected_found(self, a, b)))
88-
} else {
89-
Ok(a)
90-
}
91-
}
92-
9375
fn tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> cres<'tcx, Ty<'tcx>> {
9476
debug!("{}.tys({}, {})", self.tag(),
9577
a.repr(self.fields.infcx.tcx), b.repr(self.fields.infcx.tcx));

Diff for: src/librustc/middle/infer/glb.rs

-10
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ use super::higher_ranked::HigherRankedRelations;
1414
use super::{cres};
1515
use super::Subtype;
1616

17-
use middle::ty::{BuiltinBounds};
1817
use middle::ty::{self, Ty};
1918
use syntax::ast::{MutImmutable, MutMutable, Unsafety};
2019
use util::ppaux::mt_to_string;
@@ -94,15 +93,6 @@ impl<'f, 'tcx> Combine<'tcx> for Glb<'f, 'tcx> {
9493
}
9594
}
9695

97-
fn builtin_bounds(&self,
98-
a: ty::BuiltinBounds,
99-
b: ty::BuiltinBounds)
100-
-> cres<'tcx, ty::BuiltinBounds> {
101-
// More bounds is a subtype of fewer bounds, so
102-
// the GLB (mutual subtype) is the union.
103-
Ok(a.union(b))
104-
}
105-
10696
fn regions(&self, a: ty::Region, b: ty::Region) -> cres<'tcx, ty::Region> {
10797
debug!("{}.regions({}, {})",
10898
self.tag(),

Diff for: src/librustc/middle/infer/lub.rs

-10
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ use super::lattice::*;
1414
use super::{cres};
1515
use super::{Subtype};
1616

17-
use middle::ty::{BuiltinBounds};
1817
use middle::ty::{self, Ty};
1918
use syntax::ast::{MutMutable, MutImmutable, Unsafety};
2019
use util::ppaux::mt_to_string;
@@ -89,15 +88,6 @@ impl<'f, 'tcx> Combine<'tcx> for Lub<'f, 'tcx> {
8988
}
9089
}
9190

92-
fn builtin_bounds(&self,
93-
a: ty::BuiltinBounds,
94-
b: ty::BuiltinBounds)
95-
-> cres<'tcx, ty::BuiltinBounds> {
96-
// More bounds is a subtype of fewer bounds, so
97-
// the LUB (mutual supertype) is the intersection.
98-
Ok(a.intersection(b))
99-
}
100-
10191
fn regions(&self, a: ty::Region, b: ty::Region) -> cres<'tcx, ty::Region> {
10292
debug!("{}.regions({}, {})",
10393
self.tag(),

Diff for: src/librustc/middle/infer/sub.rs

-15
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ use super::higher_ranked::HigherRankedRelations;
1414
use super::{Subtype};
1515
use super::type_variable::{SubtypeOf, SupertypeOf};
1616

17-
use middle::ty::{BuiltinBounds};
1817
use middle::ty::{self, Ty};
1918
use middle::ty::TyVar;
2019
use util::ppaux::{Repr};
@@ -97,20 +96,6 @@ impl<'f, 'tcx> Combine<'tcx> for Sub<'f, 'tcx> {
9796
})
9897
}
9998

100-
fn builtin_bounds(&self, a: BuiltinBounds, b: BuiltinBounds)
101-
-> cres<'tcx, BuiltinBounds> {
102-
// More bounds is a subtype of fewer bounds.
103-
//
104-
// e.g., fn:Copy() <: fn(), because the former is a function
105-
// that only closes over copyable things, but the latter is
106-
// any function at all.
107-
if a.is_superset(&b) {
108-
Ok(a)
109-
} else {
110-
Err(ty::terr_builtin_bounds(expected_found(self, a, b)))
111-
}
112-
}
113-
11499
fn tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> cres<'tcx, Ty<'tcx>> {
115100
debug!("{}.tys({}, {})", self.tag(),
116101
a.repr(self.tcx()), b.repr(self.tcx()));

Diff for: src/librustc/middle/ty.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,8 @@ pub enum UnsizeKind<'tcx> {
292292
// An unsize coercion applied to the tail field of a struct.
293293
// The uint is the index of the type parameter which is unsized.
294294
UnsizeStruct(Box<UnsizeKind<'tcx>>, uint),
295-
UnsizeVtable(TyTrait<'tcx>, /* the self type of the trait */ Ty<'tcx>)
295+
UnsizeVtable(TyTrait<'tcx>, /* the self type of the trait */ Ty<'tcx>),
296+
UnsizeUpcast(Ty<'tcx>),
296297
}
297298

298299
#[derive(Clone, Debug)]
@@ -4627,6 +4628,9 @@ pub fn unsize_ty<'tcx>(cx: &ctxt<'tcx>,
46274628
&UnsizeVtable(TyTrait { ref principal, ref bounds }, _) => {
46284629
mk_trait(cx, principal.clone(), bounds.clone())
46294630
}
4631+
&UnsizeUpcast(target_ty) => {
4632+
target_ty
4633+
}
46304634
}
46314635
}
46324636

@@ -6830,6 +6834,7 @@ impl<'tcx> Repr<'tcx> for UnsizeKind<'tcx> {
68306834
UnsizeLength(n) => format!("UnsizeLength({})", n),
68316835
UnsizeStruct(ref k, n) => format!("UnsizeStruct({},{})", k.repr(tcx), n),
68326836
UnsizeVtable(ref a, ref b) => format!("UnsizeVtable({},{})", a.repr(tcx), b.repr(tcx)),
6837+
UnsizeUpcast(ref a) => format!("UnsizeUpcast({})", a.repr(tcx)),
68336838
}
68346839
}
68356840
}

Diff for: src/librustc/middle/ty_fold.rs

+1
Original file line numberDiff line numberDiff line change
@@ -480,6 +480,7 @@ impl<'tcx> TypeFoldable<'tcx> for ty::UnsizeKind<'tcx> {
480480
},
481481
self_ty.fold_with(folder))
482482
}
483+
ty::UnsizeUpcast(t) => ty::UnsizeUpcast(t.fold_with(folder)),
483484
}
484485
}
485486
}

Diff for: src/librustc/util/ppaux.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -1214,17 +1214,17 @@ impl<'tcx> Repr<'tcx> for ty::ExistentialBounds<'tcx> {
12141214
fn repr(&self, tcx: &ctxt<'tcx>) -> String {
12151215
let mut res = Vec::new();
12161216

1217-
let region_str = self.region_bound.user_string(tcx);
1217+
let region_str = self.region_bound.repr(tcx);
12181218
if !region_str.is_empty() {
12191219
res.push(region_str);
12201220
}
12211221

12221222
for bound in &self.builtin_bounds {
1223-
res.push(bound.user_string(tcx));
1223+
res.push(bound.repr(tcx));
12241224
}
12251225

12261226
for projection_bound in &self.projection_bounds {
1227-
res.push(projection_bound.user_string(tcx));
1227+
res.push(projection_bound.repr(tcx));
12281228
}
12291229

12301230
res.connect("+")

Diff for: src/librustc_trans/trans/consts.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -311,12 +311,16 @@ pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
311311
llconst = addr_of(cx, llconst, "autoref", e.id);
312312
}
313313
Some(box ty::AutoUnsize(ref k)) => {
314-
let info = expr::unsized_info(cx, k, e.id, ty, param_substs,
315-
|t| ty::mk_imm_rptr(cx.tcx(), cx.tcx().mk_region(ty::ReStatic), t));
314+
let info =
315+
expr::unsized_info(
316+
cx, k, e.id, ty, param_substs,
317+
|t| ty::mk_imm_rptr(cx.tcx(), cx.tcx().mk_region(ty::ReStatic), t),
318+
|| const_get_elt(cx, llconst, &[abi::FAT_PTR_EXTRA as u32]));
316319

317320
let unsized_ty = ty::unsize_ty(cx.tcx(), ty, k, e.span);
318321
let ptr_ty = type_of::in_memory_type_of(cx, unsized_ty).ptr_to();
319322
let base = ptrcast(llconst, ptr_ty);
323+
320324
let prev_const = cx.const_unsized().borrow_mut()
321325
.insert(base, llconst);
322326
assert!(prev_const.is_none() || prev_const == Some(llconst));

0 commit comments

Comments
 (0)