mirror of https://github.com/rust-lang/rust
180 lines
5.1 KiB
Rust
180 lines
5.1 KiB
Rust
#![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() {
|
|
}
|