about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorAriel Ben-Yehuda <ariel.byd@gmail.com>2018-12-04 13:28:06 +0200
committerAriel Ben-Yehuda <ariel.byd@gmail.com>2019-01-04 00:34:52 +0200
commit3aa1503a61d03834643a39f3e4c9de6721c31bdb (patch)
treead29fd4d3b5ad4854523a501fa94568e3536b524 /src
parentc0bbc3927e28c22edefe6a1353b5ecc95ea9a104 (diff)
downloadrust-3aa1503a61d03834643a39f3e4c9de6721c31bdb.tar.gz
rust-3aa1503a61d03834643a39f3e4c9de6721c31bdb.zip
add support for principal-less trait object types
should be a pure refactoring.
Diffstat (limited to 'src')
-rw-r--r--src/librustc/traits/coherence.rs8
-rw-r--r--src/librustc/traits/select.rs21
-rw-r--r--src/librustc/ty/error.rs6
-rw-r--r--src/librustc/ty/fast_reject.rs12
-rw-r--r--src/librustc/ty/item_path.rs2
-rw-r--r--src/librustc/ty/sty.rs21
-rw-r--r--src/librustc/ty/wf.rs2
-rw-r--r--src/librustc/util/ppaux.rs22
-rw-r--r--src/librustc_codegen_llvm/context.rs5
-rw-r--r--src/librustc_codegen_llvm/debuginfo/metadata.rs3
-rw-r--r--src/librustc_codegen_llvm/debuginfo/type_names.rs16
-rw-r--r--src/librustc_codegen_ssa/meth.rs13
-rw-r--r--src/librustc_codegen_ssa/traits/misc.rs2
-rw-r--r--src/librustc_mir/interpret/eval_context.rs2
-rw-r--r--src/librustc_mir/interpret/traits.rs13
-rw-r--r--src/librustc_mir/monomorphize/collector.rs23
-rw-r--r--src/librustc_mir/monomorphize/item.rs17
-rw-r--r--src/librustc_typeck/check/cast.rs4
-rw-r--r--src/librustc_typeck/check/closure.rs4
-rw-r--r--src/librustc_typeck/check/method/confirm.rs6
-rw-r--r--src/librustc_typeck/check/method/probe.rs33
-rw-r--r--src/librustc_typeck/check/method/suggest.rs3
-rw-r--r--src/librustc_typeck/coherence/inherent_impls.rs4
-rw-r--r--src/librustc_typeck/coherence/mod.rs39
-rw-r--r--src/librustc_typeck/outlives/implicit_infer.rs43
-rw-r--r--src/librustc_typeck/variance/constraints.rs11
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(