Refactor TyTrait to contain a interned ExistentialPredicate slice.

Renames TyTrait to TyDynamic.
This commit is contained in:
Mark-Simulacrum 2016-11-16 09:21:49 -07:00
parent 64e97d9b33
commit bb35d50cad
59 changed files with 611 additions and 512 deletions

View File

@ -140,7 +140,7 @@ DEPS_rustc_trans := arena flate getopts graphviz libc rustc rustc_back \
DEPS_rustc_incremental := rustc syntax_pos serialize rustc_data_structures DEPS_rustc_incremental := rustc syntax_pos serialize rustc_data_structures
DEPS_rustc_save_analysis := rustc log syntax syntax_pos serialize DEPS_rustc_save_analysis := rustc log syntax syntax_pos serialize
DEPS_rustc_typeck := rustc syntax syntax_pos rustc_platform_intrinsics rustc_const_math \ 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 \ DEPS_rustdoc := rustc rustc_driver native:hoedown serialize getopts test \
rustc_lint rustc_const_eval syntax_pos rustc_data_structures rustc_lint rustc_const_eval syntax_pos rustc_data_structures

View File

@ -165,7 +165,7 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for TypeFreshener<'a, 'gcx, 'tcx> {
ty::TyRef(..) | ty::TyRef(..) |
ty::TyFnDef(..) | ty::TyFnDef(..) |
ty::TyFnPtr(_) | ty::TyFnPtr(_) |
ty::TyTrait(..) | ty::TyDynamic(..) |
ty::TyClosure(..) | ty::TyClosure(..) |
ty::TyNever | ty::TyNever |
ty::TyTuple(..) | ty::TyTuple(..) |

View File

@ -227,7 +227,7 @@ fn fundamental_ty(tcx: TyCtxt, ty: Ty) -> bool {
match ty.sty { match ty.sty {
ty::TyBox(..) | ty::TyRef(..) => true, ty::TyBox(..) | ty::TyRef(..) => true,
ty::TyAdt(def, _) => def.is_fundamental(), ty::TyAdt(def, _) => def.is_fundamental(),
ty::TyTrait(ref data) => { ty::TyDynamic(ref data, ..) => {
data.principal().map_or(false, |p| tcx.has_attr(p.def_id(), "fundamental")) data.principal().map_or(false, |p| tcx.has_attr(p.def_id(), "fundamental"))
} }
_ => false _ => false
@ -270,7 +270,7 @@ fn ty_is_local_constructor(tcx: TyCtxt, ty: Ty, infer_is_local: InferIsLocal)->
krate == Some(LOCAL_CRATE) krate == Some(LOCAL_CRATE)
} }
ty::TyTrait(ref tt) => { ty::TyDynamic(ref tt, ..) => {
tt.principal().map_or(false, |p| p.def_id().is_local()) tt.principal().map_or(false, |p| p.def_id().is_local())
} }

View File

@ -156,7 +156,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
ty::TyBox(..) | ty::TyRef(..) | ty::TyRawPtr(..) => Some(5), ty::TyBox(..) | ty::TyRef(..) | ty::TyRawPtr(..) => Some(5),
ty::TyArray(..) | ty::TySlice(..) => Some(6), ty::TyArray(..) | ty::TySlice(..) => Some(6),
ty::TyFnDef(..) | ty::TyFnPtr(..) => Some(7), ty::TyFnDef(..) | ty::TyFnPtr(..) => Some(7),
ty::TyTrait(..) => Some(8), ty::TyDynamic(..) => Some(8),
ty::TyClosure(..) => Some(9), ty::TyClosure(..) => Some(9),
ty::TyTuple(..) => Some(10), ty::TyTuple(..) => Some(10),
ty::TyProjection(..) => Some(11), ty::TyProjection(..) => Some(11),

View File

@ -231,10 +231,10 @@ impl<'a, 'gcx, 'tcx> FulfillmentContext<'tcx> {
} }
pub fn register_bound(&mut self, pub fn register_bound(&mut self,
infcx: &InferCtxt<'a, 'gcx, 'tcx>, infcx: &InferCtxt<'a, 'gcx, 'tcx>,
ty: Ty<'tcx>, ty: Ty<'tcx>,
def_id: DefId, def_id: DefId,
cause: ObligationCause<'tcx>) cause: ObligationCause<'tcx>)
{ {
let trait_ref = ty::TraitRef { let trait_ref = ty::TraitRef {
def_id: def_id, def_id: def_id,

View File

@ -366,10 +366,10 @@ pub fn predicates_for_generics<'tcx>(cause: ObligationCause<'tcx>,
/// conservative towards *no impl*, which is the opposite of the /// conservative towards *no impl*, which is the opposite of the
/// `evaluate` methods). /// `evaluate` methods).
pub fn type_known_to_meet_bound<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>, pub fn type_known_to_meet_bound<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
ty: Ty<'tcx>, ty: Ty<'tcx>,
def_id: DefId, def_id: DefId,
span: Span) span: Span)
-> bool -> bool
{ {
debug!("type_known_to_meet_bound(ty={:?}, bound={:?})", debug!("type_known_to_meet_bound(ty={:?}, bound={:?})",
ty, ty,

View File

@ -1123,7 +1123,7 @@ fn confirm_object_candidate<'cx, 'gcx, 'tcx>(
debug!("confirm_object_candidate(object_ty={:?})", debug!("confirm_object_candidate(object_ty={:?})",
object_ty); object_ty);
let data = match object_ty.sty { let data = match object_ty.sty {
ty::TyTrait(ref data) => data, ty::TyDynamic(ref data, ..) => data,
_ => { _ => {
span_bug!( span_bug!(
obligation.cause.span, obligation.cause.span,
@ -1131,7 +1131,7 @@ fn confirm_object_candidate<'cx, 'gcx, 'tcx>(
object_ty) 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() p.with_self_ty(selcx.tcx(), object_ty).to_predicate()
}).collect(); }).collect();
let env_predicate = { let env_predicate = {

View File

@ -50,7 +50,6 @@ use std::fmt;
use std::marker::PhantomData; use std::marker::PhantomData;
use std::mem; use std::mem;
use std::rc::Rc; use std::rc::Rc;
use std::iter;
use syntax::abi::Abi; use syntax::abi::Abi;
use hir; use hir;
use util::nodemap::FxHashMap; use util::nodemap::FxHashMap;
@ -1094,38 +1093,30 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
// and applicable impls. There is a certain set of precedence rules here. // and applicable impls. There is a certain set of precedence rules here.
let def_id = obligation.predicate.def_id(); let def_id = obligation.predicate.def_id();
match obligation.predicate.def_id() { if self.tcx().lang_items.copy_trait() == Some(def_id) {
_ if self.tcx().lang_items.copy_trait() == Some(def_id) => { debug!("obligation self ty is {:?}",
debug!("obligation self ty is {:?}", obligation.predicate.0.self_ty());
obligation.predicate.0.self_ty());
// User-defined copy impls are permitted, but only for // User-defined copy impls are permitted, but only for
// structs and enums. // structs and enums.
self.assemble_candidates_from_impls(obligation, &mut candidates)?; self.assemble_candidates_from_impls(obligation, &mut candidates)?;
// For other types, we'll use the builtin rules. // For other types, we'll use the builtin rules.
let copy_conditions = self.copy_conditions(obligation); let copy_conditions = self.copy_conditions(obligation);
self.assemble_builtin_bound_candidates(copy_conditions, &mut candidates)?; self.assemble_builtin_bound_candidates(copy_conditions, &mut candidates)?;
} } else if self.tcx().lang_items.sized_trait() == Some(def_id) {
_ if self.tcx().lang_items.sized_trait() == Some(def_id) => { // Sized is never implementable by end-users, it is
// Sized is never implementable by end-users, it is // always automatically computed.
// always automatically computed. let sized_conditions = self.sized_conditions(obligation);
let sized_conditions = self.sized_conditions(obligation); self.assemble_builtin_bound_candidates(sized_conditions,
self.assemble_builtin_bound_candidates(sized_conditions, &mut candidates)?;
&mut candidates)?; } else if self.tcx().lang_items.unsize_trait() == Some(def_id) {
} self.assemble_candidates_for_unsizing(obligation, &mut candidates);
} else {
_ if self.tcx().lang_items.unsize_trait() == Some(def_id) => { self.assemble_closure_candidates(obligation, &mut candidates)?;
self.assemble_candidates_for_unsizing(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);
// For non-builtins and Send/Sync
_ => {
self.assemble_closure_candidates(obligation, &mut candidates)?;
self.assemble_fn_pointer_candidates(obligation, &mut candidates)?;
self.assemble_candidates_from_impls(obligation, &mut candidates)?;
self.assemble_candidates_from_object_ty(obligation, &mut candidates);
}
} }
self.assemble_candidates_from_projected_tys(obligation, &mut candidates); self.assemble_candidates_from_projected_tys(obligation, &mut candidates);
@ -1446,7 +1437,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
if self.tcx().trait_has_default_impl(def_id) { if self.tcx().trait_has_default_impl(def_id) {
match self_ty.sty { match self_ty.sty {
ty::TyTrait(..) => { ty::TyDynamic(..) => {
// For object types, we don't know what the closed // For object types, we don't know what the closed
// over types are. For most traits, this means we // over types are. For most traits, this means we
// conservatively say nothing; a candidate may be // conservatively say nothing; a candidate may be
@ -1516,7 +1507,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
// any LBR. // any LBR.
let self_ty = this.tcx().erase_late_bound_regions(&obligation.self_ty()); let self_ty = this.tcx().erase_late_bound_regions(&obligation.self_ty());
let poly_trait_ref = match self_ty.sty { let poly_trait_ref = match self_ty.sty {
ty::TyTrait(ref data) => { ty::TyDynamic(ref data, ..) => {
if data.auto_traits().any(|did| did == obligation.predicate.def_id()) { if data.auto_traits().any(|did| did == obligation.predicate.def_id()) {
debug!("assemble_candidates_from_object_ty: matched builtin bound, \ debug!("assemble_candidates_from_object_ty: matched builtin bound, \
pushing candidate"); pushing candidate");
@ -1525,7 +1516,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
} }
match data.principal() { match data.principal() {
Some(ref p) => p.with_self_ty(this.tcx(), self_ty), Some(p) => p.with_self_ty(this.tcx(), self_ty),
None => return, None => return,
} }
} }
@ -1598,7 +1589,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
let may_apply = match (&source.sty, &target.sty) { let may_apply = match (&source.sty, &target.sty) {
// Trait+Kx+'a -> Trait+Ky+'b (upcasts). // 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: // Upcasts permit two things:
// //
// 1. Dropping builtin bounds, e.g. `Foo+Send` to `Foo` // 1. Dropping builtin bounds, e.g. `Foo+Send` to `Foo`
@ -1611,7 +1602,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
// We always upcast when we can because of reason // We always upcast when we can because of reason
// #2 (region bounds). // #2 (region bounds).
match (data_a.principal(), data_b.principal()) { match (data_a.principal(), data_b.principal()) {
(Some(ref a), Some(ref b)) => a.def_id() == b.def_id() && (Some(a), Some(b)) => a.def_id() == b.def_id() &&
data_b.auto_traits() data_b.auto_traits()
// All of a's auto traits need to be in b's 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)), .all(|b| data_a.auto_traits().any(|a| a == b)),
@ -1620,7 +1611,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
} }
// T -> Trait. // T -> Trait.
(_, &ty::TyTrait(_)) => true, (_, &ty::TyDynamic(..)) => true,
// Ambiguous handling is below T -> Trait, because inference // Ambiguous handling is below T -> Trait, because inference
// variables can still implement Unsize<Trait> and nested // variables can still implement Unsize<Trait> and nested
@ -1772,7 +1763,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
Where(ty::Binder(Vec::new())) Where(ty::Binder(Vec::new()))
} }
ty::TyStr | ty::TySlice(_) | ty::TyTrait(..) => Never, ty::TyStr | ty::TySlice(_) | ty::TyDynamic(..) => Never,
ty::TyTuple(tys) => { ty::TyTuple(tys) => {
Where(ty::Binder(tys.last().into_iter().cloned().collect())) Where(ty::Binder(tys.last().into_iter().cloned().collect()))
@ -1818,7 +1809,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
Where(ty::Binder(Vec::new())) Where(ty::Binder(Vec::new()))
} }
ty::TyBox(_) | ty::TyTrait(..) | ty::TyStr | ty::TySlice(..) | ty::TyBox(_) | ty::TyDynamic(..) | ty::TyStr | ty::TySlice(..) |
ty::TyClosure(..) | ty::TyClosure(..) |
ty::TyRef(_, ty::TypeAndMut { ty: _, mutbl: hir::MutMutable }) => { ty::TyRef(_, ty::TypeAndMut { ty: _, mutbl: hir::MutMutable }) => {
Never Never
@ -1883,7 +1874,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
Vec::new() Vec::new()
} }
ty::TyTrait(..) | ty::TyDynamic(..) |
ty::TyParam(..) | ty::TyParam(..) |
ty::TyProjection(..) | ty::TyProjection(..) |
ty::TyAnon(..) | ty::TyAnon(..) |
@ -2169,11 +2160,11 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
// OK to skip binder, it is reintroduced below // OK to skip binder, it is reintroduced below
let self_ty = self.infcx.shallow_resolve(obligation.predicate.skip_binder().self_ty()); let self_ty = self.infcx.shallow_resolve(obligation.predicate.skip_binder().self_ty());
match self_ty.sty { match self_ty.sty {
ty::TyTrait(ref data) => { ty::TyDynamic(ref data, ..) => {
// OK to skip the binder, it is reintroduced below // OK to skip the binder, it is reintroduced below
let principal = data.principal().unwrap(); let principal = data.principal().unwrap();
let input_types = principal.input_types(); let input_types = principal.input_types();
let assoc_types = data.projection_bounds.iter() let assoc_types = data.projection_bounds()
.map(|pb| pb.skip_binder().ty); .map(|pb| pb.skip_binder().ty);
let all_types: Vec<_> = input_types.chain(assoc_types) let all_types: Vec<_> = input_types.chain(assoc_types)
.collect(); .collect();
@ -2305,7 +2296,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
// case that results. -nmatsakis // case that results. -nmatsakis
let self_ty = self.infcx.shallow_resolve(*obligation.self_ty().skip_binder()); let self_ty = self.infcx.shallow_resolve(*obligation.self_ty().skip_binder());
let poly_trait_ref = match self_ty.sty { let poly_trait_ref = match self_ty.sty {
ty::TyTrait(ref data) => { ty::TyDynamic(ref data, ..) => {
data.principal().unwrap().with_self_ty(self.tcx(), self_ty) data.principal().unwrap().with_self_ty(self.tcx(), self_ty)
} }
_ => { _ => {
@ -2474,14 +2465,16 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
let mut nested = vec![]; let mut nested = vec![];
match (&source.sty, &target.sty) { match (&source.sty, &target.sty) {
// Trait+Kx+'a -> Trait+Ky+'b (upcasts). // 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. // See assemble_candidates_for_unsizing for more info.
let new_trait = tcx.mk_trait(ty::TraitObject::new( // Binders reintroduced below in call to mk_existential_predicates.
data_a.principal(), let principal = data_a.skip_binder().principal();
data_b.region_bound, let iter = principal.into_iter().map(ty::ExistentialPredicate::Trait)
data_b.auto_traits().collect(), .chain(data_a.skip_binder().projection_bounds()
data_a.projection_bounds.clone(), .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, .. } = let InferOk { obligations, .. } =
self.infcx.sub_types(false, &obligation.cause, new_trait, target) self.infcx.sub_types(false, &obligation.cause, new_trait, target)
.map_err(|_| Unimplemented)?; .map_err(|_| Unimplemented)?;
@ -2491,17 +2484,16 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
let cause = ObligationCause::new(obligation.cause.span, let cause = ObligationCause::new(obligation.cause.span,
obligation.cause.body_id, obligation.cause.body_id,
ObjectCastObligation(target)); ObjectCastObligation(target));
let outlives = ty::OutlivesPredicate(data_a.region_bound, let outlives = ty::OutlivesPredicate(r_a, r_b);
data_b.region_bound);
nested.push(Obligation::with_depth(cause, nested.push(Obligation::with_depth(cause,
obligation.recursion_depth + 1, obligation.recursion_depth + 1,
ty::Binder(outlives).to_predicate())); ty::Binder(outlives).to_predicate()));
} }
// T -> Trait. // T -> Trait.
(_, &ty::TyTrait(ref data)) => { (_, &ty::TyDynamic(ref data, r)) => {
let mut object_dids = let mut object_dids =
data.auto_traits().chain(data.principal().map(|ref p| p.def_id())); data.auto_traits().chain(data.principal().map(|p| p.def_id()));
if let Some(did) = object_dids.find(|did| { if let Some(did) = object_dids.find(|did| {
!tcx.is_object_safe(*did) !tcx.is_object_safe(*did)
}) { }) {
@ -2517,35 +2509,27 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
predicate)); predicate));
}; };
// Create the obligation for casting from T to Trait. // Create obligations:
push(data.principal().unwrap().with_self_ty(tcx, source).to_predicate()); // - 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));
}
// We can only make objects from sized types. // We can only make objects from sized types.
let trait_refs = data.auto_traits() let tr = ty::TraitRef {
.chain(iter::once( def_id: tcx.lang_items.require(lang_items::SizedTraitLangItem)
tcx.lang_items.require(lang_items::SizedTraitLangItem) .unwrap_or_else(|msg| tcx.sess.fatal(&msg[..])),
.unwrap_or_else(|msg| tcx.sess.fatal(&msg[..])))) substs: tcx.mk_substs_trait(source, &[]),
.map(|did| ty::TraitRef { };
def_id: did, push(tr.to_predicate());
substs: tcx.mk_substs_trait(source, &[]),
});
// Create additional obligations for all the various builtin
// bounds attached to the object cast. (In other words, if the
// object type is Foo+Send, this would create an obligation
// for the Send check.)
for tr in trait_refs {
push(tr.to_predicate());
}
// Create obligations for the projection predicates.
for bound in &data.projection_bounds {
push(bound.with_self_ty(tcx, source).to_predicate());
}
// If the type is `Foo+'a`, ensures that the type // If the type is `Foo+'a`, ensures that the type
// being cast to `Foo+'a` outlives `'a`: // 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()); push(ty::Binder(outlives).to_predicate());
} }

View File

@ -195,7 +195,7 @@ impl<'a, 'tcx> ty::TyS<'tcx> {
tc_ty(tcx, typ, cache).owned_pointer() tc_ty(tcx, typ, cache).owned_pointer()
} }
ty::TyTrait(_) => { ty::TyDynamic(..) => {
TC::All - TC::InteriorParam TC::All - TC::InteriorParam
} }

View File

@ -29,7 +29,7 @@ use ty::{self, TraitRef, Ty, TypeAndMut};
use ty::{TyS, TypeVariants, Slice}; use ty::{TyS, TypeVariants, Slice};
use ty::{AdtKind, AdtDef, ClosureSubsts, Region}; use ty::{AdtKind, AdtDef, ClosureSubsts, Region};
use hir::FreevarMap; 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::{TyVar, TyVid, IntVar, IntVid, FloatVar, FloatVid};
use ty::TypeVariants::*; use ty::TypeVariants::*;
use ty::layout::{Layout, TargetDataLayout}; use ty::layout::{Layout, TargetDataLayout};
@ -47,6 +47,7 @@ use std::mem;
use std::ops::Deref; use std::ops::Deref;
use std::rc::Rc; use std::rc::Rc;
use std::iter; use std::iter;
use std::cmp::Ordering;
use syntax::ast::{self, Name, NodeId}; use syntax::ast::{self, Name, NodeId};
use syntax::attr; use syntax::attr;
use syntax::symbol::{Symbol, keywords}; use syntax::symbol::{Symbol, keywords};
@ -63,6 +64,7 @@ pub struct CtxtArenas<'tcx> {
region: TypedArena<Region>, region: TypedArena<Region>,
stability: TypedArena<attr::Stability>, stability: TypedArena<attr::Stability>,
layout: TypedArena<Layout>, layout: TypedArena<Layout>,
existential_predicates: TypedArena<ExistentialPredicate<'tcx>>,
// references // references
generics: TypedArena<ty::Generics<'tcx>>, generics: TypedArena<ty::Generics<'tcx>>,
@ -81,6 +83,7 @@ impl<'tcx> CtxtArenas<'tcx> {
region: TypedArena::new(), region: TypedArena::new(),
stability: TypedArena::new(), stability: TypedArena::new(),
layout: TypedArena::new(), layout: TypedArena::new(),
existential_predicates: TypedArena::new(),
generics: TypedArena::new(), generics: TypedArena::new(),
trait_def: TypedArena::new(), trait_def: TypedArena::new(),
@ -103,6 +106,7 @@ pub struct CtxtInterners<'tcx> {
region: RefCell<FxHashSet<Interned<'tcx, Region>>>, region: RefCell<FxHashSet<Interned<'tcx, Region>>>,
stability: RefCell<FxHashSet<&'tcx attr::Stability>>, stability: RefCell<FxHashSet<&'tcx attr::Stability>>,
layout: RefCell<FxHashSet<&'tcx Layout>>, layout: RefCell<FxHashSet<&'tcx Layout>>,
existential_predicates: RefCell<FxHashSet<Interned<'tcx, Slice<ExistentialPredicate<'tcx>>>>>,
} }
impl<'gcx: 'tcx, 'tcx> CtxtInterners<'tcx> { impl<'gcx: 'tcx, 'tcx> CtxtInterners<'tcx> {
@ -115,7 +119,8 @@ impl<'gcx: 'tcx, 'tcx> CtxtInterners<'tcx> {
bare_fn: RefCell::new(FxHashSet()), bare_fn: RefCell::new(FxHashSet()),
region: RefCell::new(FxHashSet()), region: RefCell::new(FxHashSet()),
stability: 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<Ty<'a>> {
} }
} }
impl<'a, 'tcx> Lift<'tcx> for &'a Slice<ExistentialPredicate<'a>> {
type Lifted = &'tcx Slice<ExistentialPredicate<'tcx>>;
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>)
-> Option<&'tcx Slice<ExistentialPredicate<'tcx>>> {
if self.is_empty() {
return Some(Slice::empty());
}
if let Some(&Interned(eps)) = tcx.interners.existential_predicates.borrow().get(&self[..]) {
if *self as *const _ == eps as *const _ {
return Some(eps);
}
}
// Also try in the global tcx if we're not that.
if !tcx.is_global() {
self.lift_to_tcx(tcx.global_tcx())
} else {
None
}
}
}
impl<'a, 'tcx> Lift<'tcx> for &'a BareFnTy<'a> { impl<'a, 'tcx> Lift<'tcx> for &'a BareFnTy<'a> {
type Lifted = &'tcx BareFnTy<'tcx>; type Lifted = &'tcx BareFnTy<'tcx>;
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, '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!( sty_debug_print!(
self, self,
TyAdt, TyBox, TyArray, TySlice, TyRawPtr, TyRef, TyFnDef, TyFnPtr, 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!("Substs interner: #{}", self.interners.substs.borrow().len());
println!("BareFnTy interner: #{}", self.interners.bare_fn.borrow().len()); println!("BareFnTy interner: #{}", self.interners.bare_fn.borrow().len());
@ -1200,6 +1226,13 @@ impl<'tcx> Borrow<Region> for Interned<'tcx, Region> {
} }
} }
impl<'tcx: 'lcx, 'lcx> Borrow<[ExistentialPredicate<'lcx>]>
for Interned<'tcx, Slice<ExistentialPredicate<'tcx>>> {
fn borrow<'a>(&'a self) -> &'a [ExistentialPredicate<'lcx>] {
&self.0[..]
}
}
macro_rules! intern_method { macro_rules! intern_method {
($lt_tcx:tt, $name:ident: $method:ident($alloc:ty, ($lt_tcx:tt, $name:ident: $method:ident($alloc:ty,
$alloc_method:ident, $alloc_method:ident,
@ -1297,6 +1330,7 @@ macro_rules! slice_interners {
} }
slice_interners!( slice_interners!(
existential_predicates: _intern_existential_predicates(ExistentialPredicate),
type_list: _intern_type_list(Ty), type_list: _intern_type_list(Ty),
substs: _intern_substs(Kind) substs: _intern_substs(Kind)
); );
@ -1437,24 +1471,27 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
self.mk_ty(TyFnPtr(fty)) self.mk_ty(TyFnPtr(fty))
} }
pub fn mk_trait(self, mut obj: TraitObject<'tcx>) -> Ty<'tcx> { pub fn mk_dynamic(
obj.projection_bounds.sort_by_key(|b| b.sort_key(self)); self,
self.mk_ty(TyTrait(box obj)) obj: ty::Binder<&'tcx Slice<ExistentialPredicate<'tcx>>>,
reg: &'tcx ty::Region
) -> Ty<'tcx> {
self.mk_ty(TyDynamic(obj, reg))
} }
pub fn mk_projection(self, pub fn mk_projection(self,
trait_ref: TraitRef<'tcx>, trait_ref: TraitRef<'tcx>,
item_name: Name) item_name: Name)
-> Ty<'tcx> { -> Ty<'tcx> {
// take a copy of substs so that we own the vectors inside // take a copy of substs so that we own the vectors inside
let inner = ProjectionTy { trait_ref: trait_ref, item_name: item_name }; let inner = ProjectionTy { trait_ref: trait_ref, item_name: item_name };
self.mk_ty(TyProjection(inner)) self.mk_ty(TyProjection(inner))
} }
pub fn mk_closure(self, pub fn mk_closure(self,
closure_id: DefId, closure_id: DefId,
substs: &'tcx Substs<'tcx>) substs: &'tcx Substs<'tcx>)
-> Ty<'tcx> { -> Ty<'tcx> {
self.mk_closure_from_closure_substs(closure_id, ClosureSubsts { self.mk_closure_from_closure_substs(closure_id, ClosureSubsts {
substs: substs substs: substs
}) })
@ -1501,6 +1538,13 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
self.mk_ty(TyAnon(def_id, substs)) self.mk_ty(TyAnon(def_id, substs))
} }
pub fn intern_existential_predicates(self, eps: &[ExistentialPredicate<'tcx>])
-> &'tcx Slice<ExistentialPredicate<'tcx>> {
assert!(!eps.is_empty());
assert!(eps.windows(2).all(|w| w[0].cmp(self, &w[1]) != Ordering::Greater));
self._intern_existential_predicates(eps)
}
pub fn intern_type_list(self, ts: &[Ty<'tcx>]) -> &'tcx Slice<Ty<'tcx>> { pub fn intern_type_list(self, ts: &[Ty<'tcx>]) -> &'tcx Slice<Ty<'tcx>> {
if ts.len() == 0 { if ts.len() == 0 {
Slice::empty() Slice::empty()
@ -1517,6 +1561,12 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
} }
} }
pub fn mk_existential_predicates<I: InternAs<[ExistentialPredicate<'tcx>],
&'tcx Slice<ExistentialPredicate<'tcx>>>>(self, iter: I)
-> I::Output {
iter.intern_with(|xs| self.intern_existential_predicates(xs))
}
pub fn mk_type_list<I: InternAs<[Ty<'tcx>], pub fn mk_type_list<I: InternAs<[Ty<'tcx>],
&'tcx Slice<Ty<'tcx>>>>(self, iter: I) -> I::Output { &'tcx Slice<Ty<'tcx>>>>(self, iter: I) -> I::Output {
iter.intern_with(|xs| self.intern_type_list(xs)) iter.intern_with(|xs| self.intern_type_list(xs))

View File

@ -49,7 +49,8 @@ pub enum TypeError<'tcx> {
CyclicTy, CyclicTy,
ProjectionNameMismatched(ExpectedFound<Name>), ProjectionNameMismatched(ExpectedFound<Name>),
ProjectionBoundsLength(ExpectedFound<usize>), ProjectionBoundsLength(ExpectedFound<usize>),
TyParamDefaultMismatch(ExpectedFound<type_variable::Default<'tcx>>) TyParamDefaultMismatch(ExpectedFound<type_variable::Default<'tcx>>),
ExistentialMismatch(ExpectedFound<&'tcx ty::Slice<ty::ExistentialPredicate<'tcx>>>),
} }
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Debug, Copy)] #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Debug, Copy)]
@ -164,6 +165,10 @@ impl<'tcx> fmt::Display for TypeError<'tcx> {
values.expected.ty, values.expected.ty,
values.found.ty) values.found.ty)
} }
ExistentialMismatch(ref values) => {
report_maybe_different(f, format!("trait `{}`", values.expected),
format!("trait `{}`", values.found))
}
} }
} }
} }
@ -200,7 +205,7 @@ impl<'a, 'gcx, 'lcx, 'tcx> ty::TyS<'tcx> {
} }
ty::TyFnDef(..) => format!("fn item"), ty::TyFnDef(..) => format!("fn item"),
ty::TyFnPtr(_) => "fn pointer".to_string(), ty::TyFnPtr(_) => "fn pointer".to_string(),
ty::TyTrait(ref inner) => { ty::TyDynamic(ref inner, ..) => {
inner.principal().map_or_else(|| "trait".to_string(), inner.principal().map_or_else(|| "trait".to_string(),
|p| format!("trait {}", tcx.item_path_str(p.def_id()))) |p| format!("trait {}", tcx.item_path_str(p.def_id())))
} }

View File

@ -59,7 +59,7 @@ pub fn simplify_type<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
ty::TyStr => Some(StrSimplifiedType), ty::TyStr => Some(StrSimplifiedType),
ty::TyArray(..) | ty::TySlice(_) => Some(ArraySimplifiedType), ty::TyArray(..) | ty::TySlice(_) => Some(ArraySimplifiedType),
ty::TyRawPtr(_) => Some(PtrSimplifiedType), ty::TyRawPtr(_) => Some(PtrSimplifiedType),
ty::TyTrait(ref trait_info) => { ty::TyDynamic(ref trait_info, ..) => {
trait_info.principal().map(|p| TraitSimplifiedType(p.def_id())) trait_info.principal().map(|p| TraitSimplifiedType(p.def_id()))
} }
ty::TyRef(_, mt) => { ty::TyRef(_, mt) => {

View File

@ -121,16 +121,21 @@ impl FlagComputation {
self.add_substs(substs); self.add_substs(substs);
} }
&ty::TyTrait(ref obj) => { &ty::TyDynamic(ref obj, r) => {
let mut computation = FlagComputation::new(); let mut computation = FlagComputation::new();
computation.add_substs(obj.principal().unwrap().skip_binder().substs); for predicate in obj.skip_binder().iter() {
for projection_bound in &obj.projection_bounds { match *predicate {
let mut proj_computation = FlagComputation::new(); ty::ExistentialPredicate::Trait(tr) => computation.add_substs(tr.substs),
proj_computation.add_existential_projection(&projection_bound.0); ty::ExistentialPredicate::Projection(p) => {
self.add_bound_computation(&proj_computation); 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_bound_computation(&computation);
self.add_region(obj.region_bound); self.add_region(r);
} }
&ty::TyBox(tt) | &ty::TyArray(tt, _) | &ty::TySlice(tt) => { &ty::TyBox(tt) | &ty::TyArray(tt, _) | &ty::TySlice(tt) => {

View File

@ -316,7 +316,7 @@ pub fn characteristic_def_id_of_type(ty: Ty) -> Option<DefId> {
match ty.sty { match ty.sty {
ty::TyAdt(adt_def, _) => Some(adt_def.did), ty::TyAdt(adt_def, _) => Some(adt_def.did),
ty::TyTrait(ref data) => data.principal().map(|ref p| p.def_id()), ty::TyDynamic(data, ..) => data.principal().map(|p| p.def_id()),
ty::TyArray(subty, _) | ty::TyArray(subty, _) |
ty::TySlice(subty) | ty::TySlice(subty) |

View File

@ -924,7 +924,7 @@ impl<'a, 'gcx, 'tcx> Layout {
ty::TySlice(_) | ty::TyStr => { ty::TySlice(_) | ty::TyStr => {
Int(dl.ptr_sized_integer()) Int(dl.ptr_sized_integer())
} }
ty::TyTrait(_) => Pointer, ty::TyDynamic(..) => Pointer,
_ => return Err(LayoutError::Unknown(unsized_part)) _ => return Err(LayoutError::Unknown(unsized_part))
}; };
FatPointer { metadata: meta, non_zero: non_zero } FatPointer { metadata: meta, non_zero: non_zero }
@ -963,7 +963,7 @@ impl<'a, 'gcx, 'tcx> Layout {
non_zero: false non_zero: false
} }
} }
ty::TyTrait(_) => { ty::TyDynamic(..) => {
let mut unit = Struct::new(dl, false); let mut unit = Struct::new(dl, false);
unit.sized = false; unit.sized = false;
Univariant { variant: unit, non_zero: false } Univariant { variant: unit, non_zero: false }

View File

@ -54,7 +54,7 @@ use hir::itemlikevisit::ItemLikeVisitor;
pub use self::sty::{Binder, DebruijnIndex}; pub use self::sty::{Binder, DebruijnIndex};
pub use self::sty::{BareFnTy, FnSig, PolyFnSig}; 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::{ClosureSubsts, TypeAndMut};
pub use self::sty::{TraitRef, TypeVariants, PolyTraitRef}; pub use self::sty::{TraitRef, TypeVariants, PolyTraitRef};
pub use self::sty::{ExistentialTraitRef, PolyExistentialTraitRef}; pub use self::sty::{ExistentialTraitRef, PolyExistentialTraitRef};
@ -1712,7 +1712,7 @@ impl<'a, 'tcx> AdtDefData<'tcx, 'tcx> {
vec![] vec![]
} }
TyStr | TyTrait(..) | TySlice(_) | TyError => { TyStr | TyDynamic(..) | TySlice(_) | TyError => {
// these are never sized - return the target type // these are never sized - return the target type
vec![ty] vec![ty]
} }

View File

@ -177,7 +177,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
ty::TyTuple(..) | // ... ty::TyTuple(..) | // ...
ty::TyFnDef(..) | // OutlivesFunction (*) ty::TyFnDef(..) | // OutlivesFunction (*)
ty::TyFnPtr(_) | // OutlivesFunction (*) ty::TyFnPtr(_) | // OutlivesFunction (*)
ty::TyTrait(..) | // OutlivesObject, OutlivesFragment (*) ty::TyDynamic(..) | // OutlivesObject, OutlivesFragment (*)
ty::TyError => { ty::TyError => {
// (*) Bare functions and traits are both binders. In the // (*) Bare functions and traits are both binders. In the
// RFC, this means we would add the bound regions to the // RFC, this means we would add the bound regions to the

View File

@ -398,26 +398,15 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R,
Ok(tcx.mk_adt(a_def, substs)) Ok(tcx.mk_adt(a_def, substs))
} }
(&ty::TyTrait(ref a_obj), &ty::TyTrait(ref b_obj)) => (&ty::TyDynamic(ref a_obj, ref a_region), &ty::TyDynamic(ref b_obj, ref b_region)) => {
{ let region_bound = relation.with_cause(Cause::ExistentialRegionBound,
let principal = match (a_obj.principal(), b_obj.principal()) { |relation| {
(Some(ref a_p), Some(ref b_p)) => Some(relation.relate(a_p, b_p)?), relation.relate_with_variance(
(None, None) => None, ty::Contravariant,
_ => return Err(TypeError::Sorts(expected_found(relation, &a, &b))), a_region,
}; b_region)
let r = })?;
relation.with_cause( Ok(tcx.mk_dynamic(relation.relate(a_obj, b_obj)?, region_bound))
Cause::ExistentialRegionBound,
|relation| relation.relate_with_variance(ty::Contravariant,
&a_obj.region_bound,
&b_obj.region_bound))?;
let nb = if !a_obj.auto_traits().eq(b_obj.auto_traits()) {
return Err(TypeError::Sorts(expected_found(relation, &a, &b)));
} else {
a_obj.auto_traits().collect()
};
let pb = relation.relate(&a_obj.projection_bounds, &b_obj.projection_bounds)?;
Ok(tcx.mk_trait(ty::TraitObject::new(principal, r, nb, pb)))
} }
(&ty::TyClosure(a_id, a_substs), (&ty::TyClosure(a_id, a_substs),
@ -513,6 +502,31 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R,
} }
} }
impl<'tcx> Relate<'tcx> for &'tcx ty::Slice<ty::ExistentialPredicate<'tcx>> {
fn relate<'a, 'gcx, R>(relation: &mut R,
a: &Self,
b: &Self)
-> RelateResult<'tcx, Self>
where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a {
if a.len() != b.len() {
return Err(TypeError::ExistentialMismatch(expected_found(relation, a, b)));
}
let tcx = relation.tcx();
let v = a.iter().zip(b.iter()).map(|(ep_a, ep_b)| {
use ty::ExistentialPredicate::*;
match (*ep_a, *ep_b) {
(Trait(ref a), Trait(ref b)) => Ok(Trait(relation.relate(a, b)?)),
(Projection(ref a), Projection(ref b)) => Ok(Projection(relation.relate(a, b)?)),
(AutoTrait(ref a), AutoTrait(ref b)) if a == b => Ok(AutoTrait(*a)),
_ => Err(TypeError::ExistentialMismatch(expected_found(relation, a, b)))
}
});
Ok(tcx.mk_existential_predicates(v)?)
}
}
impl<'tcx> Relate<'tcx> for ty::ClosureSubsts<'tcx> { impl<'tcx> Relate<'tcx> for ty::ClosureSubsts<'tcx> {
fn relate<'a, 'gcx, R>(relation: &mut R, fn relate<'a, 'gcx, R>(relation: &mut R,
a: &ty::ClosureSubsts<'tcx>, a: &ty::ClosureSubsts<'tcx>,

View File

@ -324,6 +324,7 @@ impl<'a, 'tcx> Lift<'tcx> for ty::error::TypeError<'a> {
TyParamDefaultMismatch(ref x) => { TyParamDefaultMismatch(ref x) => {
return tcx.lift(x).map(TyParamDefaultMismatch) return tcx.lift(x).map(TyParamDefaultMismatch)
} }
ExistentialMismatch(ref x) => return tcx.lift(x).map(ExistentialMismatch)
}) })
} }
} }
@ -426,20 +427,33 @@ impl<'tcx, T:TypeFoldable<'tcx>> TypeFoldable<'tcx> for ty::Binder<T> {
} }
} }
impl<'tcx> TypeFoldable<'tcx> for ty::TraitObject<'tcx> { impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::Slice<ty::ExistentialPredicate<'tcx>> {
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
ty::TraitObject::new( let v = self.iter().map(|p| p.fold_with(folder)).collect::<AccumulateVec<[_; 8]>>();
self.principal().map(|p| p.fold_with(folder)), folder.tcx().intern_existential_predicates(&v)
self.region_bound.fold_with(folder),
self.auto_traits().collect(),
self.projection_bounds.fold_with(folder),
)
} }
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool { fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
self.principal().map(|p| p.visit_with(visitor)).unwrap_or(true) || self.iter().any(|p| p.visit_with(visitor))
self.region_bound.visit_with(visitor) || }
self.projection_bounds.visit_with(visitor) }
impl<'tcx> TypeFoldable<'tcx> for ty::ExistentialPredicate<'tcx> {
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
use ty::ExistentialPredicate::*;
match *self {
Trait(ref tr) => Trait(tr.fold_with(folder)),
Projection(ref p) => Projection(p.fold_with(folder)),
AutoTrait(did) => AutoTrait(did),
}
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
match *self {
ty::ExistentialPredicate::Trait(ref tr) => tr.visit_with(visitor),
ty::ExistentialPredicate::Projection(ref p) => p.visit_with(visitor),
ty::ExistentialPredicate::AutoTrait(_) => false,
}
} }
} }
@ -462,7 +476,8 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> {
ty::TyArray(typ, sz) => ty::TyArray(typ.fold_with(folder), sz), ty::TyArray(typ, sz) => ty::TyArray(typ.fold_with(folder), sz),
ty::TySlice(typ) => ty::TySlice(typ.fold_with(folder)), ty::TySlice(typ) => ty::TySlice(typ.fold_with(folder)),
ty::TyAdt(tid, substs) => ty::TyAdt(tid, substs.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::TyTuple(ts) => ty::TyTuple(ts.fold_with(folder)),
ty::TyFnDef(def_id, substs, f) => { ty::TyFnDef(def_id, substs, f) => {
ty::TyFnDef(def_id, ty::TyFnDef(def_id,
@ -499,7 +514,8 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> {
ty::TyArray(typ, _sz) => typ.visit_with(visitor), ty::TyArray(typ, _sz) => typ.visit_with(visitor),
ty::TySlice(typ) => typ.visit_with(visitor), ty::TySlice(typ) => typ.visit_with(visitor),
ty::TyAdt(_, substs) => substs.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::TyTuple(ts) => ts.visit_with(visitor),
ty::TyFnDef(_, substs, ref f) => { ty::TyFnDef(_, substs, ref f) => {
substs.visit_with(visitor) || f.visit_with(visitor) substs.visit_with(visitor) || f.visit_with(visitor)

View File

@ -16,8 +16,11 @@ use middle::region;
use ty::subst::Substs; use ty::subst::Substs;
use ty::{self, AdtDef, TypeFlags, Ty, TyCtxt, TypeFoldable}; use ty::{self, AdtDef, TypeFlags, Ty, TyCtxt, TypeFoldable};
use ty::{Slice, TyS}; use ty::{Slice, TyS};
use ty::subst::Kind;
use std::fmt; use std::fmt;
use std::iter;
use std::cmp::Ordering;
use syntax::abi; use syntax::abi;
use syntax::ast::{self, Name, NodeId}; use syntax::ast::{self, Name, NodeId};
use syntax::symbol::{keywords, InternedString}; use syntax::symbol::{keywords, InternedString};
@ -144,7 +147,7 @@ pub enum TypeVariants<'tcx> {
TyFnPtr(&'tcx BareFnTy<'tcx>), TyFnPtr(&'tcx BareFnTy<'tcx>),
/// A trait, defined with `trait`. /// A trait, defined with `trait`.
TyTrait(Box<TraitObject<'tcx>>), TyDynamic(Binder<&'tcx Slice<ExistentialPredicate<'tcx>>>, &'tcx ty::Region),
/// The anonymous type of a closure. Used to represent the type of /// The anonymous type of a closure. Used to represent the type of
/// `|a| a`. /// `|a| a`.
@ -272,32 +275,103 @@ impl<'a, 'gcx, 'acx, 'tcx> ClosureSubsts<'tcx> {
} }
} }
#[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
pub struct TraitObject<'tcx> { pub enum ExistentialPredicate<'tcx> {
principal: Option<PolyExistentialTraitRef<'tcx>>, // e.g. Iterator
pub region_bound: &'tcx ty::Region, Trait(ExistentialTraitRef<'tcx>),
auto_traits: Vec<DefId>, // e.g. Iterator::Item = T
pub projection_bounds: Vec<PolyExistentialProjection<'tcx>>, Projection(ExistentialProjection<'tcx>),
// e.g. Send
AutoTrait(DefId),
} }
impl<'tcx> TraitObject<'tcx> { impl<'a, 'gcx, 'tcx> ExistentialPredicate<'tcx> {
pub fn new(principal: Option<PolyExistentialTraitRef<'tcx>>, region_bound: &'tcx ty::Region, pub fn cmp(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, other: &Self) -> Ordering {
auto_traits: Vec<DefId>, projection_bounds: Vec<PolyExistentialProjection<'tcx>>) use self::ExistentialPredicate::*;
-> Self { match (*self, *other) {
TraitObject { (Trait(_), Trait(_)) => Ordering::Equal,
principal: principal, (Projection(ref a), Projection(ref b)) => a.sort_key(tcx).cmp(&b.sort_key(tcx)),
region_bound: region_bound, (AutoTrait(ref a), AutoTrait(ref b)) =>
auto_traits: auto_traits, tcx.lookup_trait_def(*a).def_path_hash.cmp(&tcx.lookup_trait_def(*b).def_path_hash),
projection_bounds: projection_bounds, (Trait(_), _) => Ordering::Less,
(Projection(_), Trait(_)) => Ordering::Greater,
(Projection(_), _) => Ordering::Less,
(AutoTrait(_), _) => Ordering::Greater,
} }
} }
pub fn principal(&self) -> Option<PolyExistentialTraitRef<'tcx>> { }
self.principal
impl<'a, 'gcx, 'tcx> Binder<ExistentialPredicate<'tcx>> {
pub fn with_self_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, self_ty: Ty<'tcx>)
-> ty::Predicate<'tcx> {
use ty::ToPredicate;
match *self.skip_binder() {
ExistentialPredicate::Trait(tr) => Binder(tr).with_self_ty(tcx, self_ty).to_predicate(),
ExistentialPredicate::Projection(p) =>
ty::Predicate::Projection(Binder(p.with_self_ty(tcx, self_ty))),
ExistentialPredicate::AutoTrait(did) => {
let trait_ref = Binder(ty::TraitRef {
def_id: did,
substs: tcx.mk_substs_trait(self_ty, &[]),
});
trait_ref.to_predicate()
}
}
}
}
impl<'tcx> serialize::UseSpecializedDecodable for &'tcx Slice<ExistentialPredicate<'tcx>> {}
impl<'tcx> Slice<ExistentialPredicate<'tcx>> {
pub fn principal(&self) -> Option<ExistentialTraitRef<'tcx>> {
match self.get(0) {
Some(&ExistentialPredicate::Trait(tr)) => Some(tr),
_ => None
}
} }
#[inline]
pub fn projection_bounds<'a>(&'a self) ->
impl Iterator<Item=ExistentialProjection<'tcx>> + 'a {
self.iter().filter_map(|predicate| {
match *predicate {
ExistentialPredicate::Projection(p) => Some(p),
_ => None,
}
})
}
#[inline]
pub fn auto_traits<'a>(&'a self) -> impl Iterator<Item=DefId> + 'a { pub fn auto_traits<'a>(&'a self) -> impl Iterator<Item=DefId> + 'a {
self.auto_traits.iter().cloned() self.iter().filter_map(|predicate| {
match *predicate {
ExistentialPredicate::AutoTrait(d) => Some(d),
_ => None
}
})
}
}
impl<'tcx> Binder<&'tcx Slice<ExistentialPredicate<'tcx>>> {
pub fn principal(&self) -> Option<PolyExistentialTraitRef<'tcx>> {
self.skip_binder().principal().map(Binder)
}
#[inline]
pub fn projection_bounds<'a>(&'a self) ->
impl Iterator<Item=PolyExistentialProjection<'tcx>> + 'a {
self.skip_binder().projection_bounds().map(Binder)
}
#[inline]
pub fn auto_traits<'a>(&'a self) -> impl Iterator<Item=DefId> + 'a {
self.skip_binder().auto_traits()
}
pub fn iter<'a>(&'a self)
-> impl DoubleEndedIterator<Item=Binder<ExistentialPredicate<'tcx>>> + 'tcx {
self.skip_binder().iter().cloned().map(Binder)
} }
} }
@ -362,14 +436,30 @@ pub struct ExistentialTraitRef<'tcx> {
pub substs: &'tcx Substs<'tcx>, pub substs: &'tcx Substs<'tcx>,
} }
impl<'tcx> ExistentialTraitRef<'tcx> { impl<'a, 'gcx, 'tcx> ExistentialTraitRef<'tcx> {
pub fn input_types<'a>(&'a self) -> impl DoubleEndedIterator<Item=Ty<'tcx>> + 'a { pub fn input_types<'b>(&'b self) -> impl DoubleEndedIterator<Item=Ty<'tcx>> + 'b {
// Select only the "input types" from a trait-reference. For // Select only the "input types" from a trait-reference. For
// now this is all the types that appear in the // now this is all the types that appear in the
// trait-reference, but it should eventually exclude // trait-reference, but it should eventually exclude
// associated types. // associated types.
self.substs.types() self.substs.types()
} }
/// Object types don't have a self-type specified. Therefore, when
/// we convert the principal trait-ref into a normal trait-ref,
/// you must give *some* self-type. A common choice is `mk_err()`
/// or some skolemized type.
pub fn with_self_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, self_ty: Ty<'tcx>)
-> ty::TraitRef<'tcx> {
// otherwise the escaping regions would be captured by the binder
assert!(!self_ty.has_escaping_regions());
ty::TraitRef {
def_id: self.def_id,
substs: tcx.mk_substs(
iter::once(Kind::from(self_ty)).chain(self.substs.iter().cloned()))
}
}
} }
pub type PolyExistentialTraitRef<'tcx> = Binder<ExistentialTraitRef<'tcx>>; pub type PolyExistentialTraitRef<'tcx> = Binder<ExistentialTraitRef<'tcx>>;
@ -731,61 +821,53 @@ pub struct ExistentialProjection<'tcx> {
pub type PolyExistentialProjection<'tcx> = Binder<ExistentialProjection<'tcx>>; pub type PolyExistentialProjection<'tcx> = Binder<ExistentialProjection<'tcx>>;
impl<'a, 'tcx, 'gcx> PolyExistentialProjection<'tcx> { impl<'a, 'tcx, 'gcx> ExistentialProjection<'tcx> {
pub fn item_name(&self) -> Name { 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) { pub fn sort_key(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> (u64, InternedString) {
// We want something here that is stable across crate boundaries. // We want something here that is stable across crate boundaries.
// The DefId isn't but the `deterministic_hash` of the corresponding // The DefId isn't but the `deterministic_hash` of the corresponding
// DefPath is. // 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; let def_path_hash = trait_def.def_path_hash;
// An `ast::Name` is also not stable (it's just an index into an // An `ast::Name` is also not stable (it's just an index into an
// interning table), so map to the corresponding `InternedString`. // 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) (def_path_hash, item_name)
} }
pub fn with_self_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, pub fn with_self_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
self_ty: Ty<'tcx>) self_ty: Ty<'tcx>)
-> ty::PolyProjectionPredicate<'tcx> -> ty::ProjectionPredicate<'tcx>
{ {
// otherwise the escaping regions would be captured by the binders // otherwise the escaping regions would be captured by the binders
assert!(!self_ty.has_escaping_regions()); assert!(!self_ty.has_escaping_regions());
let trait_ref = self.map_bound(|proj| proj.trait_ref); ty::ProjectionPredicate {
self.map_bound(|proj| ty::ProjectionPredicate {
projection_ty: ty::ProjectionTy { projection_ty: ty::ProjectionTy {
trait_ref: trait_ref.with_self_ty(tcx, self_ty).0, trait_ref: self.trait_ref.with_self_ty(tcx, self_ty),
item_name: proj.item_name item_name: self.item_name
}, },
ty: proj.ty ty: self.ty
}) }
} }
} }
impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { impl<'a, 'tcx, 'gcx> PolyExistentialProjection<'tcx> {
pub fn try_add_builtin_trait(self, pub fn item_name(&self) -> Name {
id: DefId, self.skip_binder().item_name()
auto_traits: &mut Vec<DefId>) }
-> bool
{
//! Checks whether `id` refers to one of the builtin
//! traits, like `Send`, and adds it to `auto_traits` if so.
//! Returns true if `idf` refers to a builtin trait.
if Some(id) == self.lang_items.send_trait() || pub fn sort_key(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> (u64, InternedString) {
Some(id) == self.lang_items.sized_trait() || self.skip_binder().sort_key(tcx)
Some(id) == self.lang_items.copy_trait() || }
Some(id) == self.lang_items.sync_trait() {
auto_traits.push(id); pub fn with_self_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, self_ty: Ty<'tcx>)
true -> ty::PolyProjectionPredicate<'tcx> {
} else { self.map_bound(|p| p.with_self_ty(tcx, self_ty))
false
}
} }
} }
@ -1045,7 +1127,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
pub fn is_trait(&self) -> bool { pub fn is_trait(&self) -> bool {
match self.sty { match self.sty {
TyTrait(..) => true, TyDynamic(..) => true,
_ => false _ => false
} }
} }
@ -1178,7 +1260,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
pub fn ty_to_def_id(&self) -> Option<DefId> { pub fn ty_to_def_id(&self) -> Option<DefId> {
match self.sty { match self.sty {
TyTrait(ref tt) => tt.principal().map(|p| p.def_id()), TyDynamic(ref tt, ..) => tt.principal().map(|p| p.def_id()),
TyAdt(def, _) => Some(def.did), TyAdt(def, _) => Some(def.did),
TyClosure(id, _) => Some(id), TyClosure(id, _) => Some(id),
_ => None _ => None
@ -1200,9 +1282,11 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
TyRef(region, _) => { TyRef(region, _) => {
vec![region] vec![region]
} }
TyTrait(ref obj) => { TyDynamic(ref obj, region) => {
let mut v = vec![obj.region_bound]; let mut v = vec![region];
v.extend(obj.principal().unwrap().skip_binder().substs.regions()); if let Some(p) = obj.principal() {
v.extend(p.skip_binder().substs.regions());
}
v v
} }
TyAdt(_, substs) | TyAnon(_, substs) => { TyAdt(_, substs) | TyAnon(_, substs) => {

View File

@ -532,8 +532,8 @@ impl<'a, 'gcx, 'tcx, H: Hasher> TypeVisitor<'tcx> for TypeIdHasher<'a, 'gcx, 'tc
self.hash(f.sig.variadic()); self.hash(f.sig.variadic());
self.hash(f.sig.inputs().skip_binder().len()); self.hash(f.sig.inputs().skip_binder().len());
} }
TyTrait(ref data) => { TyDynamic(ref data, ..) => {
if let Some(ref p) = data.principal() { if let Some(p) = data.principal() {
self.def_id(p.def_id()); self.def_id(p.def_id());
} }
for d in data.auto_traits() { for d in data.auto_traits() {
@ -641,7 +641,7 @@ impl<'a, 'tcx> ty::TyS<'tcx> {
mutbl: hir::MutMutable, .. mutbl: hir::MutMutable, ..
}) => Some(true), }) => Some(true),
TyArray(..) | TySlice(..) | TyTrait(..) | TyTuple(..) | TyArray(..) | TySlice(..) | TyDynamic(..) | TyTuple(..) |
TyClosure(..) | TyAdt(..) | TyAnon(..) | TyClosure(..) | TyAdt(..) | TyAnon(..) |
TyProjection(..) | TyParam(..) | TyInfer(..) | TyError => None TyProjection(..) | TyParam(..) | TyInfer(..) | TyError => None
}.unwrap_or_else(|| { }.unwrap_or_else(|| {
@ -684,7 +684,7 @@ impl<'a, 'tcx> ty::TyS<'tcx> {
TyBox(..) | TyRawPtr(..) | TyRef(..) | TyFnDef(..) | TyFnPtr(_) | TyBox(..) | TyRawPtr(..) | TyRef(..) | TyFnDef(..) | TyFnPtr(_) |
TyArray(..) | TyTuple(..) | TyClosure(..) | TyNever => Some(true), TyArray(..) | TyTuple(..) | TyClosure(..) | TyNever => Some(true),
TyStr | TyTrait(..) | TySlice(_) => Some(false), TyStr | TyDynamic(..) | TySlice(_) => Some(false),
TyAdt(..) | TyProjection(..) | TyParam(..) | TyAdt(..) | TyProjection(..) | TyParam(..) |
TyInfer(..) | TyAnon(..) | TyError => None TyInfer(..) | TyAnon(..) | TyError => None

View File

@ -92,14 +92,19 @@ fn push_subtypes<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent_ty: Ty<'tcx>) {
ty::TyProjection(ref data) => { ty::TyProjection(ref data) => {
stack.extend(data.trait_ref.substs.types().rev()); stack.extend(data.trait_ref.substs.types().rev());
} }
ty::TyTrait(ref obj) => { ty::TyDynamic(ref obj, ..) => {
match obj.principal() { stack.extend(obj.iter().rev().flat_map(|predicate| {
Some(ref p) => stack.extend(p.input_types().rev()), let (substs, opt_ty) = match *predicate.skip_binder() {
None => {} ty::ExistentialPredicate::Trait(tr) => (tr.substs, None),
} ty::ExistentialPredicate::Projection(p) =>
stack.extend(obj.projection_bounds.iter().map(|pred| { (p.trait_ref.substs, Some(p.ty)),
pred.0.ty ty::ExistentialPredicate::AutoTrait(_) =>
}).rev()); // Empty iterator
(ty::Substs::empty(), None),
};
substs.types().rev().chain(opt_ty)
}));
} }
ty::TyAdt(_, substs) | ty::TyAnon(_, substs) => { ty::TyAdt(_, substs) | ty::TyAnon(_, substs) => {
stack.extend(substs.types().rev()); stack.extend(substs.types().rev());

View File

@ -374,12 +374,12 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> {
// of whatever returned this exact `impl Trait`. // of whatever returned this exact `impl Trait`.
} }
ty::TyTrait(ref data) => { ty::TyDynamic(data, r) => {
// WfObject // WfObject
// //
// Here, we defer WF checking due to higher-ranked // Here, we defer WF checking due to higher-ranked
// regions. This is perhaps not ideal. // 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 // FIXME(#27579) RFC also considers adding trait
// obligations that don't refer to Self and // obligations that don't refer to Self and
@ -388,7 +388,7 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> {
let cause = self.cause(traits::MiscObligation); let cause = self.cause(traits::MiscObligation);
let component_traits = let component_traits =
data.auto_traits().chain(data.principal().map(|ref p| p.def_id())); data.auto_traits().chain(data.principal().map(|p| p.def_id()));
self.out.extend( self.out.extend(
component_traits.map(|did| traits::Obligation::new( component_traits.map(|did| traits::Obligation::new(
cause.clone(), cause.clone(),
@ -450,7 +450,9 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> {
.collect() .collect()
} }
fn from_object_ty(&mut self, ty: Ty<'tcx>, data: &ty::TraitObject<'tcx>) { fn from_object_ty(&mut self, ty: Ty<'tcx>,
data: ty::Binder<&'tcx ty::Slice<ty::ExistentialPredicate<'tcx>>>,
region: &'tcx ty::Region) {
// Imagine a type like this: // Imagine a type like this:
// //
// trait Foo { } // trait Foo { }
@ -485,11 +487,9 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> {
if !data.has_escaping_regions() { if !data.has_escaping_regions() {
let implicit_bounds = let implicit_bounds =
object_region_bounds(self.infcx.tcx, object_region_bounds(self.infcx.tcx, data);
data.principal().unwrap(),
data.auto_traits());
let explicit_bound = data.region_bound; let explicit_bound = region;
for implicit_bound in implicit_bounds { for implicit_bound in implicit_bounds {
let cause = self.cause(traits::ObjectTypeBound(ty, explicit_bound)); let cause = self.cause(traits::ObjectTypeBound(ty, explicit_bound));
@ -506,26 +506,23 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> {
/// they declare `trait SomeTrait : 'static`, for example, then /// they declare `trait SomeTrait : 'static`, for example, then
/// `'static` would appear in the list. The hard work is done by /// `'static` would appear in the list. The hard work is done by
/// `ty::required_region_bounds`, see that for more information. /// `ty::required_region_bounds`, see that for more information.
pub fn object_region_bounds<'a, 'gcx, 'tcx, I>( pub fn object_region_bounds<'a, 'gcx, 'tcx>(
tcx: TyCtxt<'a, 'gcx, 'tcx>, tcx: TyCtxt<'a, 'gcx, 'tcx>,
principal: ty::PolyExistentialTraitRef<'tcx>, existential_predicates: ty::Binder<&'tcx ty::Slice<ty::ExistentialPredicate<'tcx>>>)
others: I)
-> Vec<&'tcx ty::Region> -> Vec<&'tcx ty::Region>
where I: Iterator<Item=DefId>
{ {
// Since we don't actually *know* the self type for an object, // Since we don't actually *know* the self type for an object,
// this "open(err)" serves as a kind of dummy standin -- basically // this "open(err)" serves as a kind of dummy standin -- basically
// a skolemized type. // a skolemized type.
let open_ty = tcx.mk_infer(ty::FreshTy(0)); let open_ty = tcx.mk_infer(ty::FreshTy(0));
let mut predicates = others.map(|d| { let predicates = existential_predicates.iter().filter_map(|predicate| {
let trait_ref = ty::TraitRef { if let ty::ExistentialPredicate::Projection(_) = *predicate.skip_binder() {
def_id: d, None
substs: tcx.mk_substs_trait(open_ty, &[]) } else {
}; Some(predicate.with_self_ty(tcx, open_ty))
trait_ref.to_predicate() }
}).collect::<Vec<_>>(); }).collect();
predicates.push(principal.with_self_ty(tcx, open_ty).to_predicate());
tcx.required_region_bounds(open_ty, predicates) tcx.required_region_bounds(open_ty, predicates)
} }

View File

@ -16,9 +16,8 @@ use ty::{TyBool, TyChar, TyAdt};
use ty::{TyError, TyStr, TyArray, TySlice, TyFloat, TyFnDef, TyFnPtr}; use ty::{TyError, TyStr, TyArray, TySlice, TyFloat, TyFnDef, TyFnPtr};
use ty::{TyParam, TyRawPtr, TyRef, TyNever, TyTuple}; use ty::{TyParam, TyRawPtr, TyRef, TyNever, TyTuple};
use ty::{TyClosure, TyProjection, TyAnon}; 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::{self, Ty, TyCtxt, TypeFoldable};
use ty::fold::{TypeFolder, TypeVisitor};
use std::cell::Cell; use std::cell::Cell;
use std::fmt; use std::fmt;
@ -298,58 +297,23 @@ fn in_binder<'a, 'gcx, 'tcx, T, U>(f: &mut fmt::Formatter,
write!(f, "{}", new_value) write!(f, "{}", new_value)
} }
/// This curious type is here to help pretty-print trait objects. In impl<'tcx> fmt::Display for &'tcx ty::Slice<ty::ExistentialPredicate<'tcx>> {
/// a trait object, the projections are stored separately from the
/// main trait bound, but in fact we want to package them together
/// when printing out; they also have separate binders, but we want
/// them to share a binder when we print them out. (And the binder
/// pretty-printing logic is kind of clever and we don't want to
/// reproduce it.) So we just repackage up the structure somewhat.
///
/// Right now there is only one trait in an object that can have
/// projection bounds, so we just stuff them altogether. But in
/// reality we should eventually sort things out better.
#[derive(Clone, Debug)]
struct TraitAndProjections<'tcx>(ty::TraitRef<'tcx>,
Vec<ty::ProjectionPredicate<'tcx>>);
impl<'tcx> TypeFoldable<'tcx> for TraitAndProjections<'tcx> {
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
TraitAndProjections(self.0.fold_with(folder), self.1.fold_with(folder))
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
self.0.visit_with(visitor) || self.1.visit_with(visitor)
}
}
impl<'tcx> fmt::Display for TraitAndProjections<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let TraitAndProjections(ref trait_ref, ref projection_bounds) = *self;
parameterized(f, trait_ref.substs,
trait_ref.def_id,
projection_bounds)
}
}
impl<'tcx> fmt::Display for ty::TraitObject<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
// Generate the main trait ref, including associated types. // Generate the main trait ref, including associated types.
ty::tls::with(|tcx| { ty::tls::with(|tcx| {
// Use a type that can't appear in defaults of type parameters. // Use a type that can't appear in defaults of type parameters.
let dummy_self = tcx.mk_infer(ty::FreshTy(0)); let dummy_self = tcx.mk_infer(ty::FreshTy(0));
let principal = self.principal().and_then(|ref p| tcx.lift(p)) if let Some(p) = self.principal() {
.expect("could not lift TraitRef for printing") let principal = tcx.lift(&p).expect("could not lift TraitRef for printing")
.with_self_ty(tcx, dummy_self).0; .with_self_ty(tcx, dummy_self);
let projections = self.projection_bounds.iter().map(|p| { let projections = self.projection_bounds().map(|p| {
tcx.lift(p) tcx.lift(&p)
.expect("could not lift projection for printing") .expect("could not lift projection for printing")
.with_self_ty(tcx, dummy_self).0 .with_self_ty(tcx, dummy_self)
}).collect(); }).collect::<Vec<_>>();
parameterized(f, principal.substs, principal.def_id, &projections)?;
let tap = ty::Binder(TraitAndProjections(principal, projections)); }
in_binder(f, tcx, &ty::Binder(""), Some(tap))?;
// Builtin bounds. // Builtin bounds.
for did in self.auto_traits() { for did in self.auto_traits() {
@ -359,16 +323,6 @@ impl<'tcx> fmt::Display for ty::TraitObject<'tcx> {
Ok(()) Ok(())
})?; })?;
// FIXME: It'd be nice to compute from context when this bound
// is implied, but that's non-trivial -- we'd perhaps have to
// use thread-local data of some kind? There are also
// advantages to just showing the region, since it makes
// people aware that it's there.
let bound = self.region_bound.to_string();
if !bound.is_empty() {
write!(f, " + {}", bound)?;
}
Ok(()) Ok(())
} }
} }
@ -455,45 +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)?;
}
ty::tls::with(|tcx| {
for did in self.auto_traits() {
maybe_continue(f)?;
write!(f, " + {}", tcx.item_path_str(did))?;
}
Ok(())
})?;
for projection_bound in &self.projection_bounds {
maybe_continue(f)?;
write!(f, "{:?}", projection_bound)?;
}
Ok(())
}
}
impl<'tcx> fmt::Debug for ty::Predicate<'tcx> { impl<'tcx> fmt::Debug for ty::Predicate<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self { match *self {
@ -746,6 +661,12 @@ impl fmt::Debug for ty::IntVarValue {
} }
}*/ }*/
impl<'tcx> fmt::Display for ty::Binder<&'tcx ty::Slice<ty::ExistentialPredicate<'tcx>>> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
ty::tls::with(|tcx| in_binder(f, tcx, self, tcx.lift(self)))
}
}
impl<'tcx> fmt::Display for ty::Binder<ty::TraitRef<'tcx>> { impl<'tcx> fmt::Display for ty::Binder<ty::TraitRef<'tcx>> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
ty::tls::with(|tcx| in_binder(f, tcx, self, tcx.lift(self))) ty::tls::with(|tcx| in_binder(f, tcx, self, tcx.lift(self)))
@ -865,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), TyProjection(ref data) => write!(f, "{}", data),
TyAnon(def_id, substs) => { TyAnon(def_id, substs) => {
ty::tls::with(|tcx| { ty::tls::with(|tcx| {

View File

@ -572,7 +572,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
consider using a raw pointer instead") consider using a raw pointer instead")
} }
ty::TyTrait(..) => { ty::TyDynamic(..) => {
FfiUnsafe("found Rust trait type in foreign module, \ FfiUnsafe("found Rust trait type in foreign module, \
consider using a raw pointer instead") consider using a raw pointer instead")
} }

View File

@ -416,6 +416,15 @@ impl<'a, 'tcx> SpecializedDecoder<ty::AdtDef<'tcx>> for DecodeContext<'a, 'tcx>
} }
} }
impl<'a, 'tcx> SpecializedDecoder<&'tcx ty::Slice<ty::ExistentialPredicate<'tcx>>>
for DecodeContext<'a, 'tcx> {
fn specialized_decode(&mut self)
-> Result<&'tcx ty::Slice<ty::ExistentialPredicate<'tcx>>, Self::Error> {
Ok(self.tcx().mk_existential_predicates((0..self.read_usize()?)
.map(|_| Decodable::decode(self)))?)
}
}
impl<'a, 'tcx> MetadataBlob { impl<'a, 'tcx> MetadataBlob {
pub fn is_compatible(&self) -> bool { pub fn is_compatible(&self) -> bool {
self.raw_bytes().starts_with(METADATA_HEADER) self.raw_bytes().starts_with(METADATA_HEADER)

View File

@ -295,16 +295,14 @@ pub fn unsized_info<'ccx, 'tcx>(ccx: &CrateContext<'ccx, 'tcx>,
let (source, target) = ccx.tcx().struct_lockstep_tails(source, target); let (source, target) = ccx.tcx().struct_lockstep_tails(source, target);
match (&source.sty, &target.sty) { match (&source.sty, &target.sty) {
(&ty::TyArray(_, len), &ty::TySlice(_)) => C_uint(ccx, len), (&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 // For now, upcasts are limited to changes in marker
// traits, and hence never actually require an actual // traits, and hence never actually require an actual
// change to the vtable. // change to the vtable.
old_info.expect("unsized_info: missing old info for trait upcast") old_info.expect("unsized_info: missing old info for trait upcast")
} }
(_, &ty::TyTrait(ref data)) => { (_, &ty::TyDynamic(ref data, ..)) => {
let trait_ref = data.principal().unwrap().with_self_ty(ccx.tcx(), source); consts::ptrcast(meth::get_vtable(ccx, source, data.principal()),
let trait_ref = ccx.tcx().erase_regions(&trait_ref);
consts::ptrcast(meth::get_vtable(ccx, trait_ref),
Type::vtable_ptr(ccx)) Type::vtable_ptr(ccx))
} }
_ => bug!("unsized_info: invalid unsizing {:?} -> {:?}", _ => bug!("unsized_info: invalid unsizing {:?} -> {:?}",

View File

@ -763,7 +763,7 @@ fn find_drop_glue_neighbors<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
ty::TyFnDef(..) | ty::TyFnDef(..) |
ty::TyFnPtr(_) | ty::TyFnPtr(_) |
ty::TyNever | ty::TyNever |
ty::TyTrait(_) => { ty::TyDynamic(..) => {
/* nothing to do */ /* nothing to do */
} }
ty::TyAdt(adt_def, substs) => { ty::TyAdt(adt_def, substs) => {
@ -1003,18 +1003,20 @@ fn create_trans_items_for_vtable_methods<'a, 'tcx>(scx: &SharedCrateContext<'a,
output: &mut Vec<TransItem<'tcx>>) { output: &mut Vec<TransItem<'tcx>>) {
assert!(!trait_ty.needs_subst() && !impl_ty.needs_subst()); assert!(!trait_ty.needs_subst() && !impl_ty.needs_subst());
if let ty::TyTrait(ref trait_ty) = trait_ty.sty { if let ty::TyDynamic(ref trait_ty, ..) = trait_ty.sty {
let poly_trait_ref = trait_ty.principal().unwrap().with_self_ty(scx.tcx(), impl_ty); if let Some(principal) = trait_ty.principal() {
let param_substs = scx.tcx().intern_substs(&[]); 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);
// 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 // Also add the destructor
let dg_type = glue::get_drop_glue_type(scx.tcx(), impl_ty); let dg_type = glue::get_drop_glue_type(scx.tcx(), impl_ty);
output.push(TransItem::DropGlue(DropGlueKind::Ty(dg_type))); output.push(TransItem::DropGlue(DropGlueKind::Ty(dg_type)));

View File

@ -95,7 +95,8 @@ pub struct LocalCrateContext<'tcx> {
/// Cache instances of monomorphic and polymorphic items /// Cache instances of monomorphic and polymorphic items
instances: RefCell<FxHashMap<Instance<'tcx>, ValueRef>>, instances: RefCell<FxHashMap<Instance<'tcx>, ValueRef>>,
/// Cache generated vtables /// Cache generated vtables
vtables: RefCell<FxHashMap<ty::PolyTraitRef<'tcx>, ValueRef>>, vtables: RefCell<FxHashMap<(ty::Ty<'tcx>,
Option<ty::PolyExistentialTraitRef<'tcx>>), ValueRef>>,
/// Cache of constant strings, /// Cache of constant strings,
const_cstr_cache: RefCell<FxHashMap<InternedString, ValueRef>>, const_cstr_cache: RefCell<FxHashMap<InternedString, ValueRef>>,
@ -800,7 +801,9 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> {
&self.local().instances &self.local().instances
} }
pub fn vtables<'a>(&'a self) -> &'a RefCell<FxHashMap<ty::PolyTraitRef<'tcx>, ValueRef>> { pub fn vtables<'a>(&'a self)
-> &'a RefCell<FxHashMap<(ty::Ty<'tcx>,
Option<ty::PolyExistentialTraitRef<'tcx>>), ValueRef>> {
&self.local().vtables &self.local().vtables
} }

View File

@ -432,7 +432,7 @@ fn trait_pointer_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
// But it does not describe the trait's methods. // But it does not describe the trait's methods.
let containing_scope = match trait_type.sty { let containing_scope = match trait_type.sty {
ty::TyTrait(ref data) => if let Some(principal) = data.principal() { ty::TyDynamic(ref data, ..) => if let Some(principal) = data.principal() {
let def_id = principal.def_id(); let def_id = principal.def_id();
get_namespace_and_span_for_item(cx, def_id).0 get_namespace_and_span_for_item(cx, def_id).0
} else { } else {
@ -523,7 +523,7 @@ pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
ty::TyStr => { ty::TyStr => {
fixed_vec_metadata(cx, unique_type_id, cx.tcx().types.i8, None, usage_site_span) fixed_vec_metadata(cx, unique_type_id, cx.tcx().types.i8, None, usage_site_span)
} }
ty::TyTrait(..) => { ty::TyDynamic(..) => {
MetadataCreationResult::new( MetadataCreationResult::new(
trait_pointer_metadata(cx, t, None, unique_type_id), trait_pointer_metadata(cx, t, None, unique_type_id),
false) false)
@ -538,7 +538,7 @@ pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
ty::TyStr => { ty::TyStr => {
vec_slice_metadata(cx, t, cx.tcx().types.u8, unique_type_id, usage_site_span) vec_slice_metadata(cx, t, cx.tcx().types.u8, unique_type_id, usage_site_span)
} }
ty::TyTrait(..) => { ty::TyDynamic(..) => {
MetadataCreationResult::new( MetadataCreationResult::new(
trait_pointer_metadata(cx, ty, Some(t), unique_type_id), trait_pointer_metadata(cx, ty, Some(t), unique_type_id),
false) false)

View File

@ -93,7 +93,7 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
push_debuginfo_type_name(cx, inner_type, true, output); push_debuginfo_type_name(cx, inner_type, true, output);
output.push(']'); output.push(']');
}, },
ty::TyTrait(ref trait_data) => { ty::TyDynamic(ref trait_data, ..) => {
if let Some(principal) = trait_data.principal() { if let Some(principal) = trait_data.principal() {
let principal = cx.tcx().erase_late_bound_regions_and_normalize( let principal = cx.tcx().erase_late_bound_regions_and_normalize(
&principal); &principal);

View File

@ -394,7 +394,7 @@ pub fn size_and_align_of_dst<'blk, 'tcx>(bcx: &BlockAndBuilder<'blk, 'tcx>,
(size, align) (size, align)
} }
ty::TyTrait(..) => { ty::TyDynamic(..) => {
// info points to the vtable and the second entry in the vtable is the // info points to the vtable and the second entry in the vtable is the
// dynamic size of the object. // dynamic size of the object.
let info = bcx.pointercast(info, Type::int(bcx.ccx()).ptr_to()); 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) trans_exchange_free_ty(bcx, llbox, content_ty, DebugLoc::None)
} }
} }
ty::TyTrait(..) => { ty::TyDynamic(..) => {
// No support in vtable for distinguishing destroying with // No support in vtable for distinguishing destroying with
// versus without calling Drop::drop. Assert caller is // versus without calling Drop::drop. Assert caller is
// okay with always calling the Drop impl, if any. // okay with always calling the Drop impl, if any.

View File

@ -110,42 +110,48 @@ pub fn trans_object_shim<'a, 'tcx>(ccx: &'a CrateContext<'a, 'tcx>,
/// making an object `Foo<Trait>` from a value of type `Foo<T>`, then /// making an object `Foo<Trait>` from a value of type `Foo<T>`, then
/// `trait_ref` would map `T:Trait`. /// `trait_ref` would map `T:Trait`.
pub fn get_vtable<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, pub fn get_vtable<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
trait_ref: ty::PolyTraitRef<'tcx>) ty: ty::Ty<'tcx>,
trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>)
-> ValueRef -> ValueRef
{ {
let tcx = ccx.tcx(); let tcx = ccx.tcx();
let _icx = push_ctxt("meth::get_vtable"); 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. // 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; return val;
} }
// Not in the cache. Build it. // Not in the cache. Build it.
let nullptr = C_null(Type::nil(ccx).ptr_to()); 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 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. // 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, size),
C_uint(ccx, align) 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 vtable_const = C_struct(ccx, &components, false);
let align = machine::llalign_of_pref(ccx, val_ty(vtable_const)); let align = machine::llalign_of_pref(ccx, val_ty(vtable_const));
let vtable = consts::addr_of(ccx, vtable_const, align, "vtable"); 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 vtable
} }

View File

@ -457,11 +457,11 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> {
self.push_type_name(inner_type, output); self.push_type_name(inner_type, output);
output.push(']'); output.push(']');
}, },
ty::TyTrait(ref trait_data) => { ty::TyDynamic(ref trait_data, ..) => {
if let Some(principal) = trait_data.principal() { if let Some(principal) = trait_data.principal() {
self.push_def_path(principal.def_id(), output); self.push_def_path(principal.def_id(), output);
self.push_type_params(principal.skip_binder().substs, self.push_type_params(principal.skip_binder().substs,
&trait_data.projection_bounds, &trait_data.projection_bounds().collect::<Vec<_>>()[..],
output); output);
} }
}, },

View File

@ -95,7 +95,7 @@ pub fn sizing_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Typ
ty::TyAnon(..) | ty::TyError => { ty::TyAnon(..) | ty::TyError => {
bug!("fictitious type {:?} in sizing_type_of()", t) 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); 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(_) => { ty::TyStr | ty::TyArray(..) | ty::TySlice(_) => {
Type::uint_from_ty(ccx, ast::UintTy::Us) 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={:?}", _ => bug!("Unexpected tail in unsized_info_ty: {:?} for ty={:?}",
unsized_part, 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 // fat pointers is of the right type (e.g. for array accesses), even
// when taking the address of an unsized field in a struct. // when taking the address of an unsized field in a struct.
ty::TySlice(ty) => in_memory_type_of(cx, ty), 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::TyFnDef(..) => Type::nil(cx),
ty::TyFnPtr(f) => { ty::TyFnPtr(f) => {

View File

@ -49,6 +49,7 @@
//! an rptr (`&r.T`) use the region `r` that appears in the rptr. //! an rptr (`&r.T`) use the region `r` that appears in the rptr.
use rustc_const_eval::eval_length; use rustc_const_eval::eval_length;
use rustc_data_structures::accumulate_vec::AccumulateVec;
use hir::{self, SelfKind}; use hir::{self, SelfKind};
use hir::def::Def; use hir::def::Def;
use hir::def_id::DefId; use hir::def_id::DefId;
@ -69,6 +70,7 @@ use util::common::{ErrorReported, FN_OUTPUT_NAME};
use util::nodemap::{NodeMap, FxHashSet}; use util::nodemap::{NodeMap, FxHashSet};
use std::cell::RefCell; use std::cell::RefCell;
use std::iter;
use syntax::{abi, ast}; use syntax::{abi, ast};
use syntax::feature_gate::{GateIssue, emit_feature_err}; use syntax::feature_gate::{GateIssue, emit_feature_err};
use syntax::symbol::{Symbol, keywords}; use syntax::symbol::{Symbol, keywords};
@ -1052,8 +1054,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
let b = &trait_bounds[0]; let b = &trait_bounds[0];
let span = b.trait_ref.path.span; let span = b.trait_ref.path.span;
struct_span_err!(self.tcx().sess, span, E0225, struct_span_err!(self.tcx().sess, span, E0225,
"only the builtin traits can be used as closure or object bounds") "only Send/Sync traits can be used as additional traits in a trait object")
.span_label(span, &format!("non-builtin trait used as bounds")) .span_label(span, &format!("non-Send/Sync additional trait"))
.emit(); .emit();
} }
@ -1070,30 +1072,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
ty: b.ty ty: b.ty
} }
}) })
}).collect(); });
let region_bound =
self.compute_object_lifetime_bound(span,
&region_bounds,
existential_principal,
&auto_traits);
let region_bound = match region_bound {
Some(r) => r,
None => {
tcx.mk_region(match rscope.object_lifetime_default(span) {
Some(r) => r,
None => {
span_err!(self.tcx().sess, span, E0228,
"the lifetime bound for this object type cannot be deduced \
from context; please supply an explicit bound");
ty::ReStatic
}
})
}
};
debug!("region_bound: {:?}", region_bound);
// ensure the super predicates and stop if we encountered an error // ensure the super predicates and stop if we encountered an error
if self.ensure_super_predicates(span, principal.def_id()).is_err() { if self.ensure_super_predicates(span, principal.def_id()).is_err() {
@ -1135,12 +1114,37 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
.emit(); .emit();
} }
let ty = tcx.mk_trait(ty::TraitObject::new( let mut v =
Some(existential_principal), iter::once(ty::ExistentialPredicate::Trait(*existential_principal.skip_binder()))
region_bound, .chain(auto_traits.into_iter().map(ty::ExistentialPredicate::AutoTrait))
auto_traits, .chain(existential_projections
existential_projections .map(|x| ty::ExistentialPredicate::Projection(*x.skip_binder())))
)); .collect::<AccumulateVec<[_; 8]>>();
v.sort_by(|a, b| a.cmp(tcx, b));
let existential_predicates = ty::Binder(tcx.mk_existential_predicates(v.into_iter()));
let region_bound = self.compute_object_lifetime_bound(span,
&region_bounds,
existential_predicates);
let region_bound = match region_bound {
Some(r) => r,
None => {
tcx.mk_region(match rscope.object_lifetime_default(span) {
Some(r) => r,
None => {
span_err!(self.tcx().sess, span, E0228,
"the lifetime bound for this object type cannot be deduced \
from context; please supply an explicit bound");
ty::ReStatic
}
})
}
};
debug!("region_bound: {:?}", region_bound);
let ty = tcx.mk_dynamic(existential_predicates, region_bound);
debug!("trait_object_type: {:?}", ty); debug!("trait_object_type: {:?}", ty);
ty ty
} }
@ -1922,38 +1926,36 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
fn compute_object_lifetime_bound(&self, fn compute_object_lifetime_bound(&self,
span: Span, span: Span,
explicit_region_bounds: &[&hir::Lifetime], explicit_region_bounds: &[&hir::Lifetime],
principal_trait_ref: ty::PolyExistentialTraitRef<'tcx>, existential_predicates: ty::Binder<&'tcx ty::Slice<ty::ExistentialPredicate<'tcx>>>)
auto_traits: &[DefId])
-> Option<&'tcx ty::Region> // if None, use the default -> Option<&'tcx ty::Region> // if None, use the default
{ {
let tcx = self.tcx(); let tcx = self.tcx();
debug!("compute_opt_region_bound(explicit_region_bounds={:?}, \ debug!("compute_opt_region_bound(explicit_region_bounds={:?}, \
principal_trait_ref={:?}, auto_traits={:?})", existential_predicates={:?})",
explicit_region_bounds, explicit_region_bounds,
principal_trait_ref, existential_predicates);
auto_traits);
if explicit_region_bounds.len() > 1 { if explicit_region_bounds.len() > 1 {
span_err!(tcx.sess, explicit_region_bounds[1].span, E0226, span_err!(tcx.sess, explicit_region_bounds[1].span, E0226,
"only a single explicit lifetime bound is permitted"); "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. // Explicitly specified region bound. Use that.
let r = explicit_region_bounds[0];
return Some(ast_region_to_region(tcx, r)); return Some(ast_region_to_region(tcx, r));
} }
if let Err(ErrorReported) = if let Some(principal) = existential_predicates.principal() {
self.ensure_super_predicates(span, principal_trait_ref.def_id()) { if let Err(ErrorReported) = self.ensure_super_predicates(span, principal.def_id()) {
return Some(tcx.mk_region(ty::ReStatic)); return Some(tcx.mk_region(ty::ReStatic));
}
} }
// No explicit region bound specified. Therefore, examine trait // No explicit region bound specified. Therefore, examine trait
// bounds and see if we can derive region bounds from those. // bounds and see if we can derive region bounds from those.
let derived_region_bounds = let derived_region_bounds =
object_region_bounds(tcx, principal_trait_ref, auto_traits.into_iter().cloned()); object_region_bounds(tcx, existential_predicates);
// If there are no derived region bounds, then report back that we // If there are no derived region bounds, then report back that we
// can find no region bound. The caller will use the default. // can find no region bound. The caller will use the default.
@ -2000,7 +2002,11 @@ pub fn partition_bounds<'a, 'b, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
hir::TraitTyParamBound(ref b, hir::TraitBoundModifier::None) => { hir::TraitTyParamBound(ref b, hir::TraitBoundModifier::None) => {
match b.trait_ref.path.def { match b.trait_ref.path.def {
Def::Trait(trait_did) => { Def::Trait(trait_did) => {
if tcx.try_add_builtin_trait(trait_did, &mut auto_traits) { // Checks whether `trait_did` refers to one of the builtin
// traits, like `Send`, and adds it to `auto_traits` if so.
if Some(trait_did) == tcx.lang_items.send_trait() ||
Some(trait_did) == tcx.lang_items.sync_trait() {
auto_traits.push(trait_did);
let segments = &b.trait_ref.path.segments; let segments = &b.trait_ref.path.segments;
let parameters = &segments[segments.len() - 1].parameters; let parameters = &segments[segments.len() - 1].parameters;
if !parameters.types().is_empty() { if !parameters.types().is_empty() {
@ -2115,12 +2121,15 @@ impl<'a, 'gcx, 'tcx> Bounds<'tcx> {
{ {
let mut vec = Vec::new(); let mut vec = Vec::new();
for trait_did in &self.auto_traits { // If it could be sized, and is, add the sized predicate
let trait_ref = ty::TraitRef { if self.implicitly_sized {
def_id: *trait_did, if let Some(sized) = tcx.lang_items.sized_trait() {
substs: tcx.mk_substs_trait(param_ty, &[]), let trait_ref = ty::TraitRef {
}; def_id: sized,
vec.push(trait_ref.to_predicate()); substs: tcx.mk_substs_trait(param_ty, &[])
};
vec.push(trait_ref.to_predicate());
}
} }
for &region_bound in &self.region_bounds { for &region_bound in &self.region_bounds {

View File

@ -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 { pub fn check_dereferencable(&self, span: Span, expected: Ty<'tcx>, inner: &hir::Pat) -> bool {
if let PatKind::Binding(..) = inner.node { if let PatKind::Binding(..) = inner.node {
if let Some(mt) = self.shallow_resolve(expected).builtin_deref(true, ty::NoPreference) { 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 // This is "x = SomeTrait" being reduced from
// "let &x = &SomeTrait" or "let box x = Box<SomeTrait>", an error. // "let &x = &SomeTrait" or "let box x = Box<SomeTrait>", an error.
let type_str = self.ty_to_string(expected); let type_str = self.ty_to_string(expected);

View File

@ -65,7 +65,7 @@ pub struct CastCheck<'tcx> {
/// fat pointers if their unsize-infos have the same kind. /// fat pointers if their unsize-infos have the same kind.
#[derive(Copy, Clone, PartialEq, Eq)] #[derive(Copy, Clone, PartialEq, Eq)]
enum UnsizeKind<'tcx> { enum UnsizeKind<'tcx> {
Vtable(DefId), Vtable(Option<DefId>),
Length, Length,
/// The unsize info of this projection /// The unsize info of this projection
OfProjection(&'tcx ty::ProjectionTy<'tcx>), OfProjection(&'tcx ty::ProjectionTy<'tcx>),
@ -79,7 +79,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
fn unsize_kind(&self, t: Ty<'tcx>) -> Option<UnsizeKind<'tcx>> { fn unsize_kind(&self, t: Ty<'tcx>) -> Option<UnsizeKind<'tcx>> {
match t.sty { match t.sty {
ty::TySlice(_) | ty::TyStr => Some(UnsizeKind::Length), ty::TySlice(_) | ty::TyStr => Some(UnsizeKind::Length),
ty::TyTrait(ref tty) => Some(UnsizeKind::Vtable(tty.principal().unwrap().def_id())), ty::TyDynamic(ref tty, ..) =>
Some(UnsizeKind::Vtable(tty.principal().map(|p| p.def_id()))),
ty::TyAdt(def, substs) if def.is_struct() => { ty::TyAdt(def, substs) if def.is_struct() => {
// FIXME(arielb1): do some kind of normalization // FIXME(arielb1): do some kind of normalization
match def.struct_variant().fields.last() { match def.struct_variant().fields.last() {
@ -130,7 +131,7 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> {
// cases now. We do a more thorough check at the end, once // cases now. We do a more thorough check at the end, once
// inference is more completely known. // inference is more completely known.
match cast_ty.sty { match cast_ty.sty {
ty::TyTrait(..) | ty::TySlice(..) => { ty::TyDynamic(..) | ty::TySlice(..) => {
check.report_cast_to_unsized_type(fcx); check.report_cast_to_unsized_type(fcx);
Err(ErrorReported) Err(ErrorReported)
} }

View File

@ -111,16 +111,15 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
expected_ty); expected_ty);
match expected_ty.sty { match expected_ty.sty {
ty::TyTrait(ref object_type) => { ty::TyDynamic(ref object_type, ..) => {
let sig = object_type.projection_bounds let sig = object_type.projection_bounds()
.iter()
.filter_map(|pb| { .filter_map(|pb| {
let pb = pb.with_self_ty(self.tcx, self.tcx.types.err); let pb = pb.with_self_ty(self.tcx, self.tcx.types.err);
self.deduce_sig_from_projection(&pb) self.deduce_sig_from_projection(&pb)
}) })
.next(); .next();
let kind = let kind = object_type.principal()
self.tcx.lang_items.fn_trait_kind(object_type.principal().unwrap().def_id()); .and_then(|p| self.tcx.lang_items.fn_trait_kind(p.def_id()));
(sig, kind) (sig, kind)
} }
ty::TyInfer(ty::TyVar(vid)) => self.deduce_expectations_from_obligations(vid), ty::TyInfer(ty::TyVar(vid)) => self.deduce_expectations_from_obligations(vid),

View File

@ -515,7 +515,7 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'b, 'gcx, 'tcx>(
} }
// these are always dtorck // 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); let revised_ty = revise_self_ty(tcx, adt_def, impl_def_id, substs);
return DropckKind::RevisedSelf(revised_ty); 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); debug!("ty: {:?} isn't known, and therefore is a dropck type", ty);
return DropckKind::BorrowedDataMustStrictlyOutliveSelf; return DropckKind::BorrowedDataMustStrictlyOutliveSelf;
}, },

View File

@ -255,7 +255,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
.autoderef(self.span, self_ty) .autoderef(self.span, self_ty)
.filter_map(|(ty, _)| { .filter_map(|(ty, _)| {
match ty.sty { match ty.sty {
ty::TyTrait(ref data) => data.principal().map(|p| closure(self, ty, p)), ty::TyDynamic(ref data, ..) => data.principal().map(|p| closure(self, ty, p)),
_ => None, _ => None,
} }
}) })

View File

@ -295,9 +295,11 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
debug!("assemble_probe: self_ty={:?}", self_ty); debug!("assemble_probe: self_ty={:?}", self_ty);
match self_ty.sty { match self_ty.sty {
ty::TyTrait(box ref data) => { ty::TyDynamic(ref data, ..) => {
self.assemble_inherent_candidates_from_object(self_ty, data.principal().unwrap()); if let Some(p) = data.principal() {
self.assemble_inherent_impl_candidates_for_type(data.principal().unwrap().def_id()); self.assemble_inherent_candidates_from_object(self_ty, p);
self.assemble_inherent_impl_candidates_for_type(p.def_id());
}
} }
ty::TyAdt(def, _) => { ty::TyAdt(def, _) => {
self.assemble_inherent_impl_candidates_for_type(def.did); self.assemble_inherent_impl_candidates_for_type(def.did);

View File

@ -379,8 +379,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
match ty.sty { match ty.sty {
ty::TyAdt(def, _) => def.did.is_local(), ty::TyAdt(def, _) => def.did.is_local(),
ty::TyTrait(ref tr) => tr.principal().map(|p| ty::TyDynamic(ref tr, ..) => tr.principal()
p.def_id().is_local()).unwrap_or(false), .map_or(false, |p| p.def_id().is_local()),
ty::TyParam(_) => true, ty::TyParam(_) => true,

View File

@ -269,7 +269,7 @@ impl<'a, 'gcx, 'tcx> Expectation<'tcx> {
/// for examples of where this comes up,. /// for examples of where this comes up,.
fn rvalue_hint(fcx: &FnCtxt<'a, 'gcx, 'tcx>, ty: Ty<'tcx>) -> Expectation<'tcx> { fn rvalue_hint(fcx: &FnCtxt<'a, 'gcx, 'tcx>, ty: Ty<'tcx>) -> Expectation<'tcx> {
match fcx.tcx.struct_tail(ty).sty { match fcx.tcx.struct_tail(ty).sty {
ty::TySlice(_) | ty::TyStr | ty::TyTrait(..) => { ty::TySlice(_) | ty::TyStr | ty::TyDynamic(..) => {
ExpectRvalueLikeUnsized(ty) ExpectRvalueLikeUnsized(ty)
} }
_ => ExpectHasType(ty) _ => ExpectHasType(ty)

View File

@ -806,11 +806,10 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
} }
/*From:*/ (_, /*From:*/ (_,
/*To: */ &ty::TyTrait(ref obj)) => { /*To: */ &ty::TyDynamic(.., r)) => {
// When T is existentially quantified as a trait // When T is existentially quantified as a trait
// `Foo+'to`, it must outlive the region bound `'to`. // `Foo+'to`, it must outlive the region bound `'to`.
self.type_must_outlive(infer::RelateObjectBound(cast_expr.span), self.type_must_outlive(infer::RelateObjectBound(cast_expr.span), from_ty, r);
from_ty, obj.region_bound);
} }
/*From:*/ (&ty::TyBox(from_referent_ty), /*From:*/ (&ty::TyBox(from_referent_ty),

View File

@ -118,15 +118,8 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> {
// FIXME(#27579) what amount of WF checking do we need for neg impls? // 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(); 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); if !ccx.tcx.trait_has_default_impl(trait_ref.def_id) {
let sync_trait = ccx.tcx.lang_items.require(lang_items::SyncTraitLangItem) error_192(ccx, item.span);
.unwrap_or_else(|msg| ccx.tcx.sess.fatal(&msg[..]));
let send_trait = ccx.tcx.lang_items.require(lang_items::SendTraitLangItem)
.unwrap_or_else(|msg| ccx.tcx.sess.fatal(&msg[..]));
if trait_ref.def_id != sync_trait && trait_ref.def_id != send_trait {
if !ccx.tcx.trait_has_default_impl(trait_ref.def_id) {
error_192(ccx, item.span);
}
} }
} }
hir::ItemFn(.., ref body) => { hir::ItemFn(.., ref body) => {

View File

@ -23,7 +23,7 @@ use rustc::traits::{self, ObligationCause, Reveal};
use rustc::ty::ParameterEnvironment; use rustc::ty::ParameterEnvironment;
use rustc::ty::{Ty, TyBool, TyChar, TyError}; use rustc::ty::{Ty, TyBool, TyChar, TyError};
use rustc::ty::{TyParam, TyRawPtr}; 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::{TyStr, TyArray, TySlice, TyFloat, TyInfer, TyInt};
use rustc::ty::{TyUint, TyClosure, TyBox, TyFnDef, TyFnPtr}; use rustc::ty::{TyUint, TyClosure, TyBox, TyFnDef, TyFnPtr};
use rustc::ty::{TyProjection, TyAnon}; use rustc::ty::{TyProjection, TyAnon};
@ -68,7 +68,7 @@ impl<'a, 'gcx, 'tcx> CoherenceChecker<'a, 'gcx, 'tcx> {
match ty.sty { match ty.sty {
TyAdt(def, _) => Some(def.did), TyAdt(def, _) => Some(def.did),
TyTrait(ref t) => t.principal().map(|p| p.def_id()), TyDynamic(ref t, ..) => t.principal().map(|p| p.def_id()),
TyBox(_) => self.inference_context.tcx.lang_items.owned_box(), TyBox(_) => self.inference_context.tcx.lang_items.owned_box(),

View File

@ -86,7 +86,7 @@ impl<'cx, 'tcx> OrphanChecker<'cx, 'tcx> {
ty::TyAdt(def, _) => { ty::TyAdt(def, _) => {
self.check_def_id(item, def.did); self.check_def_id(item, def.did);
} }
ty::TyTrait(ref data) if data.principal().is_some() => { ty::TyDynamic(ref data, ..) if data.principal().is_some() => {
self.check_def_id(item, data.principal().unwrap().def_id()); self.check_def_id(item, data.principal().unwrap().def_id());
} }
ty::TyBox(..) => { ty::TyBox(..) => {

View File

@ -178,16 +178,13 @@ impl<'cx, 'tcx, 'v> ItemLikeVisitor<'v> for OverlapChecker<'cx, 'tcx> {
} }
// check for overlap with the automatic `impl Trait for Trait` // 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 // This is something like impl Trait1 for Trait2. Illegal
// if Trait1 is a supertrait of Trait2 or Trait2 is not object safe. // if Trait1 is a supertrait of Trait2 or Trait2 is not object safe.
if data.principal().is_none() || if data.principal().map_or(true, |p| !self.tcx.is_object_safe(p.def_id())) {
!self.tcx.is_object_safe(data.principal().unwrap().def_id()) { // This is an error, but it will be reported by wfcheck. Ignore it here.
// This is an error, but it will be // This is tested by `coherence-impl-trait-for-trait-object-safe.rs`.
// reported by wfcheck. Ignore it
// here. This is tested by
// `coherence-impl-trait-for-trait-object-safe.rs`.
} else { } else {
let mut supertrait_def_ids = let mut supertrait_def_ids =
traits::supertrait_def_ids(self.tcx, traits::supertrait_def_ids(self.tcx,

View File

@ -1617,12 +1617,11 @@ fn add_unsized_bound<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>,
"default bound relaxed for a type parameter, but \ "default bound relaxed for a type parameter, but \
this does nothing because the given bound is not \ this does nothing because the given bound is not \
a default. Only `?Sized` is supported"); a default. Only `?Sized` is supported");
tcx.try_add_builtin_trait(kind_id, bounds);
} }
} }
} }
_ if kind_id.is_ok() => { _ if kind_id.is_ok() => {
tcx.try_add_builtin_trait(kind_id.unwrap(), bounds); bounds.push(kind_id.unwrap());
} }
// No lang item for Sized, so we can't add it as a bound. // No lang item for Sized, so we can't add it as a bound.
None => {} None => {}

View File

@ -2778,8 +2778,8 @@ fn main() {
} }
``` ```
Builtin traits are an exception to this rule: it's possible to have bounds of Send and Sync 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 one non-builtin trait, plus either or both of Send and Sync. For example, the
following compiles correctly: following compiles correctly:
``` ```

View File

@ -371,16 +371,17 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
variance); variance);
} }
ty::TyTrait(ref data) => { ty::TyDynamic(ref data, r) => {
// The type `Foo<T+'a>` is contravariant w/r/t `'a`: // The type `Foo<T+'a>` is contravariant w/r/t `'a`:
let contra = self.contravariant(variance); let contra = self.contravariant(variance);
self.add_constraints_from_region(generics, data.region_bound, contra); self.add_constraints_from_region(generics, r, contra);
let poly_trait_ref = data.principal().unwrap().with_self_ty(self.tcx(), if let Some(p) = data.principal() {
self.tcx().types.err); 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); 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); self.add_constraints_from_ty(generics, projection.0.ty, self.invariant);
} }
} }

View File

@ -594,10 +594,10 @@ pub enum TyParamBound {
impl TyParamBound { impl TyParamBound {
fn maybe_sized(cx: &DocContext) -> TyParamBound { fn maybe_sized(cx: &DocContext) -> TyParamBound {
let did = cx.tcx().lang_items.require(lang_items::SizedTraitLangItem) let did = cx.tcx.lang_items.require(lang_items::SizedTraitLangItem)
.unwrap_or_else(|msg| cx.tcx().sess.fatal(&msg[..])); .unwrap_or_else(|msg| cx.tcx.sess.fatal(&msg[..]));
let empty = cx.tcx().intern_substs(&[]); let empty = cx.tcx.intern_substs(&[]);
let path = external_path(cx, &cx.tcx().item_name(did).as_str(), let path = external_path(cx, &cx.tcx.item_name(did).as_str(),
Some(did), false, vec![], empty); Some(did), false, vec![], empty);
inline::record_extern_fqn(cx, did, TypeKind::Trait); inline::record_extern_fqn(cx, did, TypeKind::Trait);
TraitBound(PolyTrait { TraitBound(PolyTrait {
@ -1855,23 +1855,16 @@ impl<'tcx> Clean<Type> for ty::Ty<'tcx> {
is_generic: false, is_generic: false,
} }
} }
ty::TyTrait(ref obj) => { ty::TyDynamic(ref obj, ref reg) => {
if let Some(principal) = obj.principal() { if let Some(principal) = obj.principal() {
let did = principal.def_id(); let did = principal.def_id();
inline::record_extern_fqn(cx, did, TypeKind::Trait); inline::record_extern_fqn(cx, did, TypeKind::Trait);
let mut typarams = vec![]; let mut typarams = vec![];
obj.region_bound.clean(cx).map(|b| typarams.push(RegionBound(b))); reg.clean(cx).map(|b| typarams.push(RegionBound(b)));
for did in obj.auto_traits() { for did in obj.auto_traits() {
let tcx = match cx.tcx_opt() { let empty = cx.tcx.intern_substs(&[]);
Some(tcx) => tcx, let path = external_path(cx, &cx.tcx.item_name(did).as_str(),
None => {
typarams.push(RegionBound(Lifetime::statik()));
continue;
}
};
let empty = tcx.intern_substs(&[]);
let path = external_path(cx, &tcx.item_name(did).as_str(),
Some(did), false, vec![], empty); Some(did), false, vec![], empty);
inline::record_extern_fqn(cx, did, TypeKind::Trait); inline::record_extern_fqn(cx, did, TypeKind::Trait);
let bound = TraitBound(PolyTrait { let bound = TraitBound(PolyTrait {
@ -1887,14 +1880,14 @@ impl<'tcx> Clean<Type> for ty::Ty<'tcx> {
} }
let mut bindings = vec![]; let mut bindings = vec![];
for &ty::Binder(ref pb) in &obj.projection_bounds { for ty::Binder(ref pb) in obj.projection_bounds() {
bindings.push(TypeBinding { bindings.push(TypeBinding {
name: pb.item_name.clean(cx), name: pb.item_name.clean(cx),
ty: pb.ty.clean(cx) ty: pb.ty.clean(cx)
}); });
} }
let path = external_path(cx, &cx.tcx().item_name(did).as_str(), Some(did), let path = external_path(cx, &cx.tcx.item_name(did).as_str(), Some(did),
false, bindings, principal.0.substs); false, bindings, principal.0.substs);
ResolvedPath { ResolvedPath {
path: path, path: path,

View File

@ -10,6 +10,6 @@
fn main() { fn main() {
let _: Box<std::io::Read + std::io::Write>; let _: Box<std::io::Read + std::io::Write>;
//~^ ERROR only the builtin traits can be used as closure or object bounds [E0225] //~^ ERROR only Send/Sync traits can be used as additional traits in a trait object [E0225]
//~| NOTE non-builtin trait used as bounds //~| NOTE non-Send/Sync additional trait
} }

View File

@ -12,8 +12,7 @@ trait Trait {}
pub fn main() { pub fn main() {
let x: Vec<Trait + Sized> = Vec::new(); let x: Vec<Trait + Sized> = Vec::new();
//~^ ERROR the trait bound `Trait + std::marker::Sized: std::marker::Sized` is not satisfied //~^ ERROR only Send/Sync traits can be used as additional traits in a trait object
//~| ERROR the trait `std::marker::Sized` cannot be made into an object //~| ERROR the trait bound `Trait: std::marker::Sized` is not satisfied
//~| ERROR the trait bound `Trait + std::marker::Sized: std::marker::Sized` is not satisfied //~| ERROR the trait bound `Trait: std::marker::Sized` is not satisfied
//~| ERROR the trait `std::marker::Sized` cannot be made into an object
} }

View File

@ -20,6 +20,6 @@ type Test = Add +
//~| NOTE missing associated type `Output` value //~| NOTE missing associated type `Output` value
Sub; Sub;
//~^ ERROR E0225 //~^ ERROR E0225
//~| NOTE non-builtin trait used as bounds //~| NOTE non-Send/Sync additional trait
fn main() { } fn main() { }

View File

@ -16,6 +16,6 @@ fn size_of_copy<T: Copy+?Sized>() -> usize { mem::size_of::<T>() }
fn main() { fn main() {
size_of_copy::<Misc+Copy>(); size_of_copy::<Misc+Copy>();
//~^ ERROR the trait bound `Misc + std::marker::Copy: std::marker::Copy` is not satisfied //~^ ERROR only Send/Sync traits can be used as additional traits in a trait object
//~| ERROR the trait `std::marker::Copy` cannot be made into an object //~| ERROR the trait bound `Misc: std::marker::Copy` is not satisfied
} }

View File

@ -24,7 +24,7 @@ fn d(x: Box<Foo>) {
a(x); //~ ERROR mismatched types [E0308] a(x); //~ ERROR mismatched types [E0308]
//~| NOTE expected type `Box<Foo + std::marker::Send + 'static>` //~| NOTE expected type `Box<Foo + std::marker::Send + 'static>`
//~| NOTE found type `Box<Foo + 'static>` //~| NOTE found type `Box<Foo + 'static>`
//~| NOTE expected trait Foo, found a different trait Foo //~| NOTE expected trait `Foo + std::marker::Send`, found trait `Foo`
} }
fn main() { } fn main() { }

View File

@ -70,7 +70,7 @@ pub mod testtypes {
// Tests TyFnPtr // Tests TyFnPtr
pub type FooFnPtr = fn(u8) -> bool; pub type FooFnPtr = fn(u8) -> bool;
// Tests TyTrait // Tests TyDynamic
pub trait FooTrait { pub trait FooTrait {
fn foo_method(&self) -> usize; fn foo_method(&self) -> usize;
} }