diff options
| author | Ariel Ben-Yehuda <ariel.byd@gmail.com> | 2018-12-04 13:28:06 +0200 |
|---|---|---|
| committer | Ariel Ben-Yehuda <ariel.byd@gmail.com> | 2019-01-04 00:34:52 +0200 |
| commit | 3aa1503a61d03834643a39f3e4c9de6721c31bdb (patch) | |
| tree | ad29fd4d3b5ad4854523a501fa94568e3536b524 /src | |
| parent | c0bbc3927e28c22edefe6a1353b5ecc95ea9a104 (diff) | |
| download | rust-3aa1503a61d03834643a39f3e4c9de6721c31bdb.tar.gz rust-3aa1503a61d03834643a39f3e4c9de6721c31bdb.zip | |
add support for principal-less trait object types
should be a pure refactoring.
Diffstat (limited to 'src')
26 files changed, 203 insertions, 132 deletions
diff --git a/src/librustc/traits/coherence.rs b/src/librustc/traits/coherence.rs index b3d732ebcd7..5a4fc23a603 100644 --- a/src/librustc/traits/coherence.rs +++ b/src/librustc/traits/coherence.rs @@ -485,7 +485,13 @@ fn ty_is_local_constructor(ty: Ty<'_>, in_crate: InCrate) -> bool { ty::Adt(def, _) => def_id_is_local(def.did, in_crate), ty::Foreign(did) => def_id_is_local(did, in_crate), - ty::Dynamic(ref tt, ..) => def_id_is_local(tt.principal().def_id(), in_crate), + ty::Dynamic(ref tt, ..) => { + if let Some(principal) = tt.principal() { + def_id_is_local(principal.def_id(), in_crate) + } else { + false + } + } ty::Error => true, diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 373ec2d5e49..7c4a29ecb54 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -2016,7 +2016,12 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { return; } - data.principal().with_self_ty(self.tcx(), self_ty) + if let Some(principal) = data.principal() { + principal.with_self_ty(self.tcx(), self_ty) + } else { + // Only auto-trait bounds exist. + return; + } } ty::Infer(ty::TyVar(_)) => { debug!("assemble_candidates_from_object_ty: ambiguous"); @@ -2108,7 +2113,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // // We always upcast when we can because of reason // #2 (region bounds). - data_a.principal().def_id() == data_b.principal().def_id() + data_a.principal_def_id() == data_b.principal_def_id() && data_b.auto_traits() // All of a's auto traits need to be in b's auto traits. .all(|b| data_a.auto_traits().any(|a| a == b)) @@ -2919,7 +2924,10 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { let self_ty = self.infcx .shallow_resolve(*obligation.self_ty().skip_binder()); let poly_trait_ref = match self_ty.sty { - ty::Dynamic(ref data, ..) => data.principal().with_self_ty(self.tcx(), self_ty), + ty::Dynamic(ref data, ..) => + data.principal().unwrap_or_else(|| { + span_bug!(obligation.cause.span, "object candidate with no principal") + }).with_self_ty(self.tcx(), self_ty), _ => span_bug!(obligation.cause.span, "object candidate with non-object"), }; @@ -3222,8 +3230,9 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { (&ty::Dynamic(ref data_a, r_a), &ty::Dynamic(ref data_b, r_b)) => { // See assemble_candidates_for_unsizing for more info. let existential_predicates = data_a.map_bound(|data_a| { - let iter = iter::once(ty::ExistentialPredicate::Trait(data_a.principal())) - .chain( + let iter = + data_a.principal().map(|x| ty::ExistentialPredicate::Trait(x)) + .into_iter().chain( data_a .projection_bounds() .map(|x| ty::ExistentialPredicate::Projection(x)), @@ -3260,7 +3269,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // T -> Trait. (_, &ty::Dynamic(ref data, r)) => { let mut object_dids = data.auto_traits() - .chain(iter::once(data.principal().def_id())); + .chain(data.principal_def_id()); if let Some(did) = object_dids.find(|did| !tcx.is_object_safe(*did)) { return Err(TraitNotObjectSafe(did)); } diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs index 76e102d88d7..1ba367b8688 100644 --- a/src/librustc/ty/error.rs +++ b/src/librustc/ty/error.rs @@ -183,7 +183,11 @@ impl<'a, 'gcx, 'lcx, 'tcx> ty::TyS<'tcx> { ty::FnDef(..) => "fn item".into(), ty::FnPtr(_) => "fn pointer".into(), ty::Dynamic(ref inner, ..) => { - format!("trait {}", tcx.item_path_str(inner.principal().def_id())).into() + if let Some(principal) = inner.principal() { + format!("trait {}", tcx.item_path_str(principal.def_id())).into() + } else { + "trait".into() + } } ty::Closure(..) => "closure".into(), ty::Generator(..) => "generator".into(), diff --git a/src/librustc/ty/fast_reject.rs b/src/librustc/ty/fast_reject.rs index 7fbbfb337ea..2b41fc4fe34 100644 --- a/src/librustc/ty/fast_reject.rs +++ b/src/librustc/ty/fast_reject.rs @@ -71,11 +71,11 @@ pub fn simplify_type<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, ty::Array(..) | ty::Slice(_) => Some(ArraySimplifiedType), ty::RawPtr(_) => Some(PtrSimplifiedType), ty::Dynamic(ref trait_info, ..) => { - let principal_def_id = trait_info.principal().def_id(); - if tcx.trait_is_auto(principal_def_id) { - Some(MarkerTraitObjectSimplifiedType) - } else { - Some(TraitSimplifiedType(principal_def_id)) + match trait_info.principal_def_id() { + Some(principal_def_id) if !tcx.trait_is_auto(principal_def_id) => { + Some(TraitSimplifiedType(principal_def_id)) + } + _ => Some(MarkerTraitObjectSimplifiedType) } } ty::Ref(_, ty, _) => { @@ -140,9 +140,9 @@ impl<D: Copy + Debug + Ord + Eq + Hash> SimplifiedTypeGen<D> { ArraySimplifiedType => ArraySimplifiedType, PtrSimplifiedType => PtrSimplifiedType, NeverSimplifiedType => NeverSimplifiedType, + MarkerTraitObjectSimplifiedType => MarkerTraitObjectSimplifiedType, TupleSimplifiedType(n) => TupleSimplifiedType(n), TraitSimplifiedType(d) => TraitSimplifiedType(map(d)), - MarkerTraitObjectSimplifiedType => MarkerTraitObjectSimplifiedType, ClosureSimplifiedType(d) => ClosureSimplifiedType(map(d)), GeneratorSimplifiedType(d) => GeneratorSimplifiedType(map(d)), GeneratorWitnessSimplifiedType(n) => GeneratorWitnessSimplifiedType(n), diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs index da467f57d25..417e14054d2 100644 --- a/src/librustc/ty/item_path.rs +++ b/src/librustc/ty/item_path.rs @@ -479,7 +479,7 @@ pub fn characteristic_def_id_of_type(ty: Ty<'_>) -> Option<DefId> { match ty.sty { ty::Adt(adt_def, _) => Some(adt_def.did), - ty::Dynamic(data, ..) => Some(data.principal().def_id()), + ty::Dynamic(data, ..) => data.principal_def_id(), ty::Array(subty, _) | ty::Slice(subty) => characteristic_def_id_of_type(subty), diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index a2720bdf385..45fb8cf3dc9 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -569,13 +569,18 @@ impl<'a, 'gcx, 'tcx> Binder<ExistentialPredicate<'tcx>> { impl<'tcx> serialize::UseSpecializedDecodable for &'tcx List<ExistentialPredicate<'tcx>> {} impl<'tcx> List<ExistentialPredicate<'tcx>> { - pub fn principal(&self) -> ExistentialTraitRef<'tcx> { + pub fn principal(&self) -> Option<ExistentialTraitRef<'tcx>> { match self[0] { - ExistentialPredicate::Trait(tr) => tr, + ExistentialPredicate::Trait(tr) => Some(tr), other => bug!("first predicate is {:?}", other), } } + + pub fn principal_def_id(&self) -> Option<DefId> { + self.principal().map(|d| d.def_id) + } + #[inline] pub fn projection_bounds<'a>(&'a self) -> impl Iterator<Item=ExistentialProjection<'tcx>> + 'a { @@ -599,8 +604,12 @@ impl<'tcx> List<ExistentialPredicate<'tcx>> { } impl<'tcx> Binder<&'tcx List<ExistentialPredicate<'tcx>>> { - pub fn principal(&self) -> PolyExistentialTraitRef<'tcx> { - Binder::bind(self.skip_binder().principal()) + pub fn principal(&self) -> Option<ty::Binder<ExistentialTraitRef<'tcx>>> { + self.skip_binder().principal().map(Binder::bind) + } + + pub fn principal_def_id(&self) -> Option<DefId> { + self.skip_binder().principal_def_id() } #[inline] @@ -1917,7 +1926,9 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { } Dynamic(ref obj, region) => { out.push(region); - out.extend(obj.principal().skip_binder().substs.regions()); + if let Some(principal) = obj.principal() { + out.extend(principal.skip_binder().substs.regions()); + } } Adt(_, substs) | Opaque(_, substs) => { out.extend(substs.regions()) diff --git a/src/librustc/ty/wf.rs b/src/librustc/ty/wf.rs index aacc63c47de..1fad9643599 100644 --- a/src/librustc/ty/wf.rs +++ b/src/librustc/ty/wf.rs @@ -384,7 +384,7 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { let cause = self.cause(traits::MiscObligation); let component_traits = - data.auto_traits().chain(once(data.principal().def_id())); + data.auto_traits().chain(data.principal_def_id()); self.out.extend( component_traits.map(|did| traits::Obligation::new( cause.clone(), diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 79405b12400..d55d9c8c2ed 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -713,16 +713,18 @@ define_print! { // Use a type that can't appear in defaults of type parameters. let dummy_self = tcx.mk_infer(ty::FreshTy(0)); - let principal = tcx - .lift(&self.principal()) - .expect("could not lift TraitRef for printing") - .with_self_ty(tcx, dummy_self); - let projections = self.projection_bounds().map(|p| { - tcx.lift(&p) - .expect("could not lift projection for printing") - .with_self_ty(tcx, dummy_self) - }).collect::<Vec<_>>(); - cx.parameterized(f, principal.substs, principal.def_id, &projections)?; + if let Some(principal) = self.principal() { + let principal = tcx + .lift(&principal) + .expect("could not lift TraitRef for printing") + .with_self_ty(tcx, dummy_self); + let projections = self.projection_bounds().map(|p| { + tcx.lift(&p) + .expect("could not lift projection for printing") + .with_self_ty(tcx, dummy_self) + }).collect::<Vec<_>>(); + cx.parameterized(f, principal.substs, principal.def_id, &projections)?; + } // Builtin bounds. for did in self.auto_traits() { diff --git a/src/librustc_codegen_llvm/context.rs b/src/librustc_codegen_llvm/context.rs index 3a5da29c681..2b03e99161d 100644 --- a/src/librustc_codegen_llvm/context.rs +++ b/src/librustc_codegen_llvm/context.rs @@ -50,7 +50,8 @@ pub struct CodegenCx<'ll, 'tcx: 'll> { /// Cache instances of monomorphic and polymorphic items pub instances: RefCell<FxHashMap<Instance<'tcx>, &'ll Value>>, /// Cache generated vtables - pub vtables: RefCell<FxHashMap<(Ty<'tcx>, ty::PolyExistentialTraitRef<'tcx>), &'ll Value>>, + pub vtables: RefCell<FxHashMap< + (Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), &'ll Value>>, /// Cache of constant strings, pub const_cstr_cache: RefCell<FxHashMap<LocalInternedString, &'ll Value>>, @@ -311,7 +312,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { impl MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> { fn vtables(&self) -> &RefCell<FxHashMap<(Ty<'tcx>, - ty::PolyExistentialTraitRef<'tcx>), &'ll Value>> + Option<ty::PolyExistentialTraitRef<'tcx>>), &'ll Value>> { &self.vtables } diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs index 0fd04e9d203..72ed55df946 100644 --- a/src/librustc_codegen_llvm/debuginfo/metadata.rs +++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs @@ -429,7 +429,8 @@ fn trait_pointer_metadata( // But it does not describe the trait's methods. let containing_scope = match trait_type.sty { - ty::Dynamic(ref data, ..) => Some(get_namespace_for_item(cx, data.principal().def_id())), + ty::Dynamic(ref data, ..) => + data.principal_def_id().map(|did| get_namespace_for_item(cx, did)), _ => { bug!("debuginfo: Unexpected trait-object type in \ trait_pointer_metadata(): {:?}", diff --git a/src/librustc_codegen_llvm/debuginfo/type_names.rs b/src/librustc_codegen_llvm/debuginfo/type_names.rs index c8cbd735e85..32432f7e4ec 100644 --- a/src/librustc_codegen_llvm/debuginfo/type_names.rs +++ b/src/librustc_codegen_llvm/debuginfo/type_names.rs @@ -107,12 +107,16 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, } }, ty::Dynamic(ref trait_data, ..) => { - let principal = cx.tcx.normalize_erasing_late_bound_regions( - ty::ParamEnv::reveal_all(), - &trait_data.principal(), - ); - push_item_name(cx, principal.def_id, false, output); - push_type_params(cx, principal.substs, output); + if let Some(principal) = trait_data.principal() { + let principal = cx.tcx.normalize_erasing_late_bound_regions( + ty::ParamEnv::reveal_all(), + &principal, + ); + push_item_name(cx, principal.def_id, false, output); + push_type_params(cx, principal.substs, output); + } else { + output.push_str("dyn '_"); + } }, ty::FnDef(..) | ty::FnPtr(_) => { let sig = t.fn_sig(cx.tcx); diff --git a/src/librustc_codegen_ssa/meth.rs b/src/librustc_codegen_ssa/meth.rs index 31640826262..98ad2616eea 100644 --- a/src/librustc_codegen_ssa/meth.rs +++ b/src/librustc_codegen_ssa/meth.rs @@ -69,7 +69,7 @@ impl<'a, 'tcx: 'a> VirtualIndex { pub fn get_vtable<'tcx, Cx: CodegenMethods<'tcx>>( cx: &Cx, ty: Ty<'tcx>, - trait_ref: ty::PolyExistentialTraitRef<'tcx>, + trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>, ) -> Cx::Value { let tcx = cx.tcx(); @@ -83,8 +83,15 @@ pub fn get_vtable<'tcx, Cx: CodegenMethods<'tcx>>( // Not in the cache. Build it. let nullptr = cx.const_null(cx.type_i8p()); - let methods = tcx.vtable_methods(trait_ref.with_self_ty(tcx, ty)); - let methods = methods.iter().cloned().map(|opt_mth| { + let methods_root; + let methods = if let Some(trait_ref) = trait_ref { + methods_root = tcx.vtable_methods(trait_ref.with_self_ty(tcx, ty)); + methods_root.iter() + } else { + (&[]).iter() + }; + + let methods = methods.cloned().map(|opt_mth| { opt_mth.map_or(nullptr, |(def_id, substs)| { callee::resolve_and_get_fn_for_vtable(cx, def_id, substs) }) diff --git a/src/librustc_codegen_ssa/traits/misc.rs b/src/librustc_codegen_ssa/traits/misc.rs index c297288b255..b2315556366 100644 --- a/src/librustc_codegen_ssa/traits/misc.rs +++ b/src/librustc_codegen_ssa/traits/misc.rs @@ -11,7 +11,7 @@ use std::sync::Arc; pub trait MiscMethods<'tcx>: BackendTypes { fn vtables( &self, - ) -> &RefCell<FxHashMap<(Ty<'tcx>, ty::PolyExistentialTraitRef<'tcx>), Self::Value>>; + ) -> &RefCell<FxHashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), Self::Value>>; fn check_overflow(&self) -> bool; fn instances(&self) -> &RefCell<FxHashMap<Instance<'tcx>, Self::Value>>; fn get_fn(&self, instance: Instance<'tcx>) -> Self::Value; diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index 9a76a36ef22..19362b6cfdb 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -42,7 +42,7 @@ pub struct EvalContext<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'a, 'mir, 'tcx>> { pub(crate) stack: Vec<Frame<'mir, 'tcx, M::PointerTag, M::FrameExtra>>, /// A cache for deduplicating vtables - pub(super) vtables: FxHashMap<(Ty<'tcx>, ty::PolyExistentialTraitRef<'tcx>), AllocId>, + pub(super) vtables: FxHashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), AllocId>, } /// A stack frame. diff --git a/src/librustc_mir/interpret/traits.rs b/src/librustc_mir/interpret/traits.rs index 69a52b002ce..642bbc114f5 100644 --- a/src/librustc_mir/interpret/traits.rs +++ b/src/librustc_mir/interpret/traits.rs @@ -1,3 +1,4 @@ +use rustc_data_structures::sync::Lrc; use rustc::ty::{self, Ty}; use rustc::ty::layout::{Size, Align, LayoutOf}; 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> pub fn get_vtable( &mut self, ty: Ty<'tcx>, - poly_trait_ref: ty::PolyExistentialTraitRef<'tcx>, + poly_trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>, ) -> EvalResult<'tcx, Pointer<M::PointerTag>> { trace!("get_vtable(trait_ref={:?})", poly_trait_ref); @@ -24,10 +25,14 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> return Ok(Pointer::from(vtable).with_default_tag()); } - let trait_ref = poly_trait_ref.with_self_ty(*self.tcx, ty); - let trait_ref = self.tcx.erase_regions(&trait_ref); + let methods = if let Some(poly_trait_ref) = poly_trait_ref { + let trait_ref = poly_trait_ref.with_self_ty(*self.tcx, ty); + let trait_ref = self.tcx.erase_regions(&trait_ref); - let methods = self.tcx.vtable_methods(trait_ref); + self.tcx.vtable_methods(trait_ref) + } else { + Lrc::new(Vec::new()) + }; let layout = self.layout_of(ty)?; assert!(!layout.is_unsized(), "can't create a vtable for an unsized type"); diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index d81a4d6a4bc..e299dbc3c8f 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -894,20 +894,23 @@ fn create_mono_items_for_vtable_methods<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, !impl_ty.needs_subst() && !impl_ty.has_escaping_bound_vars()); if let ty::Dynamic(ref trait_ty, ..) = trait_ty.sty { - let poly_trait_ref = trait_ty.principal().with_self_ty(tcx, impl_ty); - assert!(!poly_trait_ref.has_escaping_bound_vars()); - - // Walk all methods of the trait, including those of its supertraits - let methods = tcx.vtable_methods(poly_trait_ref); - let methods = methods.iter().cloned().filter_map(|method| method) - .map(|(def_id, substs)| ty::Instance::resolve_for_vtable( + if let Some(principal) = trait_ty.principal() { + let poly_trait_ref = principal.with_self_ty(tcx, impl_ty); + assert!(!poly_trait_ref.has_escaping_bound_vars()); + + // Walk all methods of the trait, including those of its supertraits + let methods = tcx.vtable_methods(poly_trait_ref); + let methods = methods.iter().cloned().filter_map(|method| method) + .map(|(def_id, substs)| ty::Instance::resolve_for_vtable( tcx, ty::ParamEnv::reveal_all(), def_id, substs).unwrap()) - .filter(|&instance| should_monomorphize_locally(tcx, &instance)) - .map(|instance| create_fn_mono_item(instance)); - output.extend(methods); + .filter(|&instance| should_monomorphize_locally(tcx, &instance)) + .map(|instance| create_fn_mono_item(instance)); + output.extend(methods); + } + // Also add the destructor visit_drop_use(tcx, impl_ty, false, output); } diff --git a/src/librustc_mir/monomorphize/item.rs b/src/librustc_mir/monomorphize/item.rs index e7f4451fdd7..7014f539d57 100644 --- a/src/librustc_mir/monomorphize/item.rs +++ b/src/librustc_mir/monomorphize/item.rs @@ -304,13 +304,16 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> { output.push(']'); }, ty::Dynamic(ref trait_data, ..) => { - let principal = trait_data.principal(); - self.push_def_path(principal.def_id(), output); - self.push_type_params( - principal.skip_binder().substs, - trait_data.projection_bounds(), - output, - ); + if let Some(principal) = trait_data.principal() { + self.push_def_path(principal.def_id(), output); + self.push_type_params( + principal.skip_binder().substs, + trait_data.projection_bounds(), + output, + ); + } else { + output.push_str("dyn '_"); + } }, ty::Foreign(did) => self.push_def_path(did, output), ty::FnDef(..) | diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index 9d418704f48..38f9adee0a4 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -63,7 +63,7 @@ enum PointerKind<'tcx> { /// No metadata attached, ie pointer to sized type or foreign type Thin, /// A trait object - Vtable(DefId), + Vtable(Option<DefId>), /// Slice Length, /// The unsize info of this projection @@ -95,7 +95,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { Ok(match t.sty { ty::Slice(_) | ty::Str => Some(PointerKind::Length), ty::Dynamic(ref tty, ..) => - Some(PointerKind::Vtable(tty.principal().def_id())), + Some(PointerKind::Vtable(tty.principal_def_id())), ty::Adt(def, substs) if def.is_struct() => { match def.non_enum_variant().fields.last() { None => Some(PointerKind::Thin), diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index 25b1c0836c2..ff3b22dd1de 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -190,7 +190,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self.deduce_sig_from_projection(None, &pb) }) .next(); - let kind = self.tcx.lang_items().fn_trait_kind(object_type.principal().def_id()); + let kind = object_type.principal_def_id().and_then(|did| { + self.tcx.lang_items().fn_trait_kind(did) + }); (sig, kind) } ty::Infer(ty::TyVar(vid)) => self.deduce_expectations_from_obligations(vid), diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 4343f751e6a..2cf2974a45a 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -280,7 +280,11 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { .include_raw_pointers() .filter_map(|(ty, _)| match ty.sty { - ty::Dynamic(ref data, ..) => Some(closure(self, ty, data.principal())), + ty::Dynamic(ref data, ..) => { + Some(closure(self, ty, data.principal().unwrap_or_else(|| { + span_bug!(self.span, "calling trait method on empty object?") + }))) + }, _ => None, } ) diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 30a868622a5..9a828ce0177 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -505,17 +505,18 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { match self_ty.value.value.sty { ty::Dynamic(ref data, ..) => { - let p = data.principal(); - self.fcx.probe(|_| { - let InferOk { value: self_ty, obligations: _ } = - self.fcx.probe_instantiate_query_response( - self.span, &self.orig_steps_var_values, self_ty) - .unwrap_or_else(|_| { - span_bug!(self.span, "{:?} was applicable but now isn't?", self_ty) - }); - self.assemble_inherent_candidates_from_object(self_ty); - }); - self.assemble_inherent_impl_candidates_for_type(p.def_id()); + if let Some(p) = data.principal() { + self.fcx.probe(|_| { + let InferOk { value: self_ty, obligations: _ } = + self.fcx.probe_instantiate_query_response( + self.span, &self.orig_steps_var_values, self_ty) + .unwrap_or_else(|_| { + span_bug!(self.span, "{:?} was applicable but now isn't?", self_ty) + }); + self.assemble_inherent_candidates_from_object(self_ty); + }); + self.assemble_inherent_impl_candidates_for_type(p.def_id()); + } } ty::Adt(def, _) => { self.assemble_inherent_impl_candidates_for_type(def.did); @@ -680,10 +681,12 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { self_ty); let principal = match self_ty.sty { - ty::Dynamic(ref data, ..) => data.principal(), - _ => span_bug!(self.span, "non-object {:?} in assemble_inherent_candidates_from_object", - self_ty) - }; + ty::Dynamic(ref data, ..) => Some(data), + _ => None + }.and_then(|data| data.principal()).unwrap_or_else(|| { + span_bug!(self.span, "non-object {:?} in assemble_inherent_candidates_from_object", + self_ty) + }); // It is illegal to invoke a method on a trait instance that // refers to the `Self` type. An error will be reported by diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 98c425655d2..23bcd88d6af 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -651,7 +651,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { ty::Adt(def, _) => def.did.is_local(), ty::Foreign(did) => did.is_local(), - ty::Dynamic(ref tr, ..) => tr.principal().def_id().is_local(), + ty::Dynamic(ref tr, ..) => + tr.principal().map(|d| d.def_id().is_local()).unwrap_or(false), ty::Param(_) => true, diff --git a/src/librustc_typeck/coherence/inherent_impls.rs b/src/librustc_typeck/coherence/inherent_impls.rs index b9324a17fcc..93cc86423ac 100644 --- a/src/librustc_typeck/coherence/inherent_impls.rs +++ b/src/librustc_typeck/coherence/inherent_impls.rs @@ -95,8 +95,8 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentCollect<'a, 'tcx> { ty::Foreign(did) => { self.check_def_id(item, did); } - ty::Dynamic(ref data, ..) => { - self.check_def_id(item, data.principal().def_id()); + ty::Dynamic(ref data, ..) if data.principal_def_id().is_some() => { + self.check_def_id(item, data.principal_def_id().unwrap()); } ty::Char => { self.check_primitive_impl(def_id, diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs index 060fc4977a7..ce71be07efd 100644 --- a/src/librustc_typeck/coherence/mod.rs +++ b/src/librustc_typeck/coherence/mod.rs @@ -171,25 +171,28 @@ fn check_impl_overlap<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, node_id: ast::NodeI // This is something like impl Trait1 for Trait2. Illegal // if Trait1 is a supertrait of Trait2 or Trait2 is not object safe. - if !tcx.is_object_safe(data.principal().def_id()) { - // This is an error, but it will be reported by wfcheck. Ignore it here. - // This is tested by `coherence-impl-trait-for-trait-object-safe.rs`. - } else { - let mut supertrait_def_ids = - traits::supertrait_def_ids(tcx, data.principal().def_id()); - if supertrait_def_ids.any(|d| d == trait_def_id) { - let sp = tcx.sess.source_map().def_span(tcx.span_of_impl(impl_def_id).unwrap()); - struct_span_err!(tcx.sess, - sp, - E0371, - "the object type `{}` automatically implements the trait `{}`", - trait_ref.self_ty(), - tcx.item_path_str(trait_def_id)) - .span_label(sp, format!("`{}` automatically implements trait `{}`", - trait_ref.self_ty(), - tcx.item_path_str(trait_def_id))) - .emit(); + if let Some(principal_def_id) = data.principal_def_id() { + if !tcx.is_object_safe(principal_def_id) { + // This is an error, but it will be reported by wfcheck. Ignore it here. + // This is tested by `coherence-impl-trait-for-trait-object-safe.rs`. + } else { + let mut supertrait_def_ids = + traits::supertrait_def_ids(tcx, principal_def_id); + if supertrait_def_ids.any(|d| d == trait_def_id) { + let sp = tcx.sess.source_map().def_span(tcx.span_of_impl(impl_def_id).unwrap()); + struct_span_err!(tcx.sess, + sp, + E0371, + "the object type `{}` automatically implements the trait `{}`", + trait_ref.self_ty(), + tcx.item_path_str(trait_def_id)) + .span_label(sp, format!("`{}` automatically implements trait `{}`", + trait_ref.self_ty(), + tcx.item_path_str(trait_def_id))) + .emit(); + } } } + // FIXME: also check auto-trait def-ids? (e.g. `impl Sync for Foo+Sync`)? } } diff --git a/src/librustc_typeck/outlives/implicit_infer.rs b/src/librustc_typeck/outlives/implicit_infer.rs index 8929f5e5c6a..e388a3e0d0c 100644 --- a/src/librustc_typeck/outlives/implicit_infer.rs +++ b/src/librustc_typeck/outlives/implicit_infer.rs @@ -194,27 +194,28 @@ fn insert_required_predicates_to_be_wf<'tcx>( debug!("Dynamic"); debug!("field_ty = {}", &field_ty); debug!("ty in field = {}", &ty); - let ex_trait_ref = obj.principal(); - // Here, we are passing the type `usize` as a - // placeholder value with the function - // `with_self_ty`, since there is no concrete type - // `Self` for a `dyn Trait` at this - // stage. Therefore when checking explicit - // predicates in `check_explicit_predicates` we - // need to ignore checking the explicit_map for - // Self type. - let substs = ex_trait_ref - .with_self_ty(tcx, tcx.types.usize) - .skip_binder() - .substs; - check_explicit_predicates( - tcx, - &ex_trait_ref.skip_binder().def_id, - substs, - required_predicates, - explicit_map, - IgnoreSelfTy(true), - ); + if let Some(ex_trait_ref) = obj.principal() { + // Here, we are passing the type `usize` as a + // placeholder value with the function + // `with_self_ty`, since there is no concrete type + // `Self` for a `dyn Trait` at this + // stage. Therefore when checking explicit + // predicates in `check_explicit_predicates` we + // need to ignore checking the explicit_map for + // Self type. + let substs = ex_trait_ref + .with_self_ty(tcx, tcx.types.usize) + .skip_binder() + .substs; + check_explicit_predicates( + tcx, + &ex_trait_ref.skip_binder().def_id, + substs, + required_predicates, + explicit_map, + IgnoreSelfTy(true), + ); + } } ty::Projection(obj) => { diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs index 51d89688dc2..868c1132e44 100644 --- a/src/librustc_typeck/variance/constraints.rs +++ b/src/librustc_typeck/variance/constraints.rs @@ -301,11 +301,12 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { let contra = self.contravariant(variance); self.add_constraints_from_region(current, r, contra); - let poly_trait_ref = data - .principal() - .with_self_ty(self.tcx(), self.tcx().types.err); - self.add_constraints_from_trait_ref( - current, *poly_trait_ref.skip_binder(), variance); + if let Some(poly_trait_ref) = data.principal() { + let poly_trait_ref = + poly_trait_ref.with_self_ty(self.tcx(), self.tcx().types.err); + self.add_constraints_from_trait_ref( + current, *poly_trait_ref.skip_binder(), variance); + } for projection in data.projection_bounds() { self.add_constraints_from_ty( |
