diff --git a/mk/crates.mk b/mk/crates.mk index 7ae5846c54b99..cf985a0d980b4 100644 --- a/mk/crates.mk +++ b/mk/crates.mk @@ -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 diff --git a/src/librustc/infer/freshen.rs b/src/librustc/infer/freshen.rs index 30e18a4c569b2..19183892e4b0c 100644 --- a/src/librustc/infer/freshen.rs +++ b/src/librustc/infer/freshen.rs @@ -165,7 +165,7 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for TypeFreshener<'a, 'gcx, 'tcx> { ty::TyRef(..) | ty::TyFnDef(..) | ty::TyFnPtr(_) | - ty::TyTrait(..) | + ty::TyDynamic(..) | ty::TyClosure(..) | ty::TyNever | ty::TyTuple(..) | diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index 6ae104d79122b..72ef987aefd5c 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -24,6 +24,7 @@ use middle::free_region::FreeRegionMap; use middle::mem_categorization as mc; use middle::mem_categorization::McResult; use middle::region::CodeExtent; +use middle::lang_items; use mir::tcx::LvalueTy; use ty::subst::{Kind, Subst, Substs}; use ty::adjustment; @@ -1492,11 +1493,13 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } } + let copy_def_id = self.tcx.require_lang_item(lang_items::CopyTraitLangItem); + // this can get called from typeck (by euv), and moves_by_default // rightly refuses to work with inference variables, but // moves_by_default has a cache, which we want to use in other // cases. - !traits::type_known_to_meet_builtin_bound(self, ty, ty::BoundCopy, span) + !traits::type_known_to_meet_bound(self, ty, copy_def_id, span) } pub fn node_method_ty(&self, method_call: ty::MethodCall) diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 0942ce79a6b49..c0ea8d6b1e38b 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -32,7 +32,6 @@ #![feature(const_fn)] #![feature(core_intrinsics)] #![cfg_attr(stage0, feature(dotdot_in_tuple_patterns))] -#![feature(enumset)] #![cfg_attr(stage0, feature(item_like_imports))] #![feature(libc)] #![feature(nonzero)] diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index 5af9a2f02742e..1efc211b8c35b 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -90,31 +90,6 @@ impl LanguageItems { self.require(OwnedBoxLangItem) } - pub fn from_builtin_kind(&self, bound: ty::BuiltinBound) - -> Result - { - match bound { - ty::BoundSend => self.require(SendTraitLangItem), - ty::BoundSized => self.require(SizedTraitLangItem), - ty::BoundCopy => self.require(CopyTraitLangItem), - ty::BoundSync => self.require(SyncTraitLangItem), - } - } - - pub fn to_builtin_kind(&self, id: DefId) -> Option { - if Some(id) == self.send_trait() { - Some(ty::BoundSend) - } else if Some(id) == self.sized_trait() { - Some(ty::BoundSized) - } else if Some(id) == self.copy_trait() { - Some(ty::BoundCopy) - } else if Some(id) == self.sync_trait() { - Some(ty::BoundSync) - } else { - None - } - } - pub fn fn_trait_kind(&self, id: DefId) -> Option { let def_id_kinds = [ (self.fn_trait(), ty::ClosureKind::Fn), @@ -381,3 +356,11 @@ language_item_table! { DebugTraitLangItem, "debug_trait", debug_trait; } + +impl<'a, 'tcx, 'gcx> ty::TyCtxt<'a, 'tcx, 'gcx> { + pub fn require_lang_item(&self, lang_item: LangItem) -> DefId { + self.lang_items.require(lang_item).unwrap_or_else(|msg| { + self.sess.fatal(&msg) + }) + } +} diff --git a/src/librustc/traits/coherence.rs b/src/librustc/traits/coherence.rs index 2e06e83f8489c..58cb52e897786 100644 --- a/src/librustc/traits/coherence.rs +++ b/src/librustc/traits/coherence.rs @@ -225,14 +225,12 @@ fn ty_is_local(tcx: TyCtxt, ty: Ty, infer_is_local: InferIsLocal) -> bool { 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) => - tcx.has_attr(data.principal.def_id(), "fundamental"), - _ => - false + ty::TyBox(..) | ty::TyRef(..) => true, + ty::TyAdt(def, _) => def.is_fundamental(), + ty::TyDynamic(ref data, ..) => { + data.principal().map_or(false, |p| tcx.has_attr(p.def_id(), "fundamental")) + } + _ => false } } @@ -272,8 +270,8 @@ fn ty_is_local_constructor(tcx: TyCtxt, ty: Ty, infer_is_local: InferIsLocal)-> krate == Some(LOCAL_CRATE) } - ty::TyTrait(ref tt) => { - tt.principal.def_id().is_local() + ty::TyDynamic(ref tt, ..) => { + tt.principal().map_or(false, |p| p.def_id().is_local()) } ty::TyError => { diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 21009711cb18a..2e8e45468ddcb 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -156,7 +156,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { 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), @@ -905,16 +905,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { ObligationCauseCode::StructInitializerSized => { err.note("structs must have a statically known size to be initialized"); } - ObligationCauseCode::ClosureCapture(var_id, _, builtin_bound) => { - let def_id = tcx.lang_items.from_builtin_kind(builtin_bound).unwrap(); - let trait_name = tcx.item_path_str(def_id); - let name = tcx.local_var_name_str(var_id); - err.note( - &format!("the closure that captures `{}` requires that all captured variables \ - implement the trait `{}`", - name, - trait_name)); - } ObligationCauseCode::FieldSized => { err.note("only the last field of a struct may have a dynamically sized type"); } diff --git a/src/librustc/traits/fulfill.rs b/src/librustc/traits/fulfill.rs index f406580286da9..23c28037a3c2d 100644 --- a/src/librustc/traits/fulfill.rs +++ b/src/librustc/traits/fulfill.rs @@ -17,8 +17,8 @@ use rustc_data_structures::obligation_forest::{ForestObligation, ObligationProce use std::marker::PhantomData; use std::mem; use syntax::ast; -use util::common::ErrorReported; use util::nodemap::{FxHashSet, NodeMap}; +use hir::def_id::DefId; use super::CodeAmbiguity; use super::CodeProjectionError; @@ -230,18 +230,21 @@ impl<'a, 'gcx, 'tcx> FulfillmentContext<'tcx> { normalized.value } - pub fn register_builtin_bound(&mut self, - infcx: &InferCtxt<'a, 'gcx, 'tcx>, - ty: Ty<'tcx>, - builtin_bound: ty::BuiltinBound, - cause: ObligationCause<'tcx>) + pub fn register_bound(&mut self, + infcx: &InferCtxt<'a, 'gcx, 'tcx>, + ty: Ty<'tcx>, + def_id: DefId, + cause: ObligationCause<'tcx>) { - match infcx.tcx.predicate_for_builtin_bound(cause, builtin_bound, 0, ty) { - Ok(predicate) => { - self.register_predicate_obligation(infcx, predicate); - } - Err(ErrorReported) => { } - } + let trait_ref = ty::TraitRef { + def_id: def_id, + substs: infcx.tcx.mk_substs_trait(ty, &[]), + }; + self.register_predicate_obligation(infcx, Obligation { + cause: cause, + recursion_depth: 0, + predicate: trait_ref.to_predicate() + }); } pub fn register_region_obligation(&mut self, diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index a5fdaed971257..5c5bf130c3ba4 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -19,7 +19,7 @@ use hir; use hir::def_id::DefId; use middle::free_region::FreeRegionMap; use ty::subst::Substs; -use ty::{self, Ty, TyCtxt, TypeFoldable}; +use ty::{self, Ty, TyCtxt, TypeFoldable, ToPredicate}; use infer::InferCtxt; use std::rc::Rc; @@ -125,10 +125,6 @@ pub enum ObligationCauseCode<'tcx> { ReturnType, // Return type must be Sized RepeatVec, // [T,..n] --> T must be Copy - // Captures of variable the given id by a closure (span is the - // span of the closure) - ClosureCapture(ast::NodeId, Span, ty::BuiltinBound), - // Types of fields (other than the last) in a struct must be sized. FieldSized, @@ -369,27 +365,30 @@ pub fn predicates_for_generics<'tcx>(cause: ObligationCause<'tcx>, /// `bound` or is not known to meet bound (note that this is /// conservative towards *no impl*, which is the opposite of the /// `evaluate` methods). -pub fn type_known_to_meet_builtin_bound<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>, - ty: Ty<'tcx>, - bound: ty::BuiltinBound, - span: Span) - -> bool +pub fn type_known_to_meet_bound<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>, + ty: Ty<'tcx>, + def_id: DefId, + span: Span) +-> bool { - debug!("type_known_to_meet_builtin_bound(ty={:?}, bound={:?})", + debug!("type_known_to_meet_bound(ty={:?}, bound={:?})", ty, - bound); - - let cause = ObligationCause::misc(span, ast::DUMMY_NODE_ID); - let obligation = - infcx.tcx.predicate_for_builtin_bound(cause, bound, 0, ty); - let obligation = match obligation { - Ok(o) => o, - Err(..) => return false + infcx.tcx.item_path_str(def_id)); + + let trait_ref = ty::TraitRef { + def_id: def_id, + substs: infcx.tcx.mk_substs_trait(ty, &[]), }; + let obligation = Obligation { + cause: ObligationCause::misc(span, ast::DUMMY_NODE_ID), + recursion_depth: 0, + predicate: trait_ref.to_predicate(), + }; + let result = SelectionContext::new(infcx) .evaluate_obligation_conservatively(&obligation); - debug!("type_known_to_meet_builtin_bound: ty={:?} bound={:?} => {:?}", - ty, bound, result); + debug!("type_known_to_meet_ty={:?} bound={} => {:?}", + ty, infcx.tcx.item_path_str(def_id), result); if result && (ty.has_infer_types() || ty.has_closure_types()) { // Because of inference "guessing", selection can sometimes claim @@ -404,22 +403,22 @@ pub fn type_known_to_meet_builtin_bound<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'g // anyhow). let cause = ObligationCause::misc(span, ast::DUMMY_NODE_ID); - fulfill_cx.register_builtin_bound(infcx, ty, bound, cause); + fulfill_cx.register_bound(infcx, ty, def_id, cause); // Note: we only assume something is `Copy` if we can // *definitively* show that it implements `Copy`. Otherwise, // assume it is move; linear is always ok. match fulfill_cx.select_all_or_error(infcx) { Ok(()) => { - debug!("type_known_to_meet_builtin_bound: ty={:?} bound={:?} success", + debug!("type_known_to_meet_bound: ty={:?} bound={} success", ty, - bound); + infcx.tcx.item_path_str(def_id)); true } Err(e) => { - debug!("type_known_to_meet_builtin_bound: ty={:?} bound={:?} errors={:?}", + debug!("type_known_to_meet_bound: ty={:?} bound={} errors={:?}", ty, - bound, + infcx.tcx.item_path_str(def_id), e); false } diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index 76bead99343a7..27b7adf0ef34a 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -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 = { diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index c25e7ee344f6e..38a228034dd05 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -41,6 +41,7 @@ use ty::{self, ToPredicate, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable}; use traits; use ty::fast_reject; use ty::relate::TypeRelation; +use middle::lang_items; use rustc_data_structures::bitvec::BitVector; use rustc_data_structures::snapshot_vec::{SnapshotVecDelegate, SnapshotVec}; @@ -1091,40 +1092,31 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // Other bounds. Consider both in-scope bounds from fn decl // and applicable impls. There is a certain set of precedence rules here. - match self.tcx().lang_items.to_builtin_kind(obligation.predicate.def_id()) { - Some(ty::BoundCopy) => { - 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)?; - } - Some(ty::BoundSized) => { - // 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)?; - } - - None if self.tcx().lang_items.unsize_trait() == - Some(obligation.predicate.def_id()) => { - self.assemble_candidates_for_unsizing(obligation, &mut candidates); - } - - Some(ty::BoundSend) | - Some(ty::BoundSync) | - None => { - 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); - } + let def_id = 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)?; + } 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); @@ -1445,7 +1437,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { 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 @@ -1515,20 +1507,18 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // 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) => { - match this.tcx().lang_items.to_builtin_kind(obligation.predicate.def_id()) { - Some(bound @ ty::BoundSend) | Some(bound @ ty::BoundSync) => { - if data.builtin_bounds.contains(&bound) { - debug!("assemble_candidates_from_object_ty: matched builtin bound, \ - pushing candidate"); - candidates.vec.push(BuiltinObjectCandidate); - return; - } - } - _ => {} + 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"); + candidates.vec.push(BuiltinObjectCandidate); + return; } - data.principal.with_self_ty(this.tcx(), self_ty) + match data.principal() { + Some(p) => p.with_self_ty(this.tcx(), self_ty), + None => return, + } } ty::TyInfer(ty::TyVar(_)) => { debug!("assemble_candidates_from_object_ty: ambiguous"); @@ -1599,7 +1589,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { 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,12 +1601,17 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // // We always upcast when we can because of reason // #2 (region bounds). - data_a.principal.def_id() == data_b.principal.def_id() && - data_a.builtin_bounds.is_superset(&data_b.builtin_bounds) + match (data_a.principal(), data_b.principal()) { + (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)), + _ => false + } } // T -> Trait. - (_, &ty::TyTrait(_)) => true, + (_, &ty::TyDynamic(..)) => true, // Ambiguous handling is below T -> Trait, because inference // variables can still implement Unsize and nested @@ -1768,7 +1763,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, '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())) @@ -1814,7 +1809,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, '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 @@ -1879,7 +1874,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { Vec::new() } - ty::TyTrait(..) | + ty::TyDynamic(..) | ty::TyParam(..) | ty::TyProjection(..) | ty::TyAnon(..) | @@ -2165,10 +2160,11 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // 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 input_types = data.principal.input_types(); - let assoc_types = data.projection_bounds.iter() + let principal = data.principal().unwrap(); + let input_types = principal.input_types(); + let assoc_types = data.projection_bounds() .map(|pb| pb.skip_binder().ty); let all_types: Vec<_> = input_types.chain(assoc_types) .collect(); @@ -2300,8 +2296,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // 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) => { - data.principal.with_self_ty(self.tcx(), self_ty) + ty::TyDynamic(ref data, ..) => { + data.principal().unwrap().with_self_ty(self.tcx(), self_ty) } _ => { span_bug!(obligation.cause.span, @@ -2469,14 +2465,16 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { 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 { - principal: data_a.principal, - region_bound: data_b.region_bound, - builtin_bounds: data_b.builtin_bounds, - projection_bounds: 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)?; @@ -2486,20 +2484,16 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { 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.builtin_bounds.iter().flat_map(|bound| { - tcx.lang_items.from_builtin_kind(bound).ok() - }) - .chain(Some(data.principal.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) }) { @@ -2515,33 +2509,26 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { predicate)); }; - // Create the obligation for casting from T to Trait. - push(data.principal.with_self_ty(tcx, source).to_predicate()); - - // We can only make objects from sized types. - let mut builtin_bounds = data.builtin_bounds; - builtin_bounds.insert(ty::BoundSized); - - // 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 bound in &builtin_bounds { - if let Ok(tr) = tcx.trait_ref_for_builtin_bound(bound, source) { - push(tr.to_predicate()); - } else { - return Err(Unimplemented); - } + // 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.require_lang_item(lang_items::SizedTraitLangItem), + 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()); } diff --git a/src/librustc/traits/structural_impls.rs b/src/librustc/traits/structural_impls.rs index d03ba5b0a31f1..dedb126d7ff6d 100644 --- a/src/librustc/traits/structural_impls.rs +++ b/src/librustc/traits/structural_impls.rs @@ -190,9 +190,6 @@ impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> { super::VariableType(id) => Some(super::VariableType(id)), super::ReturnType => Some(super::ReturnType), super::RepeatVec => Some(super::RepeatVec), - super::ClosureCapture(node_id, span, bound) => { - Some(super::ClosureCapture(node_id, span, bound)) - } super::FieldSized => Some(super::FieldSized), super::ConstSized => Some(super::ConstSized), super::SharedStatic => Some(super::SharedStatic), @@ -507,7 +504,6 @@ impl<'tcx> TypeFoldable<'tcx> for traits::ObligationCauseCode<'tcx> { super::VariableType(_) | super::ReturnType | super::RepeatVec | - super::ClosureCapture(..) | super::FieldSized | super::ConstSized | super::SharedStatic | @@ -552,7 +548,6 @@ impl<'tcx> TypeFoldable<'tcx> for traits::ObligationCauseCode<'tcx> { super::VariableType(_) | super::ReturnType | super::RepeatVec | - super::ClosureCapture(..) | super::FieldSized | super::ConstSized | super::SharedStatic | diff --git a/src/librustc/traits/util.rs b/src/librustc/traits/util.rs index b94597d475927..321936fe54be1 100644 --- a/src/librustc/traits/util.rs +++ b/src/librustc/traits/util.rs @@ -12,7 +12,6 @@ use hir::def_id::DefId; use ty::subst::{Subst, Substs}; use ty::{self, Ty, TyCtxt, ToPredicate, ToPolyTraitRef}; use ty::outlives::Component; -use util::common::ErrorReported; use util::nodemap::FxHashSet; use super::{Obligation, ObligationCause, PredicateObligation, SelectionContext, Normalized}; @@ -408,25 +407,6 @@ pub fn predicate_for_trait_ref<'tcx>( } impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { - pub fn trait_ref_for_builtin_bound(self, - builtin_bound: ty::BuiltinBound, - param_ty: Ty<'tcx>) - -> Result, ErrorReported> - { - match self.lang_items.from_builtin_kind(builtin_bound) { - Ok(def_id) => { - Ok(ty::TraitRef { - def_id: def_id, - substs: self.mk_substs_trait(param_ty, &[]) - }) - } - Err(e) => { - self.sess.err(&e); - Err(ErrorReported) - } - } - } - pub fn predicate_for_trait_def(self, cause: ObligationCause<'tcx>, trait_def_id: DefId, @@ -442,17 +422,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { predicate_for_trait_ref(cause, trait_ref, recursion_depth) } - pub fn predicate_for_builtin_bound(self, - cause: ObligationCause<'tcx>, - builtin_bound: ty::BuiltinBound, - recursion_depth: usize, - param_ty: Ty<'tcx>) - -> Result, ErrorReported> - { - let trait_ref = self.trait_ref_for_builtin_bound(builtin_bound, param_ty)?; - Ok(predicate_for_trait_ref(cause, trait_ref, recursion_depth)) - } - /// Cast a trait reference into a reference to one of its super /// traits; returns `None` if `target_trait_def_id` is not a /// supertrait. diff --git a/src/librustc/ty/contents.rs b/src/librustc/ty/contents.rs index 9f80c2487fb2c..8c3cb79294880 100644 --- a/src/librustc/ty/contents.rs +++ b/src/librustc/ty/contents.rs @@ -195,7 +195,7 @@ impl<'a, 'tcx> ty::TyS<'tcx> { tc_ty(tcx, typ, cache).owned_pointer() } - ty::TyTrait(_) => { + ty::TyDynamic(..) => { TC::All - TC::InteriorParam } diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index ea81c85ba6a53..c23ee489a28f4 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -29,7 +29,7 @@ use ty::{self, TraitRef, Ty, TypeAndMut}; 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::mem; 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, stability: TypedArena, layout: TypedArena, + existential_predicates: TypedArena>, // references generics: TypedArena>, @@ -81,6 +83,7 @@ impl<'tcx> 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>>, stability: RefCell>, layout: RefCell>, + existential_predicates: RefCell>>>>, } impl<'gcx: 'tcx, 'tcx> CtxtInterners<'tcx> { @@ -115,7 +119,8 @@ impl<'gcx: 'tcx, '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 @@ impl<'a, 'tcx> Lift<'tcx> for &'a Slice> { } } +impl<'a, 'tcx> Lift<'tcx> for &'a Slice> { + type Lifted = &'tcx Slice>; + fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) + -> Option<&'tcx Slice>> { + 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 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> { 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 @@ impl<'tcx> Borrow for Interned<'tcx, Region> { } } +impl<'tcx: 'lcx, 'lcx> Borrow<[ExistentialPredicate<'lcx>]> + for Interned<'tcx, Slice>> { + 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 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, '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>>, + 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 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { self.mk_ty(TyAnon(def_id, substs)) } + pub fn intern_existential_predicates(self, eps: &[ExistentialPredicate<'tcx>]) + -> &'tcx Slice> { + 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> { if ts.len() == 0 { Slice::empty() @@ -1517,6 +1561,12 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } } + pub fn mk_existential_predicates], + &'tcx Slice>>>(self, iter: I) + -> I::Output { + iter.intern_with(|xs| self.intern_existential_predicates(xs)) + } + pub fn mk_type_list], &'tcx Slice>>>(self, iter: I) -> I::Output { iter.intern_with(|xs| self.intern_type_list(xs)) diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs index 9b345c2d02329..125ee0a02c814 100644 --- a/src/librustc/ty/error.rs +++ b/src/librustc/ty/error.rs @@ -45,12 +45,12 @@ pub enum TypeError<'tcx> { IntMismatch(ExpectedFound), FloatMismatch(ExpectedFound), Traits(ExpectedFound), - BuiltinBoundsMismatch(ExpectedFound), VariadicMismatch(ExpectedFound), CyclicTy, ProjectionNameMismatched(ExpectedFound), ProjectionBoundsLength(ExpectedFound), - TyParamDefaultMismatch(ExpectedFound>) + TyParamDefaultMismatch(ExpectedFound>), + ExistentialMismatch(ExpectedFound<&'tcx ty::Slice>>), } #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Debug, Copy)] @@ -135,19 +135,6 @@ impl<'tcx> fmt::Display for TypeError<'tcx> { format!("trait `{}`", tcx.item_path_str(values.found))) }), - BuiltinBoundsMismatch(values) => { - if values.expected.is_empty() { - write!(f, "expected no bounds, found `{}`", - values.found) - } else if values.found.is_empty() { - write!(f, "expected bounds `{}`, found no bounds", - values.expected) - } else { - write!(f, "expected bounds `{}`, found bounds `{}`", - values.expected, - values.found) - } - } IntMismatch(ref values) => { write!(f, "expected `{:?}`, found `{:?}`", values.expected, @@ -178,6 +165,10 @@ impl<'tcx> fmt::Display for TypeError<'tcx> { values.expected.ty, values.found.ty) } + ExistentialMismatch(ref values) => { + report_maybe_different(f, format!("trait `{}`", values.expected), + format!("trait `{}`", values.found)) + } } } } @@ -214,8 +205,9 @@ impl<'a, 'gcx, 'lcx, 'tcx> ty::TyS<'tcx> { } ty::TyFnDef(..) => format!("fn item"), ty::TyFnPtr(_) => "fn pointer".to_string(), - ty::TyTrait(ref inner) => { - format!("trait {}", tcx.item_path_str(inner.principal.def_id())) + ty::TyDynamic(ref inner, ..) => { + inner.principal().map_or_else(|| "trait".to_string(), + |p| format!("trait {}", tcx.item_path_str(p.def_id()))) } ty::TyClosure(..) => "closure".to_string(), ty::TyTuple(_) => "tuple".to_string(), diff --git a/src/librustc/ty/fast_reject.rs b/src/librustc/ty/fast_reject.rs index befc9533c387b..ade6cad6866df 100644 --- a/src/librustc/ty/fast_reject.rs +++ b/src/librustc/ty/fast_reject.rs @@ -11,6 +11,7 @@ use hir::def_id::DefId; use ty::{self, Ty, TyCtxt}; use syntax::ast; +use middle::lang_items::OwnedBoxLangItem; use self::SimplifiedType::*; @@ -59,8 +60,8 @@ 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) => { - Some(TraitSimplifiedType(trait_info.principal.def_id())) + ty::TyDynamic(ref trait_info, ..) => { + trait_info.principal().map(|p| TraitSimplifiedType(p.def_id())) } ty::TyRef(_, mt) => { // since we introduce auto-refs during method lookup, we @@ -70,10 +71,7 @@ pub fn simplify_type<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, } ty::TyBox(_) => { // treat like we would treat `Box` - match tcx.lang_items.require_owned_box() { - Ok(def_id) => Some(AdtSimplifiedType(def_id)), - Err(msg) => tcx.sess.fatal(&msg), - } + Some(AdtSimplifiedType(tcx.require_lang_item(OwnedBoxLangItem))) } ty::TyClosure(def_id, _) => { Some(ClosureSimplifiedType(def_id)) diff --git a/src/librustc/ty/flags.rs b/src/librustc/ty/flags.rs index 2c09b89beb232..2bcbccb7d0505 100644 --- a/src/librustc/ty/flags.rs +++ b/src/librustc/ty/flags.rs @@ -121,16 +121,21 @@ impl FlagComputation { self.add_substs(substs); } - &ty::TyTrait(ref obj) => { + &ty::TyDynamic(ref obj, r) => { let mut computation = FlagComputation::new(); - computation.add_substs(obj.principal.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) => { diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs index b93a8698f603c..440a3916786fa 100644 --- a/src/librustc/ty/item_path.rs +++ b/src/librustc/ty/item_path.rs @@ -316,7 +316,7 @@ pub fn characteristic_def_id_of_type(ty: Ty) -> Option { match ty.sty { ty::TyAdt(adt_def, _) => Some(adt_def.did), - ty::TyTrait(ref data) => Some(data.principal.def_id()), + ty::TyDynamic(data, ..) => data.principal().map(|p| p.def_id()), ty::TyArray(subty, _) | ty::TySlice(subty) | diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index bc3c5d6ed4e20..8646bccf1e9ed 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -924,7 +924,7 @@ impl<'a, 'gcx, 'tcx> Layout { 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 @@ impl<'a, 'gcx, 'tcx> Layout { non_zero: false } } - ty::TyTrait(_) => { + ty::TyDynamic(..) => { let mut unit = Struct::new(dl, false); unit.sized = false; Univariant { variant: unit, non_zero: false } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 844fc58cec37b..ab8f7d524f44d 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -53,9 +53,8 @@ use hir; use hir::itemlikevisit::ItemLikeVisitor; pub use self::sty::{Binder, DebruijnIndex}; -pub use self::sty::{BuiltinBound, BuiltinBounds}; 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}; @@ -68,11 +67,6 @@ pub use self::sty::InferTy::*; pub use self::sty::Region::*; pub use self::sty::TypeVariants::*; -pub use self::sty::BuiltinBound::Send as BoundSend; -pub use self::sty::BuiltinBound::Sized as BoundSized; -pub use self::sty::BuiltinBound::Copy as BoundCopy; -pub use self::sty::BuiltinBound::Sync as BoundSync; - pub use self::contents::TypeContents; pub use self::context::{TyCtxt, tls}; pub use self::context::{CtxtArenas, Lift, Tables}; @@ -1718,7 +1712,7 @@ impl<'a, 'tcx> AdtDefData<'tcx, 'tcx> { vec![] } - TyStr | TyTrait(..) | TySlice(_) | TyError => { + TyStr | TyDynamic(..) | TySlice(_) | TyError => { // these are never sized - return the target type vec![ty] } @@ -1884,18 +1878,14 @@ pub enum ClosureKind { impl<'a, 'tcx> ClosureKind { pub fn trait_did(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> DefId { - let result = match *self { - ClosureKind::Fn => tcx.lang_items.require(FnTraitLangItem), + match *self { + ClosureKind::Fn => tcx.require_lang_item(FnTraitLangItem), ClosureKind::FnMut => { - tcx.lang_items.require(FnMutTraitLangItem) + tcx.require_lang_item(FnMutTraitLangItem) } ClosureKind::FnOnce => { - tcx.lang_items.require(FnOnceTraitLangItem) + tcx.require_lang_item(FnOnceTraitLangItem) } - }; - match result { - Ok(trait_did) => trait_did, - Err(err) => tcx.sess.fatal(&err[..]), } } diff --git a/src/librustc/ty/outlives.rs b/src/librustc/ty/outlives.rs index e3d13f593954f..eb384eec6a6f1 100644 --- a/src/librustc/ty/outlives.rs +++ b/src/librustc/ty/outlives.rs @@ -177,7 +177,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, '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 diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs index 2a01bad33c52e..8cb1483107ff1 100644 --- a/src/librustc/ty/relate.rs +++ b/src/librustc/ty/relate.rs @@ -302,23 +302,6 @@ impl<'tcx> Relate<'tcx> for Vec> { } } -impl<'tcx> Relate<'tcx> for ty::BuiltinBounds { - fn relate<'a, 'gcx, R>(relation: &mut R, - a: &ty::BuiltinBounds, - b: &ty::BuiltinBounds) - -> RelateResult<'tcx, ty::BuiltinBounds> - where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a - { - // Two sets of builtin bounds are only relatable if they are - // precisely the same (but see the coercion code). - if a != b { - Err(TypeError::BuiltinBoundsMismatch(expected_found(relation, a, b))) - } else { - Ok(*a) - } - } -} - impl<'tcx> Relate<'tcx> for ty::TraitRef<'tcx> { fn relate<'a, 'gcx, R>(relation: &mut R, a: &ty::TraitRef<'tcx>, @@ -415,23 +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 = relation.relate(&a_obj.principal, &b_obj.principal)?; - let r = - relation.with_cause( - Cause::ExistentialRegionBound, - |relation| relation.relate_with_variance(ty::Contravariant, - &a_obj.region_bound, - &b_obj.region_bound))?; - let nb = relation.relate(&a_obj.builtin_bounds, &b_obj.builtin_bounds)?; - let pb = relation.relate(&a_obj.projection_bounds, &b_obj.projection_bounds)?; - Ok(tcx.mk_trait(ty::TraitObject { - principal: principal, - region_bound: r, - builtin_bounds: nb, - projection_bounds: 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), @@ -527,6 +502,31 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R, } } +impl<'tcx> Relate<'tcx> for &'tcx ty::Slice> { + 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>, diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index c8618cd154781..88de3575274cc 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -315,7 +315,6 @@ impl<'a, 'tcx> Lift<'tcx> for ty::error::TypeError<'a> { IntMismatch(x) => IntMismatch(x), FloatMismatch(x) => FloatMismatch(x), Traits(x) => Traits(x), - BuiltinBoundsMismatch(x) => BuiltinBoundsMismatch(x), VariadicMismatch(x) => VariadicMismatch(x), CyclicTy => CyclicTy, ProjectionNameMismatched(x) => ProjectionNameMismatched(x), @@ -325,6 +324,7 @@ impl<'a, 'tcx> Lift<'tcx> for ty::error::TypeError<'a> { TyParamDefaultMismatch(ref x) => { return tcx.lift(x).map(TyParamDefaultMismatch) } + ExistentialMismatch(ref x) => return tcx.lift(x).map(ExistentialMismatch) }) } } @@ -427,20 +427,33 @@ impl<'tcx, T:TypeFoldable<'tcx>> TypeFoldable<'tcx> for ty::Binder { } } -impl<'tcx> TypeFoldable<'tcx> for ty::TraitObject<'tcx> { +impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::Slice> { fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - ty::TraitObject { - principal: self.principal.fold_with(folder), - region_bound: self.region_bound.fold_with(folder), - builtin_bounds: self.builtin_bounds, - projection_bounds: self.projection_bounds.fold_with(folder), + let v = self.iter().map(|p| p.fold_with(folder)).collect::>(); + folder.tcx().intern_existential_predicates(&v) + } + + fn super_visit_with>(&self, visitor: &mut V) -> bool { + 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>(&self, visitor: &mut V) -> bool { - self.principal.visit_with(visitor) || - self.region_bound.visit_with(visitor) || - self.projection_bounds.visit_with(visitor) + match *self { + ty::ExistentialPredicate::Trait(ref tr) => tr.visit_with(visitor), + ty::ExistentialPredicate::Projection(ref p) => p.visit_with(visitor), + ty::ExistentialPredicate::AutoTrait(_) => false, + } } } @@ -463,7 +476,8 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> { 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, @@ -500,7 +514,8 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> { 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) @@ -703,16 +718,6 @@ impl<'tcx> TypeFoldable<'tcx> for ty::adjustment::AutoBorrow<'tcx> { } } -impl<'tcx> TypeFoldable<'tcx> for ty::BuiltinBounds { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, _folder: &mut F) -> Self { - *self - } - - fn super_visit_with>(&self, _visitor: &mut V) -> bool { - false - } -} - impl<'tcx> TypeFoldable<'tcx> for ty::TypeParameterDef<'tcx> { fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { ty::TypeParameterDef { diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index cb3176cce10bd..667db5b673054 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -14,13 +14,13 @@ use hir::def_id::DefId; use middle::region; use ty::subst::Substs; -use ty::{self, AdtDef, ToPredicate, TypeFlags, Ty, TyCtxt, TypeFoldable}; +use ty::{self, AdtDef, TypeFlags, Ty, TyCtxt, TypeFoldable}; use ty::{Slice, TyS}; -use util::common::ErrorReported; +use ty::subst::Kind; -use collections::enum_set::{self, EnumSet, CLike}; use std::fmt; -use std::ops; +use std::iter; +use std::cmp::Ordering; use syntax::abi; use syntax::ast::{self, Name, NodeId}; use syntax::symbol::{keywords, InternedString}; @@ -147,7 +147,7 @@ pub enum TypeVariants<'tcx> { TyFnPtr(&'tcx BareFnTy<'tcx>), /// A trait, defined with `trait`. - TyTrait(Box>), + TyDynamic(Binder<&'tcx Slice>>, &'tcx ty::Region), /// The anonymous type of a closure. Used to represent the type of /// `|a| a`. @@ -275,12 +275,104 @@ impl<'a, 'gcx, 'acx, 'tcx> ClosureSubsts<'tcx> { } } -#[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] -pub struct TraitObject<'tcx> { - pub principal: PolyExistentialTraitRef<'tcx>, - pub region_bound: &'tcx ty::Region, - pub builtin_bounds: BuiltinBounds, - pub projection_bounds: Vec>, +#[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<'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> { + 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> {} + +impl<'tcx> Slice> { + pub fn principal(&self) -> Option> { + match self.get(0) { + Some(&ExistentialPredicate::Trait(tr)) => Some(tr), + _ => None + } + } + + #[inline] + pub fn projection_bounds<'a>(&'a self) -> + impl Iterator> + 'a { + self.iter().filter_map(|predicate| { + match *predicate { + ExistentialPredicate::Projection(p) => Some(p), + _ => None, + } + }) + } + + #[inline] + pub fn auto_traits<'a>(&'a self) -> impl Iterator + 'a { + self.iter().filter_map(|predicate| { + match *predicate { + ExistentialPredicate::AutoTrait(d) => Some(d), + _ => None + } + }) + } +} + +impl<'tcx> Binder<&'tcx Slice>> { + pub fn principal(&self) -> Option> { + self.skip_binder().principal().map(Binder) + } + + #[inline] + pub fn projection_bounds<'a>(&'a self) -> + impl Iterator> + 'a { + self.skip_binder().projection_bounds().map(Binder) + } + + #[inline] + pub fn auto_traits<'a>(&'a self) -> impl Iterator + 'a { + self.skip_binder().auto_traits() + } + + pub fn iter<'a>(&'a self) + -> impl DoubleEndedIterator>> + 'tcx { + self.skip_binder().iter().cloned().map(Binder) + } } /// A complete reference to a trait. These take numerous guises in syntax, @@ -344,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> + 'a { +impl<'a, 'gcx, 'tcx> ExistentialTraitRef<'tcx> { + pub fn input_types<'b>(&'b self) -> impl DoubleEndedIterator> + '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>; @@ -713,122 +821,53 @@ pub struct ExistentialProjection<'tcx> { pub type PolyExistentialProjection<'tcx> = Binder>; -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 - }) - } -} - -#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)] -pub struct BuiltinBounds(EnumSet); - -impl<'a, 'gcx, 'tcx> BuiltinBounds { - pub fn empty() -> BuiltinBounds { - BuiltinBounds(EnumSet::new()) - } - - pub fn iter(&self) -> enum_set::Iter { - self.into_iter() - } - - pub fn to_predicates(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, - self_ty: Ty<'tcx>) - -> Vec> { - self.iter().filter_map(|builtin_bound| - match tcx.trait_ref_for_builtin_bound(builtin_bound, self_ty) { - Ok(trait_ref) => Some(trait_ref.to_predicate()), - Err(ErrorReported) => { None } - } - ).collect() + ty: self.ty + } } } -impl ops::Deref for BuiltinBounds { - type Target = EnumSet; - fn deref(&self) -> &Self::Target { &self.0 } -} - -impl ops::DerefMut for BuiltinBounds { - fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 } -} - -impl<'a> IntoIterator for &'a BuiltinBounds { - type Item = BuiltinBound; - type IntoIter = enum_set::Iter; - fn into_iter(self) -> Self::IntoIter { - (**self).into_iter() +impl<'a, 'tcx, 'gcx> PolyExistentialProjection<'tcx> { + pub fn item_name(&self) -> Name { + self.skip_binder().item_name() } -} - -#[derive(Clone, RustcEncodable, PartialEq, Eq, RustcDecodable, Hash, - Debug, Copy)] -pub enum BuiltinBound { - Send = 0, - Sized = 1, - Copy = 2, - Sync = 3, -} -impl CLike for BuiltinBound { - fn to_usize(&self) -> usize { - *self as usize - } - fn from_usize(v: usize) -> BuiltinBound { - match v { - 0 => BuiltinBound::Send, - 1 => BuiltinBound::Sized, - 2 => BuiltinBound::Copy, - 3 => BuiltinBound::Sync, - _ => bug!("{} is not a valid BuiltinBound", v) - } + pub fn sort_key(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> (u64, InternedString) { + self.skip_binder().sort_key(tcx) } -} -impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { - pub fn try_add_builtin_trait(self, - trait_def_id: DefId, - builtin_bounds: &mut EnumSet) - -> bool - { - //! Checks whether `trait_ref` refers to one of the builtin - //! traits, like `Send`, and adds the corresponding - //! bound to the set `builtin_bounds` if so. Returns true if `trait_ref` - //! is a builtin trait. - - match self.lang_items.to_builtin_kind(trait_def_id) { - Some(bound) => { builtin_bounds.insert(bound); true } - None => false - } + 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)) } } @@ -1088,7 +1127,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { pub fn is_trait(&self) -> bool { match self.sty { - TyTrait(..) => true, + TyDynamic(..) => true, _ => false } } @@ -1221,7 +1260,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { pub fn ty_to_def_id(&self) -> Option { match self.sty { - TyTrait(ref tt) => Some(tt.principal.def_id()), + TyDynamic(ref tt, ..) => tt.principal().map(|p| p.def_id()), TyAdt(def, _) => Some(def.did), TyClosure(id, _) => Some(id), _ => None @@ -1243,9 +1282,11 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { TyRef(region, _) => { vec![region] } - TyTrait(ref obj) => { - let mut v = vec![obj.region_bound]; - v.extend(obj.principal.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) => { diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index 1dde8106ec6a6..6ba4b8d2da77b 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -21,6 +21,7 @@ use ty::fold::TypeVisitor; use ty::layout::{Layout, LayoutError}; use ty::TypeVariants::*; use util::nodemap::FxHashMap; +use middle::lang_items; use rustc_const_math::{ConstInt, ConstIsize, ConstUsize}; @@ -531,9 +532,13 @@ impl<'a, 'gcx, 'tcx, H: Hasher> TypeVisitor<'tcx> for TypeIdHasher<'a, 'gcx, 'tc self.hash(f.sig.variadic()); self.hash(f.sig.inputs().skip_binder().len()); } - TyTrait(ref data) => { - self.def_id(data.principal.def_id()); - self.hash(data.builtin_bounds); + TyDynamic(ref data, ..) => { + if let Some(p) = data.principal() { + self.def_id(p.def_id()); + } + for d in data.auto_traits() { + self.def_id(d); + } } TyTuple(tys) => { self.hash(tys.len()); @@ -595,7 +600,7 @@ impl<'a, 'gcx, 'tcx, H: Hasher> TypeVisitor<'tcx> for TypeIdHasher<'a, 'gcx, 'tc impl<'a, 'tcx> ty::TyS<'tcx> { fn impls_bound(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>, param_env: &ParameterEnvironment<'tcx>, - bound: ty::BuiltinBound, + def_id: DefId, cache: &RefCell, bool>>, span: Span) -> bool { @@ -607,7 +612,7 @@ impl<'a, 'tcx> ty::TyS<'tcx> { let result = tcx.infer_ctxt(None, Some(param_env.clone()), Reveal::ExactMatch) .enter(|infcx| { - traits::type_known_to_meet_builtin_bound(&infcx, self, bound, span) + traits::type_known_to_meet_bound(&infcx, self, def_id, span) }); if self.has_param_types() || self.has_self_ty() { cache.borrow_mut().insert(self, result); @@ -636,12 +641,13 @@ impl<'a, 'tcx> ty::TyS<'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(|| { - !self.impls_bound(tcx, param_env, ty::BoundCopy, ¶m_env.is_copy_cache, span) - }); + !self.impls_bound(tcx, param_env, + tcx.require_lang_item(lang_items::CopyTraitLangItem), + ¶m_env.is_copy_cache, span) }); if !self.has_param_types() && !self.has_self_ty() { self.flags.set(self.flags.get() | if result { @@ -677,13 +683,13 @@ impl<'a, 'tcx> ty::TyS<'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 }.unwrap_or_else(|| { - self.impls_bound(tcx, param_env, ty::BoundSized, ¶m_env.is_sized_cache, span) - }); + self.impls_bound(tcx, param_env, tcx.require_lang_item(lang_items::SizedTraitLangItem), + ¶m_env.is_sized_cache, span) }); if !self.has_param_types() && !self.has_self_ty() { self.flags.set(self.flags.get() | if result { diff --git a/src/librustc/ty/walk.rs b/src/librustc/ty/walk.rs index 2f9468dbe5887..0848dcd2c8d21 100644 --- a/src/librustc/ty/walk.rs +++ b/src/librustc/ty/walk.rs @@ -92,11 +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) => { - stack.extend(obj.principal.input_types().rev()); - 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()); diff --git a/src/librustc/ty/wf.rs b/src/librustc/ty/wf.rs index 74c6d7d334c35..bab9964651dca 100644 --- a/src/librustc/ty/wf.rs +++ b/src/librustc/ty/wf.rs @@ -17,7 +17,7 @@ use ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable}; use std::iter::once; use syntax::ast; use syntax_pos::Span; -use util::common::ErrorReported; +use middle::lang_items; /// Returns the set of obligations needed to make `ty` well-formed. /// If `ty` contains unresolved inference variables, this may include @@ -282,14 +282,11 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { fn require_sized(&mut self, subty: Ty<'tcx>, cause: traits::ObligationCauseCode<'tcx>) { if !subty.has_escaping_regions() { let cause = self.cause(cause); - match self.infcx.tcx.trait_ref_for_builtin_bound(ty::BoundSized, subty) { - Ok(trait_ref) => { - self.out.push( - traits::Obligation::new(cause, - trait_ref.to_predicate())); - } - Err(ErrorReported) => { } - } + let trait_ref = ty::TraitRef { + def_id: self.infcx.tcx.require_lang_item(lang_items::SizedTraitLangItem), + substs: self.infcx.tcx.mk_substs_trait(subty, &[]), + }; + self.out.push(traits::Obligation::new(cause, trait_ref.to_predicate())); } } @@ -298,7 +295,6 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { /// is WF. Returns false if `ty0` is an unresolved type variable, /// in which case we are not able to simplify at all. fn compute(&mut self, ty0: Ty<'tcx>) -> bool { - let tcx = self.infcx.tcx; let mut subtys = ty0.walk(); while let Some(ty) = subtys.next() { match ty.sty { @@ -377,12 +373,12 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { // 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 @@ -391,15 +387,12 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { let cause = self.cause(traits::MiscObligation); let component_traits = - data.builtin_bounds.iter().flat_map(|bound| { - tcx.lang_items.from_builtin_kind(bound).ok() - }) - .chain(Some(data.principal.def_id())); + data.auto_traits().chain(data.principal().map(|p| p.def_id())); self.out.extend( - component_traits.map(|did| { traits::Obligation::new( + component_traits.map(|did| traits::Obligation::new( cause.clone(), ty::Predicate::ObjectSafe(did) - )}) + )) ); } @@ -456,7 +449,9 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { .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>>, + region: &'tcx ty::Region) { // Imagine a type like this: // // trait Foo { } @@ -491,11 +486,9 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { if !data.has_escaping_regions() { let implicit_bounds = - object_region_bounds(self.infcx.tcx, - data.principal, - data.builtin_bounds); + 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)); @@ -514,8 +507,7 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { /// `ty::required_region_bounds`, see that for more information. pub fn object_region_bounds<'a, 'gcx, 'tcx>( tcx: TyCtxt<'a, 'gcx, 'tcx>, - principal: ty::PolyExistentialTraitRef<'tcx>, - others: ty::BuiltinBounds) + existential_predicates: ty::Binder<&'tcx ty::Slice>>) -> Vec<&'tcx ty::Region> { // Since we don't actually *know* the self type for an object, @@ -523,8 +515,13 @@ pub fn object_region_bounds<'a, 'gcx, 'tcx>( // a skolemized type. let open_ty = tcx.mk_infer(ty::FreshTy(0)); - let mut predicates = others.to_predicates(tcx, open_ty); - 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) } diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index d04825d560444..d839df80a12ac 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -16,9 +16,8 @@ use ty::{TyBool, TyChar, TyAdt}; 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,74 +297,31 @@ 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>); - -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>(&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> { 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 = tcx.lift(&self.principal) - .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::>(); + parameterized(f, principal.substs, principal.def_id, &projections)?; + } - // Builtin bounds. - for bound in &self.builtin_bounds { - write!(f, " + {:?}", bound)?; - } + // Builtin bounds. + for did in self.auto_traits() { + write!(f, " + {}", tcx.item_path_str(did))?; + } - // 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(()) + })?; Ok(()) } @@ -453,41 +409,6 @@ impl<'tcx> fmt::Debug for ty::adjustment::Adjustment<'tcx> { } } -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)?; - } - - for bound in &self.builtin_bounds { - maybe_continue(f)?; - write!(f, "{:?}", bound)?; - } - - 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 { @@ -677,19 +598,6 @@ impl<'tcx> fmt::Display for ty::FnSig<'tcx> { } } -impl fmt::Display for ty::BuiltinBounds { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let mut bounds = self.iter(); - if let Some(bound) = bounds.next() { - write!(f, "{:?}", bound)?; - for bound in bounds { - write!(f, " + {:?}", bound)?; - } - } - Ok(()) - } -} - impl fmt::Debug for ty::TyVid { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "_#{}t", self.index) @@ -753,6 +661,12 @@ impl fmt::Debug for ty::IntVarValue { } }*/ +impl<'tcx> fmt::Display for ty::Binder<&'tcx ty::Slice>> { + 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> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { ty::tls::with(|tcx| in_binder(f, tcx, self, tcx.lift(self))) @@ -872,7 +786,15 @@ impl<'tcx> fmt::Display for ty::TypeVariants<'tcx> { } }) } - 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| { diff --git a/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs b/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs index cdb19d164bf29..49ef5dd7a1725 100644 --- a/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs +++ b/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs @@ -857,8 +857,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { let tcx = self.tcx; let unit_temp = Lvalue::Local(self.patch.new_temp(tcx.mk_nil())); - let free_func = tcx.lang_items.require(lang_items::BoxFreeFnLangItem) - .unwrap_or_else(|e| tcx.sess.fatal(&e)); + let free_func = tcx.require_lang_item(lang_items::BoxFreeFnLangItem); let substs = tcx.mk_substs(iter::once(Kind::from(ty))); let fty = tcx.item_type(free_func).subst(tcx, substs); diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index 8aa5e9e0a9460..6e9467d63dd1f 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -572,7 +572,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { consider using a raw pointer instead") } - ty::TyTrait(..) => { + ty::TyDynamic(..) => { FfiUnsafe("found Rust trait type in foreign module, \ consider using a raw pointer instead") } diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index f59f2bcc07476..1e3d12c50a394 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -416,6 +416,15 @@ impl<'a, 'tcx> SpecializedDecoder> for DecodeContext<'a, 'tcx> } } +impl<'a, 'tcx> SpecializedDecoder<&'tcx ty::Slice>> + for DecodeContext<'a, 'tcx> { + fn specialized_decode(&mut self) + -> Result<&'tcx ty::Slice>, 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) diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs index e5fac94a8a494..c02a1822d7369 100644 --- a/src/librustc_mir/build/scope.rs +++ b/src/librustc_mir/build/scope.rs @@ -783,8 +783,7 @@ fn build_free<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, data: &FreeData<'tcx>, target: BasicBlock) -> TerminatorKind<'tcx> { - let free_func = tcx.lang_items.require(lang_items::BoxFreeFnLangItem) - .unwrap_or_else(|e| tcx.sess.fatal(&e)); + let free_func = tcx.require_lang_item(lang_items::BoxFreeFnLangItem); let substs = tcx.intern_substs(&[Kind::from(data.item_ty)]); TerminatorKind::Call { func: Operand::Constant(Constant { diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 4ff2beb3fdb77..9c6922016e02a 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -29,6 +29,7 @@ use rustc::mir::traversal::ReversePostorder; use rustc::mir::transform::{Pass, MirPass, MirSource}; use rustc::mir::visit::{LvalueContext, Visitor}; use rustc::util::nodemap::DefIdMap; +use rustc::middle::lang_items; use syntax::abi::Abi; use syntax::feature_gate::UnstableFeatures; use syntax_pos::Span; @@ -1046,7 +1047,9 @@ impl<'tcx> MirPass<'tcx> for QualifyAndPromoteConstants { tcx.infer_ctxt(None, None, Reveal::NotSpecializable).enter(|infcx| { let cause = traits::ObligationCause::new(mir.span, id, traits::SharedStatic); let mut fulfillment_cx = traits::FulfillmentContext::new(); - fulfillment_cx.register_builtin_bound(&infcx, ty, ty::BoundSync, cause); + fulfillment_cx.register_bound(&infcx, ty, + tcx.require_lang_item(lang_items::SyncTraitLangItem), + cause); if let Err(err) = fulfillment_cx.select_all_or_error(&infcx) { infcx.report_fulfillment_errors(&err); } diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index ee18968ff35e3..5aac23f0f5fa2 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -71,7 +71,8 @@ impl<'a, 'tcx> EmbargoVisitor<'a, 'tcx> { fn item_ty_level(&self, item_def_id: DefId) -> Option { let ty_def_id = match self.tcx.item_type(item_def_id).sty { ty::TyAdt(adt, _) => adt.did, - ty::TyTrait(ref obj) => obj.principal.def_id(), + ty::TyDynamic(ref obj, ..) if obj.principal().is_some() => + obj.principal().unwrap().def_id(), ty::TyProjection(ref proj) => proj.trait_ref.def_id, _ => return Some(AccessLevel::Public) }; @@ -359,7 +360,7 @@ impl<'b, 'a, 'tcx> TypeVisitor<'tcx> for ReachEverythingInTheInterfaceVisitor<'b fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool { let ty_def_id = match ty.sty { ty::TyAdt(adt, _) => Some(adt.did), - ty::TyTrait(ref obj) => Some(obj.principal.def_id()), + ty::TyDynamic(ref obj, ..) => obj.principal().map(|p| p.def_id()), ty::TyProjection(ref proj) => Some(proj.trait_ref.def_id), ty::TyFnDef(def_id, ..) | ty::TyAnon(def_id, _) => Some(def_id), @@ -934,7 +935,7 @@ impl<'a, 'tcx: 'a> TypeVisitor<'tcx> for SearchInterfaceForPrivateItemsVisitor<' fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool { let ty_def_id = match ty.sty { ty::TyAdt(adt, _) => Some(adt.did), - ty::TyTrait(ref obj) => Some(obj.principal.def_id()), + ty::TyDynamic(ref obj, ..) => obj.principal().map(|p| p.def_id()), ty::TyProjection(ref proj) => { if self.required_visibility == ty::Visibility::PrivateExternal { // Conservatively approximate the whole type alias as public without diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index c94c25e0b056c..f1126e6fd256c 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -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.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 {:?} -> {:?}", diff --git a/src/librustc_trans/collector.rs b/src/librustc_trans/collector.rs index 5c7b004375ed4..120e1a562ebea 100644 --- a/src/librustc_trans/collector.rs +++ b/src/librustc_trans/collector.rs @@ -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>) { 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.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))); diff --git a/src/librustc_trans/context.rs b/src/librustc_trans/context.rs index 771c5ef6d9d28..c0d7c64bd192c 100644 --- a/src/librustc_trans/context.rs +++ b/src/librustc_trans/context.rs @@ -95,7 +95,8 @@ pub struct LocalCrateContext<'tcx> { /// Cache instances of monomorphic and polymorphic items instances: RefCell, ValueRef>>, /// Cache generated vtables - vtables: RefCell, ValueRef>>, + vtables: RefCell, + Option>), ValueRef>>, /// Cache of constant strings, const_cstr_cache: RefCell>, @@ -800,7 +801,9 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> { &self.local().instances } - pub fn vtables<'a>(&'a self) -> &'a RefCell, ValueRef>> { + pub fn vtables<'a>(&'a self) + -> &'a RefCell, + Option>), ValueRef>> { &self.local().vtables } diff --git a/src/librustc_trans/debuginfo/metadata.rs b/src/librustc_trans/debuginfo/metadata.rs index 5d01ca892b316..8bbe50af0651c 100644 --- a/src/librustc_trans/debuginfo/metadata.rs +++ b/src/librustc_trans/debuginfo/metadata.rs @@ -431,8 +431,13 @@ fn trait_pointer_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, // type is assigned the correct name, size, namespace, and source location. // But it does not describe the trait's methods. - let def_id = match trait_type.sty { - ty::TyTrait(ref data) => data.principal.def_id(), + let containing_scope = match trait_type.sty { + 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 { + NO_SCOPE_METADATA + }, _ => { bug!("debuginfo: Unexpected trait-object type in \ trait_pointer_metadata(): {:?}", @@ -444,8 +449,6 @@ fn trait_pointer_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, let trait_type_name = compute_debuginfo_type_name(cx, trait_object_type, false); - let (containing_scope, _) = get_namespace_and_span_for_item(cx, def_id); - let trait_llvm_type = type_of::type_of(cx, trait_object_type); let file_metadata = unknown_file_metadata(cx); @@ -520,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) @@ -535,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) diff --git a/src/librustc_trans/debuginfo/type_names.rs b/src/librustc_trans/debuginfo/type_names.rs index fce1ce5610555..80e6bd7aa2984 100644 --- a/src/librustc_trans/debuginfo/type_names.rs +++ b/src/librustc_trans/debuginfo/type_names.rs @@ -93,11 +93,13 @@ 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) => { - let principal = cx.tcx().erase_late_bound_regions_and_normalize( - &trait_data.principal); - push_item_name(cx, principal.def_id, false, output); - push_type_params(cx, principal.substs, output); + ty::TyDynamic(ref trait_data, ..) => { + if let Some(principal) = trait_data.principal() { + let principal = cx.tcx().erase_late_bound_regions_and_normalize( + &principal); + push_item_name(cx, principal.def_id, false, output); + push_type_params(cx, principal.substs, output); + } }, ty::TyFnDef(.., &ty::BareFnTy{ unsafety, abi, ref sig } ) | ty::TyFnPtr(&ty::BareFnTy{ unsafety, abi, ref sig } ) => { diff --git a/src/librustc_trans/glue.rs b/src/librustc_trans/glue.rs index d6d4d33923f1a..06d0b1e19828e 100644 --- a/src/librustc_trans/glue.rs +++ b/src/librustc_trans/glue.rs @@ -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. diff --git a/src/librustc_trans/meth.rs b/src/librustc_trans/meth.rs index 1e687f5ff6e3a..aa9b900fa4653 100644 --- a/src/librustc_trans/meth.rs +++ b/src/librustc_trans/meth.rs @@ -110,42 +110,48 @@ pub fn trans_object_shim<'a, 'tcx>(ccx: &'a CrateContext<'a, 'tcx>, /// making an object `Foo` from a value of type `Foo`, 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>) -> 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 } diff --git a/src/librustc_trans/trans_item.rs b/src/librustc_trans/trans_item.rs index f2d1e375793b3..322c5eb6e182a 100644 --- a/src/librustc_trans/trans_item.rs +++ b/src/librustc_trans/trans_item.rs @@ -36,6 +36,7 @@ use glue; use abi::{Abi, FnType}; use back::symbol_names; use std::fmt::Write; +use std::iter; #[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)] pub enum TransItem<'tcx> { @@ -410,7 +411,7 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> { ty::TyFloat(ast::FloatTy::F64) => output.push_str("f64"), ty::TyAdt(adt_def, substs) => { self.push_def_path(adt_def.did, output); - self.push_type_params(substs, &[], output); + self.push_type_params(substs, iter::empty(), output); }, ty::TyTuple(component_types) => { output.push('('); @@ -457,11 +458,13 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> { self.push_type_name(inner_type, output); output.push(']'); }, - ty::TyTrait(ref trait_data) => { - self.push_def_path(trait_data.principal.def_id(), output); - self.push_type_params(trait_data.principal.skip_binder().substs, - &trait_data.projection_bounds, - output); + 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(), + output); + } }, ty::TyFnDef(.., &ty::BareFnTy{ unsafety, abi, ref sig } ) | ty::TyFnPtr(&ty::BareFnTy{ unsafety, abi, ref sig } ) => { @@ -511,7 +514,7 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> { self.push_def_path(def_id, output); let generics = self.tcx.item_generics(self.tcx.closure_base_def_id(def_id)); let substs = closure_substs.substs.truncate_to(self.tcx, generics); - self.push_type_params(substs, &[], output); + self.push_type_params(substs, iter::empty(), output); } ty::TyError | ty::TyInfer(_) | @@ -551,11 +554,14 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> { output.pop(); } - pub fn push_type_params(&self, + fn push_type_params(&self, substs: &Substs<'tcx>, - projections: &[ty::PolyExistentialProjection<'tcx>], - output: &mut String) { - if substs.types().next().is_none() && projections.is_empty() { + projections: I, + output: &mut String) + where I: Iterator> + { + let mut projections = projections.peekable(); + if substs.types().next().is_none() && projections.peek().is_none() { return; } @@ -585,6 +591,6 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> { instance: Instance<'tcx>, output: &mut String) { self.push_def_path(instance.def, output); - self.push_type_params(instance.substs, &[], output); + self.push_type_params(instance.substs, iter::empty(), output); } } diff --git a/src/librustc_trans/type_of.rs b/src/librustc_trans/type_of.rs index 16d4f97200cb2..22c405fe254a6 100644 --- a/src/librustc_trans/type_of.rs +++ b/src/librustc_trans/type_of.rs @@ -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) => { diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index bb7b62533001d..9f3887a87686a 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -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::common::{ErrorReported, FN_OUTPUT_NAME}; 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}; @@ -960,7 +962,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { ty.id, path.segments.last().unwrap(), span, - partition_bounds(tcx, span, bounds)) + partition_bounds(bounds)) } else { struct_span_err!(tcx.sess, ty.span, E0172, "expected a reference to a trait") @@ -1043,17 +1045,18 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { trait_segment, &mut projection_bounds); - let PartitionedBounds { builtin_bounds, - trait_bounds, + let PartitionedBounds { trait_bounds, region_bounds } = partitioned_bounds; + let (auto_traits, trait_bounds) = split_auto_traits(tcx, trait_bounds); + if !trait_bounds.is_empty() { 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 +1073,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { ty: b.ty } }) - }).collect(); - - let region_bound = - self.compute_object_lifetime_bound(span, - ®ion_bounds, - existential_principal, - builtin_bounds); - - 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 +1115,37 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { .emit(); } - let ty = tcx.mk_trait(ty::TraitObject { - principal: existential_principal, - region_bound: region_bound, - builtin_bounds: builtin_bounds, - projection_bounds: 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::>(); + 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, + ®ion_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 } @@ -1439,7 +1444,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { path_id, path.segments.last().unwrap(), span, - partition_bounds(tcx, span, &[])) + partition_bounds(&[])) } Def::Enum(did) | Def::TyAlias(did) | Def::Struct(did) | Def::Union(did) => { assert_eq!(opt_self_ty, None); @@ -1893,7 +1898,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { ast_bounds: &[hir::TyParamBound]) -> Ty<'tcx> { - let mut partitioned_bounds = partition_bounds(self.tcx(), span, &ast_bounds[..]); + let mut partitioned_bounds = partition_bounds(ast_bounds); let trait_bound = if !partitioned_bounds.trait_bounds.is_empty() { partitioned_bounds.trait_bounds.remove(0) @@ -1922,38 +1927,36 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { fn compute_object_lifetime_bound(&self, span: Span, explicit_region_bounds: &[&hir::Lifetime], - principal_trait_ref: ty::PolyExistentialTraitRef<'tcx>, - builtin_bounds: ty::BuiltinBounds) + existential_predicates: ty::Binder<&'tcx ty::Slice>>) -> Option<&'tcx ty::Region> // if None, use the default { let tcx = self.tcx(); debug!("compute_opt_region_bound(explicit_region_bounds={:?}, \ - principal_trait_ref={:?}, builtin_bounds={:?})", + existential_predicates={:?})", explicit_region_bounds, - principal_trait_ref, - builtin_bounds); + 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, builtin_bounds); + 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. @@ -1980,46 +1983,62 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { } pub struct PartitionedBounds<'a> { - pub builtin_bounds: ty::BuiltinBounds, pub trait_bounds: Vec<&'a hir::PolyTraitRef>, pub region_bounds: Vec<&'a hir::Lifetime>, } -/// Divides a list of bounds from the AST into three groups: builtin bounds (Copy, Sized etc), -/// general trait bounds, and region bounds. -pub fn partition_bounds<'a, 'b, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, - _span: Span, - ast_bounds: &'b [hir::TyParamBound]) - -> PartitionedBounds<'b> +/// Divides a list of general trait bounds into two groups: builtin bounds (Sync/Send) and the +/// remaining general trait bounds. +fn split_auto_traits<'a, 'b, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, + trait_bounds: Vec<&'b hir::PolyTraitRef>) + -> (Vec, Vec<&'b hir::PolyTraitRef>) +{ + let (auto_traits, trait_bounds): (Vec<_>, _) = trait_bounds.into_iter().partition(|bound| { + match bound.trait_ref.path.def { + Def::Trait(trait_did) => { + // 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() { + let segments = &bound.trait_ref.path.segments; + let parameters = &segments[segments.len() - 1].parameters; + if !parameters.types().is_empty() { + check_type_argument_count(tcx, bound.trait_ref.path.span, + parameters.types().len(), &[]); + } + if !parameters.lifetimes().is_empty() { + report_lifetime_number_error(tcx, bound.trait_ref.path.span, + parameters.lifetimes().len(), 0); + } + true + } else { + false + } + } + _ => false + } + }); + + let auto_traits = auto_traits.into_iter().map(|tr| { + if let Def::Trait(trait_did) = tr.trait_ref.path.def { + trait_did + } else { + unreachable!() + } + }).collect::>(); + + (auto_traits, trait_bounds) +} + +/// Divides a list of bounds from the AST into two groups: general trait bounds and region bounds +pub fn partition_bounds<'a, 'b, 'gcx, 'tcx>(ast_bounds: &'b [hir::TyParamBound]) + -> PartitionedBounds<'b> { - let mut builtin_bounds = ty::BuiltinBounds::empty(); let mut region_bounds = Vec::new(); let mut trait_bounds = Vec::new(); for ast_bound in ast_bounds { match *ast_bound { 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 builtin_bounds) { - let segments = &b.trait_ref.path.segments; - let parameters = &segments[segments.len() - 1].parameters; - if !parameters.types().is_empty() { - check_type_argument_count(tcx, b.trait_ref.path.span, - parameters.types().len(), &[]); - } - if !parameters.lifetimes().is_empty() { - report_lifetime_number_error(tcx, b.trait_ref.path.span, - parameters.lifetimes().len(), 0); - } - continue; // success - } - } - _ => { - // Not a trait? that's an error, but it'll get - // reported later. - } - } trait_bounds.push(b); } hir::TraitTyParamBound(_, hir::TraitBoundModifier::Maybe) => {} @@ -2030,7 +2049,6 @@ pub fn partition_bounds<'a, 'b, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, } PartitionedBounds { - builtin_bounds: builtin_bounds, trait_bounds: trait_bounds, region_bounds: region_bounds, } @@ -2105,7 +2123,7 @@ fn report_lifetime_number_error(tcx: TyCtxt, span: Span, number: usize, expected #[derive(PartialEq, Eq, Clone, Debug)] pub struct Bounds<'tcx> { pub region_bounds: Vec<&'tcx ty::Region>, - pub builtin_bounds: ty::BuiltinBounds, + pub implicitly_sized: bool, pub trait_bounds: Vec>, pub projection_bounds: Vec>, } @@ -2116,10 +2134,14 @@ impl<'a, 'gcx, 'tcx> Bounds<'tcx> { { let mut vec = Vec::new(); - for builtin_bound in &self.builtin_bounds { - match tcx.trait_ref_for_builtin_bound(builtin_bound, param_ty) { - Ok(trait_ref) => { vec.push(trait_ref.to_predicate()); } - Err(ErrorReported) => { } + // 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()); } } diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 63e797a87ff21..6e2b42881a709 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -340,7 +340,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, '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", an error. let type_str = self.ty_to_string(expected); diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index 5839c606566c3..f2c8ef46a7e25 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -46,6 +46,7 @@ use rustc::hir; use rustc::traits; use rustc::ty::{self, Ty, TypeFoldable}; use rustc::ty::cast::{CastKind, CastTy}; +use rustc::middle::lang_items; use syntax::ast; use syntax_pos::Span; use util::common::ErrorReported; @@ -64,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), Length, /// The unsize info of this projection OfProjection(&'tcx ty::ProjectionTy<'tcx>), @@ -78,7 +79,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { fn unsize_kind(&self, t: Ty<'tcx>) -> Option> { match t.sty { ty::TySlice(_) | ty::TyStr => Some(UnsizeKind::Length), - ty::TyTrait(ref tty) => Some(UnsizeKind::Vtable(tty.principal.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() { @@ -129,7 +131,7 @@ impl<'a, 'gcx, 'tcx> CastCheck<'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) } @@ -543,6 +545,7 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { fn type_is_known_to_be_sized(&self, ty: Ty<'tcx>, span: Span) -> bool { - traits::type_known_to_meet_builtin_bound(self, ty, ty::BoundSized, span) + let lang_item = self.tcx.require_lang_item(lang_items::SizedTraitLangItem); + traits::type_known_to_meet_bound(self, ty, lang_item, span) } } diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index 75287d4064ae1..744d99fe60d17 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -111,15 +111,15 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { 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.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), diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs index 8868d1e54f4b9..a5446b0fbaa89 100644 --- a/src/librustc_typeck/check/dropck.rs +++ b/src/librustc_typeck/check/dropck.rs @@ -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; }, diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 54e93978b798d..ff9eaa012ba41 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -255,7 +255,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { .autoderef(self.span, self_ty) .filter_map(|(ty, _)| { match ty.sty { - ty::TyTrait(ref data) => Some(closure(self, ty, data.principal)), + ty::TyDynamic(ref data, ..) => data.principal().map(|p| closure(self, ty, p)), _ => None, } }) diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 545d4e788524f..b0787d75c9cb4 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -295,9 +295,11 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, '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); - self.assemble_inherent_impl_candidates_for_type(data.principal.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); diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 6598790355e82..9443e0a3586b0 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -379,7 +379,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { match ty.sty { ty::TyAdt(def, _) => def.did.is_local(), - ty::TyTrait(ref tr) => tr.principal.def_id().is_local(), + ty::TyDynamic(ref tr, ..) => tr.principal() + .map_or(false, |p| p.def_id().is_local()), ty::TyParam(_) => true, diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 2babb81bc407a..df3d68d225440 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -123,6 +123,7 @@ use rustc::hir::intravisit::{self, Visitor}; use rustc::hir::itemlikevisit::ItemLikeVisitor; use rustc::hir::{self, PatKind}; use rustc::hir::print as pprust; +use rustc::middle::lang_items; use rustc_back::slice; use rustc_const_eval::eval_length; @@ -268,7 +269,7 @@ impl<'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) @@ -1805,11 +1806,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { ty: Ty<'tcx>, span: Span, code: traits::ObligationCauseCode<'tcx>, - bound: ty::BuiltinBound) + def_id: DefId) { - self.register_builtin_bound( + self.register_bound( ty, - bound, + def_id, traits::ObligationCause::new(span, self.body_id, code)); } @@ -1818,16 +1819,17 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { span: Span, code: traits::ObligationCauseCode<'tcx>) { - self.require_type_meets(ty, span, code, ty::BoundSized); + let lang_item = self.tcx.require_lang_item(lang_items::SizedTraitLangItem); + self.require_type_meets(ty, span, code, lang_item); } - pub fn register_builtin_bound(&self, + pub fn register_bound(&self, ty: Ty<'tcx>, - builtin_bound: ty::BuiltinBound, + def_id: DefId, cause: traits::ObligationCause<'tcx>) { self.fulfillment_cx.borrow_mut() - .register_builtin_bound(self, ty, builtin_bound, cause); + .register_bound(self, ty, def_id, cause); } pub fn register_predicate(&self, @@ -3899,7 +3901,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if count > 1 { // For [foo, ..n] where n > 1, `foo` must have // Copy type: - self.require_type_meets(t, expr.span, traits::RepeatVec, ty::BoundCopy); + let lang_item = self.tcx.require_lang_item(lang_items::CopyTraitLangItem); + self.require_type_meets(t, expr.span, traits::RepeatVec, lang_item); } if element_ty.references_error() { diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index ca33682480c4c..fb35cb8181cb3 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -806,11 +806,10 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { } /*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), diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 1ad81660f836a..28aa4b9ef3893 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -18,6 +18,7 @@ use middle::region::{CodeExtent}; use rustc::traits::{self, ObligationCauseCode}; use rustc::ty::{self, Ty, TyCtxt}; use rustc::util::nodemap::{FxHashSet, FxHashMap}; +use rustc::middle::lang_items; use syntax::ast; use syntax_pos::Span; @@ -117,14 +118,8 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> { // 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); - match ccx.tcx.lang_items.to_builtin_kind(trait_ref.def_id) { - Some(ty::BoundSend) | Some(ty::BoundSync) => {} - Some(_) | None => { - 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) => { @@ -241,9 +236,9 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> { // For DST, all intermediate types must be sized. let unsized_len = if all_sized || variant.fields.is_empty() { 0 } else { 1 }; for field in &variant.fields[..variant.fields.len() - unsized_len] { - fcx.register_builtin_bound( + fcx.register_bound( field.ty, - ty::BoundSized, + fcx.tcx.require_lang_item(lang_items::SizedTraitLangItem), traits::ObligationCause::new(field.span, fcx.body_id, traits::FieldSized)); diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs index 2663739e36b28..30472f85db120 100644 --- a/src/librustc_typeck/coherence/mod.rs +++ b/src/librustc_typeck/coherence/mod.rs @@ -23,7 +23,7 @@ use rustc::traits::{self, ObligationCause, Reveal}; 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 @@ impl<'a, 'gcx, 'tcx> CoherenceChecker<'a, 'gcx, 'tcx> { match ty.sty { TyAdt(def, _) => Some(def.did), - TyTrait(ref t) => Some(t.principal.def_id()), + TyDynamic(ref t, ..) => t.principal().map(|p| p.def_id()), TyBox(_) => self.inference_context.tcx.lang_items.owned_box(), diff --git a/src/librustc_typeck/coherence/orphan.rs b/src/librustc_typeck/coherence/orphan.rs index a507077bef77e..f04442de09c30 100644 --- a/src/librustc_typeck/coherence/orphan.rs +++ b/src/librustc_typeck/coherence/orphan.rs @@ -86,8 +86,8 @@ impl<'cx, 'tcx> OrphanChecker<'cx, 'tcx> { ty::TyAdt(def, _) => { self.check_def_id(item, def.did); } - ty::TyTrait(ref data) => { - self.check_def_id(item, data.principal.def_id()); + ty::TyDynamic(ref data, ..) if data.principal().is_some() => { + self.check_def_id(item, data.principal().unwrap().def_id()); } ty::TyBox(..) => { match self.tcx.lang_items.require_owned_box() { diff --git a/src/librustc_typeck/coherence/overlap.rs b/src/librustc_typeck/coherence/overlap.rs index e5be7f63067a8..815811675a54b 100644 --- a/src/librustc_typeck/coherence/overlap.rs +++ b/src/librustc_typeck/coherence/overlap.rs @@ -178,18 +178,17 @@ impl<'cx, 'tcx, 'v> ItemLikeVisitor<'v> for OverlapChecker<'cx, 'tcx> { } // 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 !self.tcx.is_object_safe(data.principal.def_id()) { - // This is an error, but it will be - // reported by wfcheck. Ignore it - // here. This is tested by - // `coherence-impl-trait-for-trait-object-safe.rs`. + 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, data.principal.def_id()); + traits::supertrait_def_ids(self.tcx, + data.principal().unwrap().def_id()); if supertrait_def_ids.any(|d| d == trait_def_id) { span_err!(self.tcx.sess, item.span, diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 0dcc0bcc316ce..8495c1b3fb8ae 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1584,11 +1584,10 @@ fn convert_foreign_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, assert!(prev_predicates.is_none()); } -// Add the Sized bound, unless the type parameter is marked as `?Sized`. -fn add_unsized_bound<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>, - bounds: &mut ty::BuiltinBounds, - ast_bounds: &[hir::TyParamBound], - span: Span) +// Is it marked with ?Sized +fn is_unsized<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>, + ast_bounds: &[hir::TyParamBound], + span: Span) -> bool { let tcx = astconv.tcx(); @@ -1617,16 +1616,17 @@ 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); + return false; } // No lang item for Sized, so we can't add it as a bound. None => {} } + + true } /// Returns the early-bound lifetimes declared in this generics @@ -1908,14 +1908,9 @@ pub fn compute_bounds<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>, { let tcx = astconv.tcx(); let PartitionedBounds { - mut builtin_bounds, trait_bounds, region_bounds - } = partition_bounds(tcx, span, &ast_bounds); - - if let SizedByDefault::Yes = sized_by_default { - add_unsized_bound(astconv, &mut builtin_bounds, ast_bounds, span); - } + } = partition_bounds(&ast_bounds); let mut projection_bounds = vec![]; @@ -1933,9 +1928,15 @@ pub fn compute_bounds<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>, trait_bounds.sort_by(|a,b| a.def_id().cmp(&b.def_id())); + let implicitly_sized = if let SizedByDefault::Yes = sized_by_default { + !is_unsized(astconv, ast_bounds, span) + } else { + false + }; + Bounds { region_bounds: region_bounds, - builtin_bounds: builtin_bounds, + implicitly_sized: implicitly_sized, trait_bounds: trait_bounds, projection_bounds: projection_bounds, } diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index 04314045733ec..01e99a296e886 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -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: ``` diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs index 686d1a4a7716d..f34753c227d71 100644 --- a/src/librustc_typeck/variance/constraints.rs +++ b/src/librustc_typeck/variance/constraints.rs @@ -371,15 +371,17 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { variance); } - ty::TyTrait(ref data) => { + ty::TyDynamic(ref data, r) => { // The type `Foo` 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.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); } } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index e233613ee629e..8d65a5dbc6fcb 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -30,6 +30,7 @@ use syntax_pos::{self, DUMMY_SP, Pos}; use rustc_trans::back::link; use rustc::middle::privacy::AccessLevels; use rustc::middle::resolve_lifetime::DefRegion::*; +use rustc::middle::lang_items; use rustc::hir::def::{Def, CtorKind}; use rustc::hir::def_id::{self, DefId, DefIndex, CRATE_DEF_INDEX}; use rustc::hir::print as pprust; @@ -593,12 +594,20 @@ pub enum TyParamBound { impl TyParamBound { fn maybe_sized(cx: &DocContext) -> TyParamBound { - use rustc::hir::TraitBoundModifier as TBM; - let mut sized_bound = ty::BoundSized.clean(cx); - if let TyParamBound::TraitBound(_, ref mut tbm) = sized_bound { - *tbm = TBM::Maybe - }; - sized_bound + let did = cx.tcx.require_lang_item(lang_items::SizedTraitLangItem); + 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 { + trait_: ResolvedPath { + path: path, + typarams: None, + did: did, + is_generic: false, + }, + lifetimes: vec![] + }, hir::TraitBoundModifier::Maybe) } fn is_sized_bound(&self, cx: &DocContext) -> bool { @@ -675,37 +684,6 @@ fn external_path(cx: &DocContext, name: &str, trait_did: Option, has_self } } -impl Clean for ty::BuiltinBound { - fn clean(&self, cx: &DocContext) -> TyParamBound { - let tcx = cx.tcx; - let empty = tcx.intern_substs(&[]); - let (did, path) = match *self { - ty::BoundSend => - (tcx.lang_items.send_trait().unwrap(), - external_path(cx, "Send", None, false, vec![], empty)), - ty::BoundSized => - (tcx.lang_items.sized_trait().unwrap(), - external_path(cx, "Sized", None, false, vec![], empty)), - ty::BoundCopy => - (tcx.lang_items.copy_trait().unwrap(), - external_path(cx, "Copy", None, false, vec![], empty)), - ty::BoundSync => - (tcx.lang_items.sync_trait().unwrap(), - external_path(cx, "Sync", None, false, vec![], empty)), - }; - inline::record_extern_fqn(cx, did, TypeKind::Trait); - TraitBound(PolyTrait { - trait_: ResolvedPath { - path: path, - typarams: None, - did: did, - is_generic: false, - }, - lifetimes: vec![] - }, hir::TraitBoundModifier::None) - } -} - impl<'tcx> Clean for ty::TraitRef<'tcx> { fn clean(&self, cx: &DocContext) -> TyParamBound { inline::record_extern_fqn(cx, self.def_id, TypeKind::Trait); @@ -1876,31 +1854,48 @@ impl<'tcx> Clean for ty::Ty<'tcx> { is_generic: false, } } - ty::TyTrait(ref obj) => { - let did = obj.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))); - for bb in &obj.builtin_bounds { - typarams.push(bb.clean(cx)); - } + 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![]; + reg.clean(cx).map(|b| typarams.push(RegionBound(b))); + for did in obj.auto_traits() { + 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 { + trait_: ResolvedPath { + path: path, + typarams: None, + did: did, + is_generic: false, + }, + lifetimes: vec![] + }, hir::TraitBoundModifier::None); + typarams.push(bound); + } - let mut bindings = vec![]; - for &ty::Binder(ref pb) in &obj.projection_bounds { - bindings.push(TypeBinding { - name: pb.item_name.clean(cx), - ty: pb.ty.clean(cx) - }); - } + let mut bindings = vec![]; + 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), false, bindings, obj.principal.0.substs); - ResolvedPath { - path: path, - typarams: Some(typarams), - did: did, - is_generic: false, + let path = external_path(cx, &cx.tcx.item_name(did).as_str(), Some(did), + false, bindings, principal.0.substs); + ResolvedPath { + path: path, + typarams: Some(typarams), + did: did, + is_generic: false, + } + } else { + Never } } ty::TyTuple(ref t) => Tuple(t.clean(cx)), diff --git a/src/test/compile-fail/E0225.rs b/src/test/compile-fail/E0225.rs index b013788ceff85..8c79c15e3de5b 100644 --- a/src/test/compile-fail/E0225.rs +++ b/src/test/compile-fail/E0225.rs @@ -10,6 +10,6 @@ fn main() { let _: Box; - //~^ 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 } diff --git a/src/test/compile-fail/bad-sized.rs b/src/test/compile-fail/bad-sized.rs index e9d0b986c1176..a2e2e5caafe6d 100644 --- a/src/test/compile-fail/bad-sized.rs +++ b/src/test/compile-fail/bad-sized.rs @@ -12,8 +12,7 @@ trait Trait {} pub fn main() { let x: Vec = Vec::new(); - //~^ ERROR `Trait + Sized: std::marker::Sized` is not satisfied - //~| ERROR the trait `std::marker::Sized` cannot be made into an object - //~| ERROR `Trait + 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 } diff --git a/src/test/compile-fail/const-unsized.rs b/src/test/compile-fail/const-unsized.rs index 226b567c546e5..23cff4ac6ad6c 100644 --- a/src/test/compile-fail/const-unsized.rs +++ b/src/test/compile-fail/const-unsized.rs @@ -11,8 +11,8 @@ use std::fmt::Debug; const CONST_0: Debug+Sync = *(&0 as &(Debug+Sync)); -//~^ ERROR `std::fmt::Debug + Sync + 'static: std::marker::Sized` is not satisfied -//~| NOTE the trait `std::marker::Sized` is not implemented for `std::fmt::Debug + Sync + 'static` +//~^ ERROR `std::fmt::Debug + std::marker::Sync + 'static: std::marker::Sized` is not satisfied +//~| NOTE the trait `std::marker::Sized` is not implemented for `std::fmt::Debug + std::marker::Syn //~| NOTE does not have a constant size known at compile-time //~| NOTE constant expressions must have a statically known size @@ -23,8 +23,8 @@ const CONST_FOO: str = *"foo"; //~| NOTE constant expressions must have a statically known size static STATIC_1: Debug+Sync = *(&1 as &(Debug+Sync)); -//~^ ERROR `std::fmt::Debug + Sync + 'static: std::marker::Sized` is not satisfied -//~| NOTE the trait `std::marker::Sized` is not implemented for `std::fmt::Debug + Sync + 'static` +//~^ ERROR `std::fmt::Debug + std::marker::Sync + 'static: std::marker::Sized` is not satisfied +//~| NOTE the trait `std::marker::Sized` is not implemented for `std::fmt::Debug + std::marker::Syn //~| NOTE does not have a constant size known at compile-time //~| NOTE constant expressions must have a statically known size diff --git a/src/test/compile-fail/issue-16966.rs b/src/test/compile-fail/issue-16966.rs index 5dbf7546de224..508442fcb9453 100644 --- a/src/test/compile-fail/issue-16966.rs +++ b/src/test/compile-fail/issue-16966.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// error-pattern:type annotations required +// error-pattern:type annotations or generic parameter binding required fn main() { panic!( std::default::Default::default() diff --git a/src/test/compile-fail/issue-22560.rs b/src/test/compile-fail/issue-22560.rs index 45b110bf5631d..2ad804fc8ced7 100644 --- a/src/test/compile-fail/issue-22560.rs +++ b/src/test/compile-fail/issue-22560.rs @@ -20,6 +20,6 @@ type Test = Add + //~| NOTE missing associated type `Output` value Sub; //~^ ERROR E0225 - //~| NOTE non-builtin trait used as bounds + //~| NOTE non-Send/Sync additional trait fn main() { } diff --git a/src/test/compile-fail/issue-32963.rs b/src/test/compile-fail/issue-32963.rs index 8ba95d14931e0..f146cfbe68b96 100644 --- a/src/test/compile-fail/issue-32963.rs +++ b/src/test/compile-fail/issue-32963.rs @@ -16,6 +16,6 @@ fn size_of_copy() -> usize { mem::size_of::() } fn main() { size_of_copy::(); - //~^ ERROR `Misc + 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 } diff --git a/src/test/compile-fail/trait-bounds-cant-coerce.rs b/src/test/compile-fail/trait-bounds-cant-coerce.rs index 1fff812af5b8d..9f832c7b6e500 100644 --- a/src/test/compile-fail/trait-bounds-cant-coerce.rs +++ b/src/test/compile-fail/trait-bounds-cant-coerce.rs @@ -21,10 +21,10 @@ fn c(x: Box) { } fn d(x: Box) { - a(x); //~ ERROR mismatched types - //~| expected type `Box` - //~| found type `Box` - //~| expected bounds `Send`, found no bounds + a(x); //~ ERROR mismatched types [E0308] + //~| NOTE expected type `Box` + //~| NOTE found type `Box` + //~| NOTE expected trait `Foo + std::marker::Send`, found trait `Foo` } fn main() { } diff --git a/src/test/compile-fail/trait-bounds-not-on-bare-trait.rs b/src/test/compile-fail/trait-bounds-not-on-bare-trait.rs index fd46d1a62962c..983c66ec1c40f 100644 --- a/src/test/compile-fail/trait-bounds-not-on-bare-trait.rs +++ b/src/test/compile-fail/trait-bounds-not-on-bare-trait.rs @@ -15,7 +15,7 @@ trait Foo { // This should emit the less confusing error, not the more confusing one. fn foo(_x: Foo + Send) { - //~^ ERROR `Foo + Send + 'static: std::marker::Sized` is not satisfied + //~^ ERROR the trait bound `Foo + std::marker::Send + 'static: std::marker::Sized` is not } fn main() { } diff --git a/src/test/run-pass/auxiliary/issue13507.rs b/src/test/run-pass/auxiliary/issue13507.rs index ca1027b11adce..ba50aed42c36f 100644 --- a/src/test/run-pass/auxiliary/issue13507.rs +++ b/src/test/run-pass/auxiliary/issue13507.rs @@ -70,7 +70,7 @@ pub mod testtypes { // Tests TyFnPtr pub type FooFnPtr = fn(u8) -> bool; - // Tests TyTrait + // Tests TyDynamic pub trait FooTrait { fn foo_method(&self) -> usize; }