From 698f8c2f01ea549d77d7dc3338a12e04c11057b9 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 17 Apr 2024 14:02:58 +0200 Subject: Adding upstream version 1.64.0+dfsg1. Signed-off-by: Daniel Baumann --- ...ef-to-same-trait-object-with-separate-params.rs | 179 +++++++++++++++++++++ 1 file changed, 179 insertions(+) create mode 100644 src/test/ui/methods/method-deref-to-same-trait-object-with-separate-params.rs (limited to 'src/test/ui/methods/method-deref-to-same-trait-object-with-separate-params.rs') 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 000000000..9e53ff079 --- /dev/null +++ b/src/test/ui/methods/method-deref-to-same-trait-object-with-separate-params.rs @@ -0,0 +1,179 @@ +#![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(pub Box, pub PhantomData); + + impl Deref for Smaht { + type Target = T; + + fn deref(&self) -> &Self::Target { + &self.0 + } + } + impl, U: ?Sized, MISC> CoerceUnsized> + for Smaht + {} + impl, U: ?Sized, MISC> DispatchFromDyn> + for Smaht + {} + + pub trait Foo: X {} + pub trait X { + fn foo(self: Smaht) -> T; + } + + impl X for () { + fn foo(self: Smaht) -> u32 { + 0 + } + } + + pub trait Marker {} + impl Marker for dyn Foo {} + impl X for T { + fn foo(self: Smaht) -> 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 NuisanceFoo for T { + fn foo(self) {} + } +} + + +fn objectcandidate_impl() { + let x: internal::Smaht<(), u32> = internal::Smaht(Box::new(()), PhantomData); + let x: internal::Smaht = x; + + // This picks `>::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 = x; + + // This picks `>::foo` via `TraitCandidate`. + // + // The `ObjectCandidate` does not apply, as it only applies to + // `X` (and not `X`). + 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 = x; + + // This picks `>::foo` via `TraitCandidate`. + // + // The `ObjectCandidate` does not apply, as it only applies to + // `X` (and not `X`). + // + // 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 = 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` (and not `X`). + // + // 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 = 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 = x; + let z = x.foo(); + + // Observe the type of `z` is `u32` + let _seetype: () = z; //~ ERROR mismatched types + //~| expected `()`, found `u32` +} + +fn main() { +} -- cgit v1.2.3