| //@ revisions: current next | |
| //@[next] compile-flags: -Znext-solver | |
| //@[next] check-pass | |
| // An annoying edge case of method selection. While computing the deref-chain | |
| // constrains `T` to `u32`, the final method candidate does not and instead | |
| // constrains to `i32`. In this case, we no longer check that the opaque | |
| // remains unconstrained. Both method calls in this test constrain the opaque | |
| // to `i32`. | |
| use std::ops::Deref; | |
| struct Foo<T, U>(T, U); | |
| impl<U> Deref for Foo<u32, U> { | |
| type Target = U; | |
| fn deref(&self) -> &Self::Target { | |
| &self.1 | |
| } | |
| } | |
| impl Foo<i32, i32> { | |
| fn method(&self) {} | |
| } | |
| fn inherent_method() -> impl Sized { | |
| if false { | |
| let x = Foo(Default::default(), inherent_method()); | |
| x.method(); | |
| let _: Foo<i32, _> = x; // Test that we did not apply the deref step | |
| } | |
| 1i32 | |
| } | |
| trait Trait { | |
| fn trait_method(&self) {} | |
| } | |
| impl Trait for Foo<i32, i32> {} | |
| impl Trait for i32 {} | |
| fn trait_method() -> impl Trait { | |
| if false { | |
| let x = Foo(Default::default(), trait_method()); | |
| x.trait_method(); | |
| let _: Foo<i32, _> = x; // Test that we did not apply the deref step | |
| //[current]~^ ERROR mismatched types | |
| } | |
| 1i32 | |
| } | |
| fn main() {} |