Test whether we use DeepRejectCtxt

This commit is contained in:
Boxy 2025-05-27 18:21:24 +01:00
parent 442862bc78
commit 2a950b5637
3 changed files with 62 additions and 4 deletions

View file

@ -414,10 +414,14 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> {
// 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.
// 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)
})

View file

@ -0,0 +1,34 @@
#![feature(inherent_associated_types)]
#![expect(incomplete_features)]
// Test whether IAT resolution in item signatures will actually instantiate the
// impl's params with infers before equating self types, or if we "cheat" and
// use a heuristic (e.g. DeepRejectCtxt).
struct Foo<T, U, V>(T, U, V);
impl<T> Foo<T, T, u8> {
type IAT = u8;
}
impl<T, U> Foo<T, U, u16> {
type IAT = u16;
}
trait Identity {
type This;
}
impl<T> Identity for T {
type This = T;
}
struct Bar<T, U> {
// It would be illegal to resolve to `Foo<T, T, u8>::IAT` as `T` and `U` are
// different types. However, currently we treat all impl-side params sort of like
// they're infers and assume they can unify with anything, so we consider it a
// valid candidate.
field: Foo<T, U, <u16 as Identity>::This>::IAT,
//~^ ERROR: multiple applicable items in scope
}
fn main() {}

View file

@ -0,0 +1,20 @@
error[E0034]: multiple applicable items in scope
--> $DIR/impl_params_are_infers.rs:30:48
|
LL | field: Foo<T, U, <u16 as Identity>::This>::IAT,
| ^^^ multiple `IAT` found
|
note: candidate #1 is defined in an impl for the type `Foo<T, T, u8>`
--> $DIR/impl_params_are_infers.rs:11:5
|
LL | type IAT = u8;
| ^^^^^^^^
note: candidate #2 is defined in an impl for the type `Foo<T, U, u16>`
--> $DIR/impl_params_are_infers.rs:15:5
|
LL | type IAT = u16;
| ^^^^^^^^
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0034`.