summaryrefslogtreecommitdiffstats
path: root/src/test/ui/methods/method-deref-to-same-trait-object-with-separate-params.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:02:58 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:02:58 +0000
commit698f8c2f01ea549d77d7dc3338a12e04c11057b9 (patch)
tree173a775858bd501c378080a10dca74132f05bc50 /src/test/ui/methods/method-deref-to-same-trait-object-with-separate-params.rs
parentInitial commit. (diff)
downloadrustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.tar.xz
rustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.zip
Adding upstream version 1.64.0+dfsg1.upstream/1.64.0+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/test/ui/methods/method-deref-to-same-trait-object-with-separate-params.rs')
-rw-r--r--src/test/ui/methods/method-deref-to-same-trait-object-with-separate-params.rs179
1 files changed, 179 insertions, 0 deletions
diff --git a/src/test/ui/methods/method-deref-to-same-trait-object-with-separate-params.rs b/src/test/ui/methods/method-deref-to-same-trait-object-with-separate-params.rs
new file mode 100644
index 000000000..9e53ff079
--- /dev/null
+++ b/src/test/ui/methods/method-deref-to-same-trait-object-with-separate-params.rs
@@ -0,0 +1,179 @@
+#![feature(arbitrary_self_types, coerce_unsized, dispatch_from_dyn, unsize)]
+#![feature(unsized_locals, unsized_fn_params)]
+//~^ WARN the feature `unsized_locals` is incomplete
+
+// This tests a few edge-cases around `arbitrary_self_types`. Most specifically,
+// it checks that the `ObjectCandidate` you get from method matching can't
+// match a trait with the same DefId as a supertrait but a bad type parameter.
+
+use std::marker::PhantomData;
+
+mod internal {
+ use std::ops::{CoerceUnsized, Deref, DispatchFromDyn};
+ use std::marker::{PhantomData, Unsize};
+
+ pub struct Smaht<T: ?Sized, MISC>(pub Box<T>, pub PhantomData<MISC>);
+
+ impl<T: ?Sized, MISC> Deref for Smaht<T, MISC> {
+ type Target = T;
+
+ fn deref(&self) -> &Self::Target {
+ &self.0
+ }
+ }
+ impl<T: ?Sized + Unsize<U>, U: ?Sized, MISC> CoerceUnsized<Smaht<U, MISC>>
+ for Smaht<T, MISC>
+ {}
+ impl<T: ?Sized + Unsize<U>, U: ?Sized, MISC> DispatchFromDyn<Smaht<U, MISC>>
+ for Smaht<T, MISC>
+ {}
+
+ pub trait Foo: X<u32> {}
+ pub trait X<T> {
+ fn foo(self: Smaht<Self, T>) -> T;
+ }
+
+ impl X<u32> for () {
+ fn foo(self: Smaht<Self, u32>) -> u32 {
+ 0
+ }
+ }
+
+ pub trait Marker {}
+ impl Marker for dyn Foo {}
+ impl<T: Marker + ?Sized> X<u64> for T {
+ fn foo(self: Smaht<Self, u64>) -> u64 {
+ 1
+ }
+ }
+
+ impl Deref for dyn Foo {
+ type Target = ();
+ fn deref(&self) -> &() { &() }
+ }
+
+ impl Foo for () {}
+}
+
+pub trait FinalFoo {
+ fn foo(&self) -> u8;
+}
+
+impl FinalFoo for () {
+ fn foo(&self) -> u8 { 0 }
+}
+
+mod nuisance_foo {
+ pub trait NuisanceFoo {
+ fn foo(self);
+ }
+
+ impl<T: ?Sized> NuisanceFoo for T {
+ fn foo(self) {}
+ }
+}
+
+
+fn objectcandidate_impl() {
+ let x: internal::Smaht<(), u32> = internal::Smaht(Box::new(()), PhantomData);
+ let x: internal::Smaht<dyn internal::Foo, u32> = x;
+
+ // This picks `<dyn internal::Foo as X<u32>>::foo` via `ObjectCandidate`.
+ //
+ // The `TraitCandidate` is not relevant because `X` is not in scope.
+ let z = x.foo();
+
+ // Observe the type of `z` is `u32`
+ let _seetype: () = z; //~ ERROR mismatched types
+ //~| expected `()`, found `u32`
+}
+
+fn traitcandidate_impl() {
+ use internal::X;
+
+ let x: internal::Smaht<(), u64> = internal::Smaht(Box::new(()), PhantomData);
+ let x: internal::Smaht<dyn internal::Foo, u64> = x;
+
+ // This picks `<dyn internal::Foo as X<u64>>::foo` via `TraitCandidate`.
+ //
+ // The `ObjectCandidate` does not apply, as it only applies to
+ // `X<u32>` (and not `X<u64>`).
+ let z = x.foo();
+
+ // Observe the type of `z` is `u64`
+ let _seetype: () = z; //~ ERROR mismatched types
+ //~| expected `()`, found `u64`
+}
+
+fn traitcandidate_impl_with_nuisance() {
+ use internal::X;
+ use nuisance_foo::NuisanceFoo;
+
+ let x: internal::Smaht<(), u64> = internal::Smaht(Box::new(()), PhantomData);
+ let x: internal::Smaht<dyn internal::Foo, u64> = x;
+
+ // This picks `<dyn internal::Foo as X<u64>>::foo` via `TraitCandidate`.
+ //
+ // The `ObjectCandidate` does not apply, as it only applies to
+ // `X<u32>` (and not `X<u64>`).
+ //
+ // The NuisanceFoo impl has the same priority as the `X` impl,
+ // so we get a conflict.
+ let z = x.foo(); //~ ERROR multiple applicable items in scope
+}
+
+
+fn neither_impl() {
+ let x: internal::Smaht<(), u64> = internal::Smaht(Box::new(()), PhantomData);
+ let x: internal::Smaht<dyn internal::Foo, u64> = x;
+
+ // This can't pick the `TraitCandidate` impl, because `Foo` is not
+ // imported. However, this also can't pick the `ObjectCandidate`
+ // impl, because it only applies to `X<u32>` (and not `X<u64>`).
+ //
+ // Therefore, neither of the candidates is applicable, and we pick
+ // the `FinalFoo` impl after another deref, which will return `u8`.
+ let z = x.foo();
+
+ // Observe the type of `z` is `u8`
+ let _seetype: () = z; //~ ERROR mismatched types
+ //~| expected `()`, found `u8`
+}
+
+fn both_impls() {
+ use internal::X;
+
+ let x: internal::Smaht<(), u32> = internal::Smaht(Box::new(()), PhantomData);
+ let x: internal::Smaht<dyn internal::Foo, u32> = x;
+
+ // This can pick both the `TraitCandidate` and the `ObjectCandidate` impl.
+ //
+ // However, the `ObjectCandidate` is considered an "inherent candidate",
+ // and therefore has priority over both the `TraitCandidate` as well as
+ // any other "nuisance" candidate" (if present).
+ let z = x.foo();
+
+ // Observe the type of `z` is `u32`
+ let _seetype: () = z; //~ ERROR mismatched types
+ //~| expected `()`, found `u32`
+}
+
+
+fn both_impls_with_nuisance() {
+ // Similar to the `both_impls` example, except with a nuisance impl to
+ // make sure the `ObjectCandidate` indeed has a higher priority.
+
+ use internal::X;
+ use nuisance_foo::NuisanceFoo;
+
+ let x: internal::Smaht<(), u32> = internal::Smaht(Box::new(()), PhantomData);
+ let x: internal::Smaht<dyn internal::Foo, u32> = x;
+ let z = x.foo();
+
+ // Observe the type of `z` is `u32`
+ let _seetype: () = z; //~ ERROR mismatched types
+ //~| expected `()`, found `u32`
+}
+
+fn main() {
+}