Auto merge of #55637 - pnkfelix:issue-55552-dont-attempt-to-ascribe-projections-out-of-a-ty-var, r=nikomatsakis
Do not attempt to ascribe projections out of a ty var If we encounter `_` ascribed to structural pattern like `(a, b)`, just skip relate_types. Fix #55552
This commit is contained in:
commit
4cd3294a1d
@ -80,7 +80,8 @@ pub fn projection_ty(self, tcx: TyCtxt<'a, 'gcx, '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 @@ pub fn projection_ty(self, tcx: TyCtxt<'a, 'gcx, '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 @@ pub fn projection_ty_core<V, T>(self,
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1021,20 +1021,39 @@ fn relate_type_and_user_type(
|
||||
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 (
|
||||
|
@ -151,17 +151,35 @@ fn relate_mir_and_user_ty(
|
||||
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,
|
||||
|
@ -0,0 +1,31 @@
|
||||
// compile-pass
|
||||
|
||||
// rust-lang/rust#55552: The strategy pnkfelix landed in PR #55274
|
||||
// (for ensuring that NLL respects user-provided lifetime annotations)
|
||||
// did not handle the case where the ascribed type has some expliit
|
||||
// wildcards (`_`) mixed in, and it caused an internal compiler error
|
||||
// (ICE).
|
||||
//
|
||||
// This test is just checking that we do not ICE when such things
|
||||
// occur.
|
||||
|
||||
struct X;
|
||||
struct Y;
|
||||
struct Z;
|
||||
|
||||
struct Pair { x: X, y: Y }
|
||||
|
||||
pub fn join<A, B, RA, RB>(oper_a: A, oper_b: B) -> (RA, RB)
|
||||
where A: FnOnce() -> RA + Send,
|
||||
B: FnOnce() -> RB + Send,
|
||||
RA: Send,
|
||||
RB: Send
|
||||
{
|
||||
(oper_a(), oper_b())
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let ((_x, _y), _z): (_, Z) = join(|| (X, Y), || Z);
|
||||
|
||||
let (Pair { x: _x, y: _y }, Z): (_, Z) = join(|| Pair { x: X, y: Y }, || Z);
|
||||
}
|
Loading…
Reference in New Issue
Block a user