rustc: add TyAnon (impl Trait) to the typesystem.

This commit is contained in:
Eduard Burtescu 2016-07-22 18:56:22 +03:00
parent f0baec691f
commit ef11d4e3c7
40 changed files with 250 additions and 85 deletions

View File

@ -268,6 +268,9 @@ impl<'ast> visit::Visitor for DefCollector<'ast> {
if let TyKind::FixedLengthVec(_, ref length) = ty.node {
self.visit_ast_const_integer(length);
}
if let TyKind::ImplTrait(..) = ty.node {
self.create_def(ty.id, DefPathData::ImplTrait);
}
visit::walk_ty(self, ty);
}
@ -428,6 +431,9 @@ impl<'ast> intravisit::Visitor<'ast> for DefCollector<'ast> {
if let hir::TyFixedLengthVec(_, ref length) = ty.node {
self.visit_hir_const_integer(length);
}
if let hir::TyImplTrait(..) = ty.node {
self.create_def(ty.id, DefPathData::ImplTrait);
}
intravisit::walk_ty(self, ty);
}

View File

@ -215,6 +215,8 @@ pub enum DefPathData {
Initializer,
/// Pattern binding
Binding(InternedString),
/// An `impl Trait` type node.
ImplTrait
}
impl Definitions {
@ -369,6 +371,10 @@ impl DefPathData {
Initializer => {
InternedString::new("{{initializer}}")
}
ImplTrait => {
InternedString::new("{{impl-Trait}}")
}
}
}

View File

@ -170,7 +170,8 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for TypeFreshener<'a, 'gcx, 'tcx> {
ty::TyClosure(..) |
ty::TyTuple(..) |
ty::TyProjection(..) |
ty::TyParam(..) => {
ty::TyParam(..) |
ty::TyAnon(..) => {
t.super_fold_with(self)
}
}

View File

@ -281,7 +281,7 @@ fn ty_is_local_constructor(tcx: TyCtxt, ty: Ty, infer_is_local: InferIsLocal)->
true
}
ty::TyClosure(..) => {
ty::TyClosure(..) | ty::TyAnon(..) => {
bug!("ty_is_local invoked on unexpected type: {:?}", ty)
}
}

View File

@ -211,6 +211,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
ty::TyTuple(..) => Some(12),
ty::TyProjection(..) => Some(13),
ty::TyParam(..) => Some(14),
ty::TyAnon(..) => Some(15),
ty::TyInfer(..) | ty::TyError => None
}
}

View File

