about summary refs log tree commit diff
diff options
context:
space:
mode:
authorGuillaume Gomez <guillaume1.gomez@gmail.com>2024-11-28 03:14:49 +0100
committerGitHub <noreply@github.com>2024-11-28 03:14:49 +0100
commitb46ed7119e9626fda60fcdab5c5dc7b48b31a472 (patch)
treea8df85ce055272382155213eb401f130ab408e94
parent06815d0cc12732d8de4995b76c93d3d04261fd79 (diff)
parent26c77742c3af8e80b0e62b73939d6a112b4b7043 (diff)
downloadrust-b46ed7119e9626fda60fcdab5c5dc7b48b31a472.tar.gz
rust-b46ed7119e9626fda60fcdab5c5dc7b48b31a472.zip
Rollup merge of #133520 - compiler-errors:structurally-resolve-mir-borrowck, r=lcnr
Structurally resolve before applying projection in borrowck

As far as I can tell, all other `.normalize` calls in borrowck are noops and can remain that way. This is the only one that actually requires structurally resolving the type.

r? lcnr
-rw-r--r--compiler/rustc_borrowck/src/type_check/canonical.rs36
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs6
-rw-r--r--tests/ui/traits/next-solver/structurally-normalize-in-borrowck-field-projection.rs32
3 files changed, 72 insertions, 2 deletions
diff --git a/compiler/rustc_borrowck/src/type_check/canonical.rs b/compiler/rustc_borrowck/src/type_check/canonical.rs
index 68b843d4d0d..585d0eabf5b 100644
--- a/compiler/rustc_borrowck/src/type_check/canonical.rs
+++ b/compiler/rustc_borrowck/src/type_check/canonical.rs
@@ -7,6 +7,7 @@ use rustc_middle::mir::ConstraintCategory;
 use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, Upcast};
 use rustc_span::Span;
 use rustc_span::def_id::DefId;
+use rustc_trait_selection::solve::NoSolution;
 use rustc_trait_selection::traits::ObligationCause;
 use rustc_trait_selection::traits::query::type_op::custom::CustomTypeOp;
 use rustc_trait_selection::traits::query::type_op::{self, TypeOpOutput};
@@ -177,6 +178,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         if self.infcx.next_trait_solver() {
             let body = self.body;
             let param_env = self.infcx.param_env;
+            // FIXME: Make this into a real type op?
             self.fully_perform_op(
                 location.to_locations(),
                 ConstraintCategory::Boring,
@@ -214,6 +216,40 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
     }
 
     #[instrument(skip(self), level = "debug")]
+    pub(super) fn structurally_resolve(
+        &mut self,
+        ty: Ty<'tcx>,
+        location: impl NormalizeLocation,
+    ) -> Ty<'tcx> {
+        if self.infcx.next_trait_solver() {
+            let body = self.body;
+            let param_env = self.infcx.param_env;
+            // FIXME: Make this into a real type op?
+            self.fully_perform_op(
+                location.to_locations(),
+                ConstraintCategory::Boring,
+                CustomTypeOp::new(
+                    |ocx| {
+                        ocx.structurally_normalize(
+                            &ObligationCause::misc(
+                                location.to_locations().span(body),
+                                body.source.def_id().expect_local(),
+                            ),
+                            param_env,
+                            ty,
+                        )
+                        .map_err(|_| NoSolution)
+                    },
+                    "normalizing struct tail",
+                ),
+            )
+            .unwrap_or_else(|guar| Ty::new_error(self.tcx(), guar))
+        } else {
+            self.normalize(ty, location)
+        }
+    }
+
+    #[instrument(skip(self), level = "debug")]
     pub(super) fn ascribe_user_type(
         &mut self,
         mir_ty: Ty<'tcx>,
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 3a7ed711f68..b4763acbefa 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -1064,7 +1064,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         let tcx = self.infcx.tcx;
 
         for proj in &user_ty.projs {
-            if let ty::Alias(ty::Opaque, ..) = curr_projected_ty.ty.kind() {
+            if !self.infcx.next_trait_solver()
+                && let ty::Alias(ty::Opaque, ..) = curr_projected_ty.ty.kind()
+            {
                 // There is nothing that we can compare here if we go through an opaque type.
                 // We're always in its defining scope as we can otherwise not project through
                 // it, so we're constraining it anyways.
@@ -1075,7 +1077,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                 proj,
                 |this, field, ()| {
                     let ty = this.field_ty(tcx, field);
-                    self.normalize(ty, locations)
+                    self.structurally_resolve(ty, locations)
                 },
                 |_, _| unreachable!(),
             );
diff --git a/tests/ui/traits/next-solver/structurally-normalize-in-borrowck-field-projection.rs b/tests/ui/traits/next-solver/structurally-normalize-in-borrowck-field-projection.rs
new file mode 100644
index 00000000000..d2d68128fde
--- /dev/null
+++ b/tests/ui/traits/next-solver/structurally-normalize-in-borrowck-field-projection.rs
@@ -0,0 +1,32 @@
+//@ check-pass
+//@ compile-flags: -Znext-solver
+
+trait Interner: Sized {
+    type Value;
+}
+
+enum Kind<I: Interner> {
+    Value(I::Value),
+}
+
+struct Intern;
+
+impl Interner for Intern {
+    type Value = Wrap<u32>;
+}
+
+struct Wrap<T>(T);
+
+type KindAlias = Kind<Intern>;
+
+trait PrettyPrinter: Sized {
+    fn hello(c: KindAlias) {
+        match c {
+            KindAlias::Value(Wrap(v)) => {
+                println!("{v:?}");
+            }
+        }
+    }
+}
+
+fn main() {}