rustc: add TyAnon (impl Trait) to the typesystem.
This commit is contained in:
parent
f0baec691f
commit
ef11d4e3c7
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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}}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
})
|
||||
|
@ -240,7 +240,8 @@ impl<'a, 'tcx> ty::TyS<'tcx> {
|
||||
}
|
||||
|
||||
ty::TyProjection(..) |
|
||||
ty::TyParam(_) => {
|
||||
ty::TyParam(_) |
|
||||
ty::TyAnon(..) => {
|
||||
TC::All
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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(),
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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; }
|
||||
_ => { }
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
|
@ -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]
|
||||
|
@ -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(..) | // ...
|
||||
|
@ -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)))
|
||||
|
@ -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,
|
||||
|
@ -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) => {
|
||||
|
@ -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() {
|
||||
|
@ -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) => {
|
||||
|
@ -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
|
||||
//
|
||||
|
@ -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")?;
|
||||
|
@ -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")
|
||||
}
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
},
|
||||
|
@ -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,
|
||||
|
@ -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!(
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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");
|
||||
}
|
||||
|
||||
|
@ -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"),
|
||||
|
Loading…
Reference in New Issue
Block a user