@ -94,6 +94,16 @@ pub enum Reveal {
NotSpecializable,
/// At trans time, all monomorphic projections will succeed.
/// Also, `impl Trait` is normalized to the concrete type,
/// which has to be already collected by type-checking.
///
/// NOTE: As `impl Trait`'s concrete type should *never*
/// be observable directly by the user, `Reveal::All`
/// should not be used by checks which may expose
/// type equality or type contents to the user.
/// There are some exceptions, e.g. around OIBITS and
/// transmute-checking, which expose some details, but
/// not the whole concrete type of the `impl Trait`.
All,
}
@ -298,6 +308,17 @@ impl<'a, 'b, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for AssociatedTypeNormalizer<'a,
let ty = ty.super_fold_with(self);
match ty.sty {
ty::TyAnon(def_id, substs) if !substs.has_escaping_regions() => { // (*)
// Only normalize `impl Trait` after type-checking, usually in trans.
if self.selcx.projection_mode() == Reveal::All {
let generic_ty = self.tcx().lookup_item_type(def_id).ty;
let concrete_ty = generic_ty.subst(self.tcx(), substs);
self.fold_ty(concrete_ty)
} else {
ty
}
}
ty::TyProjection(ref data) if !data.has_escaping_regions() => { // (*)
// (*) This is kind of hacky -- we need to be able to
@ -773,8 +794,11 @@ fn assemble_candidates_from_trait_def<'cx, 'gcx, 'tcx>(
debug!("assemble_candidates_from_trait_def(..)");
// Check whether the self-type is itself a projection.
let trait_ref = match obligation_trait_ref.self_ty().sty {
ty::TyProjection(ref data) => data.trait_ref.clone(),
let (def_id, substs) = match obligation_trait_ref.self_ty().sty {
ty::TyProjection(ref data) => {
(data.trait_ref.def_id, data.trait_ref.substs)
}
ty::TyAnon(def_id, substs) => (def_id, substs),
ty::TyInfer(ty::TyVar(_)) => {
// If the self-type is an inference variable, then it MAY wind up
// being a projected type, so induce an ambiguity.
@ -785,8 +809,8 @@ fn assemble_candidates_from_trait_def<'cx, 'gcx, 'tcx>(
};
// If so, extract what we know from the trait and try to come up with a good answer.
let trait_predicates = selcx.tcx().lookup_predicates(trait_ref.def_id);
let bounds = trait_predicates.instantiate(selcx.tcx(), trait_ref.substs);
let trait_predicates = selcx.tcx().lookup_predicates(def_id);
let bounds = trait_predicates.instantiate(selcx.tcx(), substs);
let bounds = elaborate_predicates(selcx.tcx(), bounds.predicates.into_vec());
assemble_candidates_from_predicates(selcx,
obligation,

View File

@ -1158,20 +1158,17 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
// before we go into the whole skolemization thing, just
// quickly check if the self-type is a projection at all.
let trait_def_id = match obligation.predicate.0.trait_ref.self_ty().sty {
ty::TyProjection(ref data) => data.trait_ref.def_id,
match obligation.predicate.0.trait_ref.self_ty().sty {
ty::TyProjection(_) | ty::TyAnon(..) => {}
ty::TyInfer(ty::TyVar(_)) => {
span_bug!(obligation.cause.span,
"Self=_ should have been handled by assemble_candidates");
}
_ => { return; }
};
debug!("assemble_candidates_for_projected_tys: trait_def_id={:?}",
trait_def_id);
_ => return
}
let result = self.probe(|this, snapshot| {
this.match_projection_obligation_against_bounds_from_trait(obligation,
this.match_projection_obligation_against_definition_bounds(obligation,
snapshot)
});
@ -1180,7 +1177,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
}
}
fn match_projection_obligation_against_bounds_from_trait(
fn match_projection_obligation_against_definition_bounds(
&mut self,
obligation: &TraitObligation<'tcx>,
snapshot: &infer::CombinedSnapshot)
@ -1190,28 +1187,29 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
self.infcx().resolve_type_vars_if_possible(&obligation.predicate);
let (skol_trait_predicate, skol_map) =
self.infcx().skolemize_late_bound_regions(&poly_trait_predicate, snapshot);
debug!("match_projection_obligation_against_bounds_from_trait: \
debug!("match_projection_obligation_against_definition_bounds: \
skol_trait_predicate={:?} skol_map={:?}",
skol_trait_predicate,
skol_map);
let projection_trait_ref = match skol_trait_predicate.trait_ref.self_ty().sty {
ty::TyProjection(ref data) => &data.trait_ref,
let (def_id, substs) = match skol_trait_predicate.trait_ref.self_ty().sty {
ty::TyProjection(ref data) => (data.trait_ref.def_id, data.trait_ref.substs),
ty::TyAnon(def_id, substs) => (def_id, substs),
_ => {
span_bug!(
obligation.cause.span,
"match_projection_obligation_against_bounds_from_trait() called \
"match_projection_obligation_against_definition_bounds() called \
but self-ty not a projection: {:?}",
skol_trait_predicate.trait_ref.self_ty());
}
};
debug!("match_projection_obligation_against_bounds_from_trait: \
projection_trait_ref={:?}",
projection_trait_ref);
debug!("match_projection_obligation_against_definition_bounds: \
def_id={:?}, substs={:?}",
def_id, substs);
let trait_predicates = self.tcx().lookup_predicates(projection_trait_ref.def_id);
let bounds = trait_predicates.instantiate(self.tcx(), projection_trait_ref.substs);
debug!("match_projection_obligation_against_bounds_from_trait: \
let item_predicates = self.tcx().lookup_predicates(def_id);
let bounds = item_predicates.instantiate(self.tcx(), substs);
debug!("match_projection_obligation_against_definition_bounds: \
bounds={:?}",
bounds);
@ -1226,7 +1224,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
&skol_map,
snapshot)));
debug!("match_projection_obligation_against_bounds_from_trait: \
debug!("match_projection_obligation_against_definition_bounds: \
matching_bound={:?}",
matching_bound);
match matching_bound {
@ -1472,7 +1470,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
}
}
ty::TyParam(..) |
ty::TyProjection(..) => {
ty::TyProjection(..) |
ty::TyAnon(..) => {
// In these cases, we don't know what the actual
// type is. Therefore, we cannot break it down
// into its constituent types. So we don't
@ -1796,7 +1795,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
}))
}
ty::TyProjection(_) | ty::TyParam(_) => None,
ty::TyProjection(_) | ty::TyParam(_) | ty::TyAnon(..) => None,
ty::TyInfer(ty::TyVar(_)) => Ambiguous,
ty::TyInfer(ty::FreshTy(_))
@ -1842,7 +1841,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
Where(ty::Binder(tys.to_vec()))
}
ty::TyStruct(..) | ty::TyEnum(..) | ty::TyProjection(..) | ty::TyParam(..) => {
ty::TyStruct(..) | ty::TyEnum(..) |
ty::TyProjection(..) | ty::TyParam(..) | ty::TyAnon(..) => {
// Fallback to whatever user-defined impls exist in this case.
None
}
@ -1893,6 +1893,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
ty::TyTrait(..) |
ty::TyParam(..) |
ty::TyProjection(..) |
ty::TyAnon(..) |
ty::TyInfer(ty::TyVar(_)) |
ty::TyInfer(ty::FreshTy(_)) |
ty::TyInfer(ty::FreshIntTy(_)) |
@ -2073,7 +2074,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
{
self.in_snapshot(|this, snapshot| {
let result =
this.match_projection_obligation_against_bounds_from_trait(obligation,
this.match_projection_obligation_against_definition_bounds(obligation,
snapshot);
assert!(result);
})

View File

@ -240,7 +240,8 @@ impl<'a, 'tcx> ty::TyS<'tcx> {
}
ty::TyProjection(..) |
ty::TyParam(_) => {
ty::TyParam(_) |
ty::TyAnon(..) => {
TC::All
}

View File

@ -1016,7 +1016,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
sty_debug_print!(
self,
TyEnum, TyBox, TyArray, TySlice, TyRawPtr, TyRef, TyFnDef, TyFnPtr,
TyTrait, TyStruct, TyClosure, TyTuple, TyParam, TyInfer, TyProjection);
TyTrait, TyStruct, TyClosure, TyTuple, TyParam, TyInfer, TyProjection, TyAnon);
println!("Substs interner: #{}", self.interners.substs.borrow().len());
println!("BareFnTy interner: #{}", self.interners.bare_fn.borrow().len());
@ -1355,6 +1355,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
self.mk_param(def.space, def.index, def.name)
}
pub fn mk_anon(self, def_id: DefId, substs: &'tcx Substs<'tcx>) -> Ty<'tcx> {
self.mk_ty(TyAnon(def_id, substs))
}
pub fn trait_items(self, trait_did: DefId) -> Rc<Vec<ty::ImplOrTraitItem<'gcx>>> {
self.trait_items_cache.memoize(trait_did, || {
let def_ids = self.trait_item_def_ids(trait_did);

View File

@ -247,6 +247,7 @@ impl<'a, 'gcx, 'lcx, 'tcx> ty::TyS<'tcx> {
"type parameter".to_string()
}
}
ty::TyAnon(..) => "anonymized type".to_string(),
ty::TyError => "type error".to_string(),
}
}

