about summary refs log tree commit diff
diff options
context:
space:
mode:
authorlcnr <rust@lcnr.de>2025-09-24 10:28:52 +0200
committerlcnr <rust@lcnr.de>2025-09-26 16:33:15 +0200
commitd6fe5334185385372d1fe8f1c9df8f5d3e7be788 (patch)
tree98f249cd6443822421971e6fa1e6bbbba9ed4fb8
parenteebf871feaca10886f80a76a36b3771e960c047e (diff)
downloadrust-d6fe5334185385372d1fe8f1c9df8f5d3e7be788.tar.gz
rust-d6fe5334185385372d1fe8f1c9df8f5d3e7be788.zip
add tests
-rw-r--r--tests/ui/impl-trait/method/broken-deref-chain.current.stderr19
-rw-r--r--tests/ui/impl-trait/method/broken-deref-chain.rs47
-rw-r--r--tests/ui/impl-trait/method/would-constrain-opaque.current.stderr29
-rw-r--r--tests/ui/impl-trait/method/would-constrain-opaque.next.stderr27
-rw-r--r--tests/ui/impl-trait/method/would-constrain-opaque.rs39
5 files changed, 161 insertions, 0 deletions
diff --git a/tests/ui/impl-trait/method/broken-deref-chain.current.stderr b/tests/ui/impl-trait/method/broken-deref-chain.current.stderr
new file mode 100644
index 00000000000..726f076b183
--- /dev/null
+++ b/tests/ui/impl-trait/method/broken-deref-chain.current.stderr
@@ -0,0 +1,19 @@
+error[E0308]: mismatched types
+  --> $DIR/broken-deref-chain.rs:41:30
+   |
+LL | fn trait_method() -> impl Trait {
+   |                      ---------- the found opaque type
+...
+LL |         x.trait_method();
+   |         - here the type of `x` is inferred to be `Foo<u32, impl Trait>`
+LL |         let _: Foo<i32, _> = x; // Test that we did not apply the deref step
+   |                -----------   ^ expected `Foo<i32, _>`, found `Foo<u32, impl Trait>`
+   |                |
+   |                expected due to this
+   |
+   = note: expected struct `Foo<i32, _>`
+              found struct `Foo<u32, impl Trait>`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/impl-trait/method/broken-deref-chain.rs b/tests/ui/impl-trait/method/broken-deref-chain.rs
new file mode 100644
index 00000000000..8b45e044f43
--- /dev/null
+++ b/tests/ui/impl-trait/method/broken-deref-chain.rs
@@ -0,0 +1,47 @@
+//@ 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() {}
diff --git a/tests/ui/impl-trait/method/would-constrain-opaque.current.stderr b/tests/ui/impl-trait/method/would-constrain-opaque.current.stderr
new file mode 100644
index 00000000000..60533a39c53
--- /dev/null
+++ b/tests/ui/impl-trait/method/would-constrain-opaque.current.stderr
@@ -0,0 +1,29 @@
+error[E0599]: no method named `method` found for reference `&impl Sized` in the current scope
+  --> $DIR/would-constrain-opaque.rs:28:11
+   |
+LL |         x.method();
+   |           ^^^^^^ method not found in `&impl Sized`
+   |
+   = help: items from traits can only be used if the trait is implemented and in scope
+note: `Trait` defines an item `method`, perhaps you need to implement it
+  --> $DIR/would-constrain-opaque.rs:15:1
+   |
+LL | trait Trait: Sized {
+   | ^^^^^^^^^^^^^^^^^^
+
+error[E0599]: no method named `method` found for reference `&impl Sized` in the current scope
+  --> $DIR/would-constrain-opaque.rs:30:11
+   |
+LL |         x.method();
+   |           ^^^^^^ method not found in `&impl Sized`
+   |
+   = help: items from traits can only be used if the trait is implemented and in scope
+note: `Trait` defines an item `method`, perhaps you need to implement it
+  --> $DIR/would-constrain-opaque.rs:15:1
+   |
+LL | trait Trait: Sized {
+   | ^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/impl-trait/method/would-constrain-opaque.next.stderr b/tests/ui/impl-trait/method/would-constrain-opaque.next.stderr
new file mode 100644
index 00000000000..23a4ceb826a
--- /dev/null
+++ b/tests/ui/impl-trait/method/would-constrain-opaque.next.stderr
@@ -0,0 +1,27 @@
+error[E0599]: no method named `method` found for reference `&_` in the current scope
+  --> $DIR/would-constrain-opaque.rs:28:11
+   |
+LL |         x.method();
+   |           ^^^^^^ method not found in `&_`
+   |
+   = help: items from traits can only be used if the trait is implemented and in scope
+help: trait `Trait` which provides `method` is implemented but not in scope; perhaps you want to import it
+   |
+LL + use Trait;
+   |
+
+error[E0599]: no method named `method` found for reference `&_` in the current scope
+  --> $DIR/would-constrain-opaque.rs:30:11
+   |
+LL |         x.method();
+   |           ^^^^^^ method not found in `&_`
+   |
+   = help: items from traits can only be used if the trait is implemented and in scope
+help: trait `Trait` which provides `method` is implemented but not in scope; perhaps you want to import it
+   |
+LL + use Trait;
+   |
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/impl-trait/method/would-constrain-opaque.rs b/tests/ui/impl-trait/method/would-constrain-opaque.rs
new file mode 100644
index 00000000000..8dd32282529
--- /dev/null
+++ b/tests/ui/impl-trait/method/would-constrain-opaque.rs
@@ -0,0 +1,39 @@
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
+
+// If we don't treat `impl Sized` as rigid, the first call would
+// resolve to the trait method, constraining the opaque, while the
+// second call would resolve to the inherent method.
+//
+// We avoid cases like this by rejecting candidates which constrain
+// opaque types encountered in the autoderef chain.
+//
+// FIXME(-Znext-solver): ideally we would note that the inference variable
+// is an opaque type in the error message and change this to a type annotations
+// needed error.
+
+trait Trait: Sized {
+    fn method(self) {}
+}
+impl Trait for &Foo {}
+
+struct Foo;
+impl Foo {
+    fn method(&self) {}
+}
+
+fn define_opaque(b: bool) -> impl Sized {
+    if b {
+        let x = &define_opaque(false);
+        x.method();
+        //~^ ERROR no method named `method` found for reference
+        x.method();
+        //~^ ERROR no method named `method` found for reference
+    }
+
+    Foo
+}
+
+fn main() {
+    define_opaque(true);
+}