about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/test/ui/methods/method-deref-to-same-trait-object-with-separate-params.rs177
-rw-r--r--src/test/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr72
-rw-r--r--src/test/ui/methods/method-trait-object-with-hrtb.rs41
3 files changed, 290 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 00000000000..a5dae1c71cd
--- /dev/null
+++ b/src/test/ui/methods/method-deref-to-same-trait-object-with-separate-params.rs
@@ -0,0 +1,177 @@
+#![feature(arbitrary_self_types, coerce_unsized, dispatch_from_dyn, unsize, unsized_locals)]
+
+// 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() {
+}
diff --git a/src/test/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr b/src/test/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr
new file mode 100644
index 00000000000..2d8449b96de
--- /dev/null
+++ b/src/test/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr
@@ -0,0 +1,72 @@
+error[E0308]: mismatched types
+  --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:85:24
+   |
+LL |     let _seetype: () = z; //~ ERROR mismatched types
+   |                        ^ expected (), found u32
+   |
+   = note: expected type `()`
+              found type `u32`
+
+error[E0308]: mismatched types
+  --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:102:24
+   |
+LL |     let _seetype: () = z; //~ ERROR mismatched types
+   |                        ^ expected (), found u64
+   |
+   = note: expected type `()`
+              found type `u64`
+
+error[E0034]: multiple applicable items in scope
+  --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:120:15
+   |
+LL |     let z = x.foo(); //~ ERROR multiple applicable items in scope
+   |               ^^^ multiple `foo` found
+   |
+note: candidate #1 is defined in an impl of the trait `internal::X` for the type `_`
+  --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:43:9
+   |
+LL |         fn foo(self: Smaht<Self, u64>) -> u64 {
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: candidate #2 is defined in an impl of the trait `nuisance_foo::NuisanceFoo` for the type `_`
+  --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:70:9
+   |
+LL |         fn foo(self) {}
+   |         ^^^^^^^^^^^^
+note: candidate #3 is defined in the trait `FinalFoo`
+  --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:57:5
+   |
+LL |     fn foo(&self) -> u8;
+   |     ^^^^^^^^^^^^^^^^^^^^
+   = help: to disambiguate the method call, write `FinalFoo::foo(x)` instead
+
+error[E0308]: mismatched types
+  --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:137:24
+   |
+LL |     let _seetype: () = z; //~ ERROR mismatched types
+   |                        ^ expected (), found u8
+   |
+   = note: expected type `()`
+              found type `u8`
+
+error[E0308]: mismatched types
+  --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:155:24
+   |
+LL |     let _seetype: () = z; //~ ERROR mismatched types
+   |                        ^ expected (), found u32
+   |
+   = note: expected type `()`
+              found type `u32`
+
+error[E0308]: mismatched types
+  --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:172:24
+   |
+LL |     let _seetype: () = z; //~ ERROR mismatched types
+   |                        ^ expected (), found u32
+   |
+   = note: expected type `()`
+              found type `u32`
+
+error: aborting due to 6 previous errors
+
+Some errors occurred: E0034, E0308.
+For more information about an error, try `rustc --explain E0034`.
diff --git a/src/test/ui/methods/method-trait-object-with-hrtb.rs b/src/test/ui/methods/method-trait-object-with-hrtb.rs
new file mode 100644
index 00000000000..da2f13f5a2f
--- /dev/null
+++ b/src/test/ui/methods/method-trait-object-with-hrtb.rs
@@ -0,0 +1,41 @@
+// compile-pass
+
+// Check that method probing ObjectCandidate works in the presence of
+// auto traits and/or HRTBs.
+
+mod internal {
+    pub trait MyObject<'a> {
+        type Output;
+
+        fn foo(&self) -> Self::Output;
+    }
+
+    impl<'a> MyObject<'a> for () {
+        type Output = &'a u32;
+
+        fn foo(&self) -> Self::Output { &4 }
+    }
+}
+
+fn t1(d: &dyn for<'a> internal::MyObject<'a, Output=&'a u32>) {
+    d.foo();
+}
+
+fn t2(d: &dyn internal::MyObject<'static, Output=&'static u32>) {
+    d.foo();
+}
+
+fn t3(d: &(dyn for<'a> internal::MyObject<'a, Output=&'a u32> + Sync)) {
+    d.foo();
+}
+
+fn t4(d: &(dyn internal::MyObject<'static, Output=&'static u32> + Sync)) {
+    d.foo();
+}
+
+fn main() {
+    t1(&());
+    t2(&());
+    t3(&());
+    t4(&());
+}