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