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_save_analysis := rustc log syntax syntax_pos serialize
DEPS_rustc_typeck := rustc syntax syntax_pos rustc_platform_intrinsics rustc_const_math \
rustc_const_eval rustc_errors
rustc_const_eval rustc_errors rustc_data_structures
DEPS_rustdoc := rustc rustc_driver native:hoedown serialize getopts test \
rustc_lint rustc_const_eval syntax_pos rustc_data_structures

View File

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

View File

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

View File

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

View File

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

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
/// `evaluate` methods).
pub fn type_known_to_meet_bound<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
ty: Ty<'tcx>,
def_id: DefId,
span: Span)
-> bool
ty: Ty<'tcx>,
def_id: DefId,
span: Span)
-> bool
{
debug!("type_known_to_meet_bound(ty={:?}, bound={:?})",
ty,

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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

View File

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

View File

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

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

View File

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

View File

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

View File

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

View File

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

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

View File

@ -763,7 +763,7 @@ fn find_drop_glue_neighbors<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
ty::TyFnDef(..) |
ty::TyFnPtr(_) |
ty::TyNever |
ty::TyTrait(_) => {
ty::TyDynamic(..) => {
/* nothing to do */
}
ty::TyAdt(adt_def, substs) => {
@ -1003,18 +1003,20 @@ fn create_trans_items_for_vtable_methods<'a, 'tcx>(scx: &SharedCrateContext<'a,
output: &mut Vec<TransItem<'tcx>>) {
assert!(!trait_ty.needs_subst() && !impl_ty.needs_subst());
if let ty::TyTrait(ref trait_ty) = trait_ty.sty {
let poly_trait_ref = trait_ty.principal().unwrap().with_self_ty(scx.tcx(), impl_ty);
let param_substs = scx.tcx().intern_substs(&[]);
// Walk all methods of the trait, including those of its supertraits
let methods = traits::get_vtable_methods(scx.tcx(), poly_trait_ref);
let methods = methods.filter_map(|method| method)
.filter_map(|(def_id, substs)| do_static_dispatch(scx, def_id, substs, param_substs))
.filter(|&(def_id, _)| can_have_local_instance(scx.tcx(), def_id))
.map(|(def_id, substs)| create_fn_trans_item(scx, def_id, substs, param_substs));
output.extend(methods);
if let ty::TyDynamic(ref trait_ty, ..) = trait_ty.sty {
if let Some(principal) = trait_ty.principal() {
let poly_trait_ref = principal.with_self_ty(scx.tcx(), impl_ty);
let param_substs = scx.tcx().intern_substs(&[]);
// Walk all methods of the trait, including those of its supertraits
let methods = traits::get_vtable_methods(scx.tcx(), poly_trait_ref);
let methods = methods.filter_map(|method| method)
.filter_map(|(def_id, substs)| do_static_dispatch(scx, def_id, substs,
param_substs))
.filter(|&(def_id, _)| can_have_local_instance(scx.tcx(), def_id))
.map(|(def_id, substs)| create_fn_trans_item(scx, def_id, substs, param_substs));
output.extend(methods);
}
// Also add the destructor
let dg_type = glue::get_drop_glue_type(scx.tcx(), impl_ty);
output.push(TransItem::DropGlue(DropGlueKind::Ty(dg_type)));

View File

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

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.
let containing_scope = match trait_type.sty {
ty::TyTrait(ref data) => if let Some(principal) = data.principal() {
ty::TyDynamic(ref data, ..) => if let Some(principal) = data.principal() {
let def_id = principal.def_id();
get_namespace_and_span_for_item(cx, def_id).0
} else {
@ -523,7 +523,7 @@ pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
ty::TyStr => {
fixed_vec_metadata(cx, unique_type_id, cx.tcx().types.i8, None, usage_site_span)
}
ty::TyTrait(..) => {
ty::TyDynamic(..) => {
MetadataCreationResult::new(
trait_pointer_metadata(cx, t, None, unique_type_id),
false)
@ -538,7 +538,7 @@ pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
ty::TyStr => {
vec_slice_metadata(cx, t, cx.tcx().types.u8, unique_type_id, usage_site_span)
}
ty::TyTrait(..) => {
ty::TyDynamic(..) => {
MetadataCreationResult::new(
trait_pointer_metadata(cx, ty, Some(t), unique_type_id),
false)

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);
output.push(']');
},
ty::TyTrait(ref trait_data) => {
ty::TyDynamic(ref trait_data, ..) => {
if let Some(principal) = trait_data.principal() {
let principal = cx.tcx().erase_late_bound_regions_and_normalize(
&principal);

View File

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

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
/// `trait_ref` would map `T:Trait`.
pub fn get_vtable<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
trait_ref: ty::PolyTraitRef<'tcx>)
ty: ty::Ty<'tcx>,
trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>)
-> ValueRef
{
let tcx = ccx.tcx();
let _icx = push_ctxt("meth::get_vtable");
debug!("get_vtable(trait_ref={:?})", trait_ref);
debug!("get_vtable(ty={:?}, trait_ref={:?})", ty, trait_ref);
// Check the cache.
if let Some(&val) = ccx.vtables().borrow().get(&trait_ref) {
if let Some(&val) = ccx.vtables().borrow().get(&(ty, trait_ref)) {
return val;
}
// Not in the cache. Build it.
let nullptr = C_null(Type::nil(ccx).ptr_to());
let methods = traits::get_vtable_methods(tcx, trait_ref).map(|opt_mth| {
opt_mth.map_or(nullptr, |(def_id, substs)| {
Callee::def(ccx, def_id, substs).reify(ccx)
})
});
let size_ty = sizing_type_of(ccx, trait_ref.self_ty());
let size_ty = sizing_type_of(ccx, ty);
let size = machine::llsize_of_alloc(ccx, size_ty);
let align = align_of(ccx, trait_ref.self_ty());
let align = align_of(ccx, ty);
let components: Vec<_> = [
let mut components: Vec<_> = [
// Generate a destructor for the vtable.
glue::get_drop_glue(ccx, trait_ref.self_ty()),
glue::get_drop_glue(ccx, ty),
C_uint(ccx, size),
C_uint(ccx, align)
].iter().cloned().chain(methods).collect();
].iter().cloned().collect();
if let Some(trait_ref) = trait_ref {
let trait_ref = trait_ref.with_self_ty(tcx, ty);
let methods = traits::get_vtable_methods(tcx, trait_ref).map(|opt_mth| {
opt_mth.map_or(nullptr, |(def_id, substs)| {
Callee::def(ccx, def_id, substs).reify(ccx)
})
});
components.extend(methods);
}
let vtable_const = C_struct(ccx, &components, false);
let align = machine::llalign_of_pref(ccx, val_ty(vtable_const));
let vtable = consts::addr_of(ccx, vtable_const, align, "vtable");
ccx.vtables().borrow_mut().insert(trait_ref, vtable);
ccx.vtables().borrow_mut().insert((ty, trait_ref), vtable);
vtable
}

View File

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

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

View File

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

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 {
if let PatKind::Binding(..) = inner.node {
if let Some(mt) = self.shallow_resolve(expected).builtin_deref(true, ty::NoPreference) {
if let ty::TyTrait(..) = mt.ty.sty {
if let ty::TyDynamic(..) = mt.ty.sty {
// This is "x = SomeTrait" being reduced from
// "let &x = &SomeTrait" or "let box x = Box<SomeTrait>", an error.
let type_str = self.ty_to_string(expected);

View File

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

View File

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

View File

@ -515,7 +515,7 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'b, 'gcx, 'tcx>(
}
// these are always dtorck
ty::TyTrait(..) | ty::TyProjection(_) | ty::TyAnon(..) => bug!(),
ty::TyDynamic(..) | ty::TyProjection(_) | ty::TyAnon(..) => bug!(),
}
}
@ -564,7 +564,7 @@ fn has_dtor_of_interest<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
let revised_ty = revise_self_ty(tcx, adt_def, impl_def_id, substs);
return DropckKind::RevisedSelf(revised_ty);
}
ty::TyTrait(..) | ty::TyProjection(..) | ty::TyAnon(..) => {
ty::TyDynamic(..) | ty::TyProjection(..) | ty::TyAnon(..) => {
debug!("ty: {:?} isn't known, and therefore is a dropck type", ty);
return DropckKind::BorrowedDataMustStrictlyOutliveSelf;
},

View File

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

View File

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

View File

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

View File

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

View File

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

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?
let trait_ref = ccx.tcx.impl_trait_ref(ccx.tcx.map.local_def_id(item.id)).unwrap();
ccx.tcx.populate_implementations_for_trait_if_necessary(trait_ref.def_id);
let sync_trait = ccx.tcx.lang_items.require(lang_items::SyncTraitLangItem)
.unwrap_or_else(|msg| ccx.tcx.sess.fatal(&msg[..]));
let send_trait = ccx.tcx.lang_items.require(lang_items::SendTraitLangItem)
.unwrap_or_else(|msg| ccx.tcx.sess.fatal(&msg[..]));
if trait_ref.def_id != sync_trait && trait_ref.def_id != send_trait {
if !ccx.tcx.trait_has_default_impl(trait_ref.def_id) {
error_192(ccx, item.span);
}
if !ccx.tcx.trait_has_default_impl(trait_ref.def_id) {
error_192(ccx, item.span);
}
}
hir::ItemFn(.., ref body) => {

View File

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

View File

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

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`
if let ty::TyTrait(ref data) = trait_ref.self_ty().sty {
if let ty::TyDynamic(ref data, ..) = trait_ref.self_ty().sty {
// This is something like impl Trait1 for Trait2. Illegal
// if Trait1 is a supertrait of Trait2 or Trait2 is not object safe.
if data.principal().is_none() ||
!self.tcx.is_object_safe(data.principal().unwrap().def_id()) {
// This is an error, but it will be
// reported by wfcheck. Ignore it
// here. This is tested by
// `coherence-impl-trait-for-trait-object-safe.rs`.
if data.principal().map_or(true, |p| !self.tcx.is_object_safe(p.def_id())) {
// This is an error, but it will be reported by wfcheck. Ignore it here.
// This is tested by `coherence-impl-trait-for-trait-object-safe.rs`.
} else {
let mut supertrait_def_ids =
traits::supertrait_def_ids(self.tcx,

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 \
this does nothing because the given bound is not \
a default. Only `?Sized` is supported");
tcx.try_add_builtin_trait(kind_id, bounds);
}
}
}
_ if kind_id.is_ok() => {
tcx.try_add_builtin_trait(kind_id.unwrap(), bounds);
bounds.push(kind_id.unwrap());
}
// No lang item for Sized, so we can't add it as a bound.
None => {}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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