]> git.lizzy.rs Git - rust.git/blob - src/test/ui/methods/method-deref-to-same-trait-object-with-separate-params.rs
Merge commit '3e7c6dec244539970b593824334876f8b6ed0b18' into clippyup
[rust.git] / src / test / ui / methods / method-deref-to-same-trait-object-with-separate-params.rs
1 #![feature(arbitrary_self_types, coerce_unsized, dispatch_from_dyn, unsize)]
2 #![feature(unsized_locals, unsized_fn_params)]
3 //~^ WARN the feature `unsized_locals` is incomplete
4
5 // This tests a few edge-cases around `arbitrary_self_types`. Most specifically,
6 // it checks that the `ObjectCandidate` you get from method matching can't
7 // match a trait with the same DefId as a supertrait but a bad type parameter.
8
9 use std::marker::PhantomData;
10
11 mod internal {
12     use std::ops::{CoerceUnsized, Deref, DispatchFromDyn};
13     use std::marker::{PhantomData, Unsize};
14
15     pub struct Smaht<T: ?Sized, MISC>(pub Box<T>, pub PhantomData<MISC>);
16
17     impl<T: ?Sized, MISC> Deref for Smaht<T, MISC> {
18         type Target = T;
19
20         fn deref(&self) -> &Self::Target {
21             &self.0
22         }
23     }
24     impl<T: ?Sized + Unsize<U>, U: ?Sized, MISC> CoerceUnsized<Smaht<U, MISC>>
25         for Smaht<T, MISC>
26     {}
27     impl<T: ?Sized + Unsize<U>, U: ?Sized, MISC> DispatchFromDyn<Smaht<U, MISC>>
28         for Smaht<T, MISC>
29     {}
30
31     pub trait Foo: X<u32> {}
32     pub trait X<T> {
33         fn foo(self: Smaht<Self, T>) -> T;
34     }
35
36     impl X<u32> for () {
37         fn foo(self: Smaht<Self, u32>) -> u32 {
38             0
39         }
40     }
41
42     pub trait Marker {}
43     impl Marker for dyn Foo {}
44     impl<T: Marker + ?Sized> X<u64> for T {
45         fn foo(self: Smaht<Self, u64>) -> u64 {
46             1
47         }
48     }
49
50     impl Deref for dyn Foo {
51         type Target = ();
52         fn deref(&self) -> &() { &() }
53     }
54
55     impl Foo for () {}
56 }
57
58 pub trait FinalFoo {
59     fn foo(&self) -> u8;
60 }
61
62 impl FinalFoo for () {
63     fn foo(&self) -> u8 { 0 }
64 }
65
66 mod nuisance_foo {
67     pub trait NuisanceFoo {
68         fn foo(self);
69     }
70
71     impl<T: ?Sized> NuisanceFoo for T {
72         fn foo(self) {}
73     }
74 }
75
76
77 fn objectcandidate_impl() {
78     let x: internal::Smaht<(), u32> = internal::Smaht(Box::new(()), PhantomData);
79     let x: internal::Smaht<dyn internal::Foo, u32> = x;
80
81     // This picks `<dyn internal::Foo as X<u32>>::foo` via `ObjectCandidate`.
82     //
83     // The `TraitCandidate` is not relevant because `X` is not in scope.
84     let z = x.foo();
85
86     // Observe the type of `z` is `u32`
87     let _seetype: () = z; //~ ERROR mismatched types
88     //~| expected `()`, found `u32`
89 }
90
91 fn traitcandidate_impl() {
92     use internal::X;
93
94     let x: internal::Smaht<(), u64> = internal::Smaht(Box::new(()), PhantomData);
95     let x: internal::Smaht<dyn internal::Foo, u64> = x;
96
97     // This picks `<dyn internal::Foo as X<u64>>::foo` via `TraitCandidate`.
98     //
99     // The `ObjectCandidate` does not apply, as it only applies to
100     // `X<u32>` (and not `X<u64>`).
101     let z = x.foo();
102
103     // Observe the type of `z` is `u64`
104     let _seetype: () = z; //~ ERROR mismatched types
105     //~| expected `()`, found `u64`
106 }
107
108 fn traitcandidate_impl_with_nuisance() {
109     use internal::X;
110     use nuisance_foo::NuisanceFoo;
111
112     let x: internal::Smaht<(), u64> = internal::Smaht(Box::new(()), PhantomData);
113     let x: internal::Smaht<dyn internal::Foo, u64> = x;
114
115     // This picks `<dyn internal::Foo as X<u64>>::foo` via `TraitCandidate`.
116     //
117     // The `ObjectCandidate` does not apply, as it only applies to
118     // `X<u32>` (and not `X<u64>`).
119     //
120     // The NuisanceFoo impl has the same priority as the `X` impl,
121     // so we get a conflict.
122     let z = x.foo(); //~ ERROR multiple applicable items in scope
123 }
124
125
126 fn neither_impl() {
127     let x: internal::Smaht<(), u64> = internal::Smaht(Box::new(()), PhantomData);
128     let x: internal::Smaht<dyn internal::Foo, u64> = x;
129
130     // This can't pick the `TraitCandidate` impl, because `Foo` is not
131     // imported. However, this also can't pick the `ObjectCandidate`
132     // impl, because it only applies to `X<u32>` (and not `X<u64>`).
133     //
134     // Therefore, neither of the candidates is applicable, and we pick
135     // the `FinalFoo` impl after another deref, which will return `u8`.
136     let z = x.foo();
137
138     // Observe the type of `z` is `u8`
139     let _seetype: () = z; //~ ERROR mismatched types
140     //~| expected `()`, found `u8`
141 }
142
143 fn both_impls() {
144     use internal::X;
145
146     let x: internal::Smaht<(), u32> = internal::Smaht(Box::new(()), PhantomData);
147     let x: internal::Smaht<dyn internal::Foo, u32> = x;
148
149     // This can pick both the `TraitCandidate` and the `ObjectCandidate` impl.
150     //
151     // However, the `ObjectCandidate` is considered an "inherent candidate",
152     // and therefore has priority over both the `TraitCandidate` as well as
153     // any other "nuisance" candidate" (if present).
154     let z = x.foo();
155
156     // Observe the type of `z` is `u32`
157     let _seetype: () = z; //~ ERROR mismatched types
158     //~| expected `()`, found `u32`
159 }
160
161
162 fn both_impls_with_nuisance() {
163     // Similar to the `both_impls` example, except with a nuisance impl to
164     // make sure the `ObjectCandidate` indeed has a higher priority.
165
166     use internal::X;
167     use nuisance_foo::NuisanceFoo;
168
169     let x: internal::Smaht<(), u32> = internal::Smaht(Box::new(()), PhantomData);
170     let x: internal::Smaht<dyn internal::Foo, u32> = x;
171     let z = x.foo();
172
173     // Observe the type of `z` is `u32`
174     let _seetype: () = z; //~ ERROR mismatched types
175     //~| expected `()`, found `u32`
176 }
177
178 fn main() {
179 }