Test whether we use DeepRejectCtxt
This commit is contained in:
parent
442862bc78
commit
2a950b5637
3 changed files with 62 additions and 4 deletions
|
|
@ -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)
|
||||
})
|
||||
|
|
|
|||
34
tests/ui/associated-inherent-types/impl_params_are_infers.rs
Normal file
34
tests/ui/associated-inherent-types/impl_params_are_infers.rs
Normal 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() {}
|
||||
|
|
@ -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`.
|
||||
Loading…
Add table
Add a link
Reference in a new issue