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);
}
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);
}
Initializer,
/// Pattern binding
Binding(InternedString),
+ /// An `impl Trait` type node.
+ ImplTrait
}
impl Definitions {
Initializer => {
InternedString::new("{{initializer}}")
}
+
+ ImplTrait => {
+ InternedString::new("{{impl-Trait}}")
+ }
}
}
ty::TyClosure(..) |
ty::TyTuple(..) |
ty::TyProjection(..) |
- ty::TyParam(..) => {
+ ty::TyParam(..) |
+ ty::TyAnon(..) => {
t.super_fold_with(self)
}
}
true
}
- ty::TyClosure(..) => {
+ ty::TyClosure(..) | ty::TyAnon(..) => {
bug!("ty_is_local invoked on unexpected type: {:?}", ty)
}
}
ty::TyTuple(..) => Some(12),
ty::TyProjection(..) => Some(13),
ty::TyParam(..) => Some(14),
+ ty::TyAnon(..) => Some(15),
ty::TyInfer(..) | ty::TyError => None
}
}
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,
}
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
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.
};
// 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,
// 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)
});
}
}
- fn match_projection_obligation_against_bounds_from_trait(
+ fn match_projection_obligation_against_definition_bounds(
&mut self,
obligation: &TraitObligation<'tcx>,
snapshot: &infer::CombinedSnapshot)
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);
&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 {
}
}
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
}))
}
- ty::TyProjection(_) | ty::TyParam(_) => None,
+ ty::TyProjection(_) | ty::TyParam(_) | ty::TyAnon(..) => None,
ty::TyInfer(ty::TyVar(_)) => Ambiguous,
ty::TyInfer(ty::FreshTy(_))
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
}
ty::TyTrait(..) |
ty::TyParam(..) |
ty::TyProjection(..) |
+ ty::TyAnon(..) |
ty::TyInfer(ty::TyVar(_)) |
ty::TyInfer(ty::FreshTy(_)) |
ty::TyInfer(ty::FreshIntTy(_)) |
{
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);
})
}
ty::TyProjection(..) |
- ty::TyParam(_) => {
+ ty::TyParam(_) |
+ ty::TyAnon(..) => {
TC::All
}
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());
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);
"type parameter".to_string()
}
}
+ ty::TyAnon(..) => "anonymized type".to_string(),
ty::TyError => "type error".to_string(),
}
}
TraitSimplifiedType(DefId),
StructSimplifiedType(DefId),
ClosureSimplifiedType(DefId),
+ AnonSimplifiedType(DefId),
FunctionSimplifiedType(usize),
ParameterSimplifiedType,
}
None
}
}
+ ty::TyAnon(def_id, _) => {
+ Some(AnonSimplifiedType(def_id))
+ }
ty::TyInfer(_) | ty::TyError => None,
}
}
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);
// in the normalized form
if self.just_constrained {
match t.sty {
- ty::TyProjection(..) => { return false; }
+ ty::TyProjection(..) | ty::TyAnon(..) => { return false; }
_ => { }
}
}
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());
ty::TyFnPtr(_) |
ty::TyProjection(_) |
ty::TyParam(_) |
+ ty::TyAnon(..) |
ty::TyInfer(_) |
ty::TyError |
ty::TyFloat(_) => None,
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);
}
// 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));
}
}
- ty::TyProjection(_) => {
+ ty::TyProjection(_) | ty::TyAnon(..) => {
let normalized = normalize_associated_type(infcx, ty);
if ty == normalized {
Err(err)
}
}
- TyProjection(..) => {
+ TyProjection(..) | TyAnon(..) => {
// must calculate explicitly.
// FIXME: consider special-casing always-Sized projections
vec![ty]
ty::TyEnum(..) | // OutlivesNominalType
ty::TyStruct(..) | // OutlivesNominalType
ty::TyBox(..) | // OutlivesNominalType (ish)
+ ty::TyAnon(..) | // OutlivesNominalType (ish)
ty::TyStr | // OutlivesScalar (ish)
ty::TyArray(..) | // ...
ty::TySlice(..) | // ...
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)))
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(),
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,
/// `<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),
v
}
TyEnum(_, substs) |
- TyStruct(_, substs) => {
+ TyStruct(_, substs) |
+ TyAnon(_, substs) => {
substs.regions.as_slice().to_vec()
}
TyClosure(_, ref substs) => {
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);
}) => 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));
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() {
}).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) => {
// 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
//
}
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")?;
}
ty::TyParam(..) | ty::TyInfer(..) | ty::TyError |
- ty::TyClosure(..) | ty::TyProjection(..) |
+ ty::TyClosure(..) | ty::TyProjection(..) | ty::TyAnon(..) |
ty::TyFnDef(..) => {
bug!("Unexpected type in foreign function")
}
StructCtor,
Initializer,
Binding,
+ ImplTrait,
}
pub fn simplify_def_key(key: hir_map::DefKey) -> DefKey {
hir_map::DefPathData::StructCtor => DefPathData::StructCtor,
hir_map::DefPathData::Initializer => DefPathData::Initializer,
hir_map::DefPathData::Binding(_) => DefPathData::Binding,
+ hir_map::DefPathData::ImplTrait => DefPathData::ImplTrait,
}
}
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,
}
}
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;
}
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");
}
ty::TyProjection(_) |
ty::TyParam(_) |
ty::TyInfer(_) |
+ ty::TyAnon(..) |
ty::TyError => {
bug!("encountered unexpected type");
}
ty::TyError |
ty::TyInfer(_) |
ty::TyProjection(..) |
+ ty::TyAnon(..) |
ty::TyParam(_) => {
bug!("debuginfo: Trying to create type name for \
unexpected type: {:?}", t);
ty::TyError |
ty::TyInfer(_) |
ty::TyProjection(..) |
- ty::TyParam(_) => {
+ ty::TyParam(_) |
+ ty::TyAnon(..) => {
bug!("debuginfo: Trying to create type name for \
unexpected type: {:?}", t);
}
}
}
- 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!()
}
}
- 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);
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;
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);
}
// these are always dtorck
- ty::TyTrait(..) | ty::TyProjection(_) => bug!(),
+ ty::TyTrait(..) | ty::TyProjection(_) | ty::TyAnon(..) => bug!(),
}
}
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
},
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);
{
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,
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;
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!(
}
// 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();
}
}
-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,
}
}
-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,
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 {
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;
}
/* leaf type -- noop */
}
- ty::TyClosure(..) => {
+ ty::TyClosure(..) | ty::TyAnon(..) => {
bug!("Unexpected closure type in variance computation");
}
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"),