Refactor TyTrait to contain a interned ExistentialPredicate slice.
Renames TyTrait to TyDynamic.
This commit is contained in:
parent
64e97d9b33
commit
bb35d50cad
|
@ -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
|
||||
|
|
|
@ -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(..) |
|
||||
|
|
|
@ -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())
|
||||
}
|
||||
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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())))
|
||||
}
|
||||
|
|
|
@ -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) => {
|
||||
|
|
|
@ -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) => {
|
||||
|
|
|
@ -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) |
|
||||
|
|
|
@ -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 }
|
||||
|
|
|
@ -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]
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>,
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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) => {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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| {
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 {:?} -> {:?}",
|
||||
|
|
|
@ -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)));
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
},
|
||||
|
|
|
@ -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) => {
|
||||
|
|
|
@ -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,
|
||||
®ion_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,
|
||||
®ion_bounds,
|
||||
existential_predicates);
|
||||
|
||||
let region_bound = match region_bound {
|
||||
Some(r) => r,
|
||||
None => {
|
||||
tcx.mk_region(match rscope.object_lifetime_default(span) {
|
||||
Some(r) => r,
|
||||
None => {
|
||||
span_err!(self.tcx().sess, span, E0228,
|
||||
"the lifetime bound for this object type cannot be deduced \
|
||||
from context; please supply an explicit bound");
|
||||
ty::ReStatic
|
||||
}
|
||||
})
|
||||
}
|
||||
};
|
||||
|
||||
debug!("region_bound: {:?}", region_bound);
|
||||
|
||||
let ty = tcx.mk_dynamic(existential_predicates, region_bound);
|
||||
debug!("trait_object_type: {:?}", ty);
|
||||
ty
|
||||
}
|
||||
|
@ -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 ®ion_bound in &self.region_bounds {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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;
|
||||
},
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
})
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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) => {
|
||||
|
|
|
@ -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(),
|
||||
|
||||
|
|
|
@ -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(..) => {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 => {}
|
||||
|
|
|
@ -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:
|
||||
|
||||
```
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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() { }
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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() { }
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue