mirror of
				https://github.com/rust-lang/rust.git
				synced 2025-10-31 13:04:42 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			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() {
 | |
| }
 | 
