Normalize after substituting via field.ty()
This commit is contained in:
parent
b7e358ee17
commit
68b76a4835
@ -1627,8 +1627,8 @@ pub fn inhibit_union_abi_opt(&self) -> bool {
|
||||
}
|
||||
|
||||
impl<'tcx> FieldDef {
|
||||
/// Returns the type of this field. The `subst` is typically obtained
|
||||
/// via the second field of `TyKind::AdtDef`.
|
||||
/// Returns the type of this field. The resulting type is not normalized. The `subst` is
|
||||
/// typically obtained via the second field of `TyKind::AdtDef`.
|
||||
pub fn ty(&self, tcx: TyCtxt<'tcx>, subst: SubstsRef<'tcx>) -> Ty<'tcx> {
|
||||
tcx.type_of(self.did).subst(tcx, subst)
|
||||
}
|
||||
|
@ -1154,6 +1154,8 @@ fn list_variant_nonhidden_fields<'a>(
|
||||
|
||||
variant.fields.iter().enumerate().filter_map(move |(i, field)| {
|
||||
let ty = field.ty(cx.tcx, substs);
|
||||
// `field.ty()` doesn't normalize after substituting.
|
||||
let ty = cx.tcx.normalize_erasing_regions(cx.param_env, ty);
|
||||
let is_visible = adt.is_enum() || field.vis.is_accessible_from(cx.module, cx.tcx);
|
||||
let is_uninhabited = cx.is_uninhabited(ty);
|
||||
|
||||
@ -1671,7 +1673,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{}", hi)
|
||||
}
|
||||
IntRange(range) => write!(f, "{:?}", range), // Best-effort, will render e.g. `false` as `0..=0`
|
||||
Wildcard | Missing { .. } | NonExhaustive => write!(f, "_"),
|
||||
Wildcard | Missing { .. } | NonExhaustive => write!(f, "_ : {:?}", self.ty),
|
||||
Or => {
|
||||
for pat in self.iter_fields() {
|
||||
write!(f, "{}{:?}", start_or_continue(" | "), pat)?;
|
||||
|
@ -781,8 +781,7 @@ fn is_useful<'p, 'tcx>(
|
||||
|
||||
assert!(rows.iter().all(|r| r.len() == v.len()));
|
||||
|
||||
// FIXME(Nadrieril): Hack to work around type normalization issues (see #72476).
|
||||
let ty = matrix.heads().next().map_or(v.head().ty(), |r| r.ty());
|
||||
let ty = v.head().ty();
|
||||
let is_non_exhaustive = cx.is_foreign_non_exhaustive_enum(ty);
|
||||
let pcx = PatCtxt { cx, ty, span: v.head().span(), is_top_level, is_non_exhaustive };
|
||||
|
||||
|
@ -0,0 +1,56 @@
|
||||
// check-pass
|
||||
|
||||
// From https://github.com/rust-lang/rust/issues/72476
|
||||
// and https://github.com/rust-lang/rust/issues/89393
|
||||
|
||||
trait Trait {
|
||||
type Projection;
|
||||
}
|
||||
|
||||
struct A;
|
||||
impl Trait for A {
|
||||
type Projection = bool;
|
||||
}
|
||||
|
||||
struct B;
|
||||
impl Trait for B {
|
||||
type Projection = (u32, u32);
|
||||
}
|
||||
|
||||
struct Next<T: Trait>(T::Projection);
|
||||
|
||||
fn foo1(item: Next<A>) {
|
||||
match item {
|
||||
Next(true) => {}
|
||||
Next(false) => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn foo2(x: <A as Trait>::Projection) {
|
||||
match x {
|
||||
true => {}
|
||||
false => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn foo3(x: Next<B>) {
|
||||
let Next((_, _)) = x;
|
||||
match x {
|
||||
Next((_, _)) => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn foo4(x: <B as Trait>::Projection) {
|
||||
let (_, _) = x;
|
||||
match x {
|
||||
(_, _) => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn foo5<T: Trait>(x: <T as Trait>::Projection) {
|
||||
match x {
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -1,22 +0,0 @@
|
||||
// check-pass
|
||||
|
||||
// From https://github.com/rust-lang/rust/issues/72476
|
||||
|
||||
trait A {
|
||||
type Projection;
|
||||
}
|
||||
|
||||
impl A for () {
|
||||
type Projection = bool;
|
||||
}
|
||||
|
||||
struct Next<T: A>(T::Projection);
|
||||
|
||||
fn f(item: Next<()>) {
|
||||
match item {
|
||||
Next(true) => {}
|
||||
Next(false) => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
Loading…
Reference in New Issue
Block a user