]> git.lizzy.rs Git - rust.git/commitdiff
Refactor TyTrait to contain a interned ExistentialPredicate slice.
authorMark-Simulacrum <mark.simulacrum@gmail.com>
Wed, 16 Nov 2016 16:21:49 +0000 (09:21 -0700)
committerMark-Simulacrum <mark.simulacrum@gmail.com>
Tue, 29 Nov 2016 01:09:13 +0000 (18:09 -0700)
Renames TyTrait to TyDynamic.

59 files changed:
mk/crates.mk
src/librustc/infer/freshen.rs
src/librustc/traits/coherence.rs
src/librustc/traits/error_reporting.rs
src/librustc/traits/fulfill.rs
src/librustc/traits/mod.rs
src/librustc/traits/project.rs
src/librustc/traits/select.rs
src/librustc/ty/contents.rs
src/librustc/ty/context.rs
src/librustc/ty/error.rs
src/librustc/ty/fast_reject.rs
src/librustc/ty/flags.rs
src/librustc/ty/item_path.rs
src/librustc/ty/layout.rs
src/librustc/ty/mod.rs
src/librustc/ty/outlives.rs
src/librustc/ty/relate.rs
src/librustc/ty/structural_impls.rs
src/librustc/ty/sty.rs
src/librustc/ty/util.rs
src/librustc/ty/walk.rs
src/librustc/ty/wf.rs
src/librustc/util/ppaux.rs
src/librustc_lint/types.rs
src/librustc_metadata/decoder.rs
src/librustc_trans/base.rs
src/librustc_trans/collector.rs
src/librustc_trans/context.rs
src/librustc_trans/debuginfo/metadata.rs
src/librustc_trans/debuginfo/type_names.rs
src/librustc_trans/glue.rs
src/librustc_trans/meth.rs
src/librustc_trans/trans_item.rs
src/librustc_trans/type_of.rs
src/librustc_typeck/astconv.rs
src/librustc_typeck/check/_match.rs
src/librustc_typeck/check/cast.rs
src/librustc_typeck/check/closure.rs
src/librustc_typeck/check/dropck.rs
src/librustc_typeck/check/method/confirm.rs
src/librustc_typeck/check/method/probe.rs
src/librustc_typeck/check/method/suggest.rs
src/librustc_typeck/check/mod.rs
src/librustc_typeck/check/regionck.rs
src/librustc_typeck/check/wfcheck.rs
src/librustc_typeck/coherence/mod.rs
src/librustc_typeck/coherence/orphan.rs
src/librustc_typeck/coherence/overlap.rs
src/librustc_typeck/collect.rs
src/librustc_typeck/diagnostics.rs
src/librustc_typeck/variance/constraints.rs
src/librustdoc/clean/mod.rs
src/test/compile-fail/E0225.rs
src/test/compile-fail/bad-sized.rs
src/test/compile-fail/issue-22560.rs
src/test/compile-fail/issue-32963.rs
src/test/compile-fail/trait-bounds-cant-coerce.rs
src/test/run-pass/auxiliary/issue13507.rs

index 7ae5846c54b9965b8f26d6db7eca6d26bd0d8cdf..cf985a0d980b4a640e9d3018cf1740cc4ad2a447 100644 (file)
@@ -140,7 +140,7 @@ DEPS_rustc_trans := arena flate getopts graphviz libc rustc rustc_back \
 DEPS_rustc_incremental := rustc syntax_pos serialize rustc_data_structures
 DEPS_rustc_save_analysis := rustc log syntax syntax_pos serialize
 DEPS_rustc_typeck := rustc syntax syntax_pos rustc_platform_intrinsics rustc_const_math \
-                     rustc_const_eval rustc_errors
+                     rustc_const_eval rustc_errors rustc_data_structures
 
 DEPS_rustdoc := rustc rustc_driver native:hoedown serialize getopts test \
                 rustc_lint rustc_const_eval syntax_pos rustc_data_structures
index 30e18a4c569b2fa7093c9b53b66aeb7c8cea8e81..19183892e4b0c16cb68629d14b3ad7212341e9d6 100644 (file)
@@ -165,7 +165,7 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
             ty::TyRef(..) |
             ty::TyFnDef(..) |
             ty::TyFnPtr(_) |
-            ty::TyTrait(..) |
+            ty::TyDynamic(..) |
             ty::TyClosure(..) |
             ty::TyNever |
             ty::TyTuple(..) |
