about summary refs log tree commit diff
diff options
context:
space:
mode:
authorBoxy <rust@boxyuwu.dev>2025-06-17 14:45:47 +0100
committerBoxy <rust@boxyuwu.dev>2025-06-17 14:48:17 +0100
commitae65625252df45569940336bea6df8fe0c4826e6 (patch)
treedeab875b8ee6e8c0c655fecffb40735fa303b469
parent9961747414891126720b22050f2b049f0e2457c7 (diff)
downloadrust-ae65625252df45569940336bea6df8fe0c4826e6.tar.gz
rust-ae65625252df45569940336bea6df8fe0c4826e6.zip
Dont replace escaping bound vars in item sigs
-rw-r--r--compiler/rustc_hir_analysis/src/collect.rs76
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs75
-rw-r--r--tests/crashes/138131.rs15
-rw-r--r--tests/ui/associated-inherent-types/bound_vars_in_args.rs3
-rw-r--r--tests/ui/associated-inherent-types/bound_vars_in_args.stderr41
-rw-r--r--tests/ui/associated-inherent-types/issue-109299-1.rs4
-rw-r--r--tests/ui/associated-inherent-types/issue-109299-1.stderr28
7 files changed, 82 insertions, 160 deletions
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index ea4194079a6..176d955bf03 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -380,54 +380,44 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> {
         assert!(!self_ty.has_infer());
 
         // We don't just call the normal normalization routine here as we can't provide the
-        // correct `ParamEnv` and it seems dubious to invoke arbitrary trait solving under
+        // correct `ParamEnv` and it would be wrong to invoke arbitrary trait solving under
         // the wrong `ParamEnv`. Expanding free aliases doesn't need a `ParamEnv` so we do
         // this just to make resolution a little bit smarter.
         let self_ty = self.tcx.expand_free_alias_tys(self_ty);
         debug!("select_inherent_assoc_candidates: self_ty={:?}", self_ty);
 
-        // We make an infcx and replace any escaping vars with placeholders so that IAT res
-        // with type/const bound vars in arguments is slightly smarter. `for<T> <Foo<T>>::IAT`
-        // would otherwise unify with `impl Foo<u8>` when ideally we would not.
-        let infcx = self.tcx().infer_ctxt().build(TypingMode::non_body_analysis());
-        let mut universes = if self_ty.has_escaping_bound_vars() {
-            vec![None; self_ty.outer_exclusive_binder().as_usize()]
-        } else {
-            vec![]
-        };
-        let candidates =
-            rustc_trait_selection::traits::with_replaced_escaping_bound_vars(
-                &infcx,
-                &mut universes,
-                self_ty,
-                |self_ty| {
-                    candidates
-                        .into_iter()
-                        .filter(|&InherentAssocCandidate { impl_, .. }| {
-                            let impl_ty = self.tcx().type_of(impl_).instantiate_identity();
-
-                            // See comment on doing this operation for `self_ty`
-                            let impl_ty = self.tcx.expand_free_alias_tys(impl_ty);
-                            debug!("select_inherent_assoc_candidates: impl_ty={:?}", impl_ty);
-
-                            // We treat parameters in the self ty as rigid and parameters in the impl ty as infers
-                            // because it allows `impl<T> Foo<T>` to unify with `Foo<u8>::IAT`, while also disallowing
-                            // `Foo<T>::IAT` from unifying with `impl Foo<u8>`.
-                            //
-                            // We don't really care about a depth limit here because we're only working with user-written
-                            // types and if they wrote a type that would take hours to walk then that's kind of on them. On
-                            // the other hand the default depth limit is relatively low and could realistically be hit by
-                            // users in normal cases.
-                            //
-                            // `DeepRejectCtxt` leads to slightly worse IAT resolution than real type equality in cases
-                            // where the `impl_ty` has repeated uses of generic parameters. E.g. `impl<T> Foo<T, T>` would
-                            // be considered a valid candidate when resolving `Foo<u8, u16>::IAT`.
-                            ty::DeepRejectCtxt::relate_rigid_infer(self.tcx)
-                                .types_may_unify_with_depth(self_ty, impl_ty, usize::MAX)
-                        })
-                        .collect()
-                },
-            );
+        let candidates = candidates
+            .into_iter()
+            .filter(|&InherentAssocCandidate { impl_, .. }| {
+                let impl_ty = self.tcx().type_of(impl_).instantiate_identity();
+
+                // See comment on doing this operation for `self_ty`
+                let impl_ty = self.tcx.expand_free_alias_tys(impl_ty);
+                debug!("select_inherent_assoc_candidates: impl_ty={:?}", impl_ty);
+
+                // We treat parameters in the self ty as rigid and parameters in the impl ty as infers
+                // because it allows `impl<T> Foo<T>` to unify with `Foo<u8>::IAT`, while also disallowing
+                // `Foo<T>::IAT` from unifying with `impl Foo<u8>`.
+                //
+                // We don't really care about a depth limit here because we're only working with user-written
+                // types and if they wrote a type that would take hours to walk then that's kind of on them. On
+                // the other hand the default depth limit is relatively low and could realistically be hit by
+                // users in normal cases.
+                //
+                // `DeepRejectCtxt` leads to slightly worse IAT resolution than real type equality in cases
+                // where the `impl_ty` has repeated uses of generic parameters. E.g. `impl<T> Foo<T, T>` would
+                // be considered a valid candidate when resolving `Foo<u8, u16>::IAT`.
+                //
+                // Not replacing escaping bound vars in `self_ty` with placeholders also leads to slightly worse
+                // resolution, but it probably won't come up in practice and it would be backwards compatible
+                // to switch over to doing that.
+                ty::DeepRejectCtxt::relate_rigid_infer(self.tcx).types_may_unify_with_depth(
+                    self_ty,
+                    impl_ty,
+                    usize::MAX,
+                )
+            })
+            .collect();
 
         (candidates, vec![])
     }
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
index d8efb0aac4d..8c18642e54a 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
@@ -322,6 +322,39 @@ impl<'tcx> HirTyLowerer<'tcx> for FnCtxt<'_, 'tcx> {
     ) -> (Vec<InherentAssocCandidate>, Vec<FulfillmentError<'tcx>>) {
         let tcx = self.tcx();
         let infcx = &self.infcx;
+        let mut fulfillment_errors = vec![];
+
+        let mut filter_iat_candidate = |self_ty, impl_| {
+            let ocx = ObligationCtxt::new_with_diagnostics(self);
+            let self_ty = ocx.normalize(&ObligationCause::dummy(), self.param_env, self_ty);
+
+            let impl_args = infcx.fresh_args_for_item(span, impl_);
+            let impl_ty = tcx.type_of(impl_).instantiate(tcx, impl_args);
+            let impl_ty = ocx.normalize(&ObligationCause::dummy(), self.param_env, impl_ty);
+
+            // Check that the self types can be related.
+            if ocx.eq(&ObligationCause::dummy(), self.param_env, impl_ty, self_ty).is_err() {
+                return false;
+            }
+
+            // Check whether the impl imposes obligations we have to worry about.
+            let impl_bounds = tcx.predicates_of(impl_).instantiate(tcx, impl_args);
+            let impl_bounds = ocx.normalize(&ObligationCause::dummy(), self.param_env, impl_bounds);
+            let impl_obligations = traits::predicates_for_generics(
+                |_, _| ObligationCause::dummy(),
+                self.param_env,
+                impl_bounds,
+            );
+            ocx.register_obligations(impl_obligations);
+
+            let mut errors = ocx.select_where_possible();
+            if !errors.is_empty() {
+                fulfillment_errors.append(&mut errors);
+                return false;
+            }
+
+            true
+        };
 
         let mut universes = if self_ty.has_escaping_bound_vars() {
             vec![None; self_ty.outer_exclusive_binder().as_usize()]
@@ -329,52 +362,12 @@ impl<'tcx> HirTyLowerer<'tcx> for FnCtxt<'_, 'tcx> {
             vec![]
         };
 
-        let mut fulfillment_errors = vec![];
         let candidates =
             traits::with_replaced_escaping_bound_vars(infcx, &mut universes, self_ty, |self_ty| {
                 candidates
                     .into_iter()
                     .filter(|&InherentAssocCandidate { impl_, .. }| {
-                        infcx.probe(|_| {
-                            let ocx = ObligationCtxt::new_with_diagnostics(self);
-                            let self_ty =
-                                ocx.normalize(&ObligationCause::dummy(), self.param_env, self_ty);
-
-                            let impl_args = infcx.fresh_args_for_item(span, impl_);
-                            let impl_ty = tcx.type_of(impl_).instantiate(tcx, impl_args);
-                            let impl_ty =
-                                ocx.normalize(&ObligationCause::dummy(), self.param_env, impl_ty);
-
-                            // Check that the self types can be related.
-                            if ocx
-                                .eq(&ObligationCause::dummy(), self.param_env, impl_ty, self_ty)
-                                .is_err()
-                            {
-                                return false;
-                            }
-
-                            // Check whether the impl imposes obligations we have to worry about.
-                            let impl_bounds = tcx.predicates_of(impl_).instantiate(tcx, impl_args);
-                            let impl_bounds = ocx.normalize(
-                                &ObligationCause::dummy(),
-                                self.param_env,
-                                impl_bounds,
-                            );
-                            let impl_obligations = traits::predicates_for_generics(
-                                |_, _| ObligationCause::dummy(),
-                                self.param_env,
-                                impl_bounds,
-                            );
-                            ocx.register_obligations(impl_obligations);
-
-                            let mut errors = ocx.select_where_possible();
-                            if !errors.is_empty() {
-                                fulfillment_errors.append(&mut errors);
-                                return false;
-                            }
-
-                            true
-                        })
+                        infcx.probe(|_| filter_iat_candidate(self_ty, impl_))
                     })
                     .collect()
             });
diff --git a/tests/crashes/138131.rs b/tests/crashes/138131.rs
deleted file mode 100644
index d0f91b74840..00000000000
--- a/tests/crashes/138131.rs
+++ /dev/null
@@ -1,15 +0,0 @@
-//@ known-bug: #138131
-
-#![feature(min_generic_const_args, generic_const_items)]
-
-const BAR<'a>: usize = 10;
-
-struct Foo<'a> {
-    x: &'a (),
-}
-
-impl<'a> Foo<'a> {
-    fn foo(_: [u8; BAR]) {}
-}
-
-fn main() {}
diff --git a/tests/ui/associated-inherent-types/bound_vars_in_args.rs b/tests/ui/associated-inherent-types/bound_vars_in_args.rs
index 276e3cf1da0..0baa242af76 100644
--- a/tests/ui/associated-inherent-types/bound_vars_in_args.rs
+++ b/tests/ui/associated-inherent-types/bound_vars_in_args.rs
@@ -15,9 +15,8 @@ impl<T: Sized> Foo<T> {
 }
 
 struct Bar
-//~^ ERROR: the size for values of type `T` cannot be known at compilation time
-//~| ERROR: the size for values of type `T` cannot be known at compilation time
 where
     for<T> Foo<T>::IAT: Sized;
+    //~^ ERROR: multiple applicable items in scope
 
 fn main() {}
diff --git a/tests/ui/associated-inherent-types/bound_vars_in_args.stderr b/tests/ui/associated-inherent-types/bound_vars_in_args.stderr
index 108f1e531af..9e880476f6a 100644
--- a/tests/ui/associated-inherent-types/bound_vars_in_args.stderr
+++ b/tests/ui/associated-inherent-types/bound_vars_in_args.stderr
@@ -1,37 +1,20 @@
-error[E0277]: the size for values of type `T` cannot be known at compilation time
-  --> $DIR/bound_vars_in_args.rs:17:1
+error[E0034]: multiple applicable items in scope
+  --> $DIR/bound_vars_in_args.rs:19:20
    |
-LL | struct Bar
-   | ^^^^^^^^^^ doesn't have a size known at compile-time
+LL |     for<T> Foo<T>::IAT: Sized;
+   |                    ^^^ multiple `IAT` found
    |
-   = help: the trait `Sized` is not implemented for `T`
-note: required by a bound in `Foo<T>::IAT`
-  --> $DIR/bound_vars_in_args.rs:13:9
+note: candidate #1 is defined in an impl for the type `Foo<[u8]>`
+  --> $DIR/bound_vars_in_args.rs:10:5
    |
-LL | impl<T: Sized> Foo<T> {
-   |         ^^^^^ required by this bound in `Foo<T>::IAT`
 LL |     type IAT = u8;
-   |          --- required by a bound in this associated type
-
-error[E0277]: the size for values of type `T` cannot be known at compilation time
-  --> $DIR/bound_vars_in_args.rs:17:1
-   |
-LL | / struct Bar
-LL | |
-LL | |
-LL | | where
-LL | |     for<T> Foo<T>::IAT: Sized;
-   | |______________________________^ doesn't have a size known at compile-time
-   |
-   = help: the trait `Sized` is not implemented for `T`
-note: required by a bound in `Foo<T>::IAT`
-  --> $DIR/bound_vars_in_args.rs:13:9
+   |     ^^^^^^^^
+note: candidate #2 is defined in an impl for the type `Foo<T>`
+  --> $DIR/bound_vars_in_args.rs:14:5
    |
-LL | impl<T: Sized> Foo<T> {
-   |         ^^^^^ required by this bound in `Foo<T>::IAT`
 LL |     type IAT = u8;
-   |          --- required by a bound in this associated type
+   |     ^^^^^^^^
 
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
-For more information about this error, try `rustc --explain E0277`.
+For more information about this error, try `rustc --explain E0034`.
diff --git a/tests/ui/associated-inherent-types/issue-109299-1.rs b/tests/ui/associated-inherent-types/issue-109299-1.rs
index 4546785f0b1..3132d9fef69 100644
--- a/tests/ui/associated-inherent-types/issue-109299-1.rs
+++ b/tests/ui/associated-inherent-types/issue-109299-1.rs
@@ -8,8 +8,6 @@ impl Lexer<i32> {
 }
 
 type X = impl for<T> Fn() -> Lexer<T>::Cursor;
-//~^ ERROR associated type `Cursor` not found for `Lexer<T>` in the current scope
-//~| ERROR associated type `Cursor` not found for `Lexer<T>` in the current scope
-//~| ERROR: unconstrained opaque type
+//~^ ERROR: unconstrained opaque type
 
 fn main() {}
diff --git a/tests/ui/associated-inherent-types/issue-109299-1.stderr b/tests/ui/associated-inherent-types/issue-109299-1.stderr
index 6bc7a539680..bc8ea6acf28 100644
--- a/tests/ui/associated-inherent-types/issue-109299-1.stderr
+++ b/tests/ui/associated-inherent-types/issue-109299-1.stderr
@@ -6,31 +6,5 @@ LL | type X = impl for<T> Fn() -> Lexer<T>::Cursor;
    |
    = note: `X` must be used in combination with a concrete type within the same crate
 
-error[E0220]: associated type `Cursor` not found for `Lexer<T>` in the current scope
-  --> $DIR/issue-109299-1.rs:10:40
-   |
-LL | struct Lexer<T>(T);
-   | --------------- associated type `Cursor` not found for this struct
-...
-LL | type X = impl for<T> Fn() -> Lexer<T>::Cursor;
-   |                                        ^^^^^^ associated item not found in `Lexer<T>`
-   |
-   = note: the associated type was found for
-           - `Lexer<i32>`
-
-error[E0220]: associated type `Cursor` not found for `Lexer<T>` in the current scope
-  --> $DIR/issue-109299-1.rs:10:40
-   |
-LL | struct Lexer<T>(T);
-   | --------------- associated type `Cursor` not found for this struct
-...
-LL | type X = impl for<T> Fn() -> Lexer<T>::Cursor;
-   |                                        ^^^^^^ associated item not found in `Lexer<T>`
-   |
-   = note: the associated type was found for
-           - `Lexer<i32>`
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error: aborting due to 3 previous errors
+error: aborting due to 1 previous error
 
-For more information about this error, try `rustc --explain E0220`.