about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2025-05-08 15:00:11 +0000
committerMichael Goulet <michael@errs.io>2025-05-08 15:00:17 +0000
commit9af6ee50ed8630590ed02ca1c284d07b65d84d10 (patch)
treecacb538bf714e720b4fe832f222fff14e90eed92
parent19738720130a82959acd4fc45259166262f3ffbe (diff)
downloadrust-9af6ee50ed8630590ed02ca1c284d07b65d84d10.tar.gz
rust-9af6ee50ed8630590ed02ca1c284d07b65d84d10.zip
Structurally resolve in check_ref_cast and calc_adjust_mode
-rw-r--r--compiler/rustc_hir_typeck/src/pat.rs26
-rw-r--r--tests/ui/pattern/normalize-ty-in-range.rs24
2 files changed, 41 insertions, 9 deletions
diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs
index f9502153afd..17d48184dd9 100644
--- a/compiler/rustc_hir_typeck/src/pat.rs
+++ b/compiler/rustc_hir_typeck/src/pat.rs
@@ -650,14 +650,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         match &pat.kind {
             // Type checking these product-like types successfully always require
             // that the expected type be of those types and not reference types.
-            PatKind::Tuple(..)
-            | PatKind::Range(..)
-            | PatKind::Slice(..) => AdjustMode::peel_all(),
+            PatKind::Tuple(..) | PatKind::Range(..) | PatKind::Slice(..) => AdjustMode::peel_all(),
             // When checking an explicit deref pattern, only peel reference types.
             // FIXME(deref_patterns): If box patterns and deref patterns need to coexist, box
             // patterns may want `PeelKind::Implicit`, stopping on encountering a box.
-            | PatKind::Box(_)
-            | PatKind::Deref(_) => AdjustMode::Peel { kind: PeelKind::ExplicitDerefPat },
+            PatKind::Box(_) | PatKind::Deref(_) => {
+                AdjustMode::Peel { kind: PeelKind::ExplicitDerefPat }
+            }
             // A never pattern behaves somewhat like a literal or unit variant.
             PatKind::Never => AdjustMode::peel_all(),
             // For patterns with paths, how we peel the scrutinee depends on the path's resolution.
@@ -679,7 +678,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     && self.tcx.features().deref_patterns()
                     && !matches!(lt.kind, PatExprKind::Lit { .. })
                 {
-                    span_bug!(lt.span, "FIXME(deref_patterns): adjust mode unimplemented for {:?}", lt.kind);
+                    span_bug!(
+                        lt.span,
+                        "FIXME(deref_patterns): adjust mode unimplemented for {:?}",
+                        lt.kind
+                    );
                 }
                 // Call `resolve_vars_if_possible` here for inline const blocks.
                 let lit_ty = self.resolve_vars_if_possible(self.check_pat_expr_unadjusted(lt));
@@ -687,17 +690,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 if self.tcx.features().deref_patterns() {
                     let mut peeled_ty = lit_ty;
                     let mut pat_ref_layers = 0;
-                    while let ty::Ref(_, inner_ty, mutbl) = *peeled_ty.kind() {
+                    while let ty::Ref(_, inner_ty, mutbl) =
+                        *self.try_structurally_resolve_type(pat.span, peeled_ty).kind()
+                    {
                         // We rely on references at the head of constants being immutable.
                         debug_assert!(mutbl.is_not());
                         pat_ref_layers += 1;
                         peeled_ty = inner_ty;
                     }
-                    AdjustMode::Peel { kind: PeelKind::Implicit { until_adt: None, pat_ref_layers } }
+                    AdjustMode::Peel {
+                        kind: PeelKind::Implicit { until_adt: None, pat_ref_layers },
+                    }
                 } else {
                     if lit_ty.is_ref() { AdjustMode::Pass } else { AdjustMode::peel_all() }
                 }
-            },
+            }
 
             // Ref patterns are complicated, we handle them in `check_pat_ref`.
             PatKind::Ref(..)
@@ -928,6 +935,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 // be peeled to `str` while ty here is still `&str`, if we don't
                 // err early here, a rather confusing unification error will be
                 // emitted instead).
+                let ty = self.try_structurally_resolve_type(expr.span, ty);
                 let fail =
                     !(ty.is_numeric() || ty.is_char() || ty.is_ty_var() || ty.references_error());
                 Some((fail, ty, expr.span))
diff --git a/tests/ui/pattern/normalize-ty-in-range.rs b/tests/ui/pattern/normalize-ty-in-range.rs
new file mode 100644
index 00000000000..f0d22362608
--- /dev/null
+++ b/tests/ui/pattern/normalize-ty-in-range.rs
@@ -0,0 +1,24 @@
+//@ check-pass
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[next] compile-flags: -Znext-solver
+
+// Regression test for <https://github.com/rust-lang/trait-system-refactor-initiative/issues/200>.
+// Make sure we structurally normalize in range pattern checking in HIR typeck.
+
+trait Foo {
+    type Bar;
+}
+
+impl Foo for () {
+    type Bar = i32;
+}
+
+fn main() {
+    const X: <() as Foo>::Bar = 0;
+
+    match 0 {
+        X..=X => {}
+        _ => {}
+    }
+}