index d4e217fb710cc06caae5426700ff72de01b4fe2e..58cb52e897786a5687a0fe6eb13ea2f1bfa1cd1a 100644 (file)
@@ -227,7 +227,7 @@ fn fundamental_ty(tcx: TyCtxt, ty: Ty) -> bool {
     match ty.sty {
         ty::TyBox(..) | ty::TyRef(..) => true,
         ty::TyAdt(def, _) => def.is_fundamental(),
-        ty::TyTrait(ref data) => {
+        ty::TyDynamic(ref data, ..) => {
             data.principal().map_or(false, |p| tcx.has_attr(p.def_id(), "fundamental"))
         }
         _ => false
@@ -270,7 +270,7 @@ fn ty_is_local_constructor(tcx: TyCtxt, ty: Ty, infer_is_local: InferIsLocal)->
             krate == Some(LOCAL_CRATE)
         }
 
-        ty::TyTrait(ref tt) => {
+        ty::TyDynamic(ref tt, ..) => {
             tt.principal().map_or(false, |p| p.def_id().is_local())
         }
 
index 4ac4c31386e716be808d108ec2757d9c508294e4..2e8e45468ddcb2199f0cb417ee8ba45ff80db168 100644 (file)
@@ -156,7 +156,7 @@ fn type_category<'tcx>(t: Ty<'tcx>) -> Option<u32> {
                 ty::TyBox(..) | ty::TyRef(..) | ty::TyRawPtr(..) => Some(5),
                 ty::TyArray(..) | ty::TySlice(..) => Some(6),
                 ty::TyFnDef(..) | ty::TyFnPtr(..) => Some(7),
-                ty::TyTrait(..) => Some(8),
+                ty::TyDynamic(..) => Some(8),
                 ty::TyClosure(..) => Some(9),
                 ty::TyTuple(..) => Some(10),
                 ty::TyProjection(..) => Some(11),
index 9ff4048f73e77aba27596191205c7b5f297c7530..23c28037a3c2d7b629f211c195446299032a6e0d 100644 (file)
@@ -231,10 +231,10 @@ pub fn normalize_projection_type(&mut self,
     }
 
     pub fn register_bound(&mut self,
-                                  infcx: &InferCtxt<'a, 'gcx, 'tcx>,
-                                  ty: Ty<'tcx>,
-                                  def_id: DefId,
-                                  cause: ObligationCause<'tcx>)
+                          infcx: &InferCtxt<'a, 'gcx, 'tcx>,
+                          ty: Ty<'tcx>,
+                          def_id: DefId,
+                          cause: ObligationCause<'tcx>)
     {
         let trait_ref = ty::TraitRef {
             def_id: def_id,
index bdd0ee75eb195828a4001cddd13018a2b9962ff2..5c5bf130c3ba401ee28b00499fddca56a754429d 100644 (file)
@@ -366,10 +366,10 @@ pub fn predicates_for_generics<'tcx>(cause: ObligationCause<'tcx>,
 /// conservative towards *no impl*, which is the opposite of the
 /// `evaluate` methods).
 pub fn type_known_to_meet_bound<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
-                                                        ty: Ty<'tcx>,
-                                                        def_id: DefId,
-                                                        span: Span)
-                                                        -> bool
+                                                ty: Ty<'tcx>,
+                                                def_id: DefId,
+                                                span: Span)
+-> bool
 {
     debug!("type_known_to_meet_bound(ty={:?}, bound={:?})",
            ty,
index 76bead99343a7f01daa0b586ce348c2fcdcd7483..27b7adf0ef34a3887e7dc275fbfc29849ff7bc39 100644 (file)
@@ -1123,7 +1123,7 @@ fn confirm_object_candidate<'cx, 'gcx, 'tcx>(
     debug!("confirm_object_candidate(object_ty={:?})",
            object_ty);
     let data = match object_ty.sty {
-        ty::TyTrait(ref data) => data,
+        ty::TyDynamic(ref data, ..) => data,
         _ => {
             span_bug!(
                 obligation.cause.span,
@@ -1131,7 +1131,7 @@ fn confirm_object_candidate<'cx, 'gcx, 'tcx>(
                 object_ty)
         }
     };
-    let env_predicates = data.projection_bounds.iter().map(|p| {
+    let env_predicates = data.projection_bounds().map(|p| {
         p.with_self_ty(selcx.tcx(), object_ty).to_predicate()
     }).collect();
     let env_predicate = {
index 11b23d699de2f15cb3f01a3ffe77440af4661dde..a23b021cd4f4a67b1be16d2302608fdde85e38e9 100644 (file)
@@ -50,7 +50,6 @@
 use std::marker::PhantomData;
 use std::mem;
 use std::rc::Rc;
-use std::iter;
 use syntax::abi::Abi;
 use hir;
 use util::nodemap::FxHashMap;
@@ -1094,38 +1093,30 @@ fn assemble_candidates<'o>(&mut self,
         // and applicable impls. There is a certain set of precedence rules here.
 
         let def_id = obligation.predicate.def_id();
-        match obligation.predicate.def_id() {
-            _ if self.tcx().lang_items.copy_trait() == Some(def_id) => {
-                debug!("obligation self ty is {:?}",
-                       obligation.predicate.0.self_ty());
-
-                // User-defined copy impls are permitted, but only for
-                // structs and enums.
-                self.assemble_candidates_from_impls(obligation, &mut candidates)?;
-
-                // For other types, we'll use the builtin rules.
-                let copy_conditions = self.copy_conditions(obligation);
-                self.assemble_builtin_bound_candidates(copy_conditions, &mut candidates)?;
-            }
-            _ if self.tcx().lang_items.sized_trait() == Some(def_id) => {
-                // Sized is never implementable by end-users, it is
-                // always automatically computed.
-                let sized_conditions = self.sized_conditions(obligation);
-                self.assemble_builtin_bound_candidates(sized_conditions,
-                                                       &mut candidates)?;
-            }
-
-            _ if self.tcx().lang_items.unsize_trait() == Some(def_id) => {
-                self.assemble_candidates_for_unsizing(obligation, &mut candidates);
-            }
-
-            // For non-builtins and Send/Sync
-            _ => {
-                self.assemble_closure_candidates(obligation, &mut candidates)?;
-                self.assemble_fn_pointer_candidates(obligation, &mut candidates)?;
-                self.assemble_candidates_from_impls(obligation, &mut candidates)?;
-                self.assemble_candidates_from_object_ty(obligation, &mut candidates);
-            }
+        if self.tcx().lang_items.copy_trait() == Some(def_id) {
+            debug!("obligation self ty is {:?}",
+                   obligation.predicate.0.self_ty());
+
+            // User-defined copy impls are permitted, but only for
+            // structs and enums.
+            self.assemble_candidates_from_impls(obligation, &mut candidates)?;
+
+            // For other types, we'll use the builtin rules.
+            let copy_conditions = self.copy_conditions(obligation);
+            self.assemble_builtin_bound_candidates(copy_conditions, &mut candidates)?;
+        } else if self.tcx().lang_items.sized_trait() == Some(def_id) {
+            // Sized is never implementable by end-users, it is
+            // always automatically computed.
+            let sized_conditions = self.sized_conditions(obligation);
+            self.assemble_builtin_bound_candidates(sized_conditions,
+                                                   &mut candidates)?;
+         } else if self.tcx().lang_items.unsize_trait() == Some(def_id) {
+             self.assemble_candidates_for_unsizing(obligation, &mut candidates);
+         } else {
+             self.assemble_closure_candidates(obligation, &mut candidates)?;
+             self.assemble_fn_pointer_candidates(obligation, &mut candidates)?;
+             self.assemble_candidates_from_impls(obligation, &mut candidates)?;
+             self.assemble_candidates_from_object_ty(obligation, &mut candidates);
         }
 
         self.assemble_candidates_from_projected_tys(obligation, &mut candidates);
@@ -1446,7 +1437,7 @@ fn assemble_candidates_from_default_impls(&mut self,
 
         if self.tcx().trait_has_default_impl(def_id) {
             match self_ty.sty {
-                ty::TyTrait(..) => {
+                ty::TyDynamic(..) => {
                     // For object types, we don't know what the closed
                     // over types are. For most traits, this means we
                     // conservatively say nothing; a candidate may be
@@ -1516,7 +1507,7 @@ fn assemble_candidates_from_object_ty(&mut self,
             // any LBR.
             let self_ty = this.tcx().erase_late_bound_regions(&obligation.self_ty());
             let poly_trait_ref = match self_ty.sty {
-                ty::TyTrait(ref data) => {
+                ty::TyDynamic(ref data, ..) => {
                     if data.auto_traits().any(|did| did == obligation.predicate.def_id()) {
                         debug!("assemble_candidates_from_object_ty: matched builtin bound, \
                                     pushing candidate");
@@ -1525,7 +1516,7 @@ fn assemble_candidates_from_object_ty(&mut self,
                     }
 
                     match data.principal() {
-                        Some(ref p) => p.with_self_ty(this.tcx(), self_ty),
+                        Some(p) => p.with_self_ty(this.tcx(), self_ty),
                         None => return,
                     }
                 }
@@ -1598,7 +1589,7 @@ fn assemble_candidates_for_unsizing(&mut self,
 
         let may_apply = match (&source.sty, &target.sty) {
             // Trait+Kx+'a -> Trait+Ky+'b (upcasts).
-            (&ty::TyTrait(ref data_a), &ty::TyTrait(ref data_b)) => {
+            (&ty::TyDynamic(ref data_a, ..), &ty::TyDynamic(ref data_b, ..)) => {
                 // Upcasts permit two things:
                 //
                 // 1. Dropping builtin bounds, e.g. `Foo+Send` to `Foo`
@@ -1611,7 +1602,7 @@ fn assemble_candidates_for_unsizing(&mut self,
                 // We always upcast when we can because of reason
                 // #2 (region bounds).
                 match (data_a.principal(), data_b.principal()) {
-                    (Some(ref a), Some(ref b)) => a.def_id() == b.def_id() &&
+                    (Some(a), Some(b)) => a.def_id() == b.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)),
@@ -1620,7 +1611,7 @@ fn assemble_candidates_for_unsizing(&mut self,
             }
 
             // T -> Trait.
-            (_, &ty::TyTrait(_)) => true,
+            (_, &ty::TyDynamic(..)) => true,
 
             // Ambiguous handling is below T -> Trait, because inference
             // variables can still implement Unsize<Trait> and nested
@@ -1772,7 +1763,7 @@ fn sized_conditions(&mut self, obligation: &TraitObligation<'tcx>)
                 Where(ty::Binder(Vec::new()))
             }
 
-            ty::TyStr | ty::TySlice(_) | ty::TyTrait(..) => Never,
+            ty::TyStr | ty::TySlice(_) | ty::TyDynamic(..) => Never,
 
             ty::TyTuple(tys) => {
                 Where(ty::Binder(tys.last().into_iter().cloned().collect()))
@@ -1818,7 +1809,7 @@ fn copy_conditions(&mut self, obligation: &TraitObligation<'tcx>)
                 Where(ty::Binder(Vec::new()))
             }
 
-            ty::TyBox(_) | ty::TyTrait(..) | ty::TyStr | ty::TySlice(..) |
+            ty::TyBox(_) | ty::TyDynamic(..) | ty::TyStr | ty::TySlice(..) |
             ty::TyClosure(..) |
             ty::TyRef(_, ty::TypeAndMut { ty: _, mutbl: hir::MutMutable }) => {
                 Never
@@ -1883,7 +1874,7 @@ fn constituent_types_for_ty(&self, t: Ty<'tcx>) -> Vec<Ty<'tcx>> {
                 Vec::new()
             }
 
-            ty::TyTrait(..) |
+            ty::TyDynamic(..) |
             ty::TyParam(..) |
             ty::TyProjection(..) |
             ty::TyAnon(..) |
@@ -2169,11 +2160,11 @@ fn confirm_default_impl_object_candidate(&mut self,
         // OK to skip binder, it is reintroduced below
         let self_ty = self.infcx.shallow_resolve(obligation.predicate.skip_binder().self_ty());
         match self_ty.sty {
-            ty::TyTrait(ref data) => {
+            ty::TyDynamic(ref data, ..) => {
                 // OK to skip the binder, it is reintroduced below
                 let principal = data.principal().unwrap();
                 let input_types = principal.input_types();
-                let assoc_types = data.projection_bounds.iter()
+                let assoc_types = data.projection_bounds()
                                       .map(|pb| pb.skip_binder().ty);
                 let all_types: Vec<_> = input_types.chain(assoc_types)
                                                    .collect();
@@ -2305,7 +2296,7 @@ fn confirm_object_candidate(&mut self,
         // case that results. -nmatsakis
         let self_ty = self.infcx.shallow_resolve(*obligation.self_ty().skip_binder());
         let poly_trait_ref = match self_ty.sty {
-            ty::TyTrait(ref data) => {
+            ty::TyDynamic(ref data, ..) => {
                 data.principal().unwrap().with_self_ty(self.tcx(), self_ty)
             }
             _ => {
@@ -2474,14 +2465,16 @@ fn confirm_builtin_unsize_candidate(&mut self,
         let mut nested = vec![];
         match (&source.sty, &target.sty) {
             // Trait+Kx+'a -> Trait+Ky+'b (upcasts).
-            (&ty::TyTrait(ref data_a), &ty::TyTrait(ref data_b)) => {
+            (&ty::TyDynamic(ref data_a, r_a), &ty::TyDynamic(ref data_b, r_b)) => {
                 // See assemble_candidates_for_unsizing for more info.
-                let new_trait = tcx.mk_trait(ty::TraitObject::new(
-                    data_a.principal(),
-                    data_b.region_bound,
-                    data_b.auto_traits().collect(),
-                    data_a.projection_bounds.clone(),
-                ));
+                // Binders reintroduced below in call to mk_existential_predicates.
+                let principal = data_a.skip_binder().principal();
+                let iter = principal.into_iter().map(ty::ExistentialPredicate::Trait)
+                    .chain(data_a.skip_binder().projection_bounds()
+                           .map(|x| ty::ExistentialPredicate::Projection(x)))
+                    .chain(data_b.auto_traits().map(ty::ExistentialPredicate::AutoTrait));
+                let new_trait = tcx.mk_dynamic(
+                    ty::Binder(tcx.mk_existential_predicates(iter)), r_b);
                 let InferOk { obligations, .. } =
                     self.infcx.sub_types(false, &obligation.cause, new_trait, target)
                     .map_err(|_| Unimplemented)?;
@@ -2491,17 +2484,16 @@ fn confirm_builtin_unsize_candidate(&mut self,
                 let cause = ObligationCause::new(obligation.cause.span,
                                                  obligation.cause.body_id,
                                                  ObjectCastObligation(target));
-                let outlives = ty::OutlivesPredicate(data_a.region_bound,
-                                                     data_b.region_bound);
+                let outlives = ty::OutlivesPredicate(r_a, r_b);
                 nested.push(Obligation::with_depth(cause,
                                                    obligation.recursion_depth + 1,
                                                    ty::Binder(outlives).to_predicate()));
             }
 
             // T -> Trait.
-            (_, &ty::TyTrait(ref data)) => {
+            (_, &ty::TyDynamic(ref data, r)) => {
                 let mut object_dids =
-                    data.auto_traits().chain(data.principal().map(|ref p| p.def_id()));
+                    data.auto_traits().chain(data.principal().map(|p| p.def_id()));
                 if let Some(did) = object_dids.find(|did| {
                     !tcx.is_object_safe(*did)
                 }) {
@@ -2517,35 +2509,27 @@ fn confirm_builtin_unsize_candidate(&mut self,
                                                        predicate));
                 };
 
-                // Create the obligation for casting from T to Trait.
-                push(data.principal().unwrap().with_self_ty(tcx, source).to_predicate());
-
-                // We can only make objects from sized types.
-                let trait_refs = data.auto_traits()
-                    .chain(iter::once(
-                            tcx.lang_items.require(lang_items::SizedTraitLangItem)
-                            .unwrap_or_else(|msg| tcx.sess.fatal(&msg[..]))))
-                    .map(|did| ty::TraitRef {
-                        def_id: did,
-                        substs: tcx.mk_substs_trait(source, &[]),
-                    });
-
-                // Create additional obligations for all the various builtin
-                // bounds attached to the object cast. (In other words, if the
-                // object type is Foo+Send, this would create an obligation
-                // for the Send check.)
-                for tr in trait_refs {
-                    push(tr.to_predicate());
+                // Create obligations:
+                //  - Casting T to Trait
+                //  - For all the various builtin bounds attached to the object cast. (In other
+                //  words, if the object type is Foo+Send, this would create an obligation for the
+                //  Send check.)
+                //  - Projection predicates
+                for predicate in data.iter() {
+                    push(predicate.with_self_ty(tcx, source));
                 }
 
-                // Create obligations for the projection predicates.
-                for bound in &data.projection_bounds {
-                    push(bound.with_self_ty(tcx, source).to_predicate());
-                }
+                // We can only make objects from sized types.
+                let tr = ty::TraitRef {
+                    def_id: tcx.lang_items.require(lang_items::SizedTraitLangItem)
+                        .unwrap_or_else(|msg| tcx.sess.fatal(&msg[..])),
+                    substs: tcx.mk_substs_trait(source, &[]),
+                };
+                push(tr.to_predicate());
 
                 // If the type is `Foo+'a`, ensures that the type
                 // being cast to `Foo+'a` outlives `'a`:
-                let outlives = ty::OutlivesPredicate(source, data.region_bound);
+                let outlives = ty::OutlivesPredicate(source, r);
                 push(ty::Binder(outlives).to_predicate());
             }
 
index 9f80c2487fb2cca52651b36a9d0acad719e0f3ff..8c3cb7929488064cb3982949452d352e121388bd 100644 (file)
@@ -195,7 +195,7 @@ fn tc_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                     tc_ty(tcx, typ, cache).owned_pointer()
                 }
 
-                ty::TyTrait(_) => {
+                ty::TyDynamic(..) => {
                     TC::All - TC::InteriorParam
                 }
 
index ea81c85ba6a53f96fe1280de57646157bb560dbf..c23ee489a28f41128e6d5714e25085d944ac6f5b 100644 (file)
@@ -29,7 +29,7 @@
 use ty::{TyS, TypeVariants, Slice};
 use ty::{AdtKind, AdtDef, ClosureSubsts, Region};
 use hir::FreevarMap;
-use ty::{BareFnTy, InferTy, ParamTy, ProjectionTy, TraitObject};
+use ty::{BareFnTy, InferTy, ParamTy, ProjectionTy, ExistentialPredicate};
 use ty::{TyVar, TyVid, IntVar, IntVid, FloatVar, FloatVid};
 use ty::TypeVariants::*;
 use ty::layout::{Layout, TargetDataLayout};
@@ -47,6 +47,7 @@
 use std::ops::Deref;
 use std::rc::Rc;
 use std::iter;
+use std::cmp::Ordering;
 use syntax::ast::{self, Name, NodeId};
 use syntax::attr;
 use syntax::symbol::{Symbol, keywords};
@@ -63,6 +64,7 @@ pub struct CtxtArenas<'tcx> {
     region: TypedArena<Region>,
     stability: TypedArena<attr::Stability>,
     layout: TypedArena<Layout>,
+    existential_predicates: TypedArena<ExistentialPredicate<'tcx>>,
 
     // references
     generics: TypedArena<ty::Generics<'tcx>>,
@@ -81,6 +83,7 @@ pub fn new() -> CtxtArenas<'tcx> {
             region: TypedArena::new(),
             stability: TypedArena::new(),
             layout: TypedArena::new(),
+            existential_predicates: TypedArena::new(),
 
             generics: TypedArena::new(),
             trait_def: TypedArena::new(),
@@ -103,6 +106,7 @@ pub struct CtxtInterners<'tcx> {
     region: RefCell<FxHashSet<Interned<'tcx, Region>>>,
     stability: RefCell<FxHashSet<&'tcx attr::Stability>>,
     layout: RefCell<FxHashSet<&'tcx Layout>>,
+    existential_predicates: RefCell<FxHashSet<Interned<'tcx, Slice<ExistentialPredicate<'tcx>>>>>,
 }
 
 impl<'gcx: 'tcx, 'tcx> CtxtInterners<'tcx> {
@@ -115,7 +119,8 @@ fn new(arenas: &'tcx CtxtArenas<'tcx>) -> CtxtInterners<'tcx> {
             bare_fn: RefCell::new(FxHashSet()),
             region: RefCell::new(FxHashSet()),
             stability: RefCell::new(FxHashSet()),
-            layout: RefCell::new(FxHashSet())
+            layout: RefCell::new(FxHashSet()),
+            existential_predicates: RefCell::new(FxHashSet()),
         }
     }
 
@@ -958,6 +963,27 @@ fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>)
     }
 }
 
+impl<'a, 'tcx> Lift<'tcx> for &'a Slice<ExistentialPredicate<'a>> {
+    type Lifted = &'tcx Slice<ExistentialPredicate<'tcx>>;
+    fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>)
+        -> Option<&'tcx Slice<ExistentialPredicate<'tcx>>> {
+        if self.is_empty() {
+            return Some(Slice::empty());
+        }
+        if let Some(&Interned(eps)) = tcx.interners.existential_predicates.borrow().get(&self[..]) {
+            if *self as *const _ == eps as *const _ {
+                return Some(eps);
+            }
+        }
+        // Also try in the global tcx if we're not that.
+        if !tcx.is_global() {
+            self.lift_to_tcx(tcx.global_tcx())
+        } else {
+            None
+        }
+    }
+}
+
 impl<'a, 'tcx> Lift<'tcx> for &'a BareFnTy<'a> {
     type Lifted = &'tcx BareFnTy<'tcx>;
     fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>)
@@ -1126,7 +1152,7 @@ pub fn print_debug_stats(self) {
         sty_debug_print!(
             self,
             TyAdt, TyBox, TyArray, TySlice, TyRawPtr, TyRef, TyFnDef, TyFnPtr,
-            TyTrait, TyClosure, TyTuple, TyParam, TyInfer, TyProjection, TyAnon);
+            TyDynamic, TyClosure, TyTuple, TyParam, TyInfer, TyProjection, TyAnon);
 
         println!("Substs interner: #{}", self.interners.substs.borrow().len());
         println!("BareFnTy interner: #{}", self.interners.bare_fn.borrow().len());
@@ -1200,6 +1226,13 @@ fn borrow<'a>(&'a self) -> &'a Region {
     }
 }
 
+impl<'tcx: 'lcx, 'lcx> Borrow<[ExistentialPredicate<'lcx>]>
+    for Interned<'tcx, Slice<ExistentialPredicate<'tcx>>> {
+    fn borrow<'a>(&'a self) -> &'a [ExistentialPredicate<'lcx>] {
+        &self.0[..]
+    }
+}
+
 macro_rules! intern_method {
     ($lt_tcx:tt, $name:ident: $method:ident($alloc:ty,
                                             $alloc_method:ident,
@@ -1297,6 +1330,7 @@ macro_rules! slice_interners {
 }
 
 slice_interners!(
+    existential_predicates: _intern_existential_predicates(ExistentialPredicate),
     type_list: _intern_type_list(Ty),
     substs: _intern_substs(Kind)
 );
@@ -1437,24 +1471,27 @@ pub fn mk_fn_ptr(self, fty: &'tcx BareFnTy<'tcx>) -> Ty<'tcx> {
         self.mk_ty(TyFnPtr(fty))
     }
 
-    pub fn mk_trait(self, mut obj: TraitObject<'tcx>) -> Ty<'tcx> {
-        obj.projection_bounds.sort_by_key(|b| b.sort_key(self));
-        self.mk_ty(TyTrait(box obj))
+    pub fn mk_dynamic(
+        self,
+        obj: ty::Binder<&'tcx Slice<ExistentialPredicate<'tcx>>>,
+        reg: &'tcx ty::Region
+    ) -> Ty<'tcx> {
+        self.mk_ty(TyDynamic(obj, reg))
     }
 
     pub fn mk_projection(self,
                          trait_ref: TraitRef<'tcx>,
                          item_name: Name)
-                         -> Ty<'tcx> {
-        // take a copy of substs so that we own the vectors inside
-        let inner = ProjectionTy { trait_ref: trait_ref, item_name: item_name };
-        self.mk_ty(TyProjection(inner))
-    }
+        -> Ty<'tcx> {
+            // take a copy of substs so that we own the vectors inside
+            let inner = ProjectionTy { trait_ref: trait_ref, item_name: item_name };
+            self.mk_ty(TyProjection(inner))
+        }
 
     pub fn mk_closure(self,
                       closure_id: DefId,
                       substs: &'tcx Substs<'tcx>)
-                      -> Ty<'tcx> {
+        -> Ty<'tcx> {
         self.mk_closure_from_closure_substs(closure_id, ClosureSubsts {
             substs: substs
         })
@@ -1501,6 +1538,13 @@ pub fn mk_anon(self, def_id: DefId, substs: &'tcx Substs<'tcx>) -> Ty<'tcx> {
         self.mk_ty(TyAnon(def_id, substs))
     }
 
+    pub fn intern_existential_predicates(self, eps: &[ExistentialPredicate<'tcx>])
+        -> &'tcx Slice<ExistentialPredicate<'tcx>> {
+        assert!(!eps.is_empty());
+        assert!(eps.windows(2).all(|w| w[0].cmp(self, &w[1]) != Ordering::Greater));
+        self._intern_existential_predicates(eps)
+    }
+
     pub fn intern_type_list(self, ts: &[Ty<'tcx>]) -> &'tcx Slice<Ty<'tcx>> {
         if ts.len() == 0 {
             Slice::empty()
@@ -1517,6 +1561,12 @@ pub fn intern_substs(self, ts: &[Kind<'tcx>]) -> &'tcx Slice<Kind<'tcx>> {
         }
     }
 
+    pub fn mk_existential_predicates<I: InternAs<[ExistentialPredicate<'tcx>],
+                                     &'tcx Slice<ExistentialPredicate<'tcx>>>>(self, iter: I)
+                                     -> I::Output {
+        iter.intern_with(|xs| self.intern_existential_predicates(xs))
+    }
+
     pub fn mk_type_list<I: InternAs<[Ty<'tcx>],
                         &'tcx Slice<Ty<'tcx>>>>(self, iter: I) -> I::Output {
         iter.intern_with(|xs| self.intern_type_list(xs))
index 8ef13e62901a6e2e28a7cc715f1951fd167fa91c..125ee0a02c814a7f77c67d76ac6654e8014a0362 100644 (file)
@@ -49,7 +49,8 @@ pub enum TypeError<'tcx> {
     CyclicTy,
     ProjectionNameMismatched(ExpectedFound<Name>),
     ProjectionBoundsLength(ExpectedFound<usize>),
-    TyParamDefaultMismatch(ExpectedFound<type_variable::Default<'tcx>>)
+    TyParamDefaultMismatch(ExpectedFound<type_variable::Default<'tcx>>),
+    ExistentialMismatch(ExpectedFound<&'tcx ty::Slice<ty::ExistentialPredicate<'tcx>>>),
 }
 
 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Debug, Copy)]
@@ -164,6 +165,10 @@ fn report_maybe_different(f: &mut fmt::Formatter,
                        values.expected.ty,
                        values.found.ty)
             }
+            ExistentialMismatch(ref values) => {
+                report_maybe_different(f, format!("trait `{}`", values.expected),
+                                       format!("trait `{}`", values.found))
+            }
         }
     }
 }
@@ -200,7 +205,7 @@ pub fn sort_string(&self, tcx: TyCtxt<'a, 'gcx, 'lcx>) -> String {
             }
             ty::TyFnDef(..) => format!("fn item"),
             ty::TyFnPtr(_) => "fn pointer".to_string(),
-            ty::TyTrait(ref inner) => {
+            ty::TyDynamic(ref inner, ..) => {
                 inner.principal().map_or_else(|| "trait".to_string(),
                     |p| format!("trait {}", tcx.item_path_str(p.def_id())))
             }
index 3eab06dc674bf8c2b92af3871a5fd9c91a5058d2..9791ccb101380716c1dc4d68f889c9803df5b7db 100644 (file)
@@ -59,7 +59,7 @@ pub fn simplify_type<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
         ty::TyStr => Some(StrSimplifiedType),
         ty::TyArray(..) | ty::TySlice(_) => Some(ArraySimplifiedType),
         ty::TyRawPtr(_) => Some(PtrSimplifiedType),
-        ty::TyTrait(ref trait_info) => {
+        ty::TyDynamic(ref trait_info, ..) => {
             trait_info.principal().map(|p| TraitSimplifiedType(p.def_id()))
         }
         ty::TyRef(_, mt) => {
index 026bf64533c882e3b70c7eea311f87257f8e72c3..2bcbccb7d0505933e55f6dddfe4ed61fd60a144f 100644 (file)
@@ -121,16 +121,21 @@ fn add_sty(&mut self, st: &ty::TypeVariants) {
                 self.add_substs(substs);
             }
 
-            &ty::TyTrait(ref obj) => {
+            &ty::TyDynamic(ref obj, r) => {
                 let mut computation = FlagComputation::new();
-                computation.add_substs(obj.principal().unwrap().skip_binder().substs);
-                for projection_bound in &obj.projection_bounds {
-                    let mut proj_computation = FlagComputation::new();
-                    proj_computation.add_existential_projection(&projection_bound.0);
-                    self.add_bound_computation(&proj_computation);
+                for predicate in obj.skip_binder().iter() {
+                    match *predicate {
+                        ty::ExistentialPredicate::Trait(tr) => computation.add_substs(tr.substs),
+                        ty::ExistentialPredicate::Projection(p) => {
+                            let mut proj_computation = FlagComputation::new();
+                            proj_computation.add_existential_projection(&p);
+                            self.add_bound_computation(&proj_computation);
+                        }
+                        ty::ExistentialPredicate::AutoTrait(_) => {}
+                    }
                 }
                 self.add_bound_computation(&computation);
-                self.add_region(obj.region_bound);
+                self.add_region(r);
             }
 
             &ty::TyBox(tt) | &ty::TyArray(tt, _) | &ty::TySlice(tt) => {
index d1e6f5b8cd12e5799b28633d28e671a356cb267b..440a3916786fa3224fb25ecf8bc6a002d6fa8c77 100644 (file)
@@ -316,7 +316,7 @@ pub fn characteristic_def_id_of_type(ty: Ty) -> Option<DefId> {
     match ty.sty {
         ty::TyAdt(adt_def, _) => Some(adt_def.did),
 
-        ty::TyTrait(ref data) => data.principal().map(|ref p| p.def_id()),
+        ty::TyDynamic(data, ..) => data.principal().map(|p| p.def_id()),
 
         ty::TyArray(subty, _) |
         ty::TySlice(subty) |
index bc3c5d6ed4e203d845ae3e6c3697d0a8394175ab..8646bccf1e9ed75d91856385a5d2b7e3865f0ffe 100644 (file)
@@ -924,7 +924,7 @@ pub fn compute_uncached(ty: Ty<'gcx>,
                         ty::TySlice(_) | ty::TyStr => {
                             Int(dl.ptr_sized_integer())
                         }
-                        ty::TyTrait(_) => Pointer,
+                        ty::TyDynamic(..) => Pointer,
                         _ => return Err(LayoutError::Unknown(unsized_part))
                     };
                     FatPointer { metadata: meta, non_zero: non_zero }
@@ -963,7 +963,7 @@ pub fn compute_uncached(ty: Ty<'gcx>,
                     non_zero: false
                 }
             }
-            ty::TyTrait(_) => {
+            ty::TyDynamic(..) => {
                 let mut unit = Struct::new(dl, false);
                 unit.sized = false;
                 Univariant { variant: unit, non_zero: false }
index 4544cda0ae9aef953785fe78367f4f9f674cc808..86fe14ea504b6e1682815679a9de95cce5c78856 100644 (file)
@@ -54,7 +54,7 @@
 
 pub use self::sty::{Binder, DebruijnIndex};
 pub use self::sty::{BareFnTy, FnSig, PolyFnSig};
-pub use self::sty::{ClosureTy, InferTy, ParamTy, ProjectionTy, TraitObject};
+pub use self::sty::{ClosureTy, InferTy, ParamTy, ProjectionTy, ExistentialPredicate};
 pub use self::sty::{ClosureSubsts, TypeAndMut};
 pub use self::sty::{TraitRef, TypeVariants, PolyTraitRef};
 pub use self::sty::{ExistentialTraitRef, PolyExistentialTraitRef};
@@ -1712,7 +1712,7 @@ fn sized_constraint_for_ty(
                 vec![]
             }
 
-            TyStr | TyTrait(..) | TySlice(_) | TyError => {
+            TyStr | TyDynamic(..) | TySlice(_) | TyError => {
                 // these are never sized - return the target type
                 vec![ty]
             }
index e3d13f593954f6ee8ba39356cecdda23e22d5e1c..eb384eec6a6f1e3b583fcf5e0f355a023f0c6158 100644 (file)
@@ -177,7 +177,7 @@ fn compute_components(&self, ty: Ty<'tcx>, out: &mut Vec<Component<'tcx>>) {
             ty::TyTuple(..) |       // ...
             ty::TyFnDef(..) |       // OutlivesFunction (*)
             ty::TyFnPtr(_) |        // OutlivesFunction (*)
-            ty::TyTrait(..) |       // OutlivesObject, OutlivesFragment (*)
+            ty::TyDynamic(..) |       // OutlivesObject, OutlivesFragment (*)
             ty::TyError => {
                 // (*) Bare functions and traits are both binders. In the
                 // RFC, this means we would add the bound regions to the
index 02704e94fee98241161c7df135481be357fa2eec..8cb1483107ff119d3e0b5018fef3db5157a5a49b 100644 (file)
@@ -398,26 +398,15 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R,
             Ok(tcx.mk_adt(a_def, substs))
         }
 
-        (&ty::TyTrait(ref a_obj), &ty::TyTrait(ref b_obj)) =>
-        {
-            let principal = match (a_obj.principal(), b_obj.principal()) {
-                (Some(ref a_p), Some(ref b_p)) => Some(relation.relate(a_p, b_p)?),
-                (None, None) => None,
-                _ => return Err(TypeError::Sorts(expected_found(relation, &a, &b))),
-            };
-            let r =
-                relation.with_cause(
-                    Cause::ExistentialRegionBound,
-                    |relation| relation.relate_with_variance(ty::Contravariant,
-                                                             &a_obj.region_bound,
-                                                             &b_obj.region_bound))?;
-            let nb = if !a_obj.auto_traits().eq(b_obj.auto_traits()) {
-                return Err(TypeError::Sorts(expected_found(relation, &a, &b)));
-            } else {
-                a_obj.auto_traits().collect()
-            };
-            let pb = relation.relate(&a_obj.projection_bounds, &b_obj.projection_bounds)?;
-            Ok(tcx.mk_trait(ty::TraitObject::new(principal, r, nb, pb)))
+        (&ty::TyDynamic(ref a_obj, ref a_region), &ty::TyDynamic(ref b_obj, ref b_region)) => {
+            let region_bound = relation.with_cause(Cause::ExistentialRegionBound,
+                                                       |relation| {
+                                                           relation.relate_with_variance(
+                                                               ty::Contravariant,
+                                                               a_region,
+                                                               b_region)
+                                                       })?;
+            Ok(tcx.mk_dynamic(relation.relate(a_obj, b_obj)?, region_bound))
         }
 
         (&ty::TyClosure(a_id, a_substs),
@@ -513,6 +502,31 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R,
     }
 }
 
+impl<'tcx> Relate<'tcx> for &'tcx ty::Slice<ty::ExistentialPredicate<'tcx>> {
+    fn relate<'a, 'gcx, R>(relation: &mut R,
+                           a: &Self,
+                           b: &Self)
+        -> RelateResult<'tcx, Self>
+            where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a {
+
+        if a.len() != b.len() {
+            return Err(TypeError::ExistentialMismatch(expected_found(relation, a, b)));
+        }
+
+        let tcx = relation.tcx();
+        let v = a.iter().zip(b.iter()).map(|(ep_a, ep_b)| {
+            use ty::ExistentialPredicate::*;
+            match (*ep_a, *ep_b) {
+                (Trait(ref a), Trait(ref b)) => Ok(Trait(relation.relate(a, b)?)),
+                (Projection(ref a), Projection(ref b)) => Ok(Projection(relation.relate(a, b)?)),
+                (AutoTrait(ref a), AutoTrait(ref b)) if a == b => Ok(AutoTrait(*a)),
+                _ => Err(TypeError::ExistentialMismatch(expected_found(relation, a, b)))
+            }
+        });
+        Ok(tcx.mk_existential_predicates(v)?)
+    }
+}
+
 impl<'tcx> Relate<'tcx> for ty::ClosureSubsts<'tcx> {
     fn relate<'a, 'gcx, R>(relation: &mut R,
                            a: &ty::ClosureSubsts<'tcx>,
index e890d750a7b50bb0ff8b2c4d2e398bd264946c41..88de3575274cc4a8ea22ea69e49f1e275c48238a 100644 (file)
@@ -324,6 +324,7 @@ fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lif
             TyParamDefaultMismatch(ref x) => {
                 return tcx.lift(x).map(TyParamDefaultMismatch)
             }
+            ExistentialMismatch(ref x) => return tcx.lift(x).map(ExistentialMismatch)
         })
     }
 }
@@ -426,20 +427,33 @@ fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
     }
 }
 
-impl<'tcx> TypeFoldable<'tcx> for ty::TraitObject<'tcx> {
+impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::Slice<ty::ExistentialPredicate<'tcx>> {
     fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
-        ty::TraitObject::new(
-            self.principal().map(|p| p.fold_with(folder)),
-            self.region_bound.fold_with(folder),
-            self.auto_traits().collect(),
-            self.projection_bounds.fold_with(folder),
-        )
+        let v = self.iter().map(|p| p.fold_with(folder)).collect::<AccumulateVec<[_; 8]>>();
+        folder.tcx().intern_existential_predicates(&v)
     }
 
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
-        self.principal().map(|p| p.visit_with(visitor)).unwrap_or(true) ||
-        self.region_bound.visit_with(visitor) ||
-        self.projection_bounds.visit_with(visitor)
+        self.iter().any(|p| p.visit_with(visitor))
+    }
+}
+
+impl<'tcx> TypeFoldable<'tcx> for ty::ExistentialPredicate<'tcx> {
+    fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self  {
+        use ty::ExistentialPredicate::*;
+        match *self {
+            Trait(ref tr) => Trait(tr.fold_with(folder)),
+            Projection(ref p) => Projection(p.fold_with(folder)),
+            AutoTrait(did) => AutoTrait(did),
+        }
+    }
+
+    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
+        match *self {
+            ty::ExistentialPredicate::Trait(ref tr) => tr.visit_with(visitor),
+            ty::ExistentialPredicate::Projection(ref p) => p.visit_with(visitor),
+            ty::ExistentialPredicate::AutoTrait(_) => false,
+        }
     }
 }
 
@@ -462,7 +476,8 @@ fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F)
             ty::TyArray(typ, sz) => ty::TyArray(typ.fold_with(folder), sz),
             ty::TySlice(typ) => ty::TySlice(typ.fold_with(folder)),
             ty::TyAdt(tid, substs) => ty::TyAdt(tid, substs.fold_with(folder)),
-            ty::TyTrait(ref trait_ty) => ty::TyTrait(trait_ty.fold_with(folder)),
+            ty::TyDynamic(ref trait_ty, ref region) =>
+                ty::TyDynamic(trait_ty.fold_with(folder), region.fold_with(folder)),
             ty::TyTuple(ts) => ty::TyTuple(ts.fold_with(folder)),
             ty::TyFnDef(def_id, substs, f) => {
                 ty::TyFnDef(def_id,
@@ -499,7 +514,8 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
             ty::TyArray(typ, _sz) => typ.visit_with(visitor),
             ty::TySlice(typ) => typ.visit_with(visitor),
             ty::TyAdt(_, substs) => substs.visit_with(visitor),
-            ty::TyTrait(ref trait_ty) => trait_ty.visit_with(visitor),
+            ty::TyDynamic(ref trait_ty, ref reg) =>
+                trait_ty.visit_with(visitor) || reg.visit_with(visitor),
             ty::TyTuple(ts) => ts.visit_with(visitor),
             ty::TyFnDef(_, substs, ref f) => {
                 substs.visit_with(visitor) || f.visit_with(visitor)
index e6411ca1e4f68297f763bf051a3c90de50eb1438..667db5b673054e437330923fb54077e4222af13f 100644 (file)
 use ty::subst::Substs;
 use ty::{self, AdtDef, TypeFlags, Ty, TyCtxt, TypeFoldable};
 use ty::{Slice, TyS};
+use ty::subst::Kind;
 
 use std::fmt;
+use std::iter;
+use std::cmp::Ordering;
 use syntax::abi;
 use syntax::ast::{self, Name, NodeId};
 use syntax::symbol::{keywords, InternedString};
@@ -144,7 +147,7 @@ pub enum TypeVariants<'tcx> {
     TyFnPtr(&'tcx BareFnTy<'tcx>),
 
     /// A trait, defined with `trait`.
-    TyTrait(Box<TraitObject<'tcx>>),
+    TyDynamic(Binder<&'tcx Slice<ExistentialPredicate<'tcx>>>, &'tcx ty::Region),
 
     /// The anonymous type of a closure. Used to represent the type of
     /// `|a| a`.
@@ -272,32 +275,103 @@ impl Iterator<Item=Ty<'tcx>> + 'tcx
     }
 }
 
-#[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
-pub struct TraitObject<'tcx> {
-    principal: Option<PolyExistentialTraitRef<'tcx>>,
-    pub region_bound: &'tcx ty::Region,
-    auto_traits: Vec<DefId>,
-    pub projection_bounds: Vec<PolyExistentialProjection<'tcx>>,
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
+pub enum ExistentialPredicate<'tcx> {
+    // e.g. Iterator
+    Trait(ExistentialTraitRef<'tcx>),
+    // e.g. Iterator::Item = T
+    Projection(ExistentialProjection<'tcx>),
+    // e.g. Send
+    AutoTrait(DefId),
 }
 
-impl<'tcx> TraitObject<'tcx> {
-    pub fn new(principal: Option<PolyExistentialTraitRef<'tcx>>, region_bound: &'tcx ty::Region,
-               auto_traits: Vec<DefId>, projection_bounds: Vec<PolyExistentialProjection<'tcx>>)
-        -> Self {
-        TraitObject {
-            principal: principal,
-            region_bound: region_bound,
-            auto_traits: auto_traits,
-            projection_bounds: projection_bounds,
+impl<'a, 'gcx, 'tcx> ExistentialPredicate<'tcx> {
+    pub fn cmp(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, other: &Self) -> Ordering {
+        use self::ExistentialPredicate::*;
+        match (*self, *other) {
+            (Trait(_), Trait(_)) => Ordering::Equal,
+            (Projection(ref a), Projection(ref b)) => a.sort_key(tcx).cmp(&b.sort_key(tcx)),
+            (AutoTrait(ref a), AutoTrait(ref b)) =>
+                tcx.lookup_trait_def(*a).def_path_hash.cmp(&tcx.lookup_trait_def(*b).def_path_hash),
+            (Trait(_), _) => Ordering::Less,
+            (Projection(_), Trait(_)) => Ordering::Greater,
+            (Projection(_), _) => Ordering::Less,
+            (AutoTrait(_), _) => Ordering::Greater,
+        }
+    }
+
+}
+
+impl<'a, 'gcx, 'tcx> Binder<ExistentialPredicate<'tcx>> {
+    pub fn with_self_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, self_ty: Ty<'tcx>)
+        -> ty::Predicate<'tcx> {
+        use ty::ToPredicate;
+        match *self.skip_binder() {
+            ExistentialPredicate::Trait(tr) => Binder(tr).with_self_ty(tcx, self_ty).to_predicate(),
+            ExistentialPredicate::Projection(p) =>
+                ty::Predicate::Projection(Binder(p.with_self_ty(tcx, self_ty))),
+            ExistentialPredicate::AutoTrait(did) => {
+                let trait_ref = Binder(ty::TraitRef {
+                    def_id: did,
+                    substs: tcx.mk_substs_trait(self_ty, &[]),
+                });
+                trait_ref.to_predicate()
+            }
+        }
+    }
+}
+
+impl<'tcx> serialize::UseSpecializedDecodable for &'tcx Slice<ExistentialPredicate<'tcx>> {}
+
+impl<'tcx> Slice<ExistentialPredicate<'tcx>> {
+    pub fn principal(&self) -> Option<ExistentialTraitRef<'tcx>> {
+        match self.get(0) {
+            Some(&ExistentialPredicate::Trait(tr)) => Some(tr),
+            _ => None
         }
     }
 
+    #[inline]
+    pub fn projection_bounds<'a>(&'a self) ->
+        impl Iterator<Item=ExistentialProjection<'tcx>> + 'a {
+        self.iter().filter_map(|predicate| {
+            match *predicate {
+                ExistentialPredicate::Projection(p) => Some(p),
+                _ => None,
+            }
+        })
+    }
+
+    #[inline]
+    pub fn auto_traits<'a>(&'a self) -> impl Iterator<Item=DefId> + 'a {
+        self.iter().filter_map(|predicate| {
+            match *predicate {
+                ExistentialPredicate::AutoTrait(d) => Some(d),
+                _ => None
+            }
+        })
+    }
+}
+
+impl<'tcx> Binder<&'tcx Slice<ExistentialPredicate<'tcx>>> {
     pub fn principal(&self) -> Option<PolyExistentialTraitRef<'tcx>> {
-        self.principal
+        self.skip_binder().principal().map(Binder)
+    }
+
+    #[inline]
+    pub fn projection_bounds<'a>(&'a self) ->
+        impl Iterator<Item=PolyExistentialProjection<'tcx>> + 'a {
+        self.skip_binder().projection_bounds().map(Binder)
     }
 
+    #[inline]
     pub fn auto_traits<'a>(&'a self) -> impl Iterator<Item=DefId> + 'a {
-        self.auto_traits.iter().cloned()
+        self.skip_binder().auto_traits()
+    }
+
+    pub fn iter<'a>(&'a self)
+        -> impl DoubleEndedIterator<Item=Binder<ExistentialPredicate<'tcx>>> + 'tcx {
+        self.skip_binder().iter().cloned().map(Binder)
     }
 }
 
@@ -362,14 +436,30 @@ pub struct ExistentialTraitRef<'tcx> {
     pub substs: &'tcx Substs<'tcx>,
 }
 
-impl<'tcx> ExistentialTraitRef<'tcx> {
-    pub fn input_types<'a>(&'a self) -> impl DoubleEndedIterator<Item=Ty<'tcx>> + 'a {
+impl<'a, 'gcx, 'tcx> ExistentialTraitRef<'tcx> {
+    pub fn input_types<'b>(&'b self) -> impl DoubleEndedIterator<Item=Ty<'tcx>> + 'b {
         // Select only the "input types" from a trait-reference. For
         // now this is all the types that appear in the
         // trait-reference, but it should eventually exclude
         // associated types.
         self.substs.types()
     }
+
+    /// Object types don't have a self-type specified. Therefore, when
+    /// we convert the principal trait-ref into a normal trait-ref,
+    /// you must give *some* self-type. A common choice is `mk_err()`
+    /// or some skolemized type.
+    pub fn with_self_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, self_ty: Ty<'tcx>)
+        -> ty::TraitRef<'tcx>  {
+        // otherwise the escaping regions would be captured by the binder
+        assert!(!self_ty.has_escaping_regions());
+
+        ty::TraitRef {
+            def_id: self.def_id,
+            substs: tcx.mk_substs(
+                iter::once(Kind::from(self_ty)).chain(self.substs.iter().cloned()))
+        }
+    }
 }
 
 pub type PolyExistentialTraitRef<'tcx> = Binder<ExistentialTraitRef<'tcx>>;
@@ -731,61 +821,53 @@ pub struct ExistentialProjection<'tcx> {
 
 pub type PolyExistentialProjection<'tcx> = Binder<ExistentialProjection<'tcx>>;
 
-impl<'a, 'tcx, 'gcx> PolyExistentialProjection<'tcx> {
+impl<'a, 'tcx, 'gcx> ExistentialProjection<'tcx> {
     pub fn item_name(&self) -> Name {
-        self.0.item_name // safe to skip the binder to access a name
+        self.item_name // safe to skip the binder to access a name
     }
 
     pub fn sort_key(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> (u64, InternedString) {
         // We want something here that is stable across crate boundaries.
         // The DefId isn't but the `deterministic_hash` of the corresponding
         // DefPath is.
-        let trait_def = tcx.lookup_trait_def(self.0.trait_ref.def_id);
+        let trait_def = tcx.lookup_trait_def(self.trait_ref.def_id);
         let def_path_hash = trait_def.def_path_hash;
 
         // An `ast::Name` is also not stable (it's just an index into an
         // interning table), so map to the corresponding `InternedString`.
-        let item_name = self.0.item_name.as_str();
+        let item_name = self.item_name.as_str();
         (def_path_hash, item_name)
     }
 
     pub fn with_self_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
                         self_ty: Ty<'tcx>)
-                        -> ty::PolyProjectionPredicate<'tcx>
+                        -> ty::ProjectionPredicate<'tcx>
     {
         // otherwise the escaping regions would be captured by the binders
         assert!(!self_ty.has_escaping_regions());
 
-        let trait_ref = self.map_bound(|proj| proj.trait_ref);
-        self.map_bound(|proj| ty::ProjectionPredicate {
+        ty::ProjectionPredicate {
             projection_ty: ty::ProjectionTy {
-                trait_ref: trait_ref.with_self_ty(tcx, self_ty).0,
-                item_name: proj.item_name
+                trait_ref: self.trait_ref.with_self_ty(tcx, self_ty),
+                item_name: self.item_name
             },
-            ty: proj.ty
-        })
+            ty: self.ty
+        }
     }
 }
 
-impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
-    pub fn try_add_builtin_trait(self,
-                                 id: DefId,
-                                 auto_traits: &mut Vec<DefId>)
-                                 -> bool
-    {
-        //! Checks whether `id` refers to one of the builtin
-        //! traits, like `Send`, and adds it to `auto_traits` if so.
-        //! Returns true if `idf` refers to a builtin trait.
-
-        if Some(id) == self.lang_items.send_trait() ||
-            Some(id) == self.lang_items.sized_trait() ||
-            Some(id) == self.lang_items.copy_trait() ||
-            Some(id) == self.lang_items.sync_trait() {
-            auto_traits.push(id);
-            true
-        } else {
-            false
-        }
+impl<'a, 'tcx, 'gcx> PolyExistentialProjection<'tcx> {
+    pub fn item_name(&self) -> Name {
+        self.skip_binder().item_name()
+    }
+
+    pub fn sort_key(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> (u64, InternedString) {
+        self.skip_binder().sort_key(tcx)
+    }
+
+    pub fn with_self_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, self_ty: Ty<'tcx>)
+        -> ty::PolyProjectionPredicate<'tcx> {
+        self.map_bound(|p| p.with_self_ty(tcx, self_ty))
     }
 }
 
@@ -1045,7 +1127,7 @@ pub fn is_floating_point(&self) -> bool {
 
     pub fn is_trait(&self) -> bool {
         match self.sty {
-            TyTrait(..) => true,
+            TyDynamic(..) => true,
             _ => false
         }
     }
@@ -1178,7 +1260,7 @@ pub fn is_fn(&self) -> bool {
 
     pub fn ty_to_def_id(&self) -> Option<DefId> {
         match self.sty {
-            TyTrait(ref tt) => tt.principal().map(|p| p.def_id()),
+            TyDynamic(ref tt, ..) => tt.principal().map(|p| p.def_id()),
             TyAdt(def, _) => Some(def.did),
             TyClosure(id, _) => Some(id),
             _ => None
@@ -1200,9 +1282,11 @@ pub fn regions(&self) -> Vec<&'tcx ty::Region> {
             TyRef(region, _) => {
                 vec![region]
             }
-            TyTrait(ref obj) => {
-                let mut v = vec![obj.region_bound];
-                v.extend(obj.principal().unwrap().skip_binder().substs.regions());
+            TyDynamic(ref obj, region) => {
+                let mut v = vec![region];
+                if let Some(p) = obj.principal() {
+                    v.extend(p.skip_binder().substs.regions());
+                }
                 v
             }
             TyAdt(_, substs) | TyAnon(_, substs) => {
index 350426e7f3e827ccdf05d71574a8520c268535b7..ed9a327750a1604c3329a7e8863ba2f55e4e76fb 100644 (file)
@@ -532,8 +532,8 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool {
                 self.hash(f.sig.variadic());
                 self.hash(f.sig.inputs().skip_binder().len());
             }
-            TyTrait(ref data) => {
-                if let Some(ref p) = data.principal() {
+            TyDynamic(ref data, ..) => {
+                if let Some(p) = data.principal() {
                     self.def_id(p.def_id());
                 }
                 for d in data.auto_traits() {
@@ -641,7 +641,7 @@ pub fn moves_by_default(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 mutbl: hir::MutMutable, ..
             }) => Some(true),
 
-            TyArray(..) | TySlice(..) | TyTrait(..) | TyTuple(..) |
+            TyArray(..) | TySlice(..) | TyDynamic(..) | TyTuple(..) |
             TyClosure(..) | TyAdt(..) | TyAnon(..) |
             TyProjection(..) | TyParam(..) | TyInfer(..) | TyError => None
         }.unwrap_or_else(|| {
@@ -684,7 +684,7 @@ fn is_sized_uncached(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
             TyBox(..) | TyRawPtr(..) | TyRef(..) | TyFnDef(..) | TyFnPtr(_) |
             TyArray(..) | TyTuple(..) | TyClosure(..) | TyNever => Some(true),
 
-            TyStr | TyTrait(..) | TySlice(_) => Some(false),
+            TyStr | TyDynamic(..) | TySlice(_) => Some(false),
 
             TyAdt(..) | TyProjection(..) | TyParam(..) |
             TyInfer(..) | TyAnon(..) | TyError => None
index 02f55c6e340823d611c7394cda03f9eb4a110041..0848dcd2c8d213ec4f37bf3e930e2aee6b50cba4 100644 (file)
@@ -92,14 +92,19 @@ fn push_subtypes<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent_ty: Ty<'tcx>) {
         ty::TyProjection(ref data) => {
             stack.extend(data.trait_ref.substs.types().rev());
         }
-        ty::TyTrait(ref obj) => {
-            match obj.principal() {
-                Some(ref p) => stack.extend(p.input_types().rev()),
-                None => {}
-            }
-            stack.extend(obj.projection_bounds.iter().map(|pred| {
-                pred.0.ty
-            }).rev());
+        ty::TyDynamic(ref obj, ..) => {
+            stack.extend(obj.iter().rev().flat_map(|predicate| {
+                let (substs, opt_ty) = match *predicate.skip_binder() {
+                    ty::ExistentialPredicate::Trait(tr) => (tr.substs, None),
+                    ty::ExistentialPredicate::Projection(p) =>
+                        (p.trait_ref.substs, Some(p.ty)),
+                    ty::ExistentialPredicate::AutoTrait(_) =>
+                        // Empty iterator
+                        (ty::Substs::empty(), None),
+                };
+
+                substs.types().rev().chain(opt_ty)
+            }));
         }
         ty::TyAdt(_, substs) | ty::TyAnon(_, substs) => {
             stack.extend(substs.types().rev());
index d0bc2f079770588952d27b49cd6561769fd499dc..87a0339fff7d29d3fda7508aa88d1544fe8de121 100644 (file)
@@ -374,12 +374,12 @@ fn compute(&mut self, ty0: Ty<'tcx>) -> bool {
                     // of whatever returned this exact `impl Trait`.
                 }
 
-                ty::TyTrait(ref data) => {
+                ty::TyDynamic(data, r) => {
                     // WfObject
                     //
                     // Here, we defer WF checking due to higher-ranked
                     // regions. This is perhaps not ideal.
-                    self.from_object_ty(ty, data);
+                    self.from_object_ty(ty, data, r);
 
                     // FIXME(#27579) RFC also considers adding trait
                     // obligations that don't refer to Self and
@@ -388,7 +388,7 @@ fn compute(&mut self, ty0: Ty<'tcx>) -> bool {
                     let cause = self.cause(traits::MiscObligation);
 
                     let component_traits =
-                        data.auto_traits().chain(data.principal().map(|ref p| p.def_id()));
+                        data.auto_traits().chain(data.principal().map(|p| p.def_id()));
                     self.out.extend(
                         component_traits.map(|did| traits::Obligation::new(
                             cause.clone(),
@@ -450,7 +450,9 @@ fn nominal_obligations(&mut self,
                   .collect()
     }
 
-    fn from_object_ty(&mut self, ty: Ty<'tcx>, data: &ty::TraitObject<'tcx>) {
+    fn from_object_ty(&mut self, ty: Ty<'tcx>,
+                      data: ty::Binder<&'tcx ty::Slice<ty::ExistentialPredicate<'tcx>>>,
+                      region: &'tcx ty::Region) {
         // Imagine a type like this:
         //
         //     trait Foo { }
@@ -485,11 +487,9 @@ fn from_object_ty(&mut self, ty: Ty<'tcx>, data: &ty::TraitObject<'tcx>) {
 
         if !data.has_escaping_regions() {
             let implicit_bounds =
-                object_region_bounds(self.infcx.tcx,
-                                     data.principal().unwrap(),
-                                     data.auto_traits());
+                object_region_bounds(self.infcx.tcx, data);
 
-            let explicit_bound = data.region_bound;
+            let explicit_bound = region;
 
             for implicit_bound in implicit_bounds {
                 let cause = self.cause(traits::ObjectTypeBound(ty, explicit_bound));
@@ -506,26 +506,23 @@ fn from_object_ty(&mut self, ty: Ty<'tcx>, data: &ty::TraitObject<'tcx>) {
 /// they declare `trait SomeTrait : 'static`, for example, then
 /// `'static` would appear in the list. The hard work is done by
 /// `ty::required_region_bounds`, see that for more information.
-pub fn object_region_bounds<'a, 'gcx, 'tcx, I>(
+pub fn object_region_bounds<'a, 'gcx, 'tcx>(
     tcx: TyCtxt<'a, 'gcx, 'tcx>,
-    principal: ty::PolyExistentialTraitRef<'tcx>,
-    others: I)
+    existential_predicates: ty::Binder<&'tcx ty::Slice<ty::ExistentialPredicate<'tcx>>>)
     -> Vec<&'tcx ty::Region>
-    where I: Iterator<Item=DefId>
 {
     // Since we don't actually *know* the self type for an object,
     // this "open(err)" serves as a kind of dummy standin -- basically
     // a skolemized type.
     let open_ty = tcx.mk_infer(ty::FreshTy(0));
 
-    let mut predicates = others.map(|d| {
-        let trait_ref = ty::TraitRef {
-            def_id: d,
-            substs: tcx.mk_substs_trait(open_ty, &[])
-        };
-        trait_ref.to_predicate()
-    }).collect::<Vec<_>>();
-    predicates.push(principal.with_self_ty(tcx, open_ty).to_predicate());
+    let predicates = existential_predicates.iter().filter_map(|predicate| {
+        if let ty::ExistentialPredicate::Projection(_) = *predicate.skip_binder() {
+            None
+        } else {
+            Some(predicate.with_self_ty(tcx, open_ty))
+        }
+    }).collect();
 
     tcx.required_region_bounds(open_ty, predicates)
 }
index 242342a7f93d61fe731269190a60fd6c7ea26dd1..d839df80a12acc25d4fd9630c64e1b187276b4f8 100644 (file)
@@ -16,9 +16,8 @@
 use ty::{TyError, TyStr, TyArray, TySlice, TyFloat, TyFnDef, TyFnPtr};
 use ty::{TyParam, TyRawPtr, TyRef, TyNever, TyTuple};
 use ty::{TyClosure, TyProjection, TyAnon};
-use ty::{TyBox, TyTrait, TyInt, TyUint, TyInfer};
+use ty::{TyBox, TyDynamic, TyInt, TyUint, TyInfer};
 use ty::{self, Ty, TyCtxt, TypeFoldable};
-use ty::fold::{TypeFolder, TypeVisitor};
 
 use std::cell::Cell;
 use std::fmt;
@@ -298,58 +297,23 @@ fn in_binder<'a, 'gcx, 'tcx, T, U>(f: &mut fmt::Formatter,
     write!(f, "{}", new_value)
 }
 
-/// This curious type is here to help pretty-print trait objects. In
-/// a trait object, the projections are stored separately from the
-/// main trait bound, but in fact we want to package them together
-/// when printing out; they also have separate binders, but we want
-/// them to share a binder when we print them out. (And the binder
-/// pretty-printing logic is kind of clever and we don't want to
-/// reproduce it.) So we just repackage up the structure somewhat.
-///
-/// Right now there is only one trait in an object that can have
-/// projection bounds, so we just stuff them altogether. But in
-/// reality we should eventually sort things out better.
-#[derive(Clone, Debug)]
-struct TraitAndProjections<'tcx>(ty::TraitRef<'tcx>,
-                                 Vec<ty::ProjectionPredicate<'tcx>>);
-
-impl<'tcx> TypeFoldable<'tcx> for TraitAndProjections<'tcx> {
-    fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
-        TraitAndProjections(self.0.fold_with(folder), self.1.fold_with(folder))
-    }
-
-    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
-        self.0.visit_with(visitor) || self.1.visit_with(visitor)
-    }
-}
-
-impl<'tcx> fmt::Display for TraitAndProjections<'tcx> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        let TraitAndProjections(ref trait_ref, ref projection_bounds) = *self;
-        parameterized(f, trait_ref.substs,
-                      trait_ref.def_id,
-                      projection_bounds)
-    }
-}
-
-impl<'tcx> fmt::Display for ty::TraitObject<'tcx> {
+impl<'tcx> fmt::Display for &'tcx ty::Slice<ty::ExistentialPredicate<'tcx>> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         // Generate the main trait ref, including associated types.
         ty::tls::with(|tcx| {
             // Use a type that can't appear in defaults of type parameters.
             let dummy_self = tcx.mk_infer(ty::FreshTy(0));
 
-            let principal = self.principal().and_then(|ref p| tcx.lift(p))
-                               .expect("could not lift TraitRef for printing")
-                               .with_self_ty(tcx, dummy_self).0;
-            let projections = self.projection_bounds.iter().map(|p| {
-                tcx.lift(p)
-                    .expect("could not lift projection for printing")
-                    .with_self_ty(tcx, dummy_self).0
-            }).collect();
-
-            let tap = ty::Binder(TraitAndProjections(principal, projections));
-            in_binder(f, tcx, &ty::Binder(""), Some(tap))?;
+            if let Some(p) = self.principal() {
+                let principal = tcx.lift(&p).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<_>>();
+                parameterized(f, principal.substs, principal.def_id, &projections)?;
+            }
 
             // Builtin bounds.
             for did in self.auto_traits() {
@@ -359,16 +323,6 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
             Ok(())
         })?;
 
-        // FIXME: It'd be nice to compute from context when this bound
-        // is implied, but that's non-trivial -- we'd perhaps have to
-        // use thread-local data of some kind? There are also
-        // advantages to just showing the region, since it makes
-        // people aware that it's there.
-        let bound = self.region_bound.to_string();
-        if !bound.is_empty() {
-            write!(f, " + {}", bound)?;
-        }
-
         Ok(())
     }
 }
@@ -455,45 +409,6 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
     }
 }
 
-impl<'tcx> fmt::Debug for ty::TraitObject<'tcx> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        let mut empty = true;
-        let mut maybe_continue = |f: &mut fmt::Formatter| {
-            if empty {
-                empty = false;
-                Ok(())
-            } else {
-                write!(f, " + ")
-            }
-        };
-
-        maybe_continue(f)?;
-        write!(f, "{:?}", self.principal())?;
-
-        let region_str = format!("{:?}", self.region_bound);
-        if !region_str.is_empty() {
-            maybe_continue(f)?;
-            write!(f, "{}", region_str)?;
-        }
-
-        ty::tls::with(|tcx| {
-            for did in self.auto_traits() {
-                maybe_continue(f)?;
-                write!(f, " + {}", tcx.item_path_str(did))?;
-            }
-
-            Ok(())
-        })?;
-
-        for projection_bound in &self.projection_bounds {
-            maybe_continue(f)?;
-            write!(f, "{:?}", projection_bound)?;
-        }
-
-        Ok(())
-    }
-}
-
 impl<'tcx> fmt::Debug for ty::Predicate<'tcx> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match *self {
@@ -746,6 +661,12 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
     }
 }*/
 
+impl<'tcx> fmt::Display for ty::Binder<&'tcx ty::Slice<ty::ExistentialPredicate<'tcx>>> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        ty::tls::with(|tcx| in_binder(f, tcx, self, tcx.lift(self)))
+    }
+}
+
 impl<'tcx> fmt::Display for ty::Binder<ty::TraitRef<'tcx>> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         ty::tls::with(|tcx| in_binder(f, tcx, self, tcx.lift(self)))
@@ -865,7 +786,15 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                     }
                 })
             }
-            TyTrait(ref data) => write!(f, "{}", data),
+            TyDynamic(data, r) => {
+                write!(f, "{}", data)?;
+                let r = r.to_string();
+                if !r.is_empty() {
+                    write!(f, " + {}", r)
+                } else {
+                    Ok(())
+                }
+            }
             TyProjection(ref data) => write!(f, "{}", data),
             TyAnon(def_id, substs) => {
                 ty::tls::with(|tcx| {
index 8aa5e9e0a9460afb18d08531d44fc44577a0f1f7..6e9467d63dd1f84d43158ca7f4fc1f71a234ec36 100644 (file)
@@ -572,7 +572,7 @@ fn check_type_for_ffi(&self, cache: &mut FxHashSet<Ty<'tcx>>, ty: Ty<'tcx>) -> F
                            consider using a raw pointer instead")
             }
 
-            ty::TyTrait(..) => {
+            ty::TyDynamic(..) => {
                 FfiUnsafe("found Rust trait type in foreign module, \
                            consider using a raw pointer instead")
             }
index f59f2bcc074764c42bf61f55e5da3a6729239536..1e3d12c50a394ae4300978cdd7bdf6fc7776392d 100644 (file)
@@ -416,6 +416,15 @@ fn specialized_decode(&mut self) -> Result<ty::AdtDef<'tcx>, Self::Error> {
     }
 }
 
+impl<'a, 'tcx> SpecializedDecoder<&'tcx ty::Slice<ty::ExistentialPredicate<'tcx>>>
+    for DecodeContext<'a, 'tcx> {
+    fn specialized_decode(&mut self)
+        -> Result<&'tcx ty::Slice<ty::ExistentialPredicate<'tcx>>, Self::Error> {
+        Ok(self.tcx().mk_existential_predicates((0..self.read_usize()?)
+                                                .map(|_| Decodable::decode(self)))?)
+    }
+}
+
 impl<'a, 'tcx> MetadataBlob {
     pub fn is_compatible(&self) -> bool {
         self.raw_bytes().starts_with(METADATA_HEADER)
index a79f7e1733c26f703858303e52b12e71ad8c0f7a..f1126e6fd256c033d31f4c5256e48bc04c3b402f 100644 (file)
@@ -295,16 +295,14 @@ pub fn unsized_info<'ccx, 'tcx>(ccx: &CrateContext<'ccx, 'tcx>,
     let (source, target) = ccx.tcx().struct_lockstep_tails(source, target);
     match (&source.sty, &target.sty) {
         (&ty::TyArray(_, len), &ty::TySlice(_)) => C_uint(ccx, len),
-        (&ty::TyTrait(_), &ty::TyTrait(_)) => {
+        (&ty::TyDynamic(..), &ty::TyDynamic(..)) => {
             // For now, upcasts are limited to changes in marker
             // traits, and hence never actually require an actual
             // change to the vtable.
             old_info.expect("unsized_info: missing old info for trait upcast")
         }
-        (_, &ty::TyTrait(ref data)) => {
-            let trait_ref = data.principal().unwrap().with_self_ty(ccx.tcx(), source);
-            let trait_ref = ccx.tcx().erase_regions(&trait_ref);
-            consts::ptrcast(meth::get_vtable(ccx, trait_ref),
+        (_, &ty::TyDynamic(ref data, ..)) => {
+            consts::ptrcast(meth::get_vtable(ccx, source, data.principal()),
                             Type::vtable_ptr(ccx))
         }
         _ => bug!("unsized_info: invalid unsizing {:?} -> {:?}",
index ac8793c47e726edac4d56276859361ae778dd325..120e1a562ebea80be0bf135dd4bc07b9eaac2740 100644 (file)
@@ -763,7 +763,7 @@ fn find_drop_glue_neighbors<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
         ty::TyFnDef(..) |
         ty::TyFnPtr(_)  |
         ty::TyNever     |
-        ty::TyTrait(_)  => {
+        ty::TyDynamic(..)  => {
             /* nothing to do */
         }
         ty::TyAdt(adt_def, substs) => {
@@ -1003,18 +1003,20 @@ fn create_trans_items_for_vtable_methods<'a, 'tcx>(scx: &SharedCrateContext<'a,
                                                    output: &mut Vec<TransItem<'tcx>>) {
     assert!(!trait_ty.needs_subst() && !impl_ty.needs_subst());
 
-    if let ty::TyTrait(ref trait_ty) = trait_ty.sty {
-        let poly_trait_ref = trait_ty.principal().unwrap().with_self_ty(scx.tcx(), impl_ty);
-        let param_substs = scx.tcx().intern_substs(&[]);
-
-        // Walk all methods of the trait, including those of its supertraits
-        let methods = traits::get_vtable_methods(scx.tcx(), poly_trait_ref);
-        let methods = methods.filter_map(|method| method)
-            .filter_map(|(def_id, substs)| do_static_dispatch(scx, def_id, substs, param_substs))
-            .filter(|&(def_id, _)| can_have_local_instance(scx.tcx(), def_id))
-            .map(|(def_id, substs)| create_fn_trans_item(scx, def_id, substs, param_substs));
-        output.extend(methods);
-
+    if let ty::TyDynamic(ref trait_ty, ..) = trait_ty.sty {
+        if let Some(principal) = trait_ty.principal() {
+            let poly_trait_ref = principal.with_self_ty(scx.tcx(), impl_ty);
+            let param_substs = scx.tcx().intern_substs(&[]);
+
+            // Walk all methods of the trait, including those of its supertraits
+            let methods = traits::get_vtable_methods(scx.tcx(), poly_trait_ref);
+            let methods = methods.filter_map(|method| method)
+                .filter_map(|(def_id, substs)| do_static_dispatch(scx, def_id, substs,
+                                                                  param_substs))
+                .filter(|&(def_id, _)| can_have_local_instance(scx.tcx(), def_id))
+                .map(|(def_id, substs)| create_fn_trans_item(scx, def_id, substs, param_substs));
+            output.extend(methods);
+        }
         // Also add the destructor
         let dg_type = glue::get_drop_glue_type(scx.tcx(), impl_ty);
         output.push(TransItem::DropGlue(DropGlueKind::Ty(dg_type)));
index 771c5ef6d9d28c019b45bdecc93be31b3d8293ad..c0d7c64bd192c8713e422040360ea6a50387346d 100644 (file)
@@ -95,7 +95,8 @@ pub struct LocalCrateContext<'tcx> {
     /// Cache instances of monomorphic and polymorphic items
     instances: RefCell<FxHashMap<Instance<'tcx>, ValueRef>>,
     /// Cache generated vtables
-    vtables: RefCell<FxHashMap<ty::PolyTraitRef<'tcx>, ValueRef>>,
+    vtables: RefCell<FxHashMap<(ty::Ty<'tcx>,
+                                Option<ty::PolyExistentialTraitRef<'tcx>>), ValueRef>>,
     /// Cache of constant strings,
     const_cstr_cache: RefCell<FxHashMap<InternedString, ValueRef>>,
 
@@ -800,7 +801,9 @@ pub fn instances<'a>(&'a self) -> &'a RefCell<FxHashMap<Instance<'tcx>, ValueRef
         &self.local().instances
     }
 
-    pub fn vtables<'a>(&'a self) -> &'a RefCell<FxHashMap<ty::PolyTraitRef<'tcx>, ValueRef>> {
+    pub fn vtables<'a>(&'a self)
+        -> &'a RefCell<FxHashMap<(ty::Ty<'tcx>,
+                                  Option<ty::PolyExistentialTraitRef<'tcx>>), ValueRef>> {
         &self.local().vtables
     }
 
index 5af1b0faebc4a4d013becbe489a25ad77ca30e06..8bbe50af0651c6f4f7357266fb453a74f09ff784 100644 (file)
@@ -432,7 +432,7 @@ fn trait_pointer_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
     // But it does not describe the trait's methods.
 
     let containing_scope = match trait_type.sty {
-        ty::TyTrait(ref data) => if let Some(principal) = data.principal() {
+        ty::TyDynamic(ref data, ..) => if let Some(principal) = data.principal() {
             let def_id = principal.def_id();
             get_namespace_and_span_for_item(cx, def_id).0
         } else {
@@ -523,7 +523,7 @@ pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
         ty::TyStr => {
             fixed_vec_metadata(cx, unique_type_id, cx.tcx().types.i8, None, usage_site_span)
         }
-        ty::TyTrait(..) => {
+        ty::TyDynamic(..) => {
             MetadataCreationResult::new(
                         trait_pointer_metadata(cx, t, None, unique_type_id),
             false)
@@ -538,7 +538,7 @@ pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                 ty::TyStr => {
                     vec_slice_metadata(cx, t, cx.tcx().types.u8, unique_type_id, usage_site_span)
                 }
-                ty::TyTrait(..) => {
+                ty::TyDynamic(..) => {
                     MetadataCreationResult::new(
                         trait_pointer_metadata(cx, ty, Some(t), unique_type_id),
                         false)
index 1831125e8eb9ef51cce3ab7312a5a22c3c492b6d..80e6bd7aa29840528f16526205f4716a0d36cbad 100644 (file)
@@ -93,7 +93,7 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
             push_debuginfo_type_name(cx, inner_type, true, output);
             output.push(']');
         },
-        ty::TyTrait(ref trait_data) => {
+        ty::TyDynamic(ref trait_data, ..) => {
             if let Some(principal) = trait_data.principal() {
                 let principal = cx.tcx().erase_late_bound_regions_and_normalize(
                     &principal);
index d6d4d33923f1a91fb4529461eb54996c693bd2af..06d0b1e19828e4f912fdc0e4b6f780a996d5ec3e 100644 (file)
@@ -394,7 +394,7 @@ pub fn size_and_align_of_dst<'blk, 'tcx>(bcx: &BlockAndBuilder<'blk, 'tcx>,
 
             (size, align)
         }
-        ty::TyTrait(..) => {
+        ty::TyDynamic(..) => {
             // info points to the vtable and the second entry in the vtable is the
             // dynamic size of the object.
             let info = bcx.pointercast(info, Type::int(bcx.ccx()).ptr_to());
@@ -463,7 +463,7 @@ fn make_drop_glue<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                 trans_exchange_free_ty(bcx, llbox, content_ty, DebugLoc::None)
             }
         }
-        ty::TyTrait(..) => {
+        ty::TyDynamic(..) => {
             // No support in vtable for distinguishing destroying with
             // versus without calling Drop::drop. Assert caller is
             // okay with always calling the Drop impl, if any.
index 1e687f5ff6e3a51bc29e304e3d3838349a7c7291..aa9b900fa465396573edae7f1f02801a0de67667 100644 (file)
@@ -110,42 +110,48 @@ pub fn trans_object_shim<'a, 'tcx>(ccx: &'a CrateContext<'a, 'tcx>,
 /// making an object `Foo<Trait>` from a value of type `Foo<T>`, then
 /// `trait_ref` would map `T:Trait`.
 pub fn get_vtable<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
-                            trait_ref: ty::PolyTraitRef<'tcx>)
+                            ty: ty::Ty<'tcx>,
+                            trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>)
                             -> ValueRef
 {
     let tcx = ccx.tcx();
     let _icx = push_ctxt("meth::get_vtable");
 
-    debug!("get_vtable(trait_ref={:?})", trait_ref);
+    debug!("get_vtable(ty={:?}, trait_ref={:?})", ty, trait_ref);
 
     // Check the cache.
-    if let Some(&val) = ccx.vtables().borrow().get(&trait_ref) {
+    if let Some(&val) = ccx.vtables().borrow().get(&(ty, trait_ref)) {
         return val;
     }
 
     // Not in the cache. Build it.
     let nullptr = C_null(Type::nil(ccx).ptr_to());
-    let methods = traits::get_vtable_methods(tcx, trait_ref).map(|opt_mth| {
-        opt_mth.map_or(nullptr, |(def_id, substs)| {
-            Callee::def(ccx, def_id, substs).reify(ccx)
-        })
-    });
 
-    let size_ty = sizing_type_of(ccx, trait_ref.self_ty());
+    let size_ty = sizing_type_of(ccx, ty);
     let size = machine::llsize_of_alloc(ccx, size_ty);
-    let align = align_of(ccx, trait_ref.self_ty());
+    let align = align_of(ccx, ty);
 
-    let components: Vec<_> = [
+    let mut components: Vec<_> = [
         // Generate a destructor for the vtable.
-        glue::get_drop_glue(ccx, trait_ref.self_ty()),
+        glue::get_drop_glue(ccx, ty),
         C_uint(ccx, size),
         C_uint(ccx, align)
-    ].iter().cloned().chain(methods).collect();
+    ].iter().cloned().collect();
+
+    if let Some(trait_ref) = trait_ref {
+        let trait_ref = trait_ref.with_self_ty(tcx, ty);
+        let methods = traits::get_vtable_methods(tcx, trait_ref).map(|opt_mth| {
+            opt_mth.map_or(nullptr, |(def_id, substs)| {
+                Callee::def(ccx, def_id, substs).reify(ccx)
+            })
+        });
+        components.extend(methods);
+    }
 
     let vtable_const = C_struct(ccx, &components, false);
     let align = machine::llalign_of_pref(ccx, val_ty(vtable_const));
     let vtable = consts::addr_of(ccx, vtable_const, align, "vtable");
 
-    ccx.vtables().borrow_mut().insert(trait_ref, vtable);
+    ccx.vtables().borrow_mut().insert((ty, trait_ref), vtable);
     vtable
 }
index c46c6e6f769affc2e6ee67373abef00af28cabac..979c2206fc1dea788f993c889cff2242ce1c2ca8 100644 (file)
@@ -457,11 +457,11 @@ pub fn push_type_name(&self, t: Ty<'tcx>, output: &mut String) {
                 self.push_type_name(inner_type, output);
                 output.push(']');
             },
-            ty::TyTrait(ref trait_data) => {
+            ty::TyDynamic(ref trait_data, ..) => {
                 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,
+                        &trait_data.projection_bounds().collect::<Vec<_>>()[..],
                         output);
                 }
             },
index 16d4f97200cb2147ad07734f45ee6cfc266d4f52..22c405fe254a62c400d818d54e51de617f67c405 100644 (file)
@@ -95,7 +95,7 @@ pub fn sizing_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Typ
         ty::TyAnon(..) | ty::TyError => {
             bug!("fictitious type {:?} in sizing_type_of()", t)
         }
-        ty::TySlice(_) | ty::TyTrait(..) | ty::TyStr => bug!()
+        ty::TySlice(_) | ty::TyDynamic(..) | ty::TyStr => bug!()
     };
 
     debug!("--> mapped t={:?} to llsizingty={:?}", t, llsizingty);
@@ -148,7 +148,7 @@ fn unsized_info_ty<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -> Type
         ty::TyStr | ty::TyArray(..) | ty::TySlice(_) => {
             Type::uint_from_ty(ccx, ast::UintTy::Us)
         }
-        ty::TyTrait(_) => Type::vtable_ptr(ccx),
+        ty::TyDynamic(..) => Type::vtable_ptr(ccx),
         _ => bug!("Unexpected tail in unsized_info_ty: {:?} for ty={:?}",
                           unsized_part, ty)
     }
@@ -258,7 +258,7 @@ pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) ->
       // fat pointers is of the right type (e.g. for array accesses), even
       // when taking the address of an unsized field in a struct.
       ty::TySlice(ty) => in_memory_type_of(cx, ty),
-      ty::TyStr | ty::TyTrait(..) => Type::i8(cx),
+      ty::TyStr | ty::TyDynamic(..) => Type::i8(cx),
 
       ty::TyFnDef(..) => Type::nil(cx),
       ty::TyFnPtr(f) => {
index bffd85c57f705ab24a004498c91df38d1025e922..986d817a10cc3868212c273f294d3e15204947d3 100644 (file)
@@ -49,6 +49,7 @@
 //! an rptr (`&r.T`) use the region `r` that appears in the rptr.
 
 use rustc_const_eval::eval_length;
+use rustc_data_structures::accumulate_vec::AccumulateVec;
 use hir::{self, SelfKind};
 use hir::def::Def;
 use hir::def_id::DefId;
@@ -69,6 +70,7 @@
 use util::nodemap::{NodeMap, FxHashSet};
 
 use std::cell::RefCell;
+use std::iter;
 use syntax::{abi, ast};
 use syntax::feature_gate::{GateIssue, emit_feature_err};
 use syntax::symbol::{Symbol, keywords};
@@ -1052,8 +1054,8 @@ fn trait_path_to_object_type(&self,
             let b = &trait_bounds[0];
             let span = b.trait_ref.path.span;
             struct_span_err!(self.tcx().sess, span, E0225,
-                             "only the builtin traits can be used as closure or object bounds")
-                .span_label(span, &format!("non-builtin trait used as bounds"))
+                "only Send/Sync traits can be used as additional traits in a trait object")
+                .span_label(span, &format!("non-Send/Sync additional trait"))
                 .emit();
         }
 
@@ -1070,30 +1072,7 @@ fn trait_path_to_object_type(&self,
                     ty: b.ty
                 }
             })
-        }).collect();
-
-        let region_bound =
-            self.compute_object_lifetime_bound(span,
-                                               &region_bounds,
-                                               existential_principal,
-                                               &auto_traits);
-
-        let region_bound = match region_bound {
-            Some(r) => r,
-            None => {
-                tcx.mk_region(match rscope.object_lifetime_default(span) {
-                    Some(r) => r,
-                    None => {
-                        span_err!(self.tcx().sess, span, E0228,
-                                  "the lifetime bound for this object type cannot be deduced \
-                                   from context; please supply an explicit bound");
-                        ty::ReStatic
-                    }
-                })
-            }
-        };
-
-        debug!("region_bound: {:?}", region_bound);
+        });
 
         // ensure the super predicates and stop if we encountered an error
         if self.ensure_super_predicates(span, principal.def_id()).is_err() {
@@ -1135,12 +1114,37 @@ fn trait_path_to_object_type(&self,
                         .emit();
         }
 
-        let ty = tcx.mk_trait(ty::TraitObject::new(
-            Some(existential_principal),
-            region_bound,
-            auto_traits,
-            existential_projections
-        ));
+        let mut v =
+            iter::once(ty::ExistentialPredicate::Trait(*existential_principal.skip_binder()))
+            .chain(auto_traits.into_iter().map(ty::ExistentialPredicate::AutoTrait))
+            .chain(existential_projections
+                   .map(|x| ty::ExistentialPredicate::Projection(*x.skip_binder())))
+            .collect::<AccumulateVec<[_; 8]>>();
+        v.sort_by(|a, b| a.cmp(tcx, b));
+        let existential_predicates = ty::Binder(tcx.mk_existential_predicates(v.into_iter()));
+
+        let region_bound = self.compute_object_lifetime_bound(span,
+                                                              &region_bounds,
+                                                              existential_predicates);
+
+        let region_bound = match region_bound {
+            Some(r) => r,
+            None => {
+                tcx.mk_region(match rscope.object_lifetime_default(span) {
+                    Some(r) => r,
+                    None => {
+                        span_err!(self.tcx().sess, span, E0228,
+                                  "the lifetime bound for this object type cannot be deduced \
+                                   from context; please supply an explicit bound");
+                        ty::ReStatic
+                    }
+                })
+            }
+        };
+
+        debug!("region_bound: {:?}", region_bound);
+
+        let ty = tcx.mk_dynamic(existential_predicates, region_bound);
         debug!("trait_object_type: {:?}", ty);
         ty
     }
@@ -1922,38 +1926,36 @@ fn conv_object_ty_poly_trait_ref(&self,
     fn compute_object_lifetime_bound(&self,
         span: Span,
         explicit_region_bounds: &[&hir::Lifetime],
-        principal_trait_ref: ty::PolyExistentialTraitRef<'tcx>,
-        auto_traits: &[DefId])
+        existential_predicates: ty::Binder<&'tcx ty::Slice<ty::ExistentialPredicate<'tcx>>>)
         -> Option<&'tcx ty::Region> // if None, use the default
     {
         let tcx = self.tcx();
 
         debug!("compute_opt_region_bound(explicit_region_bounds={:?}, \
-               principal_trait_ref={:?}, auto_traits={:?})",
+               existential_predicates={:?})",
                explicit_region_bounds,
-               principal_trait_ref,
-               auto_traits);
+               existential_predicates);
 
         if explicit_region_bounds.len() > 1 {
             span_err!(tcx.sess, explicit_region_bounds[1].span, E0226,
                 "only a single explicit lifetime bound is permitted");
         }
 
-        if !explicit_region_bounds.is_empty() {
+        if let Some(&r) = explicit_region_bounds.get(0) {
             // Explicitly specified region bound. Use that.
-            let r = explicit_region_bounds[0];
             return Some(ast_region_to_region(tcx, r));
         }
 
-        if let Err(ErrorReported) =
-                self.ensure_super_predicates(span, principal_trait_ref.def_id()) {
-            return Some(tcx.mk_region(ty::ReStatic));
+        if let Some(principal) = existential_predicates.principal() {
+            if let Err(ErrorReported) = self.ensure_super_predicates(span, principal.def_id()) {
+                return Some(tcx.mk_region(ty::ReStatic));
+            }
         }
 
         // No explicit region bound specified. Therefore, examine trait
         // bounds and see if we can derive region bounds from those.
         let derived_region_bounds =
-            object_region_bounds(tcx, principal_trait_ref, auto_traits.into_iter().cloned());
+            object_region_bounds(tcx, existential_predicates);
 
         // If there are no derived region bounds, then report back that we
         // can find no region bound. The caller will use the default.
@@ -2000,7 +2002,11 @@ pub fn partition_bounds<'a, 'b, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
             hir::TraitTyParamBound(ref b, hir::TraitBoundModifier::None) => {
                 match b.trait_ref.path.def {
                     Def::Trait(trait_did) => {
-                        if tcx.try_add_builtin_trait(trait_did, &mut auto_traits) {
+                        // Checks whether `trait_did` refers to one of the builtin
+                        // traits, like `Send`, and adds it to `auto_traits` if so.
+                        if Some(trait_did) == tcx.lang_items.send_trait() ||
+                            Some(trait_did) == tcx.lang_items.sync_trait() {
+                            auto_traits.push(trait_did);
                             let segments = &b.trait_ref.path.segments;
                             let parameters = &segments[segments.len() - 1].parameters;
                             if !parameters.types().is_empty() {
@@ -2115,12 +2121,15 @@ pub fn predicates(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, param_ty: Ty<'tcx>)
     {
         let mut vec = Vec::new();
 
-        for trait_did in &self.auto_traits {
-           let trait_ref = ty::TraitRef {
-               def_id: *trait_did,
-               substs: tcx.mk_substs_trait(param_ty, &[]),
-           };
-           vec.push(trait_ref.to_predicate());
+        // If it could be sized, and is, add the sized predicate
+        if self.implicitly_sized {
+            if let Some(sized) = tcx.lang_items.sized_trait() {
+                let trait_ref = ty::TraitRef {
+                    def_id: sized,
+                    substs: tcx.mk_substs_trait(param_ty, &[])
+                };
+                vec.push(trait_ref.to_predicate());
+            }
         }
 
         for &region_bound in &self.region_bounds {
index 63e797a87ff2191fea50e7246cb2d83eea4cf9ab..6e2b42881a709622c876a403d315d7dca3d1df4b 100644 (file)
@@ -340,7 +340,7 @@ pub fn check_pat(&self, pat: &'gcx hir::Pat, expected: Ty<'tcx>) {
     pub fn check_dereferencable(&self, span: Span, expected: Ty<'tcx>, inner: &hir::Pat) -> bool {
         if let PatKind::Binding(..) = inner.node {
             if let Some(mt) = self.shallow_resolve(expected).builtin_deref(true, ty::NoPreference) {
-                if let ty::TyTrait(..) = mt.ty.sty {
+                if let ty::TyDynamic(..) = mt.ty.sty {
                     // This is "x = SomeTrait" being reduced from
                     // "let &x = &SomeTrait" or "let box x = Box<SomeTrait>", an error.
                     let type_str = self.ty_to_string(expected);
index 197e7793f4b2ad5f4d63aa0b8c783b37912b5a39..5f904f507e27270dbf9572ef3dad2c5df52589f7 100644 (file)
@@ -65,7 +65,7 @@ pub struct CastCheck<'tcx> {
 /// fat pointers if their unsize-infos have the same kind.
 #[derive(Copy, Clone, PartialEq, Eq)]
 enum UnsizeKind<'tcx> {
-    Vtable(DefId),
+    Vtable(Option<DefId>),
     Length,
     /// The unsize info of this projection
     OfProjection(&'tcx ty::ProjectionTy<'tcx>),
@@ -79,7 +79,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
     fn unsize_kind(&self, t: Ty<'tcx>) -> Option<UnsizeKind<'tcx>> {
         match t.sty {
             ty::TySlice(_) | ty::TyStr => Some(UnsizeKind::Length),
-            ty::TyTrait(ref tty) => Some(UnsizeKind::Vtable(tty.principal().unwrap().def_id())),
+            ty::TyDynamic(ref tty, ..) =>
+                Some(UnsizeKind::Vtable(tty.principal().map(|p| p.def_id()))),
             ty::TyAdt(def, substs) if def.is_struct() => {
                 // FIXME(arielb1): do some kind of normalization
                 match def.struct_variant().fields.last() {
@@ -130,7 +131,7 @@ pub fn new(fcx: &FnCtxt<'a, 'gcx, 'tcx>,
         // cases now. We do a more thorough check at the end, once
         // inference is more completely known.
         match cast_ty.sty {
-            ty::TyTrait(..) | ty::TySlice(..) => {
+            ty::TyDynamic(..) | ty::TySlice(..) => {
                 check.report_cast_to_unsized_type(fcx);
                 Err(ErrorReported)
             }
index be6d65bf511fdb29984c890f8bfca3998dfb4584..744d99fe60d17b1faae4c9b667fbfe9c1058a72e 100644 (file)
@@ -111,16 +111,15 @@ fn deduce_expectations_from_expected_type
                expected_ty);
 
         match expected_ty.sty {
-            ty::TyTrait(ref object_type) => {
-                let sig = object_type.projection_bounds
-                    .iter()
+            ty::TyDynamic(ref object_type, ..) => {
+                let sig = object_type.projection_bounds()
                     .filter_map(|pb| {
                         let pb = pb.with_self_ty(self.tcx, self.tcx.types.err);
                         self.deduce_sig_from_projection(&pb)
                     })
                     .next();
-                let kind =
-                    self.tcx.lang_items.fn_trait_kind(object_type.principal().unwrap().def_id());
+                let kind = object_type.principal()
+                    .and_then(|p| self.tcx.lang_items.fn_trait_kind(p.def_id()));
                 (sig, kind)
             }
             ty::TyInfer(ty::TyVar(vid)) => self.deduce_expectations_from_obligations(vid),
index 8868d1e54f4b9661362b845c5d769e4734b8de1e..a5446b0fbaa89edc025b8c1c279b3dd3cada64ea 100644 (file)
@@ -515,7 +515,7 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'b, 'gcx, 'tcx>(
         }
 
         // these are always dtorck
-        ty::TyTrait(..) | ty::TyProjection(_) | ty::TyAnon(..) => bug!(),
+        ty::TyDynamic(..) | ty::TyProjection(_) | ty::TyAnon(..) => bug!(),
     }
 }
 
@@ -564,7 +564,7 @@ fn has_dtor_of_interest<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
             let revised_ty = revise_self_ty(tcx, adt_def, impl_def_id, substs);
             return DropckKind::RevisedSelf(revised_ty);
         }
-        ty::TyTrait(..) | ty::TyProjection(..) | ty::TyAnon(..) => {
+        ty::TyDynamic(..) | ty::TyProjection(..) | ty::TyAnon(..) => {
             debug!("ty: {:?} isn't known, and therefore is a dropck type", ty);
             return DropckKind::BorrowedDataMustStrictlyOutliveSelf;
         },
index 4c19ea46e5a7f21a564a1a985e18105ad3a514c2..ff9eaa012ba41e3c37f1ed4652134de01c00becb 100644 (file)
@@ -255,7 +255,7 @@ fn extract_existential_trait_ref<R, F>(&mut self, self_ty: Ty<'tcx>, mut closure
             .autoderef(self.span, self_ty)
             .filter_map(|(ty, _)| {
                 match ty.sty {
-                    ty::TyTrait(ref data) => data.principal().map(|p| closure(self, ty, p)),
+                    ty::TyDynamic(ref data, ..) => data.principal().map(|p| closure(self, ty, p)),
                     _ => None,
                 }
             })
index b76d13125b474fff432c1302b10684a819e24f33..b0787d75c9cb4f903fa58a2794eddee5c6cb0db4 100644 (file)
@@ -295,9 +295,11 @@ fn assemble_probe(&mut self, self_ty: Ty<'tcx>) {
         debug!("assemble_probe: self_ty={:?}", self_ty);
 
         match self_ty.sty {
-            ty::TyTrait(box ref data) => {
-                self.assemble_inherent_candidates_from_object(self_ty, data.principal().unwrap());
-                self.assemble_inherent_impl_candidates_for_type(data.principal().unwrap().def_id());
+            ty::TyDynamic(ref data, ..) => {
+                if let Some(p) = data.principal() {
+                    self.assemble_inherent_candidates_from_object(self_ty, p);
+                    self.assemble_inherent_impl_candidates_for_type(p.def_id());
+                }
             }
             ty::TyAdt(def, _) => {
                 self.assemble_inherent_impl_candidates_for_type(def.did);
index 508b0e820cef1afd8eb3a61de240bcf6b2966378..9443e0a3586b016abf563a0161ae11437dd8264e 100644 (file)
@@ -379,8 +379,8 @@ fn is_local(ty: Ty) -> bool {
             match ty.sty {
                 ty::TyAdt(def, _) => def.did.is_local(),
 
-                ty::TyTrait(ref tr) => tr.principal().map(|p|
-                                                          p.def_id().is_local()).unwrap_or(false),
+                ty::TyDynamic(ref tr, ..) => tr.principal()
+                    .map_or(false, |p| p.def_id().is_local()),
 
                 ty::TyParam(_) => true,
 
index c921936800b38ab85b7fe379f97fe9eb737767b2..bad7b4d96cac670c38bb3c9a3e3894c78048b9a7 100644 (file)
@@ -269,7 +269,7 @@ fn adjust_for_branches(&self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) -> Expectation<'tcx>
     /// for examples of where this comes up,.
     fn rvalue_hint(fcx: &FnCtxt<'a, 'gcx, 'tcx>, ty: Ty<'tcx>) -> Expectation<'tcx> {
         match fcx.tcx.struct_tail(ty).sty {
-            ty::TySlice(_) | ty::TyStr | ty::TyTrait(..) => {
+            ty::TySlice(_) | ty::TyStr | ty::TyDynamic(..) => {
                 ExpectRvalueLikeUnsized(ty)
             }
             _ => ExpectHasType(ty)
index ca33682480c4c61c1667243b0b56d16bbf58f8bb..fb35cb8181cb3de6de0d3ce332e55f96e05ab9d5 100644 (file)
@@ -806,11 +806,10 @@ fn walk_cast(&mut self,
             }
 
             /*From:*/ (_,
-            /*To:  */  &ty::TyTrait(ref obj)) => {
+            /*To:  */  &ty::TyDynamic(.., r)) => {
                 // When T is existentially quantified as a trait
                 // `Foo+'to`, it must outlive the region bound `'to`.
-                self.type_must_outlive(infer::RelateObjectBound(cast_expr.span),
-                                       from_ty, obj.region_bound);
+                self.type_must_outlive(infer::RelateObjectBound(cast_expr.span), from_ty, r);
             }
 
             /*From:*/ (&ty::TyBox(from_referent_ty),
index 57859f9c84cb69fbab92f3739f6bc0f673b8bddb..f29965ee47c8f38c51da689b873d90e679300c8b 100644 (file)
@@ -118,15 +118,8 @@ fn check_item_well_formed(&mut self, item: &hir::Item) {
                 // FIXME(#27579) what amount of WF checking do we need for neg impls?
 
                 let trait_ref = ccx.tcx.impl_trait_ref(ccx.tcx.map.local_def_id(item.id)).unwrap();
-                ccx.tcx.populate_implementations_for_trait_if_necessary(trait_ref.def_id);
-                let sync_trait = ccx.tcx.lang_items.require(lang_items::SyncTraitLangItem)
-                    .unwrap_or_else(|msg| ccx.tcx.sess.fatal(&msg[..]));
-                let send_trait = ccx.tcx.lang_items.require(lang_items::SendTraitLangItem)
-                    .unwrap_or_else(|msg| ccx.tcx.sess.fatal(&msg[..]));
-                if trait_ref.def_id != sync_trait && trait_ref.def_id != send_trait {
-                    if !ccx.tcx.trait_has_default_impl(trait_ref.def_id) {
-                        error_192(ccx, item.span);
-                    }
+                if !ccx.tcx.trait_has_default_impl(trait_ref.def_id) {
+                    error_192(ccx, item.span);
                 }
             }
             hir::ItemFn(.., ref body) => {
index 0b6f2f554a17787ce6f574569ba2414d5d0378b3..30472f85db1207a9db955aecc7289cb3f4974420 100644 (file)
@@ -23,7 +23,7 @@
 use rustc::ty::ParameterEnvironment;
 use rustc::ty::{Ty, TyBool, TyChar, TyError};
 use rustc::ty::{TyParam, TyRawPtr};
-use rustc::ty::{TyRef, TyAdt, TyTrait, TyNever, TyTuple};
+use rustc::ty::{TyRef, TyAdt, TyDynamic, TyNever, TyTuple};
 use rustc::ty::{TyStr, TyArray, TySlice, TyFloat, TyInfer, TyInt};
 use rustc::ty::{TyUint, TyClosure, TyBox, TyFnDef, TyFnPtr};
 use rustc::ty::{TyProjection, TyAnon};
@@ -68,7 +68,7 @@ fn get_base_type_def_id(&self, span: Span, ty: Ty<'tcx>) -> Option<DefId> {
         match ty.sty {
             TyAdt(def, _) => Some(def.did),
 
-            TyTrait(ref t) => t.principal().map(|p| p.def_id()),
+            TyDynamic(ref t, ..) => t.principal().map(|p| p.def_id()),
 
             TyBox(_) => self.inference_context.tcx.lang_items.owned_box(),
 
index f949a8796c7e0de4c00976c4d58e979c2e25d484..f04442de09c307547d3d30f53417da51c2fcd030 100644 (file)
@@ -86,7 +86,7 @@ fn check_item(&self, item: &hir::Item) {
                     ty::TyAdt(def, _) => {
                         self.check_def_id(item, def.did);
                     }
-                    ty::TyTrait(ref data) if data.principal().is_some() => {
+                    ty::TyDynamic(ref data, ..) if data.principal().is_some() => {
                         self.check_def_id(item, data.principal().unwrap().def_id());
                     }
                     ty::TyBox(..) => {
index 5ae233f647939b675041470c7d2ef355616a7374..815811675a54bff05321ee3fef482003bb8bf6c7 100644 (file)
@@ -178,16 +178,13 @@ fn visit_item(&mut self, item: &'v hir::Item) {
                 }
 
                 // check for overlap with the automatic `impl Trait for Trait`
-                if let ty::TyTrait(ref data) = trait_ref.self_ty().sty {
+                if let ty::TyDynamic(ref data, ..) = trait_ref.self_ty().sty {
                     // This is something like impl Trait1 for Trait2. Illegal
                     // if Trait1 is a supertrait of Trait2 or Trait2 is not object safe.
 
-                    if data.principal().is_none() ||
-                        !self.tcx.is_object_safe(data.principal().unwrap().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`.
+                    if data.principal().map_or(true, |p| !self.tcx.is_object_safe(p.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(self.tcx,
index 0f8fe32c8982e73e5e98e2308b7bdde4c6a53234..2b69ac12a2c4d1f5f93a6e274d723e85290c37cf 100644 (file)
@@ -1617,12 +1617,11 @@ fn add_unsized_bound<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>,
                                        "default bound relaxed for a type parameter, but \
                                        this does nothing because the given bound is not \
                                        a default. Only `?Sized` is supported");
-                    tcx.try_add_builtin_trait(kind_id, bounds);
                 }
             }
         }
         _ if kind_id.is_ok() => {
-            tcx.try_add_builtin_trait(kind_id.unwrap(), bounds);
+            bounds.push(kind_id.unwrap());
         }
         // No lang item for Sized, so we can't add it as a bound.
         None => {}
index 04314045733ec8e37115d90976c50ebec3168feb..01e99a296e886bb49fb99e6cfe8f02527c768c55 100644 (file)
@@ -2778,8 +2778,8 @@ fn main() {
 }
 ```
 
-Builtin traits are an exception to this rule: it's possible to have bounds of
-one non-builtin type, plus any number of builtin types. For example, the
+Send and Sync are an exception to this rule: it's possible to have bounds of
+one non-builtin trait, plus either or both of Send and Sync. For example, the
 following compiles correctly:
 
 ```
index 076d024c1e1bb13774b5f472c1f6b1e24cde70d6..f34753c227d71c34d1625cceadcf31687e59d9f5 100644 (file)
@@ -371,16 +371,17 @@ fn add_constraints_from_ty(&mut self,
                                                  variance);
             }
 
-            ty::TyTrait(ref data) => {
+            ty::TyDynamic(ref data, r) => {
                 // The type `Foo<T+'a>` is contravariant w/r/t `'a`:
                 let contra = self.contravariant(variance);
-                self.add_constraints_from_region(generics, data.region_bound, contra);
+                self.add_constraints_from_region(generics, r, contra);
 
-                let poly_trait_ref = data.principal().unwrap().with_self_ty(self.tcx(),
-                    self.tcx().types.err);
-                self.add_constraints_from_trait_ref(generics, poly_trait_ref.0, variance);
+                if let Some(p) = data.principal() {
+                    let poly_trait_ref = p.with_self_ty(self.tcx(), self.tcx().types.err);
+                    self.add_constraints_from_trait_ref(generics, poly_trait_ref.0, variance);
+                }
 
-                for projection in &data.projection_bounds {
+                for projection in data.projection_bounds() {
                     self.add_constraints_from_ty(generics, projection.0.ty, self.invariant);
                 }
             }
index 9d98cdd3f03771d840041b873aff71e466a78376..b9ba7f732a68eaa9f26ce8482c00f775b18c12e7 100644 (file)
@@ -594,10 +594,10 @@ pub enum TyParamBound {
 
 impl TyParamBound {
     fn maybe_sized(cx: &DocContext) -> TyParamBound {
-        let did = cx.tcx().lang_items.require(lang_items::SizedTraitLangItem)
-            .unwrap_or_else(|msg| cx.tcx().sess.fatal(&msg[..]));
-        let empty = cx.tcx().intern_substs(&[]);
-        let path = external_path(cx, &cx.tcx().item_name(did).as_str(),
+        let did = cx.tcx.lang_items.require(lang_items::SizedTraitLangItem)
+            .unwrap_or_else(|msg| cx.tcx.sess.fatal(&msg[..]));
+        let empty = cx.tcx.intern_substs(&[]);
+        let path = external_path(cx, &cx.tcx.item_name(did).as_str(),
             Some(did), false, vec![], empty);
         inline::record_extern_fqn(cx, did, TypeKind::Trait);
         TraitBound(PolyTrait {
@@ -1855,23 +1855,16 @@ fn clean(&self, cx: &DocContext) -> Type {
                     is_generic: false,
                 }
             }
-            ty::TyTrait(ref obj) => {
+            ty::TyDynamic(ref obj, ref reg) => {
                 if let Some(principal) = obj.principal() {
                     let did = principal.def_id();
                     inline::record_extern_fqn(cx, did, TypeKind::Trait);
 
                     let mut typarams = vec![];
-                    obj.region_bound.clean(cx).map(|b| typarams.push(RegionBound(b)));
+                    reg.clean(cx).map(|b| typarams.push(RegionBound(b)));
                     for did in obj.auto_traits() {
-                        let tcx = match cx.tcx_opt() {
-                            Some(tcx) => tcx,
-                            None => {
-                                typarams.push(RegionBound(Lifetime::statik()));
-                                continue;
-                            }
-                        };
-                        let empty = tcx.intern_substs(&[]);
-                        let path = external_path(cx, &tcx.item_name(did).as_str(),
+                        let empty = cx.tcx.intern_substs(&[]);
+                        let path = external_path(cx, &cx.tcx.item_name(did).as_str(),
                             Some(did), false, vec![], empty);
                         inline::record_extern_fqn(cx, did, TypeKind::Trait);
                         let bound = TraitBound(PolyTrait {
@@ -1887,14 +1880,14 @@ fn clean(&self, cx: &DocContext) -> Type {
                     }
 
                     let mut bindings = vec![];
-                    for &ty::Binder(ref pb) in &obj.projection_bounds {
+                    for ty::Binder(ref pb) in obj.projection_bounds() {
                         bindings.push(TypeBinding {
                             name: pb.item_name.clean(cx),
                             ty: pb.ty.clean(cx)
                         });
                     }
 
-                    let path = external_path(cx, &cx.tcx().item_name(did).as_str(), Some(did),
+                    let path = external_path(cx, &cx.tcx.item_name(did).as_str(), Some(did),
                         false, bindings, principal.0.substs);
                     ResolvedPath {
                         path: path,
index b013788ceff8506f95d52844f4f56c7279d76604..8c79c15e3de5bf8c053da24e8c126aa88c38c281 100644 (file)
@@ -10,6 +10,6 @@
 
 fn main() {
     let _: Box<std::io::Read + std::io::Write>;
-    //~^ ERROR only the builtin traits can be used as closure or object bounds [E0225]
-    //~| NOTE non-builtin trait used as bounds
+    //~^ ERROR only Send/Sync traits can be used as additional traits in a trait object [E0225]
+    //~| NOTE non-Send/Sync additional trait
 }
index 59a039057f37ffd77595454754d566d5576e9643..a2e2e5caafe6d0c408cd5a13d2ed7de8c43cb06d 100644 (file)
@@ -12,8 +12,7 @@ trait Trait {}
 
 pub fn main() {
     let x: Vec<Trait + Sized> = Vec::new();
-    //~^ ERROR the trait bound `Trait + std::marker::Sized: std::marker::Sized` is not satisfied
-    //~| ERROR the trait `std::marker::Sized` cannot be made into an object
-    //~| ERROR the trait bound `Trait + std::marker::Sized: std::marker::Sized` is not satisfied
-    //~| ERROR the trait `std::marker::Sized` cannot be made into an object
+    //~^ ERROR only Send/Sync traits can be used as additional traits in a trait object
+    //~| ERROR the trait bound `Trait: std::marker::Sized` is not satisfied
+    //~| ERROR the trait bound `Trait: std::marker::Sized` is not satisfied
 }
index 45b110bf5631ddcb251bae2f69f6bfd517be8997..2ad804fc8ced7e3c92964c1825f0553697c9521f 100644 (file)
@@ -20,6 +20,6 @@
             //~| NOTE missing associated type `Output` value
             Sub;
             //~^ ERROR E0225
-            //~| NOTE non-builtin trait used as bounds
+            //~| NOTE non-Send/Sync additional trait
 
 fn main() { }
index 14ab0dd5f631c84a1439c4bedcf6d923c8530272..f146cfbe68b9631f50540cd022caa2c588095100 100644 (file)
@@ -16,6 +16,6 @@ fn size_of_copy<T: Copy+?Sized>() -> usize { mem::size_of::<T>() }
 
 fn main() {
     size_of_copy::<Misc+Copy>();
-    //~^ ERROR the trait bound `Misc + std::marker::Copy: std::marker::Copy` is not satisfied
-    //~| ERROR the trait `std::marker::Copy` cannot be made into an object
+    //~^ ERROR only Send/Sync traits can be used as additional traits in a trait object
+    //~| ERROR the trait bound `Misc: std::marker::Copy` is not satisfied
 }
index 0bfa328751ac15a96cba3869df6bbe3bcc216e48..9f832c7b6e500f52e87a900e82b0c47cebb5c6f3 100644 (file)
@@ -24,7 +24,7 @@ fn d(x: Box<Foo>) {
     a(x); //~ ERROR mismatched types [E0308]
           //~| NOTE expected type `Box<Foo + std::marker::Send + 'static>`
           //~| NOTE found type `Box<Foo + 'static>`
-          //~| NOTE expected trait Foo, found a different trait Foo
+          //~| NOTE expected trait `Foo + std::marker::Send`, found trait `Foo`
 }
 
 fn main() { }
index ca1027b11adce26a27549f0eb4f975a79ae0041d..ba50aed42c36f64f1f21fe4709517dc5f45759a7 100644 (file)
@@ -70,7 +70,7 @@ pub fn type_ids() -> Vec<TypeId> {
     // Tests TyFnPtr
     pub type FooFnPtr = fn(u8) -> bool;
 
-    // Tests TyTrait
+    // Tests TyDynamic
     pub trait FooTrait {
         fn foo_method(&self) -> usize;
     }