#![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() { }