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 --- src/test/ui/traits/object/auto-dedup-in-impl.rs | 19 ++++ .../ui/traits/object/auto-dedup-in-impl.stderr | 12 +++ src/test/ui/traits/object/auto-dedup.rs | 46 +++++++++ src/test/ui/traits/object/bounds-cycle-1.rs | 24 +++++ src/test/ui/traits/object/bounds-cycle-2.rs | 28 ++++++ src/test/ui/traits/object/bounds-cycle-3.rs | 25 +++++ src/test/ui/traits/object/bounds-cycle-4.rs | 25 +++++ .../traits/object/enforce-supertrait-projection.rs | 24 +++++ .../object/enforce-supertrait-projection.stderr | 26 +++++ src/test/ui/traits/object/exclusion.rs | 19 ++++ src/test/ui/traits/object/generics.rs | 41 ++++++++ .../traits/object/issue-33140-traitobject-crate.rs | 108 +++++++++++++++++++++ .../object/issue-33140-traitobject-crate.stderr | 42 ++++++++ src/test/ui/traits/object/lifetime-first.rs | 13 +++ src/test/ui/traits/object/macro-matcher.rs | 12 +++ src/test/ui/traits/object/macro-matcher.stderr | 19 ++++ src/test/ui/traits/object/safety.rs | 17 ++++ src/test/ui/traits/object/safety.stderr | 49 ++++++++++ .../ui/traits/object/supertrait-lifetime-bound.rs | 14 +++ .../traits/object/supertrait-lifetime-bound.stderr | 11 +++ src/test/ui/traits/object/vs-lifetime-2.rs | 11 +++ src/test/ui/traits/object/vs-lifetime-2.stderr | 9 ++ src/test/ui/traits/object/vs-lifetime.rs | 17 ++++ src/test/ui/traits/object/vs-lifetime.stderr | 52 ++++++++++ src/test/ui/traits/object/with-lifetime-bound.rs | 34 +++++++ .../object/with-self-in-projection-output-bad.rs | 50 ++++++++++ .../with-self-in-projection-output-bad.stderr | 21 ++++ .../object/with-self-in-projection-output-good.rs | 28 ++++++ ...elf-in-projection-output-repeated-supertrait.rs | 51 ++++++++++ 29 files changed, 847 insertions(+) create mode 100644 src/test/ui/traits/object/auto-dedup-in-impl.rs create mode 100644 src/test/ui/traits/object/auto-dedup-in-impl.stderr create mode 100644 src/test/ui/traits/object/auto-dedup.rs create mode 100644 src/test/ui/traits/object/bounds-cycle-1.rs create mode 100644 src/test/ui/traits/object/bounds-cycle-2.rs create mode 100644 src/test/ui/traits/object/bounds-cycle-3.rs create mode 100644 src/test/ui/traits/object/bounds-cycle-4.rs create mode 100644 src/test/ui/traits/object/enforce-supertrait-projection.rs create mode 100644 src/test/ui/traits/object/enforce-supertrait-projection.stderr create mode 100644 src/test/ui/traits/object/exclusion.rs create mode 100644 src/test/ui/traits/object/generics.rs create mode 100644 src/test/ui/traits/object/issue-33140-traitobject-crate.rs create mode 100644 src/test/ui/traits/object/issue-33140-traitobject-crate.stderr create mode 100644 src/test/ui/traits/object/lifetime-first.rs create mode 100644 src/test/ui/traits/object/macro-matcher.rs create mode 100644 src/test/ui/traits/object/macro-matcher.stderr create mode 100644 src/test/ui/traits/object/safety.rs create mode 100644 src/test/ui/traits/object/safety.stderr create mode 100644 src/test/ui/traits/object/supertrait-lifetime-bound.rs create mode 100644 src/test/ui/traits/object/supertrait-lifetime-bound.stderr create mode 100644 src/test/ui/traits/object/vs-lifetime-2.rs create mode 100644 src/test/ui/traits/object/vs-lifetime-2.stderr create mode 100644 src/test/ui/traits/object/vs-lifetime.rs create mode 100644 src/test/ui/traits/object/vs-lifetime.stderr create mode 100644 src/test/ui/traits/object/with-lifetime-bound.rs create mode 100644 src/test/ui/traits/object/with-self-in-projection-output-bad.rs create mode 100644 src/test/ui/traits/object/with-self-in-projection-output-bad.stderr create mode 100644 src/test/ui/traits/object/with-self-in-projection-output-good.rs create mode 100644 src/test/ui/traits/object/with-self-in-projection-output-repeated-supertrait.rs (limited to 'src/test/ui/traits/object') diff --git a/src/test/ui/traits/object/auto-dedup-in-impl.rs b/src/test/ui/traits/object/auto-dedup-in-impl.rs new file mode 100644 index 000000000..85698f194 --- /dev/null +++ b/src/test/ui/traits/object/auto-dedup-in-impl.rs @@ -0,0 +1,19 @@ +// Checks to make sure that `dyn Trait + Send` and `dyn Trait + Send + Send` are the same type. +// Issue: #47010 + +struct Struct; +impl Trait for Struct {} +trait Trait {} + +type Send1 = dyn Trait + Send; +type Send2 = dyn Trait + Send + Send; + +fn main () {} + +impl dyn Trait + Send { + fn test(&self) { println!("one"); } //~ ERROR duplicate definitions with name `test` +} + +impl dyn Trait + Send + Send { + fn test(&self) { println!("two"); } +} diff --git a/src/test/ui/traits/object/auto-dedup-in-impl.stderr b/src/test/ui/traits/object/auto-dedup-in-impl.stderr new file mode 100644 index 000000000..5f13c7813 --- /dev/null +++ b/src/test/ui/traits/object/auto-dedup-in-impl.stderr @@ -0,0 +1,12 @@ +error[E0592]: duplicate definitions with name `test` + --> $DIR/auto-dedup-in-impl.rs:14:5 + | +LL | fn test(&self) { println!("one"); } + | ^^^^^^^^^^^^^^ duplicate definitions for `test` +... +LL | fn test(&self) { println!("two"); } + | -------------- other definition for `test` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0592`. diff --git a/src/test/ui/traits/object/auto-dedup.rs b/src/test/ui/traits/object/auto-dedup.rs new file mode 100644 index 000000000..39d25eb7f --- /dev/null +++ b/src/test/ui/traits/object/auto-dedup.rs @@ -0,0 +1,46 @@ +// run-pass + +#![allow(unused_assignments)] + +// Test that duplicate auto trait bounds in trait objects don't create new types. +#[allow(unused_assignments)] +use std::marker::Send as SendAlias; + +// A dummy trait for the non-auto trait. +trait Trait {} + +// A dummy struct to implement `Trait` and `Send`. +struct Struct; + +impl Trait for Struct {} + +// These three functions should be equivalent. +fn takes_dyn_trait_send(_: Box) {} +fn takes_dyn_trait_send_send(_: Box) {} +fn takes_dyn_trait_send_sendalias(_: Box) {} + +impl dyn Trait + Send + Send { + fn do_nothing(&self) {} +} + +fn main() { + // 1. Moving into a variable with more `Send`s and back. + let mut dyn_trait_send = Box::new(Struct) as Box; + let dyn_trait_send_send: Box = dyn_trait_send; + dyn_trait_send = dyn_trait_send_send; + + // 2. Calling methods with different number of `Send`s. + let dyn_trait_send = Box::new(Struct) as Box; + takes_dyn_trait_send_send(dyn_trait_send); + + let dyn_trait_send_send = Box::new(Struct) as Box; + takes_dyn_trait_send(dyn_trait_send_send); + + // 3. Aliases to the trait are transparent. + let dyn_trait_send = Box::new(Struct) as Box; + takes_dyn_trait_send_sendalias(dyn_trait_send); + + // 4. Calling an impl that duplicates an auto trait. + let dyn_trait_send = Box::new(Struct) as Box; + dyn_trait_send.do_nothing(); +} diff --git a/src/test/ui/traits/object/bounds-cycle-1.rs b/src/test/ui/traits/object/bounds-cycle-1.rs new file mode 100644 index 000000000..314676492 --- /dev/null +++ b/src/test/ui/traits/object/bounds-cycle-1.rs @@ -0,0 +1,24 @@ +// Check that we don't have a cycle when we try to normalize `Self::U` in the +// bound below. + +// check-pass + +trait Is { + type T; +} + +impl Is for U { + type T = U; +} + +trait Obj { + type U: Is; +} + +fn is_obj(_: &T) {} + +fn f(x: &dyn Obj) { + is_obj(x) +} + +fn main() {} diff --git a/src/test/ui/traits/object/bounds-cycle-2.rs b/src/test/ui/traits/object/bounds-cycle-2.rs new file mode 100644 index 000000000..4c1df3805 --- /dev/null +++ b/src/test/ui/traits/object/bounds-cycle-2.rs @@ -0,0 +1,28 @@ +// Check that we don't have a cycle when we try to normalize `Self::V` in the +// bound below. + +// check-pass + +trait Is { + type T; +} + +impl Is for U { + type T = U; +} + +trait Super { + type V; +} + +trait Obj: Super { + type U: Is; +} + +fn is_obj(_: &T) {} + +fn f(x: &dyn Obj) { + is_obj(x) +} + +fn main() {} diff --git a/src/test/ui/traits/object/bounds-cycle-3.rs b/src/test/ui/traits/object/bounds-cycle-3.rs new file mode 100644 index 000000000..55726a5ae --- /dev/null +++ b/src/test/ui/traits/object/bounds-cycle-3.rs @@ -0,0 +1,25 @@ +// Check that we don't have a cycle when we try to normalize `Self::V` in the +// bound below. + +// check-pass + +trait Is { + type T; +} + +impl Is for U { + type T = U; +} + +trait Obj { + type U: Is; + type V; +} + +fn is_obj(_: &T) {} + +fn f(x: &dyn Obj) { + is_obj(x) +} + +fn main() {} diff --git a/src/test/ui/traits/object/bounds-cycle-4.rs b/src/test/ui/traits/object/bounds-cycle-4.rs new file mode 100644 index 000000000..f83cb75c7 --- /dev/null +++ b/src/test/ui/traits/object/bounds-cycle-4.rs @@ -0,0 +1,25 @@ +// Check that we don't have a cycle when we try to normalize `Self::U` in the +// bound below. Make sure that having a lifetime on the trait object doesn't break things + +// check-pass + +trait Is { + type T; +} + +impl Is for U { + type T = U; +} + +trait Obj<'a> { + type U: Is; + type V; +} + +fn is_obj<'a, T: ?Sized + Obj<'a>>(_: &T) {} + +fn f<'a>(x: &dyn Obj<'a, U = i32, V = i32>) { + is_obj(x) +} + +fn main() {} diff --git a/src/test/ui/traits/object/enforce-supertrait-projection.rs b/src/test/ui/traits/object/enforce-supertrait-projection.rs new file mode 100644 index 000000000..2c9b41eea --- /dev/null +++ b/src/test/ui/traits/object/enforce-supertrait-projection.rs @@ -0,0 +1,24 @@ +trait SuperTrait { + type A; + type B; +} + +trait Trait: SuperTrait::B> {} + +fn transmute(x: A) -> B { + foo::>(x) + //~^ ERROR type mismatch resolving ` as SuperTrait>::A == B` +} + +fn foo(x: T::A) -> B +where + T: Trait, +{ + x +} + +static X: u8 = 0; +fn main() { + let x = transmute::<&u8, &[u8; 1_000_000]>(&X); + println!("{:?}", x[100_000]); +} diff --git a/src/test/ui/traits/object/enforce-supertrait-projection.stderr b/src/test/ui/traits/object/enforce-supertrait-projection.stderr new file mode 100644 index 000000000..eab42ca56 --- /dev/null +++ b/src/test/ui/traits/object/enforce-supertrait-projection.stderr @@ -0,0 +1,26 @@ +error[E0271]: type mismatch resolving ` as SuperTrait>::A == B` + --> $DIR/enforce-supertrait-projection.rs:9:5 + | +LL | fn transmute(x: A) -> B { + | - - expected type parameter + | | + | found type parameter +LL | foo::>(x) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected type parameter `B`, found type parameter `A` + | + = note: expected type parameter `B` + found type parameter `A` + = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound + = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters +note: required by a bound in `foo` + --> $DIR/enforce-supertrait-projection.rs:15:8 + | +LL | fn foo(x: T::A) -> B + | --- required by a bound in this +LL | where +LL | T: Trait, + | ^^^^^^^^^^^^ required by this bound in `foo` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0271`. diff --git a/src/test/ui/traits/object/exclusion.rs b/src/test/ui/traits/object/exclusion.rs new file mode 100644 index 000000000..766dceeaf --- /dev/null +++ b/src/test/ui/traits/object/exclusion.rs @@ -0,0 +1,19 @@ +// run-pass +trait Future: 'static { + // The requirement for Self: Sized must prevent instantiation of + // Future::forget in vtables, otherwise there's an infinite type + // recursion through as Future>::forget. + fn forget(self) where Self: Sized { + Box::new(Map(self)) as Box; + } +} + +struct Map(#[allow(unused_tuple_struct_fields)] A); +impl Future for Map {} + +pub struct Promise; +impl Future for Promise {} + +fn main() { + Promise.forget(); +} diff --git a/src/test/ui/traits/object/generics.rs b/src/test/ui/traits/object/generics.rs new file mode 100644 index 000000000..5a4a6aecc --- /dev/null +++ b/src/test/ui/traits/object/generics.rs @@ -0,0 +1,41 @@ +// run-pass +// test for #8664 + +use std::marker; + +pub trait Trait2 { + fn doit(&self) -> A; +} + +pub struct Impl { + m1: marker::PhantomData<(A1,A2,A3)>, + /* + * With A2 we get the ICE: + * task failed at 'index out of bounds: the len is 1 but the index is 1', + * src/librustc/middle/subst.rs:58 + */ + t: Box+'static> +} + +impl Impl { + pub fn step(&self) { + self.t.doit(); + } +} + +// test for #8601 + +enum Type { Constant(#[allow(unused_tuple_struct_fields)] T) } + +trait Trait { + fn method(&self, _: Type<(K,V)>) -> isize; +} + +impl Trait for () { + fn method(&self, _x: Type<(u8,V)>) -> isize { 0 } +} + +pub fn main() { + let a = Box::new(()) as Box>; + assert_eq!(a.method(Type::Constant((1, 2))), 0); +} diff --git a/src/test/ui/traits/object/issue-33140-traitobject-crate.rs b/src/test/ui/traits/object/issue-33140-traitobject-crate.rs new file mode 100644 index 000000000..8abd92da3 --- /dev/null +++ b/src/test/ui/traits/object/issue-33140-traitobject-crate.rs @@ -0,0 +1,108 @@ +// check-pass + +#![warn(order_dependent_trait_objects)] +#![allow(dyn_drop)] + +// Check that traitobject 0.1.0 compiles + +//! # traitobject +//! +//! Unsafe helpers for working with raw TraitObjects. + +/// A trait implemented for all trait objects. +/// +/// Implementations for all traits in std are provided. +pub unsafe trait Trait {} + +unsafe impl Trait for dyn (::std::any::Any) + Send { } +unsafe impl Trait for dyn (::std::any::Any) + Sync { } +unsafe impl Trait for dyn (::std::any::Any) + Send + Sync { } +unsafe impl Trait for dyn (::std::borrow::Borrow) + Send { } +unsafe impl Trait for dyn (::std::borrow::Borrow) + Sync { } +unsafe impl Trait for dyn (::std::borrow::Borrow) + Send + Sync { } +unsafe impl Trait for dyn (::std::borrow::BorrowMut) + Send { } +unsafe impl Trait for dyn (::std::borrow::BorrowMut) + Sync { } +unsafe impl Trait for dyn (::std::borrow::BorrowMut) + Send + Sync { } +unsafe impl Trait for dyn (::std::convert::AsMut) + Send { } +unsafe impl Trait for dyn (::std::convert::AsMut) + Sync { } +unsafe impl Trait for dyn (::std::convert::AsMut) + Send + Sync { } +unsafe impl Trait for dyn (::std::convert::AsRef) + Send { } +unsafe impl Trait for dyn (::std::convert::AsRef) + Sync { } +unsafe impl Trait for dyn (::std::convert::AsRef) + Send + Sync { } +unsafe impl Trait for dyn (::std::error::Error) + Send { } +unsafe impl Trait for dyn (::std::error::Error) + Sync { } +unsafe impl Trait for dyn (::std::error::Error) + Send + Sync { } +unsafe impl Trait for dyn (::std::fmt::Binary) + Send { } +unsafe impl Trait for dyn (::std::fmt::Binary) + Sync { } +unsafe impl Trait for dyn (::std::fmt::Binary) + Send + Sync { } +unsafe impl Trait for dyn (::std::fmt::Debug) + Send { } +unsafe impl Trait for dyn (::std::fmt::Debug) + Sync { } +unsafe impl Trait for dyn (::std::fmt::Debug) + Send + Sync { } +unsafe impl Trait for dyn (::std::fmt::Display) + Send { } +unsafe impl Trait for dyn (::std::fmt::Display) + Sync { } +unsafe impl Trait for dyn (::std::fmt::Display) + Send + Sync { } +unsafe impl Trait for dyn (::std::fmt::LowerExp) + Send { } +unsafe impl Trait for dyn (::std::fmt::LowerExp) + Sync { } +unsafe impl Trait for dyn (::std::fmt::LowerExp) + Send + Sync { } +unsafe impl Trait for dyn (::std::fmt::LowerHex) + Send { } +unsafe impl Trait for dyn (::std::fmt::LowerHex) + Sync { } +unsafe impl Trait for dyn (::std::fmt::LowerHex) + Send + Sync { } +unsafe impl Trait for dyn (::std::fmt::Octal) + Send { } +unsafe impl Trait for dyn (::std::fmt::Octal) + Sync { } +unsafe impl Trait for dyn (::std::fmt::Octal) + Send + Sync { } +unsafe impl Trait for dyn (::std::fmt::Pointer) + Send { } +unsafe impl Trait for dyn (::std::fmt::Pointer) + Sync { } +unsafe impl Trait for dyn (::std::fmt::Pointer) + Send + Sync { } +unsafe impl Trait for dyn (::std::fmt::UpperExp) + Send { } +unsafe impl Trait for dyn (::std::fmt::UpperExp) + Sync { } +unsafe impl Trait for dyn (::std::fmt::UpperExp) + Send + Sync { } +unsafe impl Trait for dyn (::std::fmt::UpperHex) + Send { } +unsafe impl Trait for dyn (::std::fmt::UpperHex) + Sync { } +unsafe impl Trait for dyn (::std::fmt::UpperHex) + Send + Sync { } +unsafe impl Trait for dyn (::std::fmt::Write) + Send { } +unsafe impl Trait for dyn (::std::fmt::Write) + Sync { } +unsafe impl Trait for dyn (::std::fmt::Write) + Send + Sync { } +unsafe impl Trait for dyn (::std::hash::Hasher) + Send { } +unsafe impl Trait for dyn (::std::hash::Hasher) + Sync { } +unsafe impl Trait for dyn (::std::hash::Hasher) + Send + Sync { } +unsafe impl Trait for dyn (::std::io::BufRead) + Send { } +unsafe impl Trait for dyn (::std::io::BufRead) + Sync { } +unsafe impl Trait for dyn (::std::io::BufRead) + Send + Sync { } +unsafe impl Trait for dyn (::std::io::Read) + Send { } +unsafe impl Trait for dyn (::std::io::Read) + Sync { } +unsafe impl Trait for dyn (::std::io::Read) + Send + Sync { } +unsafe impl Trait for dyn (::std::io::Seek) + Send { } +unsafe impl Trait for dyn (::std::io::Seek) + Sync { } +unsafe impl Trait for dyn (::std::io::Seek) + Send + Sync { } +unsafe impl Trait for dyn (::std::io::Write) + Send { } +unsafe impl Trait for dyn (::std::io::Write) + Sync { } +unsafe impl Trait for dyn (::std::io::Write) + Send + Sync { } +unsafe impl Trait for dyn (::std::iter::IntoIterator) { } +unsafe impl Trait for dyn (::std::iter::Iterator) + Send { } +unsafe impl Trait for dyn (::std::iter::Iterator) + Sync { } +unsafe impl Trait for dyn (::std::iter::Iterator) + Send + Sync { } +unsafe impl Trait for dyn (::std::marker::Send) + Send { } +unsafe impl Trait for dyn (::std::marker::Send) + Sync { } +unsafe impl Trait for dyn (::std::marker::Send) + Send + Sync { } +//~^ WARNING conflicting implementations of trait `Trait` for type +//~| WARNING this was previously accepted by the compiler but is being phased out +unsafe impl Trait for dyn (::std::marker::Sync) + Send { } +//~^ WARNING conflicting implementations of trait `Trait` for type +//~| WARNING this was previously accepted by the compiler but is being phased out +unsafe impl Trait for dyn (::std::marker::Sync) + Sync { } +unsafe impl Trait for dyn (::std::marker::Sync) + Send + Sync { } +//~^ WARNING conflicting implementations of trait `Trait` for type +//~| WARNING this was previously accepted by the compiler but is being phased out +unsafe impl Trait for dyn (::std::ops::Drop) + Send { } +unsafe impl Trait for dyn (::std::ops::Drop) + Sync { } +unsafe impl Trait for dyn (::std::ops::Drop) + Send + Sync { } +unsafe impl Trait for dyn (::std::string::ToString) + Send { } +unsafe impl Trait for dyn (::std::string::ToString) + Sync { } +unsafe impl Trait for dyn (::std::string::ToString) + Send + Sync { } +fn assert_trait() {} + +fn main() { + assert_trait::(); + assert_trait::(); + assert_trait::(); +} diff --git a/src/test/ui/traits/object/issue-33140-traitobject-crate.stderr b/src/test/ui/traits/object/issue-33140-traitobject-crate.stderr new file mode 100644 index 000000000..77d71360b --- /dev/null +++ b/src/test/ui/traits/object/issue-33140-traitobject-crate.stderr @@ -0,0 +1,42 @@ +warning: conflicting implementations of trait `Trait` for type `(dyn std::marker::Send + std::marker::Sync + 'static)`: (E0119) + --> $DIR/issue-33140-traitobject-crate.rs:86:1 + | +LL | unsafe impl Trait for dyn (::std::marker::Send) + Sync { } + | ------------------------------------------------------ first implementation here +LL | unsafe impl Trait for dyn (::std::marker::Send) + Send + Sync { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + std::marker::Sync + 'static)` + | +note: the lint level is defined here + --> $DIR/issue-33140-traitobject-crate.rs:3:9 + | +LL | #![warn(order_dependent_trait_objects)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #56484 + +warning: conflicting implementations of trait `Trait` for type `(dyn std::marker::Send + std::marker::Sync + 'static)`: (E0119) + --> $DIR/issue-33140-traitobject-crate.rs:89:1 + | +LL | unsafe impl Trait for dyn (::std::marker::Send) + Send + Sync { } + | ------------------------------------------------------------- first implementation here +... +LL | unsafe impl Trait for dyn (::std::marker::Sync) + Send { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + std::marker::Sync + 'static)` + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #56484 + +warning: conflicting implementations of trait `Trait` for type `(dyn std::marker::Send + std::marker::Sync + 'static)`: (E0119) + --> $DIR/issue-33140-traitobject-crate.rs:93:1 + | +LL | unsafe impl Trait for dyn (::std::marker::Sync) + Send { } + | ------------------------------------------------------ first implementation here +... +LL | unsafe impl Trait for dyn (::std::marker::Sync) + Send + Sync { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + std::marker::Sync + 'static)` + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #56484 + +warning: 3 warnings emitted + diff --git a/src/test/ui/traits/object/lifetime-first.rs b/src/test/ui/traits/object/lifetime-first.rs new file mode 100644 index 000000000..33757cb7c --- /dev/null +++ b/src/test/ui/traits/object/lifetime-first.rs @@ -0,0 +1,13 @@ +// run-pass +use std::fmt::Display; + +static BYTE: u8 = 33; + +fn main() { + let x: &(dyn 'static + Display) = &BYTE; + let y: Box = Box::new(BYTE); + let xstr = format!("{}", x); + let ystr = format!("{}", y); + assert_eq!(xstr, "33"); + assert_eq!(ystr, "33"); +} diff --git a/src/test/ui/traits/object/macro-matcher.rs b/src/test/ui/traits/object/macro-matcher.rs new file mode 100644 index 000000000..910978749 --- /dev/null +++ b/src/test/ui/traits/object/macro-matcher.rs @@ -0,0 +1,12 @@ +// `ty` matcher accepts trait object types + +macro_rules! m { + ($t: ty) => ( let _: $t; ) +} + +fn main() { + m!(dyn Copy + Send + 'static); + //~^ ERROR the trait `Copy` cannot be made into an object + m!(dyn 'static + Send); + m!(dyn 'static +); //~ ERROR at least one trait is required for an object type +} diff --git a/src/test/ui/traits/object/macro-matcher.stderr b/src/test/ui/traits/object/macro-matcher.stderr new file mode 100644 index 000000000..6d1e236c0 --- /dev/null +++ b/src/test/ui/traits/object/macro-matcher.stderr @@ -0,0 +1,19 @@ +error[E0224]: at least one trait is required for an object type + --> $DIR/macro-matcher.rs:11:8 + | +LL | m!(dyn 'static +); + | ^^^^^^^^^^^^^ + +error[E0038]: the trait `Copy` cannot be made into an object + --> $DIR/macro-matcher.rs:8:8 + | +LL | m!(dyn Copy + Send + 'static); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ `Copy` cannot be made into an object + | + = note: the trait cannot be made into an object because it requires `Self: Sized` + = note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0038, E0224. +For more information about an error, try `rustc --explain E0038`. diff --git a/src/test/ui/traits/object/safety.rs b/src/test/ui/traits/object/safety.rs new file mode 100644 index 000000000..f43d332d6 --- /dev/null +++ b/src/test/ui/traits/object/safety.rs @@ -0,0 +1,17 @@ +// Check that static methods are not object-safe. + +trait Tr { + fn foo(); + fn bar(&self) { } +} + +struct St; + +impl Tr for St { + fn foo() {} +} + +fn main() { + let _: &dyn Tr = &St; //~ ERROR E0038 + //~^ ERROR E0038 +} diff --git a/src/test/ui/traits/object/safety.stderr b/src/test/ui/traits/object/safety.stderr new file mode 100644 index 000000000..cf534d984 --- /dev/null +++ b/src/test/ui/traits/object/safety.stderr @@ -0,0 +1,49 @@ +error[E0038]: the trait `Tr` cannot be made into an object + --> $DIR/safety.rs:15:22 + | +LL | let _: &dyn Tr = &St; + | ^^^ `Tr` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/safety.rs:4:8 + | +LL | trait Tr { + | -- this trait cannot be made into an object... +LL | fn foo(); + | ^^^ ...because associated function `foo` has no `self` parameter + = note: required because of the requirements on the impl of `CoerceUnsized<&dyn Tr>` for `&St` + = note: required by cast to type `&dyn Tr` +help: consider turning `foo` into a method by giving it a `&self` argument + | +LL | fn foo(&self); + | +++++ +help: alternatively, consider constraining `foo` so it does not apply to trait objects + | +LL | fn foo() where Self: Sized; + | +++++++++++++++++ + +error[E0038]: the trait `Tr` cannot be made into an object + --> $DIR/safety.rs:15:12 + | +LL | let _: &dyn Tr = &St; + | ^^^^^^^ `Tr` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/safety.rs:4:8 + | +LL | trait Tr { + | -- this trait cannot be made into an object... +LL | fn foo(); + | ^^^ ...because associated function `foo` has no `self` parameter +help: consider turning `foo` into a method by giving it a `&self` argument + | +LL | fn foo(&self); + | +++++ +help: alternatively, consider constraining `foo` so it does not apply to trait objects + | +LL | fn foo() where Self: Sized; + | +++++++++++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0038`. diff --git a/src/test/ui/traits/object/supertrait-lifetime-bound.rs b/src/test/ui/traits/object/supertrait-lifetime-bound.rs new file mode 100644 index 000000000..f929a9bb6 --- /dev/null +++ b/src/test/ui/traits/object/supertrait-lifetime-bound.rs @@ -0,0 +1,14 @@ +trait Foo: 'static { } + +trait Bar: Foo { } + +fn test1, S>() { } + +fn test2<'a>() { + // Here: the type `dyn Bar<&'a u32>` references `'a`, + // and so it does not outlive `'static`. + test1::, _>(); + //~^ ERROR lifetime may not live long enough +} + +fn main() { } diff --git a/src/test/ui/traits/object/supertrait-lifetime-bound.stderr b/src/test/ui/traits/object/supertrait-lifetime-bound.stderr new file mode 100644 index 000000000..ed2f86243 --- /dev/null +++ b/src/test/ui/traits/object/supertrait-lifetime-bound.stderr @@ -0,0 +1,11 @@ +error: lifetime may not live long enough + --> $DIR/supertrait-lifetime-bound.rs:10:5 + | +LL | fn test2<'a>() { + | -- lifetime `'a` defined here +... +LL | test1::, _>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` + +error: aborting due to previous error + diff --git a/src/test/ui/traits/object/vs-lifetime-2.rs b/src/test/ui/traits/object/vs-lifetime-2.rs new file mode 100644 index 000000000..0b33dc7f6 --- /dev/null +++ b/src/test/ui/traits/object/vs-lifetime-2.rs @@ -0,0 +1,11 @@ +// A few contrived examples where lifetime should (or should not) be parsed as an object type. +// Lifetimes parsed as types are still rejected later by semantic checks. + +// `'static` is a lifetime, `'static +` is a type, `'a` is a type +fn g() where + 'static: 'static, + dyn 'static +: 'static + Copy, + //~^ ERROR at least one trait is required for an object type +{} + +fn main() {} diff --git a/src/test/ui/traits/object/vs-lifetime-2.stderr b/src/test/ui/traits/object/vs-lifetime-2.stderr new file mode 100644 index 000000000..9b8e793df --- /dev/null +++ b/src/test/ui/traits/object/vs-lifetime-2.stderr @@ -0,0 +1,9 @@ +error[E0224]: at least one trait is required for an object type + --> $DIR/vs-lifetime-2.rs:7:5 + | +LL | dyn 'static +: 'static + Copy, + | ^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0224`. diff --git a/src/test/ui/traits/object/vs-lifetime.rs b/src/test/ui/traits/object/vs-lifetime.rs new file mode 100644 index 000000000..14ae67cff --- /dev/null +++ b/src/test/ui/traits/object/vs-lifetime.rs @@ -0,0 +1,17 @@ +// A few contrived examples where lifetime should (or should not) be parsed as an object type. +// Lifetimes parsed as types are still rejected later by semantic checks. + +struct S<'a, T>(&'a u8, T); + +fn main() { + // `'static` is a lifetime argument, `'static +` is a type argument + let _: S<'static, u8>; + let _: S<'static, dyn 'static +>; + //~^ at least one trait is required for an object type + let _: S<'static, 'static>; + //~^ ERROR this struct takes 1 lifetime argument but 2 lifetime arguments were supplied + //~| ERROR this struct takes 1 generic argument but 0 generic arguments were supplied + let _: S; + //~^ ERROR type provided when a lifetime was expected + //~| ERROR at least one trait is required for an object type +} diff --git a/src/test/ui/traits/object/vs-lifetime.stderr b/src/test/ui/traits/object/vs-lifetime.stderr new file mode 100644 index 000000000..224465228 --- /dev/null +++ b/src/test/ui/traits/object/vs-lifetime.stderr @@ -0,0 +1,52 @@ +error[E0224]: at least one trait is required for an object type + --> $DIR/vs-lifetime.rs:9:23 + | +LL | let _: S<'static, dyn 'static +>; + | ^^^^^^^^^^^^^ + +error[E0107]: this struct takes 1 lifetime argument but 2 lifetime arguments were supplied + --> $DIR/vs-lifetime.rs:11:12 + | +LL | let _: S<'static, 'static>; + | ^ ------- help: remove this lifetime argument + | | + | expected 1 lifetime argument + | +note: struct defined here, with 1 lifetime parameter: `'a` + --> $DIR/vs-lifetime.rs:4:8 + | +LL | struct S<'a, T>(&'a u8, T); + | ^ -- + +error[E0107]: this struct takes 1 generic argument but 0 generic arguments were supplied + --> $DIR/vs-lifetime.rs:11:12 + | +LL | let _: S<'static, 'static>; + | ^ expected 1 generic argument + | +note: struct defined here, with 1 generic parameter: `T` + --> $DIR/vs-lifetime.rs:4:8 + | +LL | struct S<'a, T>(&'a u8, T); + | ^ - +help: add missing generic argument + | +LL | let _: S<'static, 'static, T>; + | +++ + +error[E0224]: at least one trait is required for an object type + --> $DIR/vs-lifetime.rs:14:14 + | +LL | let _: S; + | ^^^^^^^^^^^^^ + +error[E0747]: type provided when a lifetime was expected + --> $DIR/vs-lifetime.rs:14:14 + | +LL | let _: S; + | ^^^^^^^^^^^^^ + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0107, E0224, E0747. +For more information about an error, try `rustc --explain E0107`. diff --git a/src/test/ui/traits/object/with-lifetime-bound.rs b/src/test/ui/traits/object/with-lifetime-bound.rs new file mode 100644 index 000000000..05aab5e3b --- /dev/null +++ b/src/test/ui/traits/object/with-lifetime-bound.rs @@ -0,0 +1,34 @@ +// run-pass +// Uncovered during work on new scoping rules for safe destructors +// as an important use case to support properly. + + +pub struct E<'a> { + pub f: &'a u8, +} +impl<'b> E<'b> { + pub fn m(&self) -> &'b u8 { self.f } +} + +pub struct P<'c> { + pub g: &'c u8, +} +pub trait M { + fn n(&self) -> u8; +} +impl<'d> M for P<'d> { + fn n(&self) -> u8 { *self.g } +} + +fn extension<'e>(x: &'e E<'e>) -> Box { + loop { + let p = P { g: x.m() }; + return Box::new(p) as Box; + } +} + +fn main() { + let w = E { f: &10 }; + let o = extension(&w); + assert_eq!(o.n(), 10); +} diff --git a/src/test/ui/traits/object/with-self-in-projection-output-bad.rs b/src/test/ui/traits/object/with-self-in-projection-output-bad.rs new file mode 100644 index 000000000..f34fa80a0 --- /dev/null +++ b/src/test/ui/traits/object/with-self-in-projection-output-bad.rs @@ -0,0 +1,50 @@ +// Regression test for #56288. Checks that if a supertrait defines an associated type +// projection that references `Self`, then that associated type must still be explicitly +// specified in the `dyn Trait` variant, since we don't know what `Self` is anymore. + +trait Base { + type Output; +} + +trait Helper: Base::Target> { + type Target; +} + +impl Base for u32 +{ + type Output = i32; +} + +impl Helper for u32 +{ + type Target = i32; +} + +trait ConstI32 { + type Out; +} + +impl ConstI32 for T { + type Out = i32; +} + +// Test that you still need to manually give a projection type if the Output type +// is normalizable. +trait NormalizableHelper: + Base::Out> +{ + type Target; +} + +impl NormalizableHelper for u32 +{ + type Target = i32; +} + +fn main() { + let _x: Box> = Box::new(2u32); + //~^ ERROR the value of the associated type `Output` (from trait `Base`) must be specified + + let _y: Box> = Box::new(2u32); + //~^ ERROR the value of the associated type `Output` (from trait `Base`) must be specified +} diff --git a/src/test/ui/traits/object/with-self-in-projection-output-bad.stderr b/src/test/ui/traits/object/with-self-in-projection-output-bad.stderr new file mode 100644 index 000000000..641bfe236 --- /dev/null +++ b/src/test/ui/traits/object/with-self-in-projection-output-bad.stderr @@ -0,0 +1,21 @@ +error[E0191]: the value of the associated type `Output` (from trait `Base`) must be specified + --> $DIR/with-self-in-projection-output-bad.rs:45:21 + | +LL | type Output; + | ----------- `Output` defined here +... +LL | let _x: Box> = Box::new(2u32); + | ^^^^^^^^^^^^^^^^^^ help: specify the associated type: `Helper` + +error[E0191]: the value of the associated type `Output` (from trait `Base`) must be specified + --> $DIR/with-self-in-projection-output-bad.rs:48:21 + | +LL | type Output; + | ----------- `Output` defined here +... +LL | let _y: Box> = Box::new(2u32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: specify the associated type: `NormalizableHelper` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0191`. diff --git a/src/test/ui/traits/object/with-self-in-projection-output-good.rs b/src/test/ui/traits/object/with-self-in-projection-output-good.rs new file mode 100644 index 000000000..d1b7bf6c2 --- /dev/null +++ b/src/test/ui/traits/object/with-self-in-projection-output-good.rs @@ -0,0 +1,28 @@ +// build-pass (FIXME(62277): could be check-pass?) + +// Regression test related to #56288. Check that a supertrait projection (of +// `Output`) that references `Self` can be ok if it is referencing a projection (of +// `Self::Target`, in this case). Note that we still require the user to manually +// specify both `Target` and `Output` for now. + +trait Base { + type Output; +} + +trait Helper: Base::Target> { + type Target; +} + +impl Base for u32 +{ + type Output = i32; +} + +impl Helper for u32 +{ + type Target = i32; +} + +fn main() { + let _x: Box> = Box::new(2u32); +} diff --git a/src/test/ui/traits/object/with-self-in-projection-output-repeated-supertrait.rs b/src/test/ui/traits/object/with-self-in-projection-output-repeated-supertrait.rs new file mode 100644 index 000000000..39e817168 --- /dev/null +++ b/src/test/ui/traits/object/with-self-in-projection-output-repeated-supertrait.rs @@ -0,0 +1,51 @@ +// build-pass (FIXME(62277): could be check-pass?) + +// FIXME(eddyb) shorten the name so windows doesn't choke on it. +#![crate_name = "trait_test"] + +// Regression test related to #56288. Check that a supertrait projection (of +// `Output`) that references `Self` is ok if there is another occurrence of +// the same supertrait that specifies the projection explicitly, even if +// the projection's associated type is not explicitly specified in the object type. +// +// Note that in order for this to compile, we need the `Self`-referencing projection +// to normalize fairly directly to a concrete type, otherwise the trait resolver +// will hate us. +// +// There is a test in `trait-object-with-self-in-projection-output-bad.rs` that +// having a normalizing, but `Self`-containing projection does not *by itself* +// allow you to avoid writing the projected type (`Output`, in this example) +// explicitly. + +trait ConstI32 { + type Out; +} + +impl ConstI32 for T { + type Out = i32; +} + +trait Base { + type Output; +} + +trait NormalizingHelper: Base::Out> + Base { + type Target; +} + +impl Base for u32 +{ + type Output = i32; +} + +impl NormalizingHelper for u32 +{ + type Target = i32; +} + +fn main() { + // Make sure this works both with and without the associated type + // being specified. + let _x: Box> = Box::new(2u32); + let _y: Box> = Box::new(2u32); +} -- cgit v1.2.3