Skip to content

Commit 3aa1503

Browse files
committed
add support for principal-less trait object types
should be a pure refactoring.
1 parent c0bbc39 commit 3aa1503

File tree

26 files changed

+203
-132
lines changed

26 files changed

+203
-132
lines changed

src/librustc/traits/coherence.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -485,7 +485,13 @@ fn ty_is_local_constructor(ty: Ty<'_>, in_crate: InCrate) -> bool {
485485
ty::Adt(def, _) => def_id_is_local(def.did, in_crate),
486486
ty::Foreign(did) => def_id_is_local(did, in_crate),
487487

488-
ty::Dynamic(ref tt, ..) => def_id_is_local(tt.principal().def_id(), in_crate),
488+
ty::Dynamic(ref tt, ..) => {
489+
if let Some(principal) = tt.principal() {
490+
def_id_is_local(principal.def_id(), in_crate)
491+
} else {
492+
false
493+
}
494+
}
489495

490496
ty::Error => true,
491497

src/librustc/traits/select.rs

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2016,7 +2016,12 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
20162016
return;
20172017
}
20182018

2019-
data.principal().with_self_ty(self.tcx(), self_ty)
2019+
if let Some(principal) = data.principal() {
2020+
principal.with_self_ty(self.tcx(), self_ty)
2021+
} else {
2022+
// Only auto-trait bounds exist.
2023+
return;
2024+
}
20202025
}
20212026
ty::Infer(ty::TyVar(_)) => {
20222027
debug!("assemble_candidates_from_object_ty: ambiguous");
@@ -2108,7 +2113,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
21082113
//
21092114
// We always upcast when we can because of reason
21102115
// #2 (region bounds).
2111-
data_a.principal().def_id() == data_b.principal().def_id()
2116+
data_a.principal_def_id() == data_b.principal_def_id()
21122117
&& data_b.auto_traits()
21132118
// All of a's auto traits need to be in b's auto traits.
21142119
.all(|b| data_a.auto_traits().any(|a| a == b))
@@ -2919,7 +2924,10 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
29192924
let self_ty = self.infcx
29202925
.shallow_resolve(*obligation.self_ty().skip_binder());
29212926
let poly_trait_ref = match self_ty.sty {
2922-
ty::Dynamic(ref data, ..) => data.principal().with_self_ty(self.tcx(), self_ty),
2927+
ty::Dynamic(ref data, ..) =>
2928+
data.principal().unwrap_or_else(|| {
2929+
span_bug!(obligation.cause.span, "object candidate with no principal")
2930+
}).with_self_ty(self.tcx(), self_ty),
29232931
_ => span_bug!(obligation.cause.span, "object candidate with non-object"),
29242932
};
29252933

@@ -3222,8 +3230,9 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
32223230
(&ty::Dynamic(ref data_a, r_a), &ty::Dynamic(ref data_b, r_b)) => {
32233231
// See assemble_candidates_for_unsizing for more info.
32243232
let existential_predicates = data_a.map_bound(|data_a| {
3225-
let iter = iter::once(ty::ExistentialPredicate::Trait(data_a.principal()))
3226-
.chain(
3233+
let iter =
3234+
data_a.principal().map(|x| ty::ExistentialPredicate::Trait(x))
3235+
.into_iter().chain(
32273236
data_a
32283237
.projection_bounds()
32293238
.map(|x| ty::ExistentialPredicate::Projection(x)),
@@ -3260,7 +3269,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
32603269
// T -> Trait.
32613270
(_, &ty::Dynamic(ref data, r)) => {
32623271
let mut object_dids = data.auto_traits()
3263-
.chain(iter::once(data.principal().def_id()));
3272+
.chain(data.principal_def_id());
32643273
if let Some(did) = object_dids.find(|did| !tcx.is_object_safe(*did)) {
32653274
return Err(TraitNotObjectSafe(did));
32663275
}

src/librustc/ty/error.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,11 @@ impl<'a, 'gcx, 'lcx, 'tcx> ty::TyS<'tcx> {
183183
ty::FnDef(..) => "fn item".into(),
184184
ty::FnPtr(_) => "fn pointer".into(),
185185
ty::Dynamic(ref inner, ..) => {
186-
format!("trait {}", tcx.item_path_str(inner.principal().def_id())).into()
186+
if let Some(principal) = inner.principal() {
187+
format!("trait {}", tcx.item_path_str(principal.def_id())).into()
188+
} else {
189+
"trait".into()
190+
}
187191
}
188192
ty::Closure(..) => "closure".into(),
189193
ty::Generator(..) => "generator".into(),

src/librustc/ty/fast_reject.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -71,11 +71,11 @@ pub fn simplify_type<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
7171
ty::Array(..) | ty::Slice(_) => Some(ArraySimplifiedType),
7272
ty::RawPtr(_) => Some(PtrSimplifiedType),
7373
ty::Dynamic(ref trait_info, ..) => {
74-
let principal_def_id = trait_info.principal().def_id();
75-
if tcx.trait_is_auto(principal_def_id) {
76-
Some(MarkerTraitObjectSimplifiedType)
77-
} else {
78-
Some(TraitSimplifiedType(principal_def_id))
74+
match trait_info.principal_def_id() {
75+
Some(principal_def_id) if !tcx.trait_is_auto(principal_def_id) => {
76+
Some(TraitSimplifiedType(principal_def_id))
77+
}
78+
_ => Some(MarkerTraitObjectSimplifiedType)
7979
}
8080
}
8181
ty::Ref(_, ty, _) => {
@@ -140,9 +140,9 @@ impl<D: Copy + Debug + Ord + Eq + Hash> SimplifiedTypeGen<D> {
140140
ArraySimplifiedType => ArraySimplifiedType,
141141
PtrSimplifiedType => PtrSimplifiedType,
142142
NeverSimplifiedType => NeverSimplifiedType,
143+
MarkerTraitObjectSimplifiedType => MarkerTraitObjectSimplifiedType,
143144
TupleSimplifiedType(n) => TupleSimplifiedType(n),
144145
TraitSimplifiedType(d) => TraitSimplifiedType(map(d)),
145-
MarkerTraitObjectSimplifiedType => MarkerTraitObjectSimplifiedType,
146146
ClosureSimplifiedType(d) => ClosureSimplifiedType(map(d)),
147147
GeneratorSimplifiedType(d) => GeneratorSimplifiedType(map(d)),
148148
GeneratorWitnessSimplifiedType(n) => GeneratorWitnessSimplifiedType(n),

src/librustc/ty/item_path.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -479,7 +479,7 @@ pub fn characteristic_def_id_of_type(ty: Ty<'_>) -> Option<DefId> {
479479
match ty.sty {
480480
ty::Adt(adt_def, _) => Some(adt_def.did),
481481

482-
ty::Dynamic(data, ..) => Some(data.principal().def_id()),
482+
ty::Dynamic(data, ..) => data.principal_def_id(),
483483

484484
ty::Array(subty, _) |
485485
ty::Slice(subty) => characteristic_def_id_of_type(subty),

src/librustc/ty/sty.rs

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -569,13 +569,18 @@ impl<'a, 'gcx, 'tcx> Binder<ExistentialPredicate<'tcx>> {
569569
impl<'tcx> serialize::UseSpecializedDecodable for &'tcx List<ExistentialPredicate<'tcx>> {}
570570

571571
impl<'tcx> List<ExistentialPredicate<'tcx>> {
572-
pub fn principal(&self) -> ExistentialTraitRef<'tcx> {
572+
pub fn principal(&self) -> Option<ExistentialTraitRef<'tcx>> {
573573
match self[0] {
574-
ExistentialPredicate::Trait(tr) => tr,
574+
ExistentialPredicate::Trait(tr) => Some(tr),
575575
other => bug!("first predicate is {:?}", other),
576576
}
577577
}
578578

579+
580+
pub fn principal_def_id(&self) -> Option<DefId> {
581+
self.principal().map(|d| d.def_id)
582+
}
583+
579584
#[inline]
580585
pub fn projection_bounds<'a>(&'a self) ->
581586
impl Iterator<Item=ExistentialProjection<'tcx>> + 'a {
@@ -599,8 +604,12 @@ impl<'tcx> List<ExistentialPredicate<'tcx>> {
599604
}
600605

601606
impl<'tcx> Binder<&'tcx List<ExistentialPredicate<'tcx>>> {
602-
pub fn principal(&self) -> PolyExistentialTraitRef<'tcx> {
603-
Binder::bind(self.skip_binder().principal())
607+
pub fn principal(&self) -> Option<ty::Binder<ExistentialTraitRef<'tcx>>> {
608+
self.skip_binder().principal().map(Binder::bind)
609+
}
610+
611+
pub fn principal_def_id(&self) -> Option<DefId> {
612+
self.skip_binder().principal_def_id()
604613
}
605614

606615
#[inline]
@@ -1917,7 +1926,9 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
19171926
}
19181927
Dynamic(ref obj, region) => {
19191928
out.push(region);
1920-
out.extend(obj.principal().skip_binder().substs.regions());
1929+
if let Some(principal) = obj.principal() {
1930+
out.extend(principal.skip_binder().substs.regions());
1931+
}
19211932
}
19221933
Adt(_, substs) | Opaque(_, substs) => {
19231934
out.extend(substs.regions())

src/librustc/ty/wf.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,7 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> {
384384

385385
let cause = self.cause(traits::MiscObligation);
386386
let component_traits =
387-
data.auto_traits().chain(once(data.principal().def_id()));
387+
data.auto_traits().chain(data.principal_def_id());
388388
self.out.extend(
389389
component_traits.map(|did| traits::Obligation::new(
390390
cause.clone(),

src/librustc/util/ppaux.rs

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -713,16 +713,18 @@ define_print! {
713713
// Use a type that can't appear in defaults of type parameters.
714714
let dummy_self = tcx.mk_infer(ty::FreshTy(0));
715715

716-
let principal = tcx
717-
.lift(&self.principal())
718-
.expect("could not lift TraitRef for printing")
719-
.with_self_ty(tcx, dummy_self);
720-
let projections = self.projection_bounds().map(|p| {
721-
tcx.lift(&p)
722-
.expect("could not lift projection for printing")
723-
.with_self_ty(tcx, dummy_self)
724-
}).collect::<Vec<_>>();
725-
cx.parameterized(f, principal.substs, principal.def_id, &projections)?;
716+
if let Some(principal) = self.principal() {
717+
let principal = tcx
718+
.lift(&principal)
719+
.expect("could not lift TraitRef for printing")
720+
.with_self_ty(tcx, dummy_self);
721+
let projections = self.projection_bounds().map(|p| {
722+
tcx.lift(&p)
723+
.expect("could not lift projection for printing")
724+
.with_self_ty(tcx, dummy_self)
725+
}).collect::<Vec<_>>();
726+
cx.parameterized(f, principal.substs, principal.def_id, &projections)?;
727+
}
726728

727729
// Builtin bounds.
728730
for did in self.auto_traits() {

src/librustc_codegen_llvm/context.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,8 @@ pub struct CodegenCx<'ll, 'tcx: 'll> {
5050
/// Cache instances of monomorphic and polymorphic items
5151
pub instances: RefCell<FxHashMap<Instance<'tcx>, &'ll Value>>,
5252
/// Cache generated vtables
53-
pub vtables: RefCell<FxHashMap<(Ty<'tcx>, ty::PolyExistentialTraitRef<'tcx>), &'ll Value>>,
53+
pub vtables: RefCell<FxHashMap<
54+
(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), &'ll Value>>,
5455
/// Cache of constant strings,
5556
pub const_cstr_cache: RefCell<FxHashMap<LocalInternedString, &'ll Value>>,
5657

@@ -311,7 +312,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
311312

312313
impl MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> {
313314
fn vtables(&self) -> &RefCell<FxHashMap<(Ty<'tcx>,
314-
ty::PolyExistentialTraitRef<'tcx>), &'ll Value>>
315+
Option<ty::PolyExistentialTraitRef<'tcx>>), &'ll Value>>
315316
{
316317
&self.vtables
317318
}

src/librustc_codegen_llvm/debuginfo/metadata.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -429,7 +429,8 @@ fn trait_pointer_metadata(
429429
// But it does not describe the trait's methods.
430430

431431
let containing_scope = match trait_type.sty {
432-
ty::Dynamic(ref data, ..) => Some(get_namespace_for_item(cx, data.principal().def_id())),
432+
ty::Dynamic(ref data, ..) =>
433+
data.principal_def_id().map(|did| get_namespace_for_item(cx, did)),
433434
_ => {
434435
bug!("debuginfo: Unexpected trait-object type in \
435436
trait_pointer_metadata(): {:?}",

src/librustc_codegen_llvm/debuginfo/type_names.rs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -107,12 +107,16 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
107107
}
108108
},
109109
ty::Dynamic(ref trait_data, ..) => {
110-
let principal = cx.tcx.normalize_erasing_late_bound_regions(
111-
ty::ParamEnv::reveal_all(),
112-
&trait_data.principal(),
113-
);
114-
push_item_name(cx, principal.def_id, false, output);
115-
push_type_params(cx, principal.substs, output);
110+
if let Some(principal) = trait_data.principal() {
111+
let principal = cx.tcx.normalize_erasing_late_bound_regions(
112+
ty::ParamEnv::reveal_all(),
113+
&principal,
114+
);
115+
push_item_name(cx, principal.def_id, false, output);
116+
push_type_params(cx, principal.substs, output);
117+
} else {
118+
output.push_str("dyn '_");
119+
}
116120
},
117121
ty::FnDef(..) | ty::FnPtr(_) => {
118122
let sig = t.fn_sig(cx.tcx);

src/librustc_codegen_ssa/meth.rs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ impl<'a, 'tcx: 'a> VirtualIndex {
6969
pub fn get_vtable<'tcx, Cx: CodegenMethods<'tcx>>(
7070
cx: &Cx,
7171
ty: Ty<'tcx>,
72-
trait_ref: ty::PolyExistentialTraitRef<'tcx>,
72+
trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>,
7373
) -> Cx::Value {
7474
let tcx = cx.tcx();
7575

@@ -83,8 +83,15 @@ pub fn get_vtable<'tcx, Cx: CodegenMethods<'tcx>>(
8383
// Not in the cache. Build it.
8484
let nullptr = cx.const_null(cx.type_i8p());
8585

86-
let methods = tcx.vtable_methods(trait_ref.with_self_ty(tcx, ty));
87-
let methods = methods.iter().cloned().map(|opt_mth| {
86+
let methods_root;
87+
let methods = if let Some(trait_ref) = trait_ref {
88+
methods_root = tcx.vtable_methods(trait_ref.with_self_ty(tcx, ty));
89+
methods_root.iter()
90+
} else {
91+
(&[]).iter()
92+
};
93+
94+
let methods = methods.cloned().map(|opt_mth| {
8895
opt_mth.map_or(nullptr, |(def_id, substs)| {
8996
callee::resolve_and_get_fn_for_vtable(cx, def_id, substs)
9097
})

src/librustc_codegen_ssa/traits/misc.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use std::sync::Arc;
1111
pub trait MiscMethods<'tcx>: BackendTypes {
1212
fn vtables(
1313
&self,
14-
) -> &RefCell<FxHashMap<(Ty<'tcx>, ty::PolyExistentialTraitRef<'tcx>), Self::Value>>;
14+
) -> &RefCell<FxHashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), Self::Value>>;
1515
fn check_overflow(&self) -> bool;
1616
fn instances(&self) -> &RefCell<FxHashMap<Instance<'tcx>, Self::Value>>;
1717
fn get_fn(&self, instance: Instance<'tcx>) -> Self::Value;

src/librustc_mir/interpret/eval_context.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ pub struct EvalContext<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'a, 'mir, 'tcx>> {
4242
pub(crate) stack: Vec<Frame<'mir, 'tcx, M::PointerTag, M::FrameExtra>>,
4343

4444
/// A cache for deduplicating vtables
45-
pub(super) vtables: FxHashMap<(Ty<'tcx>, ty::PolyExistentialTraitRef<'tcx>), AllocId>,
45+
pub(super) vtables: FxHashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), AllocId>,
4646
}
4747

4848
/// A stack frame.

src/librustc_mir/interpret/traits.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use rustc_data_structures::sync::Lrc;
12
use rustc::ty::{self, Ty};
23
use rustc::ty::layout::{Size, Align, LayoutOf};
34
use rustc::mir::interpret::{Scalar, Pointer, EvalResult, PointerArithmetic};
@@ -14,7 +15,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
1415
pub fn get_vtable(
1516
&mut self,
1617
ty: Ty<'tcx>,
17-
poly_trait_ref: ty::PolyExistentialTraitRef<'tcx>,
18+
poly_trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>,
1819
) -> EvalResult<'tcx, Pointer<M::PointerTag>> {
1920
trace!("get_vtable(trait_ref={:?})", poly_trait_ref);
2021

@@ -24,10 +25,14 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
2425
return Ok(Pointer::from(vtable).with_default_tag());
2526
}
2627

27-
let trait_ref = poly_trait_ref.with_self_ty(*self.tcx, ty);
28-
let trait_ref = self.tcx.erase_regions(&trait_ref);
28+
let methods = if let Some(poly_trait_ref) = poly_trait_ref {
29+
let trait_ref = poly_trait_ref.with_self_ty(*self.tcx, ty);
30+
let trait_ref = self.tcx.erase_regions(&trait_ref);
2931

30-
let methods = self.tcx.vtable_methods(trait_ref);
32+
self.tcx.vtable_methods(trait_ref)
33+
} else {
34+
Lrc::new(Vec::new())
35+
};
3136

3237
let layout = self.layout_of(ty)?;
3338
assert!(!layout.is_unsized(), "can't create a vtable for an unsized type");

src/librustc_mir/monomorphize/collector.rs

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -894,20 +894,23 @@ fn create_mono_items_for_vtable_methods<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
894894
!impl_ty.needs_subst() && !impl_ty.has_escaping_bound_vars());
895895

896896
if let ty::Dynamic(ref trait_ty, ..) = trait_ty.sty {
897-
let poly_trait_ref = trait_ty.principal().with_self_ty(tcx, impl_ty);
898-
assert!(!poly_trait_ref.has_escaping_bound_vars());
899-
900-
// Walk all methods of the trait, including those of its supertraits
901-
let methods = tcx.vtable_methods(poly_trait_ref);
902-
let methods = methods.iter().cloned().filter_map(|method| method)
903-
.map(|(def_id, substs)| ty::Instance::resolve_for_vtable(
897+
if let Some(principal) = trait_ty.principal() {
898+
let poly_trait_ref = principal.with_self_ty(tcx, impl_ty);
899+
assert!(!poly_trait_ref.has_escaping_bound_vars());
900+
901+
// Walk all methods of the trait, including those of its supertraits
902+
let methods = tcx.vtable_methods(poly_trait_ref);
903+
let methods = methods.iter().cloned().filter_map(|method| method)
904+
.map(|(def_id, substs)| ty::Instance::resolve_for_vtable(
904905
tcx,
905906
ty::ParamEnv::reveal_all(),
906907
def_id,
907908
substs).unwrap())
908-
.filter(|&instance| should_monomorphize_locally(tcx, &instance))
909-
.map(|instance| create_fn_mono_item(instance));
910-
output.extend(methods);
909+
.filter(|&instance| should_monomorphize_locally(tcx, &instance))
910+
.map(|instance| create_fn_mono_item(instance));
911+
output.extend(methods);
912+
}
913+
911914
// Also add the destructor
912915
visit_drop_use(tcx, impl_ty, false, output);
913916
}

src/librustc_mir/monomorphize/item.rs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -304,13 +304,16 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> {
304304
output.push(']');
305305
},
306306
ty::Dynamic(ref trait_data, ..) => {
307-
let principal = trait_data.principal();
308-
self.push_def_path(principal.def_id(), output);
309-
self.push_type_params(
310-
principal.skip_binder().substs,
311-
trait_data.projection_bounds(),
312-
output,
313-
);
307+
if let Some(principal) = trait_data.principal() {
308+
self.push_def_path(principal.def_id(), output);
309+
self.push_type_params(
310+
principal.skip_binder().substs,
311+
trait_data.projection_bounds(),
312+
output,
313+
);
314+
} else {
315+
output.push_str("dyn '_");
316+
}
314317
},
315318
ty::Foreign(did) => self.push_def_path(did, output),
316319
ty::FnDef(..) |

0 commit comments

Comments
 (0)