If we encounter _ ascribed to structural pattern like (a, b), just skip relate_types.

This commit is contained in:
Felix S. Klock II 2018-11-03 01:53:57 +01:00
parent 05812fa8c5
commit 09edfb885c
3 changed files with 62 additions and 22 deletions

View file

@ -80,7 +80,8 @@ impl<'a, 'gcx, 'tcx> PlaceTy<'tcx> {
elem: &PlaceElem<'tcx>)
-> PlaceTy<'tcx>
{
self.projection_ty_core(tcx, elem, |_, _, ty| ty)
self.projection_ty_core(tcx, elem, |_, _, ty| -> Result<Ty<'tcx>, ()> { Ok(ty) })
.unwrap()
}
/// `place_ty.projection_ty_core(tcx, elem, |...| { ... })`
@ -88,11 +89,12 @@ impl<'a, 'gcx, 'tcx> PlaceTy<'tcx> {
/// `Ty` or downcast variant corresponding to that projection.
/// The `handle_field` callback must map a `Field` to its `Ty`,
/// (which should be trivial when `T` = `Ty`).
pub fn projection_ty_core<V, T>(self,
tcx: TyCtxt<'a, 'gcx, 'tcx>,
elem: &ProjectionElem<'tcx, V, T>,
mut handle_field: impl FnMut(&Self, &Field, &T) -> Ty<'tcx>)
-> PlaceTy<'tcx>
pub fn projection_ty_core<V, T, E>(
self,
tcx: TyCtxt<'a, 'gcx, 'tcx>,
elem: &ProjectionElem<'tcx, V, T>,
mut handle_field: impl FnMut(&Self, &Field, &T) -> Result<Ty<'tcx>, E>)
-> Result<PlaceTy<'tcx>, E>
where
V: ::std::fmt::Debug, T: ::std::fmt::Debug
{
@ -142,10 +144,11 @@ impl<'a, 'gcx, 'tcx> PlaceTy<'tcx> {
bug!("cannot downcast non-ADT type: `{:?}`", self)
}
},
ProjectionElem::Field(ref f, ref fty) => PlaceTy::Ty { ty: handle_field(&self, f, fty) }
ProjectionElem::Field(ref f, ref fty) =>
PlaceTy::Ty { ty: handle_field(&self, f, fty)? },
};
debug!("projection_ty self: {:?} elem: {:?} yields: {:?}", self, elem, answer);
answer
Ok(answer)
}
}

View file

@ -991,20 +991,39 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
let v1 = ty::Contravariant.xform(v);
let tcx = self.infcx.tcx;
let mut projected_ty = PlaceTy::from_ty(ty);
let ty = self.normalize(ty, locations);
// We need to follow any provided projetions into the type.
//
// if we hit a ty var as we descend, then just skip the
// attempt to relate the mir local with any type.
#[derive(Debug)] struct HitTyVar;
let mut curr_projected_ty: Result<PlaceTy, HitTyVar>;
curr_projected_ty = Ok(PlaceTy::from_ty(ty));
for proj in &user_ty.projs {
projected_ty = projected_ty.projection_ty_core(
let projected_ty = if let Ok(projected_ty) = curr_projected_ty {
projected_ty
} else {
break;
};
curr_projected_ty = projected_ty.projection_ty_core(
tcx, proj, |this, field, &()| {
let ty = this.field_ty(tcx, field);
self.normalize(ty, locations)
if this.to_ty(tcx).is_ty_var() {
Err(HitTyVar)
} else {
let ty = this.field_ty(tcx, field);
Ok(self.normalize(ty, locations))
}
});
}
debug!("user_ty base: {:?} freshened: {:?} projs: {:?} yields: {:?}",
user_ty.base, ty, user_ty.projs, projected_ty);
user_ty.base, ty, user_ty.projs, curr_projected_ty);
let ty = projected_ty.to_ty(tcx);
self.relate_types(ty, v1, a, locations, category)?;
if let Ok(projected_ty) = curr_projected_ty {
let ty = projected_ty.to_ty(tcx);
self.relate_types(ty, v1, a, locations, category)?;
}
}
UserTypeAnnotation::TypeOf(def_id, canonical_substs) => {
let (

View file

@ -151,17 +151,35 @@ impl AscribeUserTypeCx<'me, 'gcx, 'tcx> {
debug!("relate_type_and_user_type: ty of def-id is {:?}", ty);
let ty = self.normalize(ty);
let mut projected_ty = PlaceTy::from_ty(ty);
// We need to follow any provided projetions into the type.
//
// if we hit a ty var as we descend, then just skip the
// attempt to relate the mir local with any type.
struct HitTyVar;
let mut curr_projected_ty: Result<PlaceTy, HitTyVar>;
curr_projected_ty = Ok(PlaceTy::from_ty(ty));
for proj in projs {
projected_ty = projected_ty.projection_ty_core(
let projected_ty = if let Ok(projected_ty) = curr_projected_ty {
projected_ty
} else {
break;
};
curr_projected_ty = projected_ty.projection_ty_core(
tcx, proj, |this, field, &()| {
let ty = this.field_ty(tcx, field);
self.normalize(ty)
if this.to_ty(tcx).is_ty_var() {
Err(HitTyVar)
} else {
let ty = this.field_ty(tcx, field);
Ok(self.normalize(ty))
}
});
}
let ty = projected_ty.to_ty(tcx);
self.relate(mir_ty, variance, ty)?;
if let Ok(projected_ty) = curr_projected_ty {
let ty = projected_ty.to_ty(tcx);
self.relate(mir_ty, variance, ty)?;
}
if let Some(UserSelfTy {
impl_def_id,