View File

@ -30,6 +30,7 @@ pub enum SimplifiedType {
TraitSimplifiedType(DefId),
StructSimplifiedType(DefId),
ClosureSimplifiedType(DefId),
AnonSimplifiedType(DefId),
FunctionSimplifiedType(usize),
ParameterSimplifiedType,
}
@ -98,6 +99,9 @@ pub fn simplify_type<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
None
}
}
ty::TyAnon(def_id, _) => {
Some(AnonSimplifiedType(def_id))
}
ty::TyInfer(_) | ty::TyError => None,
}
}

View File

@ -110,6 +110,11 @@ impl FlagComputation {
self.add_projection_ty(data);
}
&ty::TyAnon(_, substs) => {
self.add_flags(TypeFlags::HAS_PROJECTION);
self.add_substs(substs);
}
&ty::TyTrait(box ty::TraitTy { ref principal, ref bounds }) => {
let mut computation = FlagComputation::new();
computation.add_substs(principal.0.substs);

View File

@ -695,7 +695,7 @@ impl<'tcx> TypeVisitor<'tcx> for LateBoundRegionsCollector {
// in the normalized form
if self.just_constrained {
match t.sty {
ty::TyProjection(..) => { return false; }
ty::TyProjection(..) | ty::TyAnon(..) => { return false; }
_ => { }
}
}

View File

@ -188,7 +188,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
data @ DefPathData::Initializer |
data @ DefPathData::MacroDef(..) |
data @ DefPathData::ClosureExpr |
data @ DefPathData::Binding(..) => {
data @ DefPathData::Binding(..) |
data @ DefPathData::ImplTrait => {
let parent_def_id = self.parent_def_id(def_id).unwrap();
self.push_item_path(buffer, parent_def_id);
buffer.push(&data.as_interned_str());
@ -345,6 +346,7 @@ pub fn characteristic_def_id_of_type(ty: Ty) -> Option<DefId> {
ty::TyFnPtr(_) |
ty::TyProjection(_) |
ty::TyParam(_) |
ty::TyAnon(..) |
ty::TyInfer(_) |
ty::TyError |
ty::TyFloat(_) => None,

View File

@ -594,7 +594,7 @@ impl<'a, 'gcx, 'tcx> Struct {
Struct::non_zero_field_path(infcx, Some(ety).into_iter())
}
(_, &ty::TyProjection(_)) => {
(_, &ty::TyProjection(_)) | (_, &ty::TyAnon(..)) => {
let normalized = normalize_associated_type(infcx, ty);
if ty == normalized {
return Ok(None);
@ -1108,7 +1108,7 @@ impl<'a, 'gcx, 'tcx> Layout {
}
// Types with no meaningful known layout.
ty::TyProjection(_) => {
ty::TyProjection(_) | ty::TyAnon(..) => {
let normalized = normalize_associated_type(infcx, ty);
if ty == normalized {
return Err(LayoutError::Unknown(ty));
@ -1332,7 +1332,7 @@ impl<'a, 'gcx, 'tcx> SizeSkeleton<'gcx> {
}
}
ty::TyProjection(_) => {
ty::TyProjection(_) | ty::TyAnon(..) => {
let normalized = normalize_associated_type(infcx, ty);
if ty == normalized {
Err(err)

View File

@ -1885,7 +1885,7 @@ impl<'a, 'tcx> AdtDefData<'tcx, 'tcx> {
}
}
TyProjection(..) => {
TyProjection(..) | TyAnon(..) => {
// must calculate explicitly.
// FIXME: consider special-casing always-Sized projections
vec![ty]

View File

@ -174,6 +174,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
ty::TyEnum(..) | // OutlivesNominalType
ty::TyStruct(..) | // OutlivesNominalType
ty::TyBox(..) | // OutlivesNominalType (ish)
ty::TyAnon(..) | // OutlivesNominalType (ish)
ty::TyStr | // OutlivesScalar (ish)
ty::TyArray(..) | // ...
ty::TySlice(..) | // ...

View File

@ -582,6 +582,13 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R,
Ok(tcx.mk_projection(projection_ty.trait_ref, projection_ty.item_name))
}
(&ty::TyAnon(a_def_id, a_substs), &ty::TyAnon(b_def_id, b_substs))
if a_def_id == b_def_id =>
{
let substs = relate_substs(relation, None, a_substs, b_substs)?;
Ok(tcx.mk_anon(a_def_id, substs))
}
_ =>
{
Err(TypeError::Sorts(expected_found(relation, &a, &b)))

View File

@ -485,6 +485,7 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> {
ty::TyStruct(did, substs) => ty::TyStruct(did, substs.fold_with(folder)),
ty::TyClosure(did, substs) => ty::TyClosure(did, substs.fold_with(folder)),
ty::TyProjection(ref data) => ty::TyProjection(data.fold_with(folder)),
ty::TyAnon(did, substs) => ty::TyAnon(did, substs.fold_with(folder)),
ty::TyBool | ty::TyChar | ty::TyStr | ty::TyInt(_) |
ty::TyUint(_) | ty::TyFloat(_) | ty::TyError | ty::TyInfer(_) |
ty::TyParam(..) => self.sty.clone(),
@ -513,6 +514,7 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> {
ty::TyStruct(_did, ref substs) => substs.visit_with(visitor),
ty::TyClosure(_did, ref substs) => substs.visit_with(visitor),
ty::TyProjection(ref data) => data.visit_with(visitor),
ty::TyAnon(_, ref substs) => substs.visit_with(visitor),
ty::TyBool | ty::TyChar | ty::TyStr | ty::TyInt(_) |
ty::TyUint(_) | ty::TyFloat(_) | ty::TyError | ty::TyInfer(_) |
ty::TyParam(..) => false,

View File

@ -166,6 +166,12 @@ pub enum TypeVariants<'tcx> {
/// `<T as Trait<..>>::N`.
TyProjection(ProjectionTy<'tcx>),
/// Anonymized (`impl Trait`) type found in a return type.
/// The DefId comes from the `impl Trait` ast::Ty node, and the
/// substitutions are for the generics of the function in question.
/// After typeck, the concrete type can be found in the `tcache` map.
TyAnon(DefId, &'tcx Substs<'tcx>),
/// A type parameter; for example, `T` in `fn f<T>(x: T) {}
TyParam(ParamTy),
@ -1232,7 +1238,8 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
v
}
TyEnum(_, substs) |
TyStruct(_, substs) => {
TyStruct(_, substs) |
TyAnon(_, substs) => {
substs.regions.as_slice().to_vec()
}
TyClosure(_, ref substs) => {

View File

@ -437,6 +437,7 @@ impl<'a, 'gcx, 'tcx> TypeVisitor<'tcx> for TypeIdHasher<'a, 'gcx, 'tcx> {
TyRawPtr(m) |
TyRef(_, m) => self.hash(m.mutbl),
TyClosure(def_id, _) |
TyAnon(def_id, _) |
TyFnDef(def_id, _, _) => self.def_id(def_id),
TyFnPtr(f) => {
self.hash(f.unsafety);
@ -559,7 +560,7 @@ impl<'a, 'tcx> ty::TyS<'tcx> {
}) => Some(true),
TyArray(..) | TySlice(_) | TyTrait(..) | TyTuple(..) |
TyClosure(..) | TyEnum(..) | TyStruct(..) |
TyClosure(..) | TyEnum(..) | TyStruct(..) | TyAnon(..) |
TyProjection(..) | TyParam(..) | TyInfer(..) | TyError => None
}.unwrap_or_else(|| !self.impls_bound(tcx, param_env, ty::BoundCopy, span));
@ -600,7 +601,7 @@ impl<'a, 'tcx> ty::TyS<'tcx> {
TyStr | TyTrait(..) | TySlice(_) => Some(false),
TyEnum(..) | TyStruct(..) | TyProjection(..) | TyParam(..) |
TyInfer(..) | TyError => None
TyInfer(..) | TyAnon(..) | TyError => None
}.unwrap_or_else(|| self.impls_bound(tcx, param_env, ty::BoundSized, span));
if !self.has_param_types() && !self.has_self_ty() {

View File

@ -88,7 +88,8 @@ fn push_subtypes<'tcx>(stack: &mut Vec<Ty<'tcx>>, parent_ty: Ty<'tcx>) {
}).collect::<Vec<_>>());
}
ty::TyEnum(_, ref substs) |
ty::TyStruct(_, ref substs) => {
ty::TyStruct(_, ref substs) |
ty::TyAnon(_, ref substs) => {
push_reversed(stack, substs.types.as_slice());
}
ty::TyClosure(_, ref substs) => {

View File

@ -383,6 +383,12 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> {
// types appearing in the fn signature
}
ty::TyAnon(..) => {
// all of the requirements on type parameters
// should've been checked by the instantiation
// of whatever returned this exact `impl Trait`.
}
ty::TyTrait(ref data) => {
// WfObject
//

View File

@ -907,6 +907,37 @@ impl<'tcx> fmt::Display for ty::TypeVariants<'tcx> {
}
TyTrait(ref data) => write!(f, "{}", data),
ty::TyProjection(ref data) => write!(f, "{}", data),
ty::TyAnon(def_id, substs) => {
ty::tls::with(|tcx| {
// Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
// by looking up the projections associated with the def_id.
let item_predicates = tcx.lookup_predicates(def_id);
let substs = tcx.lift(&substs).unwrap_or_else(|| {
tcx.mk_substs(subst::Substs::empty())
});
let bounds = item_predicates.instantiate(tcx, substs);
let mut first = true;
let mut is_sized = false;
write!(f, "impl")?;
for predicate in bounds.predicates.into_vec() {
if let Some(trait_ref) = predicate.to_opt_poly_trait_ref() {
// Don't print +Sized, but rather +?Sized if absent.
if Some(trait_ref.def_id()) == tcx.lang_items.sized_trait() {
is_sized = true;
continue;
}
write!(f, "{}{}", if first { " " } else { "+" }, trait_ref)?;
first = false;
}
}
if !is_sized {
write!(f, "{}?Sized", if first { " " } else { "+" })?;
}
Ok(())
})
}
TyStr => write!(f, "str"),
TyClosure(did, substs) => ty::tls::with(|tcx| {
write!(f, "[closure")?;

View File

@ -596,7 +596,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
}
ty::TyParam(..) | ty::TyInfer(..) | ty::TyError |
ty::TyClosure(..) | ty::TyProjection(..) |
ty::TyClosure(..) | ty::TyProjection(..) | ty::TyAnon(..) |
ty::TyFnDef(..) => {
bug!("Unexpected type in foreign function")
}

View File

@ -41,6 +41,7 @@ pub enum DefPathData {
StructCtor,
Initializer,
Binding,
ImplTrait,
}
pub fn simplify_def_key(key: hir_map::DefKey) -> DefKey {
@ -72,6 +73,7 @@ fn simplify_def_path_data(data: hir_map::DefPathData) -> DefPathData {
hir_map::DefPathData::StructCtor => DefPathData::StructCtor,
hir_map::DefPathData::Initializer => DefPathData::Initializer,
hir_map::DefPathData::Binding(_) => DefPathData::Binding,
hir_map::DefPathData::ImplTrait => DefPathData::ImplTrait,
}
}
@ -103,5 +105,6 @@ fn recover_def_path_data(data: DefPathData, name: Option<InternedString>) -> hir
DefPathData::StructCtor => hir_map::DefPathData::StructCtor,
DefPathData::Initializer => hir_map::DefPathData::Initializer,
DefPathData::Binding => hir_map::DefPathData::Binding(name.unwrap()),
DefPathData::ImplTrait => hir_map::DefPathData::ImplTrait,
}
}

View File

@ -445,6 +445,13 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> {
let name = token::intern(&self.parse_str(']'));
return tcx.mk_projection(trait_ref, name);
}
'A' => {
assert_eq!(self.next(), '[');
let def_id = self.parse_def();
let substs = self.parse_substs();
assert_eq!(self.next(), ']');
return self.tcx.mk_anon(def_id, self.tcx.mk_substs(substs));
}
'e' => {
return tcx.types.err;
}

View File

@ -170,6 +170,11 @@ pub fn enc_ty<'a, 'tcx>(w: &mut Cursor<Vec<u8>>, cx: &ctxt<'a, 'tcx>, t: Ty<'tcx
enc_trait_ref(w, cx, data.trait_ref);
write!(w, "{}]", data.item_name);
}
ty::TyAnon(def_id, substs) => {
write!(w, "A[{}|", (cx.ds)(cx.tcx, def_id));
enc_substs(w, cx, substs);
write!(w, "]");
}
ty::TyError => {
write!(w, "e");
}

View File

@ -796,6 +796,7 @@ fn find_drop_glue_neighbors<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
ty::TyProjection(_) |
ty::TyParam(_) |
ty::TyInfer(_) |
ty::TyAnon(..) |
ty::TyError => {
bug!("encountered unexpected type");
}

View File

@ -150,6 +150,7 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
ty::TyError |
ty::TyInfer(_) |
ty::TyProjection(..) |
ty::TyAnon(..) |
ty::TyParam(_) => {
bug!("debuginfo: Trying to create type name for \
unexpected type: {:?}", t);

View File

@ -536,7 +536,8 @@ pub fn push_unique_type_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
ty::TyError |
ty::TyInfer(_) |
ty::TyProjection(..) |
ty::TyParam(_) => {
ty::TyParam(_) |
ty::TyAnon(..) => {
bug!("debuginfo: Trying to create type name for \
unexpected type: {:?}", t);
}

View File

@ -112,7 +112,8 @@ pub fn sizing_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Typ
}
}
ty::TyProjection(..) | ty::TyInfer(..) | ty::TyParam(..) | ty::TyError => {
ty::TyProjection(..) | ty::TyInfer(..) | ty::TyParam(..) |
ty::TyAnon(..) | ty::TyError => {
bug!("fictitious type {:?} in sizing_type_of()", t)
}
ty::TySlice(_) | ty::TyTrait(..) | ty::TyStr => bug!()
@ -339,10 +340,11 @@ pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) ->
}
}
ty::TyInfer(..) => bug!("type_of with TyInfer"),
ty::TyProjection(..) => bug!("type_of with TyProjection"),
ty::TyParam(..) => bug!("type_of with ty_param"),
ty::TyError => bug!("type_of with TyError"),
ty::TyInfer(..) |
ty::TyProjection(..) |
ty::TyParam(..) |
ty::TyAnon(..) |
ty::TyError => bug!("type_of with {:?}", t),
};
debug!("--> mapped t={:?} to llty={:?}", t, llty);

View File

@ -56,6 +56,7 @@ use hir::print as pprust;
use middle::resolve_lifetime as rl;
use rustc::lint;
use rustc::ty::subst::{FnSpace, TypeSpace, SelfSpace, Subst, Substs, ParamSpace};
use rustc::ty::subst::VecPerParamSpace;
use rustc::traits;
use rustc::ty::{self, Ty, TyCtxt, ToPredicate, TypeFoldable};
use rustc::ty::wf::object_region_bounds;
@ -1745,6 +1746,24 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
hir::TyPolyTraitRef(ref bounds) => {
self.conv_ty_poly_trait_ref(rscope, ast_ty.span, bounds)
}
hir::TyImplTrait(ref bounds) => {
use collect::{compute_bounds, SizedByDefault};
// Create the anonymized type.
let def_id = tcx.map.local_def_id(ast_ty.id);
let substs = tcx.mk_substs(Substs::empty());
let ty = tcx.mk_anon(tcx.map.local_def_id(ast_ty.id), substs);
// Collect the bounds, i.e. the `Trait` in `impl Trait`.
let bounds = compute_bounds(self, ty, bounds, SizedByDefault::Yes, ast_ty.span);
let predicates = tcx.lift_to_global(&bounds.predicates(tcx, ty)).unwrap();
let predicates = ty::GenericPredicates {
predicates: VecPerParamSpace::new(vec![], vec![], predicates)
};
tcx.predicates.borrow_mut().insert(def_id, predicates);
ty
}
hir::TyPath(ref maybe_qself, ref path) => {
debug!("ast_ty_to_ty: maybe_qself={:?} path={:?}", maybe_qself, path);
let path_res = tcx.expect_resolution(ast_ty.id);

View File

@ -499,7 +499,7 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'b, 'gcx, 'tcx>(
}
// these are always dtorck
ty::TyTrait(..) | ty::TyProjection(_) => bug!(),
ty::TyTrait(..) | ty::TyProjection(_) | ty::TyAnon(..) => bug!(),
}
}
@ -509,7 +509,7 @@ fn has_dtor_of_interest<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
ty::TyEnum(def, _) | ty::TyStruct(def, _) => {
def.is_dtorck(tcx)
}
ty::TyTrait(..) | ty::TyProjection(..) => {
ty::TyTrait(..) | ty::TyProjection(..) | ty::TyAnon(..) => {
debug!("ty: {:?} isn't known, and therefore is a dropck type", ty);
true
},

View File

@ -786,16 +786,19 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
debug!("assemble_projection_candidates: step={:?}",
step);
let projection_trait_ref = match step.self_ty.sty {
ty::TyProjection(ref data) => &data.trait_ref,
let (def_id, substs) = match step.self_ty.sty {
ty::TyProjection(ref data) => {
(data.trait_ref.def_id, data.trait_ref.substs)
}
ty::TyAnon(def_id, substs) => (def_id, substs),
_ => continue,
};
debug!("assemble_projection_candidates: projection_trait_ref={:?}",
projection_trait_ref);
debug!("assemble_projection_candidates: def_id={:?} substs={:?}",
def_id, substs);
let trait_predicates = self.tcx.lookup_predicates(projection_trait_ref.def_id);
let bounds = trait_predicates.instantiate(self.tcx, projection_trait_ref.substs);
let trait_predicates = self.tcx.lookup_predicates(def_id);
let bounds = trait_predicates.instantiate(self.tcx, substs);
let predicates = bounds.predicates.into_vec();
debug!("assemble_projection_candidates: predicates={:?}",
predicates);
@ -806,9 +809,8 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
{
let bound = self.erase_late_bound_regions(&poly_bound);
debug!("assemble_projection_candidates: projection_trait_ref={:?} bound={:?}",
projection_trait_ref,
bound);
debug!("assemble_projection_candidates: def_id={:?} substs={:?} bound={:?}",
def_id, substs, bound);
if self.can_equate(&step.self_ty, &bound.self_ty()).is_ok() {
let xform_self_ty = self.xform_self_ty(&item,

View File

@ -27,7 +27,7 @@ use rustc::ty::{TyParam, TyRawPtr};
use rustc::ty::{TyRef, TyStruct, TyTrait, TyTuple};
use rustc::ty::{TyStr, TyArray, TySlice, TyFloat, TyInfer, TyInt};
use rustc::ty::{TyUint, TyClosure, TyBox, TyFnDef, TyFnPtr};
use rustc::ty::TyProjection;
use rustc::ty::{TyProjection, TyAnon};
use rustc::ty::util::CopyImplementationError;
use middle::free_region::FreeRegionMap;
use CrateCtxt;
@ -89,7 +89,7 @@ impl<'a, 'gcx, 'tcx> CoherenceChecker<'a, 'gcx, 'tcx> {
None
}
TyInfer(..) | TyClosure(..) => {
TyInfer(..) | TyClosure(..) | TyAnon(..) => {
// `ty` comes from a user declaration so we should only expect types
// that the user can type
span_bug!(

View File

@ -1694,10 +1694,10 @@ fn ty_generic_predicates_for_fn<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
}
// Add the Sized bound, unless the type parameter is marked as `?Sized`.
fn add_unsized_bound<'tcx>(astconv: &AstConv<'tcx, 'tcx>,
bounds: &mut ty::BuiltinBounds,
ast_bounds: &[hir::TyParamBound],
span: Span)
fn add_unsized_bound<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>,
bounds: &mut ty::BuiltinBounds,
ast_bounds: &[hir::TyParamBound],
span: Span)
{
let tcx = astconv.tcx();
@ -2038,17 +2038,17 @@ fn compute_object_lifetime_default<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
}
}
enum SizedByDefault { Yes, No, }
pub enum SizedByDefault { Yes, No, }
/// Translate the AST's notion of ty param bounds (which are an enum consisting of a newtyped Ty or
/// a region) to ty's notion of ty param bounds, which can either be user-defined traits, or the
/// built-in trait (formerly known as kind): Send.
fn compute_bounds<'tcx>(astconv: &AstConv<'tcx, 'tcx>,
param_ty: ty::Ty<'tcx>,
ast_bounds: &[hir::TyParamBound],
sized_by_default: SizedByDefault,
span: Span)
-> Bounds<'tcx>
pub fn compute_bounds<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>,
param_ty: ty::Ty<'tcx>,
ast_bounds: &[hir::TyParamBound],
sized_by_default: SizedByDefault,
span: Span)
-> Bounds<'tcx>
{
let mut bounds =
conv_param_bounds(astconv,
@ -2098,11 +2098,11 @@ fn predicates_from_bound<'tcx>(astconv: &AstConv<'tcx, 'tcx>,
}
}
fn conv_poly_trait_ref<'tcx>(astconv: &AstConv<'tcx, 'tcx>,
param_ty: Ty<'tcx>,
trait_ref: &hir::PolyTraitRef,
projections: &mut Vec<ty::PolyProjectionPredicate<'tcx>>)
-> ty::PolyTraitRef<'tcx>
fn conv_poly_trait_ref<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>,
param_ty: Ty<'tcx>,
trait_ref: &hir::PolyTraitRef,
projections: &mut Vec<ty::PolyProjectionPredicate<'tcx>>)
-> ty::PolyTraitRef<'tcx>
{
AstConv::instantiate_poly_trait_ref(astconv,
&ExplicitRscope,
@ -2111,11 +2111,11 @@ fn conv_poly_trait_ref<'tcx>(astconv: &AstConv<'tcx, 'tcx>,
projections)
}
fn conv_param_bounds<'a,'tcx>(astconv: &AstConv<'tcx, 'tcx>,
span: Span,
param_ty: ty::Ty<'tcx>,
ast_bounds: &[hir::TyParamBound])
-> Bounds<'tcx>
fn conv_param_bounds<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>,
span: Span,
param_ty: ty::Ty<'tcx>,
ast_bounds: &[hir::TyParamBound])
-> Bounds<'tcx>
{
let tcx = astconv.tcx();
let PartitionedBounds {

View File

@ -45,7 +45,7 @@ struct ParameterCollector {
impl<'tcx> TypeVisitor<'tcx> for ParameterCollector {
fn visit_ty(&mut self, t: Ty<'tcx>) -> bool {
match t.sty {
ty::TyProjection(..) if !self.include_nonconstraining => {
ty::TyProjection(..) | ty::TyAnon(..) if !self.include_nonconstraining => {
// projections are not injective
return false;
}

View File

@ -326,7 +326,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
/* leaf type -- noop */
}
ty::TyClosure(..) => {
ty::TyClosure(..) | ty::TyAnon(..) => {
bug!("Unexpected closure type in variance computation");
}

View File

@ -1867,6 +1867,18 @@ impl<'tcx> Clean<Type> for ty::Ty<'tcx> {
ty::TyParam(ref p) => Generic(p.name.to_string()),
ty::TyAnon(def_id, substs) => {
// Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
// by looking up the projections associated with the def_id.
let item_predicates = cx.tcx().lookup_predicates(def_id);
let substs = cx.tcx().lift(&substs).unwrap();
let bounds = item_predicates.instantiate(cx.tcx(), substs);
let predicates = bounds.predicates.into_vec();
ImplTrait(predicates.into_iter().filter_map(|predicate| {
predicate.to_opt_poly_trait_ref().clean(cx)
}).collect())
}
ty::TyClosure(..) => Tuple(vec![]), // FIXME(pcwalton)
ty::TyInfer(..) => panic!("TyInfer"),