diff options
Diffstat (limited to 'tests/ui/specialization')
162 files changed, 4017 insertions, 0 deletions
diff --git a/tests/ui/specialization/README-rpass.md b/tests/ui/specialization/README-rpass.md new file mode 100644 index 000000000..c1486ce1e --- /dev/null +++ b/tests/ui/specialization/README-rpass.md @@ -0,0 +1,37 @@ +Tests that specialization is working correctly: + +- Dispatch + - [On methods](specialization-basics.rs), includes: + - Specialization via adding a trait bound + - Including both remote and local traits + - Specialization via pure structure (e.g. `(T, U)` vs `(T, T)`) + - Specialization via concrete types vs unknown types + - In top level of the trait reference + - Embedded within another type (`Vec<T>` vs `Vec<i32>`) + - [Specialization based on super trait relationships](specialization-supertraits.rs) + - [On assoc fns](specialization-assoc-fns.rs) + - [Ensure that impl order doesn't matter](specialization-out-of-order.rs) + +- Item inheritance + - [Correct default cascading for methods](specialization-default-methods.rs) + - Inheritance works across impls with varying generics + - [With projections](specialization-translate-projections.rs) + - [With projections that involve input types](specialization-translate-projections-with-params.rs) + +- Normalization issues + - [Non-default assoc types can be projected](specialization-projection.rs) + - Including non-specialized cases + - Including specialized cases + - [Specialized Impls can happen on projections](specialization-on-projection.rs) + - [Projections and aliases play well together](specialization-projection-alias.rs) + - [Projections involving specialization allowed in the trait ref for impls, and overlap can still be determined](specialization-overlap-projection.rs) + - Only works for the simple case where the most specialized impl directly + provides a non-`default` associated type + +- Across crates + - [For traits defined in upstream crate](specialization-allowed-cross-crate.rs) + - [Full method dispatch tests, drawing from upstream crate](specialization-cross-crate.rs) + - Including *additional* local specializations + - [Full method dispatch tests, *without* turning on specialization in local crate](specialization-cross-crate-no-gate.rs) + - [Test that defaults cascade correctly from upstream crates](specialization-cross-crate-defaults.rs) + - Including *additional* local use of defaults diff --git a/tests/ui/specialization/README.md b/tests/ui/specialization/README.md new file mode 100644 index 000000000..f2b4bf946 --- /dev/null +++ b/tests/ui/specialization/README.md @@ -0,0 +1,21 @@ +This directory contains the test for incorrect usage of specialization that +should lead to compile failure. Those tests break down into a few categories: + +- Feature gating + - [On use of the `default` keyword](specialization-feature-gate-default.rs) + - [On overlapping impls](specialization-feature-gate-overlap.rs) + +- Overlap checking with specialization enabled + - [Basic overlap scenarios](specialization-overlap.rs) + - Includes purely structural overlap + - Includes purely trait-based overlap + - Includes mix + - [Overlap with differing polarity](specialization-overlap-negative.rs) + +- [Attempt to specialize without using `default`](specialization-no-default.rs) + +- [Attempt to change impl polarity in a specialization](specialization-polarity.rs) + +- Attempt to rely on projection of a `default` type + - [Rely on it externally in both generic and monomorphic contexts](specialization-default-projection.rs) + - [Rely on it both within an impl and outside it](specialization-default-types.rs) diff --git a/tests/ui/specialization/assoc-ty-graph-cycle.rs b/tests/ui/specialization/assoc-ty-graph-cycle.rs new file mode 100644 index 000000000..fc39b553a --- /dev/null +++ b/tests/ui/specialization/assoc-ty-graph-cycle.rs @@ -0,0 +1,25 @@ +// run-pass + +// Make sure we don't crash with a cycle error during coherence. + +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +trait Trait<T> { + type Assoc; +} + +impl<T> Trait<T> for Vec<T> { + default type Assoc = (); +} + +impl Trait<u8> for Vec<u8> { + type Assoc = u8; +} + +impl<T> Trait<T> for String { + type Assoc = (); +} + +impl Trait<<Vec<u8> as Trait<u8>>::Assoc> for String {} + +fn main() {} diff --git a/tests/ui/specialization/assoc-ty-graph-cycle.stderr b/tests/ui/specialization/assoc-ty-graph-cycle.stderr new file mode 100644 index 000000000..f5529c24d --- /dev/null +++ b/tests/ui/specialization/assoc-ty-graph-cycle.stderr @@ -0,0 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/assoc-ty-graph-cycle.rs:5:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/specialization/auxiliary/cross_crates_defaults.rs b/tests/ui/specialization/auxiliary/cross_crates_defaults.rs new file mode 100644 index 000000000..1e5555355 --- /dev/null +++ b/tests/ui/specialization/auxiliary/cross_crates_defaults.rs @@ -0,0 +1,40 @@ +#![feature(specialization)] + +// First, test only use of explicit `default` items: + +pub trait Foo { + fn foo(&self) -> bool; +} + +impl<T> Foo for T { + default fn foo(&self) -> bool { false } +} + +impl Foo for i32 {} + +impl Foo for i64 { + fn foo(&self) -> bool { true } +} + +// Next, test mixture of explicit `default` and provided methods: + +pub trait Bar { + fn bar(&self) -> i32 { 0 } +} + +impl<T> Bar for T { + default fn bar(&self) -> i32 { 0 } +} + +impl Bar for i32 { + fn bar(&self) -> i32 { 1 } +} +impl<'a> Bar for &'a str {} + +impl<T> Bar for Vec<T> { + default fn bar(&self) -> i32 { 2 } +} +impl Bar for Vec<i32> {} +impl Bar for Vec<i64> { + fn bar(&self) -> i32 { 3 } +} diff --git a/tests/ui/specialization/auxiliary/go_trait.rs b/tests/ui/specialization/auxiliary/go_trait.rs new file mode 100644 index 000000000..aa0ec2289 --- /dev/null +++ b/tests/ui/specialization/auxiliary/go_trait.rs @@ -0,0 +1,43 @@ +#![feature(specialization)] + +// Common code used for tests that model the Fn/FnMut/FnOnce hierarchy. + +pub trait Go { + fn go(&self, arg: isize); +} + +pub fn go<G:Go>(this: &G, arg: isize) { + this.go(arg) +} + +pub trait GoMut { + fn go_mut(&mut self, arg: isize); +} + +pub fn go_mut<G:GoMut>(this: &mut G, arg: isize) { + this.go_mut(arg) +} + +pub trait GoOnce { + fn go_once(self, arg: isize); +} + +pub fn go_once<G:GoOnce>(this: G, arg: isize) { + this.go_once(arg) +} + +impl<G> GoMut for G + where G : Go +{ + default fn go_mut(&mut self, arg: isize) { + go(&*self, arg) + } +} + +impl<G> GoOnce for G + where G : GoMut +{ + default fn go_once(mut self, arg: isize) { + go_mut(&mut self, arg) + } +} diff --git a/tests/ui/specialization/auxiliary/specialization_cross_crate.rs b/tests/ui/specialization/auxiliary/specialization_cross_crate.rs new file mode 100644 index 000000000..8caa8524f --- /dev/null +++ b/tests/ui/specialization/auxiliary/specialization_cross_crate.rs @@ -0,0 +1,72 @@ +#![feature(specialization)] + +pub trait Foo { + fn foo(&self) -> &'static str; +} + +impl<T> Foo for T { + default fn foo(&self) -> &'static str { + "generic" + } +} + +impl<T: Clone> Foo for T { + default fn foo(&self) -> &'static str { + "generic Clone" + } +} + +impl<T, U> Foo for (T, U) where T: Clone, U: Clone { + default fn foo(&self) -> &'static str { + "generic pair" + } +} + +impl<T: Clone> Foo for (T, T) { + default fn foo(&self) -> &'static str { + "generic uniform pair" + } +} + +impl Foo for (u8, u32) { + default fn foo(&self) -> &'static str { + "(u8, u32)" + } +} + +impl Foo for (u8, u8) { + default fn foo(&self) -> &'static str { + "(u8, u8)" + } +} + +impl<T: Clone> Foo for Vec<T> { + default fn foo(&self) -> &'static str { + "generic Vec" + } +} + +impl Foo for Vec<i32> { + fn foo(&self) -> &'static str { + "Vec<i32>" + } +} + +impl Foo for String { + fn foo(&self) -> &'static str { + "String" + } +} + +impl Foo for i32 { + fn foo(&self) -> &'static str { + "i32" + } +} + +pub trait MyMarker {} +impl<T: Clone + MyMarker> Foo for T { + default fn foo(&self) -> &'static str { + "generic Clone + MyMarker" + } +} diff --git a/tests/ui/specialization/const_trait_impl.rs b/tests/ui/specialization/const_trait_impl.rs new file mode 100644 index 000000000..05ba4c8d4 --- /dev/null +++ b/tests/ui/specialization/const_trait_impl.rs @@ -0,0 +1,55 @@ +// check-pass +#![feature(const_trait_impl, min_specialization, rustc_attrs)] + +#[rustc_specialization_trait] +#[const_trait] +pub unsafe trait Sup { + fn foo() -> u32; +} + +#[rustc_specialization_trait] +#[const_trait] +pub unsafe trait Sub: ~const Sup {} + +unsafe impl const Sup for u8 { + default fn foo() -> u32 { + 1 + } +} + +unsafe impl const Sup for () { + fn foo() -> u32 { + 42 + } +} + +unsafe impl const Sub for () {} + +#[const_trait] +pub trait A { + fn a() -> u32; +} + +impl<T: ~const Default> const A for T { + default fn a() -> u32 { + 2 + } +} + +impl<T: ~const Default + ~const Sup> const A for T { + default fn a() -> u32 { + 3 + } +} + +impl<T: ~const Default + ~const Sub> const A for T { + fn a() -> u32 { + T::foo() + } +} + +const _: () = assert!(<()>::a() == 42); +const _: () = assert!(<u8>::a() == 3); +const _: () = assert!(<u16>::a() == 2); + +fn main() {} diff --git a/tests/ui/specialization/cross-crate-defaults.rs b/tests/ui/specialization/cross-crate-defaults.rs new file mode 100644 index 000000000..fc28d0c81 --- /dev/null +++ b/tests/ui/specialization/cross-crate-defaults.rs @@ -0,0 +1,41 @@ +// run-pass + +// aux-build:cross_crates_defaults.rs + +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +extern crate cross_crates_defaults; + +use cross_crates_defaults::*; + +struct LocalDefault; +struct LocalOverride; + +impl Foo for LocalDefault {} + +impl Foo for LocalOverride { + fn foo(&self) -> bool { true } +} + +fn test_foo() { + assert!(!0i8.foo()); + assert!(!0i32.foo()); + assert!(0i64.foo()); + + assert!(!LocalDefault.foo()); + assert!(LocalOverride.foo()); +} + +fn test_bar() { + assert!(0u8.bar() == 0); + assert!(0i32.bar() == 1); + assert!("hello".bar() == 0); + assert!(vec![()].bar() == 2); + assert!(vec![0i32].bar() == 2); + assert!(vec![0i64].bar() == 3); +} + +fn main() { + test_foo(); + test_bar(); +} diff --git a/tests/ui/specialization/cross-crate-defaults.stderr b/tests/ui/specialization/cross-crate-defaults.stderr new file mode 100644 index 000000000..ee5c77a76 --- /dev/null +++ b/tests/ui/specialization/cross-crate-defaults.stderr @@ -0,0 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/cross-crate-defaults.rs:5:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/specialization/default-associated-type-bound-1.rs b/tests/ui/specialization/default-associated-type-bound-1.rs new file mode 100644 index 000000000..c043114b5 --- /dev/null +++ b/tests/ui/specialization/default-associated-type-bound-1.rs @@ -0,0 +1,24 @@ +// Check that we check that default associated types satisfy the required +// bounds on them. + +#![feature(specialization)] +//~^ WARNING `specialization` is incomplete + +trait X { + type U: Clone; + fn unsafe_clone(&self, x: Option<&Self::U>) { + x.cloned(); + } +} + +// We cannot normalize `<T as X>::U` to `str` here, because the default could +// be overridden. The error here must therefore be found by a method other than +// normalization. +impl<T> X for T { + default type U = str; + //~^ ERROR the trait bound `str: Clone` is not satisfied +} + +pub fn main() { + 1.unsafe_clone(None); +} diff --git a/tests/ui/specialization/default-associated-type-bound-1.stderr b/tests/ui/specialization/default-associated-type-bound-1.stderr new file mode 100644 index 000000000..e498187c0 --- /dev/null +++ b/tests/ui/specialization/default-associated-type-bound-1.stderr @@ -0,0 +1,26 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/default-associated-type-bound-1.rs:4:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +error[E0277]: the trait bound `str: Clone` is not satisfied + --> $DIR/default-associated-type-bound-1.rs:18:22 + | +LL | default type U = str; + | ^^^ the trait `Clone` is not implemented for `str` + | + = help: the trait `Clone` is implemented for `String` +note: required by a bound in `X::U` + --> $DIR/default-associated-type-bound-1.rs:8:13 + | +LL | type U: Clone; + | ^^^^^ required by this bound in `X::U` + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/specialization/default-associated-type-bound-2.rs b/tests/ui/specialization/default-associated-type-bound-2.rs new file mode 100644 index 000000000..0a21b1f09 --- /dev/null +++ b/tests/ui/specialization/default-associated-type-bound-2.rs @@ -0,0 +1,22 @@ +// Check that generic predicates are also checked for default associated types. +#![feature(specialization)] +//~^ WARNING `specialization` is incomplete + +trait X<T> { + type U: PartialEq<T>; + fn unsafe_compare(x: Option<Self::U>, y: Option<T>) { + match (x, y) { + (Some(a), Some(b)) => a == b, + _ => false, + }; + } +} + +impl<B: 'static, T> X<B> for T { + default type U = &'static B; + //~^ ERROR can't compare `&'static B` with `B` +} + +pub fn main() { + <i32 as X<i32>>::unsafe_compare(None, None); +} diff --git a/tests/ui/specialization/default-associated-type-bound-2.stderr b/tests/ui/specialization/default-associated-type-bound-2.stderr new file mode 100644 index 000000000..4dbe251ed --- /dev/null +++ b/tests/ui/specialization/default-associated-type-bound-2.stderr @@ -0,0 +1,30 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/default-associated-type-bound-2.rs:2:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +error[E0277]: can't compare `&'static B` with `B` + --> $DIR/default-associated-type-bound-2.rs:16:22 + | +LL | default type U = &'static B; + | ^^^^^^^^^^ no implementation for `&'static B == B` + | + = help: the trait `PartialEq<B>` is not implemented for `&'static B` +note: required by a bound in `X::U` + --> $DIR/default-associated-type-bound-2.rs:6:13 + | +LL | type U: PartialEq<T>; + | ^^^^^^^^^^^^ required by this bound in `X::U` +help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement + | +LL | impl<B: 'static, T> X<B> for T where &'static B: PartialEq<B> { + | ++++++++++++++++++++++++++++++ + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/specialization/default-generic-associated-type-bound.rs b/tests/ui/specialization/default-generic-associated-type-bound.rs new file mode 100644 index 000000000..31a0685d0 --- /dev/null +++ b/tests/ui/specialization/default-generic-associated-type-bound.rs @@ -0,0 +1,25 @@ +// Check that default generics associated types are validated. + +#![feature(specialization)] +//~^ WARNING `specialization` is incomplete + +trait X { + type U<'a>: PartialEq<&'a Self> where Self: 'a; + fn unsafe_compare<'b>(x: Option<Self::U<'b>>, y: Option<&'b Self>) { + match (x, y) { + (Some(a), Some(b)) => a == b, + _ => false, + }; + } +} + +impl<T: 'static> X for T { + default type U<'a> = &'a T; + //~^ ERROR can't compare `T` with `T` +} + +struct NotComparable; + +pub fn main() { + <NotComparable as X>::unsafe_compare(None, None); +} diff --git a/tests/ui/specialization/default-generic-associated-type-bound.stderr b/tests/ui/specialization/default-generic-associated-type-bound.stderr new file mode 100644 index 000000000..c597eed37 --- /dev/null +++ b/tests/ui/specialization/default-generic-associated-type-bound.stderr @@ -0,0 +1,30 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/default-generic-associated-type-bound.rs:3:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +error[E0277]: can't compare `T` with `T` + --> $DIR/default-generic-associated-type-bound.rs:17:26 + | +LL | default type U<'a> = &'a T; + | ^^^^^ no implementation for `T == T` + | + = note: required for `&'a T` to implement `PartialEq` +note: required by a bound in `X::U` + --> $DIR/default-generic-associated-type-bound.rs:7:17 + | +LL | type U<'a>: PartialEq<&'a Self> where Self: 'a; + | ^^^^^^^^^^^^^^^^^^^ required by this bound in `X::U` +help: consider further restricting this bound + | +LL | impl<T: 'static + std::cmp::PartialEq> X for T { + | +++++++++++++++++++++ + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/specialization/defaultimpl/allowed-cross-crate.rs b/tests/ui/specialization/defaultimpl/allowed-cross-crate.rs new file mode 100644 index 000000000..5d67160eb --- /dev/null +++ b/tests/ui/specialization/defaultimpl/allowed-cross-crate.rs @@ -0,0 +1,26 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_variables)] +#![allow(unused_imports)] + +// aux-build:go_trait.rs + +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +extern crate go_trait; + +use go_trait::{Go,GoMut}; +use std::fmt::Debug; +use std::default::Default; + +struct MyThingy; + +impl Go for MyThingy { + fn go(&self, arg: isize) { } +} + +impl GoMut for MyThingy { + fn go_mut(&mut self, arg: isize) { } +} + +fn main() { } diff --git a/tests/ui/specialization/defaultimpl/allowed-cross-crate.stderr b/tests/ui/specialization/defaultimpl/allowed-cross-crate.stderr new file mode 100644 index 000000000..02f13d461 --- /dev/null +++ b/tests/ui/specialization/defaultimpl/allowed-cross-crate.stderr @@ -0,0 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/allowed-cross-crate.rs:8:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/specialization/defaultimpl/auxiliary/go_trait.rs b/tests/ui/specialization/defaultimpl/auxiliary/go_trait.rs new file mode 100644 index 000000000..c065593b4 --- /dev/null +++ b/tests/ui/specialization/defaultimpl/auxiliary/go_trait.rs @@ -0,0 +1,43 @@ +#![feature(specialization)] + +// Common code used for tests that model the Fn/FnMut/FnOnce hierarchy. + +pub trait Go { + fn go(&self, arg: isize); +} + +pub fn go<G:Go>(this: &G, arg: isize) { + this.go(arg) +} + +pub trait GoMut { + fn go_mut(&mut self, arg: isize); +} + +pub fn go_mut<G:GoMut>(this: &mut G, arg: isize) { + this.go_mut(arg) +} + +pub trait GoOnce { + fn go_once(self, arg: isize); +} + +pub fn go_once<G:GoOnce>(this: G, arg: isize) { + this.go_once(arg) +} + +default impl<G> GoMut for G + where G : Go +{ + fn go_mut(&mut self, arg: isize) { + go(&*self, arg) + } +} + +default impl<G> GoOnce for G + where G : GoMut +{ + fn go_once(mut self, arg: isize) { + go_mut(&mut self, arg) + } +} diff --git a/tests/ui/specialization/defaultimpl/out-of-order.rs b/tests/ui/specialization/defaultimpl/out-of-order.rs new file mode 100644 index 000000000..13258ac8c --- /dev/null +++ b/tests/ui/specialization/defaultimpl/out-of-order.rs @@ -0,0 +1,19 @@ +// run-pass + +// Test that you can list the more specific impl before the more general one. + +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +trait Foo { + type Out; +} + +impl Foo for bool { + type Out = (); +} + +default impl<T> Foo for T { + type Out = bool; +} + +fn main() {} diff --git a/tests/ui/specialization/defaultimpl/out-of-order.stderr b/tests/ui/specialization/defaultimpl/out-of-order.stderr new file mode 100644 index 000000000..2cf1ac909 --- /dev/null +++ b/tests/ui/specialization/defaultimpl/out-of-order.stderr @@ -0,0 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/out-of-order.rs:5:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/specialization/defaultimpl/overlap-projection.rs b/tests/ui/specialization/defaultimpl/overlap-projection.rs new file mode 100644 index 000000000..0add4d551 --- /dev/null +++ b/tests/ui/specialization/defaultimpl/overlap-projection.rs @@ -0,0 +1,25 @@ +// run-pass + +// Test that impls on projected self types can resolve overlap, even when the +// projections involve specialization, so long as the associated type is +// provided by the most specialized impl. + +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +trait Assoc { + type Output; +} + +default impl<T> Assoc for T { + type Output = bool; +} + +impl Assoc for u8 { type Output = u8; } +impl Assoc for u16 { type Output = u16; } + +trait Foo {} +impl Foo for u32 {} +impl Foo for <u8 as Assoc>::Output {} +impl Foo for <u16 as Assoc>::Output {} + +fn main() {} diff --git a/tests/ui/specialization/defaultimpl/overlap-projection.stderr b/tests/ui/specialization/defaultimpl/overlap-projection.stderr new file mode 100644 index 000000000..75fdfafd9 --- /dev/null +++ b/tests/ui/specialization/defaultimpl/overlap-projection.stderr @@ -0,0 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/overlap-projection.rs:7:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/specialization/defaultimpl/projection.rs b/tests/ui/specialization/defaultimpl/projection.rs new file mode 100644 index 000000000..f19c55b04 --- /dev/null +++ b/tests/ui/specialization/defaultimpl/projection.rs @@ -0,0 +1,42 @@ +// run-pass +#![allow(dead_code)] + +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +// Make sure we *can* project non-defaulted associated types +// cf ui/specialization/specialization-default-projection.rs + +// First, do so without any use of specialization + +trait Foo { + type Assoc; +} + +impl<T> Foo for T { + type Assoc = (); +} + +fn generic_foo<T>() -> <T as Foo>::Assoc { + () +} + +// Next, allow for one layer of specialization + +trait Bar { + type Assoc; +} + +default impl<T> Bar for T { + type Assoc = (); +} + +impl<T: Clone> Bar for T { + type Assoc = u8; +} + +fn generic_bar_clone<T: Clone>() -> <T as Bar>::Assoc { + 0u8 +} + +fn main() { +} diff --git a/tests/ui/specialization/defaultimpl/projection.stderr b/tests/ui/specialization/defaultimpl/projection.stderr new file mode 100644 index 000000000..cc3fe8237 --- /dev/null +++ b/tests/ui/specialization/defaultimpl/projection.stderr @@ -0,0 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/projection.rs:4:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/specialization/defaultimpl/specialization-feature-gate-default.rs b/tests/ui/specialization/defaultimpl/specialization-feature-gate-default.rs new file mode 100644 index 000000000..89158b65a --- /dev/null +++ b/tests/ui/specialization/defaultimpl/specialization-feature-gate-default.rs @@ -0,0 +1,11 @@ +// Check that specialization must be ungated to use the `default` keyword + +trait Foo { + fn foo(&self); +} + +default impl<T> Foo for T { //~ ERROR specialization is unstable + fn foo(&self) {} +} + +fn main() {} diff --git a/tests/ui/specialization/defaultimpl/specialization-feature-gate-default.stderr b/tests/ui/specialization/defaultimpl/specialization-feature-gate-default.stderr new file mode 100644 index 000000000..64e14f580 --- /dev/null +++ b/tests/ui/specialization/defaultimpl/specialization-feature-gate-default.stderr @@ -0,0 +1,14 @@ +error[E0658]: specialization is unstable + --> $DIR/specialization-feature-gate-default.rs:7:1 + | +LL | / default impl<T> Foo for T { +LL | | fn foo(&self) {} +LL | | } + | |_^ + | + = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information + = help: add `#![feature(specialization)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/specialization/defaultimpl/specialization-no-default.rs b/tests/ui/specialization/defaultimpl/specialization-no-default.rs new file mode 100644 index 000000000..661724eef --- /dev/null +++ b/tests/ui/specialization/defaultimpl/specialization-no-default.rs @@ -0,0 +1,77 @@ +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +// Check a number of scenarios in which one impl tries to override another, +// without correctly using `default`. + +// Test 1: one layer of specialization, multiple methods, missing `default` + +trait Foo { + fn foo(&self); + fn bar(&self); +} + +impl<T> Foo for T { + fn foo(&self) {} + fn bar(&self) {} +} + +impl Foo for u8 {} +impl Foo for u16 { + fn foo(&self) {} //~ ERROR E0520 +} +impl Foo for u32 { + fn bar(&self) {} //~ ERROR E0520 +} + +// Test 2: one layer of specialization, missing `default` on associated type + +trait Bar { + type T; +} + +impl<T> Bar for T { + type T = u8; +} + +impl Bar for u8 { + type T = (); //~ ERROR E0520 +} + +// Test 3a: multiple layers of specialization, missing interior `default` + +trait Baz { + fn baz(&self); +} + +default impl<T> Baz for T { + fn baz(&self) {} +} + +impl<T: Clone> Baz for T { + fn baz(&self) {} +} + +impl Baz for i32 { + fn baz(&self) {} //~ ERROR E0520 +} + +// Test 3b: multiple layers of specialization, missing interior `default`, +// redundant `default` in bottom layer. + +trait Redundant { + fn redundant(&self); +} + +default impl<T> Redundant for T { + fn redundant(&self) {} +} + +impl<T: Clone> Redundant for T { + fn redundant(&self) {} +} + +default impl Redundant for i32 { + fn redundant(&self) {} //~ ERROR E0520 +} + +fn main() {} diff --git a/tests/ui/specialization/defaultimpl/specialization-no-default.stderr b/tests/ui/specialization/defaultimpl/specialization-no-default.stderr new file mode 100644 index 000000000..770be2af2 --- /dev/null +++ b/tests/ui/specialization/defaultimpl/specialization-no-default.stderr @@ -0,0 +1,68 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/specialization-no-default.rs:1:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +error[E0520]: `foo` specializes an item from a parent `impl`, but that item is not marked `default` + --> $DIR/specialization-no-default.rs:20:5 + | +LL | impl<T> Foo for T { + | ----------------- parent `impl` is here +... +LL | fn foo(&self) {} + | ^^^^^^^^^^^^^^^^ cannot specialize default item `foo` + | + = note: to specialize, `foo` in the parent `impl` must be marked `default` + +error[E0520]: `bar` specializes an item from a parent `impl`, but that item is not marked `default` + --> $DIR/specialization-no-default.rs:23:5 + | +LL | impl<T> Foo for T { + | ----------------- parent `impl` is here +... +LL | fn bar(&self) {} + | ^^^^^^^^^^^^^^^^ cannot specialize default item `bar` + | + = note: to specialize, `bar` in the parent `impl` must be marked `default` + +error[E0520]: `T` specializes an item from a parent `impl`, but that item is not marked `default` + --> $DIR/specialization-no-default.rs:37:5 + | +LL | impl<T> Bar for T { + | ----------------- parent `impl` is here +... +LL | type T = (); + | ^^^^^^^^^^^^ cannot specialize default item `T` + | + = note: to specialize, `T` in the parent `impl` must be marked `default` + +error[E0520]: `baz` specializes an item from a parent `impl`, but that item is not marked `default` + --> $DIR/specialization-no-default.rs:55:5 + | +LL | impl<T: Clone> Baz for T { + | ------------------------ parent `impl` is here +... +LL | fn baz(&self) {} + | ^^^^^^^^^^^^^^^^ cannot specialize default item `baz` + | + = note: to specialize, `baz` in the parent `impl` must be marked `default` + +error[E0520]: `redundant` specializes an item from a parent `impl`, but that item is not marked `default` + --> $DIR/specialization-no-default.rs:74:5 + | +LL | impl<T: Clone> Redundant for T { + | ------------------------------ parent `impl` is here +... +LL | fn redundant(&self) {} + | ^^^^^^^^^^^^^^^^^^^^^^ cannot specialize default item `redundant` + | + = note: to specialize, `redundant` in the parent `impl` must be marked `default` + +error: aborting due to 5 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0520`. diff --git a/tests/ui/specialization/defaultimpl/specialization-trait-item-not-implemented-rpass.rs b/tests/ui/specialization/defaultimpl/specialization-trait-item-not-implemented-rpass.rs new file mode 100644 index 000000000..89fef5b5e --- /dev/null +++ b/tests/ui/specialization/defaultimpl/specialization-trait-item-not-implemented-rpass.rs @@ -0,0 +1,34 @@ +// run-pass + +// Tests that we can combine a default impl that supplies one method with a +// full impl that supplies the other, and they can invoke one another. + +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +trait Foo { + fn foo_one(&self) -> &'static str; + fn foo_two(&self) -> &'static str; + fn foo_three(&self) -> &'static str; +} + +struct MyStruct; + +default impl<T> Foo for T { + fn foo_one(&self) -> &'static str { + self.foo_three() + } +} + +impl Foo for MyStruct { + fn foo_two(&self) -> &'static str { + self.foo_one() + } + + fn foo_three(&self) -> &'static str { + "generic" + } +} + +fn main() { + assert!(MyStruct.foo_two() == "generic"); +} diff --git a/tests/ui/specialization/defaultimpl/specialization-trait-item-not-implemented-rpass.stderr b/tests/ui/specialization/defaultimpl/specialization-trait-item-not-implemented-rpass.stderr new file mode 100644 index 000000000..407c1ab77 --- /dev/null +++ b/tests/ui/specialization/defaultimpl/specialization-trait-item-not-implemented-rpass.stderr @@ -0,0 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/specialization-trait-item-not-implemented-rpass.rs:6:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/specialization/defaultimpl/specialization-trait-item-not-implemented.rs b/tests/ui/specialization/defaultimpl/specialization-trait-item-not-implemented.rs new file mode 100644 index 000000000..3c5414469 --- /dev/null +++ b/tests/ui/specialization/defaultimpl/specialization-trait-item-not-implemented.rs @@ -0,0 +1,23 @@ +// Tests that default impls do not have to supply all items but regular impls do. + +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +trait Foo { + fn foo_one(&self) -> &'static str; + fn foo_two(&self) -> &'static str; +} + +struct MyStruct; + +default impl<T> Foo for T { + fn foo_one(&self) -> &'static str { + "generic" + } +} + +impl Foo for MyStruct {} +//~^ ERROR not all trait items implemented, missing: `foo_two` [E0046] + +fn main() { + println!("{}", MyStruct.foo_one()); +} diff --git a/tests/ui/specialization/defaultimpl/specialization-trait-item-not-implemented.stderr b/tests/ui/specialization/defaultimpl/specialization-trait-item-not-implemented.stderr new file mode 100644 index 000000000..f19975060 --- /dev/null +++ b/tests/ui/specialization/defaultimpl/specialization-trait-item-not-implemented.stderr @@ -0,0 +1,22 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/specialization-trait-item-not-implemented.rs:3:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +error[E0046]: not all trait items implemented, missing: `foo_two` + --> $DIR/specialization-trait-item-not-implemented.rs:18:1 + | +LL | fn foo_two(&self) -> &'static str; + | ---------------------------------- `foo_two` from trait +... +LL | impl Foo for MyStruct {} + | ^^^^^^^^^^^^^^^^^^^^^ missing `foo_two` in implementation + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0046`. diff --git a/tests/ui/specialization/defaultimpl/specialization-trait-not-implemented.rs b/tests/ui/specialization/defaultimpl/specialization-trait-not-implemented.rs new file mode 100644 index 000000000..6834d5736 --- /dev/null +++ b/tests/ui/specialization/defaultimpl/specialization-trait-not-implemented.rs @@ -0,0 +1,24 @@ +// Tests that: +// - default impls do not have to supply all items and +// - a default impl does not count as an impl (in this case, an incomplete default impl). + +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +trait Foo { + fn foo_one(&self) -> &'static str; + fn foo_two(&self) -> &'static str; +} + +struct MyStruct; + +default impl<T> Foo for T { + fn foo_one(&self) -> &'static str { + "generic" + } +} + + +fn main() { + println!("{}", MyStruct.foo_one()); + //~^ ERROR the method +} diff --git a/tests/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr b/tests/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr new file mode 100644 index 000000000..37788612f --- /dev/null +++ b/tests/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr @@ -0,0 +1,44 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/specialization-trait-not-implemented.rs:5:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +error[E0599]: the method `foo_one` exists for struct `MyStruct`, but its trait bounds were not satisfied + --> $DIR/specialization-trait-not-implemented.rs:22:29 + | +LL | struct MyStruct; + | --------------- + | | + | method `foo_one` not found for this struct + | doesn't satisfy `MyStruct: Foo` +... +LL | println!("{}", MyStruct.foo_one()); + | ^^^^^^^ method cannot be called on `MyStruct` due to unsatisfied trait bounds + | +note: trait bound `MyStruct: Foo` was not satisfied + --> $DIR/specialization-trait-not-implemented.rs:14:1 + | +LL | default impl<T> Foo for T { + | ^^^^^^^^^^^^^^^^---^^^^^- + | | + | unsatisfied trait bound introduced here +note: the trait `Foo` must be implemented + --> $DIR/specialization-trait-not-implemented.rs:7:1 + | +LL | trait Foo { + | ^^^^^^^^^ + = help: items from traits can only be used if the trait is implemented and in scope +note: `Foo` defines an item `foo_one`, perhaps you need to implement it + --> $DIR/specialization-trait-not-implemented.rs:7:1 + | +LL | trait Foo { + | ^^^^^^^^^ + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/specialization/defaultimpl/specialization-wfcheck.rs b/tests/ui/specialization/defaultimpl/specialization-wfcheck.rs new file mode 100644 index 000000000..eb18d6eaa --- /dev/null +++ b/tests/ui/specialization/defaultimpl/specialization-wfcheck.rs @@ -0,0 +1,10 @@ +// Tests that a default impl still has to have a WF trait ref. + +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +trait Foo<'a, T: Eq + 'a> { } + +default impl<U> Foo<'static, U> for () {} +//~^ ERROR the trait bound `U: Eq` is not satisfied + +fn main(){} diff --git a/tests/ui/specialization/defaultimpl/specialization-wfcheck.stderr b/tests/ui/specialization/defaultimpl/specialization-wfcheck.stderr new file mode 100644 index 000000000..e78016034 --- /dev/null +++ b/tests/ui/specialization/defaultimpl/specialization-wfcheck.stderr @@ -0,0 +1,29 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/specialization-wfcheck.rs:3:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +error[E0277]: the trait bound `U: Eq` is not satisfied + --> $DIR/specialization-wfcheck.rs:7:17 + | +LL | default impl<U> Foo<'static, U> for () {} + | ^^^^^^^^^^^^^^^ the trait `Eq` is not implemented for `U` + | +note: required by a bound in `Foo` + --> $DIR/specialization-wfcheck.rs:5:18 + | +LL | trait Foo<'a, T: Eq + 'a> { } + | ^^ required by this bound in `Foo` +help: consider restricting type parameter `U` + | +LL | default impl<U: std::cmp::Eq> Foo<'static, U> for () {} + | ++++++++++++++ + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/specialization/defaultimpl/validation.rs b/tests/ui/specialization/defaultimpl/validation.rs new file mode 100644 index 000000000..8558a1efb --- /dev/null +++ b/tests/ui/specialization/defaultimpl/validation.rs @@ -0,0 +1,16 @@ +#![feature(negative_impls)] +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +struct S; +struct Z; + +default impl S {} //~ ERROR inherent impls cannot be `default` + +default unsafe impl Send for S {} //~ ERROR impls of auto traits cannot be default +default impl !Send for Z {} //~ ERROR impls of auto traits cannot be default + //~^ ERROR negative impls cannot be default impls + +trait Tr {} +default impl !Tr for S {} //~ ERROR negative impls cannot be default impls + +fn main() {} diff --git a/tests/ui/specialization/defaultimpl/validation.stderr b/tests/ui/specialization/defaultimpl/validation.stderr new file mode 100644 index 000000000..eb6dc9355 --- /dev/null +++ b/tests/ui/specialization/defaultimpl/validation.stderr @@ -0,0 +1,51 @@ +error: inherent impls cannot be `default` + --> $DIR/validation.rs:7:14 + | +LL | default impl S {} + | ------- ^ inherent impl for this type + | | + | `default` because of this + | + = note: only trait implementations may be annotated with `default` + +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/validation.rs:2:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +error: impls of auto traits cannot be default + --> $DIR/validation.rs:9:21 + | +LL | default unsafe impl Send for S {} + | ------- ^^^^ auto trait + | | + | default because of this + +error: impls of auto traits cannot be default + --> $DIR/validation.rs:10:15 + | +LL | default impl !Send for Z {} + | ------- ^^^^ auto trait + | | + | default because of this + +error[E0750]: negative impls cannot be default impls + --> $DIR/validation.rs:10:1 + | +LL | default impl !Send for Z {} + | ^^^^^^^ ^ + +error[E0750]: negative impls cannot be default impls + --> $DIR/validation.rs:14:1 + | +LL | default impl !Tr for S {} + | ^^^^^^^ ^ + +error: aborting due to 5 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0750`. diff --git a/tests/ui/specialization/issue-33017.rs b/tests/ui/specialization/issue-33017.rs new file mode 100644 index 000000000..8dbadf58d --- /dev/null +++ b/tests/ui/specialization/issue-33017.rs @@ -0,0 +1,45 @@ +// Test to ensure that trait bounds are properly +// checked on specializable associated types + +#![allow(incomplete_features)] +#![feature(specialization)] + +trait UncheckedCopy: Sized { + type Output: From<Self> + Copy + Into<Self>; +} + +impl<T> UncheckedCopy for T { + default type Output = Self; + //~^ ERROR: the trait bound `T: Copy` is not satisfied +} + +fn unchecked_copy<T: UncheckedCopy>(other: &T::Output) -> T { + (*other).into() +} + +fn bug(origin: String) { + // Turn the String into it's Output type... + // Which we can just do by `.into()`, the assoc type states `From<Self>`. + let origin_output = origin.into(); + + // Make a copy of String::Output, which is a String... + let mut copy: String = unchecked_copy::<String>(&origin_output); + + // Turn the Output type into a String again, + // Which we can just do by `.into()`, the assoc type states `Into<Self>`. + let mut origin: String = origin_output.into(); + + // assert both Strings use the same buffer. + assert_eq!(copy.as_ptr(), origin.as_ptr()); + + // Any use of the copy we made becomes invalid, + drop(origin); + + // OH NO! UB UB UB UB! + copy.push_str(" world!"); + println!("{}", copy); +} + +fn main() { + bug(String::from("hello")); +} diff --git a/tests/ui/specialization/issue-33017.stderr b/tests/ui/specialization/issue-33017.stderr new file mode 100644 index 000000000..78e94cec2 --- /dev/null +++ b/tests/ui/specialization/issue-33017.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `T: Copy` is not satisfied + --> $DIR/issue-33017.rs:12:27 + | +LL | default type Output = Self; + | ^^^^ the trait `Copy` is not implemented for `T` + | +note: required by a bound in `UncheckedCopy::Output` + --> $DIR/issue-33017.rs:8:31 + | +LL | type Output: From<Self> + Copy + Into<Self>; + | ^^^^ required by this bound in `UncheckedCopy::Output` +help: consider restricting type parameter `T` + | +LL | impl<T: std::marker::Copy> UncheckedCopy for T { + | +++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/specialization/issue-35376.rs b/tests/ui/specialization/issue-35376.rs new file mode 100644 index 000000000..cc35213b9 --- /dev/null +++ b/tests/ui/specialization/issue-35376.rs @@ -0,0 +1,43 @@ +// check-pass +#![feature(specialization)] +//~^ WARN the feature `specialization` is incomplete + +fn main() {} + +pub trait Alpha<T> { } + +pub trait Beta { + type Event; +} + +pub trait Delta { + type Handle; + fn process(&self); +} + +pub struct Parent<A, T>(A, T); + +impl<A, T> Delta for Parent<A, T> +where A: Alpha<T::Handle>, + T: Delta, + T::Handle: Beta<Event = <Handle as Beta>::Event> { + type Handle = Handle; + default fn process(&self) { + unimplemented!() + } +} + +impl<A, T> Delta for Parent<A, T> +where A: Alpha<T::Handle> + Alpha<Handle>, + T: Delta, + T::Handle: Beta<Event = <Handle as Beta>::Event> { + fn process(&self) { + unimplemented!() + } +} + +pub struct Handle; + +impl Beta for Handle { + type Event = (); +} diff --git a/tests/ui/specialization/issue-35376.stderr b/tests/ui/specialization/issue-35376.stderr new file mode 100644 index 000000000..6c4167f3f --- /dev/null +++ b/tests/ui/specialization/issue-35376.stderr @@ -0,0 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-35376.rs:2:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/specialization/issue-36804.rs b/tests/ui/specialization/issue-36804.rs new file mode 100644 index 000000000..89350602f --- /dev/null +++ b/tests/ui/specialization/issue-36804.rs @@ -0,0 +1,35 @@ +// check-pass +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +pub struct Cloned<I>(I); + +impl<'a, I, T: 'a> Iterator for Cloned<I> +where + I: Iterator<Item = &'a T>, + T: Clone, +{ + type Item = T; + + fn next(&mut self) -> Option<T> { + unimplemented!() + } + + default fn count(self) -> usize where Self: Sized { + self.fold(0, |cnt, _| cnt + 1) + } +} + +impl<'a, I, T: 'a> Iterator for Cloned<I> +where + I: Iterator<Item = &'a T>, + T: Copy, +{ + fn count(self) -> usize { + unimplemented!() + } +} + +fn main() { + let a = [1,2,3,4]; + Cloned(a.iter()).count(); +} diff --git a/tests/ui/specialization/issue-36804.stderr b/tests/ui/specialization/issue-36804.stderr new file mode 100644 index 000000000..c2113b25f --- /dev/null +++ b/tests/ui/specialization/issue-36804.stderr @@ -0,0 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-36804.rs:2:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/specialization/issue-38091-2.rs b/tests/ui/specialization/issue-38091-2.rs new file mode 100644 index 000000000..9ed0b240d --- /dev/null +++ b/tests/ui/specialization/issue-38091-2.rs @@ -0,0 +1,28 @@ +// build-fail +//~^ ERROR overflow evaluating the requirement `i32: Check` + +#![feature(specialization)] +//~^ WARN the feature `specialization` is incomplete + +trait Iterate<'a> { + type Ty: Valid; + fn iterate(self); +} +impl<'a, T> Iterate<'a> for T +where + T: Check, +{ + default type Ty = (); + default fn iterate(self) {} +} + +trait Check {} +impl<'a, T> Check for T where <T as Iterate<'a>>::Ty: Valid {} + +trait Valid {} + +impl Valid for () {} + +fn main() { + Iterate::iterate(0); +} diff --git a/tests/ui/specialization/issue-38091-2.stderr b/tests/ui/specialization/issue-38091-2.stderr new file mode 100644 index 000000000..5a05f9c27 --- /dev/null +++ b/tests/ui/specialization/issue-38091-2.stderr @@ -0,0 +1,24 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-38091-2.rs:4:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +error[E0275]: overflow evaluating the requirement `i32: Check` + | +note: required for `i32` to implement `Iterate<'_>` + --> $DIR/issue-38091-2.rs:11:13 + | +LL | impl<'a, T> Iterate<'a> for T + | ^^^^^^^^^^^ ^ +LL | where +LL | T: Check, + | ----- unsatisfied trait bound introduced here + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/specialization/issue-38091.rs b/tests/ui/specialization/issue-38091.rs new file mode 100644 index 000000000..5b398368a --- /dev/null +++ b/tests/ui/specialization/issue-38091.rs @@ -0,0 +1,24 @@ +#![feature(specialization)] +//~^ WARN the feature `specialization` is incomplete + +trait Iterate<'a> { + type Ty: Valid; + fn iterate(self); +} +impl<'a, T> Iterate<'a> for T +where + T: Check, +{ + default type Ty = (); + //~^ ERROR the trait bound `(): Valid` is not satisfied + default fn iterate(self) {} +} + +trait Check {} +impl<'a, T> Check for T where <T as Iterate<'a>>::Ty: Valid {} + +trait Valid {} + +fn main() { + Iterate::iterate(0); +} diff --git a/tests/ui/specialization/issue-38091.stderr b/tests/ui/specialization/issue-38091.stderr new file mode 100644 index 000000000..f2210a407 --- /dev/null +++ b/tests/ui/specialization/issue-38091.stderr @@ -0,0 +1,25 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-38091.rs:1:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +error[E0277]: the trait bound `(): Valid` is not satisfied + --> $DIR/issue-38091.rs:12:23 + | +LL | default type Ty = (); + | ^^ the trait `Valid` is not implemented for `()` + | +note: required by a bound in `Iterate::Ty` + --> $DIR/issue-38091.rs:5:14 + | +LL | type Ty: Valid; + | ^^^^^ required by this bound in `Iterate::Ty` + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/specialization/issue-39448.rs b/tests/ui/specialization/issue-39448.rs new file mode 100644 index 000000000..a15c4bd6b --- /dev/null +++ b/tests/ui/specialization/issue-39448.rs @@ -0,0 +1,50 @@ +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +// Regression test for a specialization-related ICE (#39448). + +trait A: Sized { + fn foo(self, _: Self) -> Self { + self + } +} + +impl A for u8 {} +impl A for u16 {} + +impl FromA<u8> for u16 { + fn from(x: u8) -> u16 { + x as u16 + } +} + +trait FromA<T> { + fn from(t: T) -> Self; +} + +impl<T: A, U: A + FromA<T>> FromA<T> for U { + default fn from(x: T) -> Self { + ToA::to(x) + } +} + +trait ToA<T> { + fn to(self) -> T; +} + +impl<T, U> ToA<U> for T +where + U: FromA<T>, +{ + fn to(self) -> U { + U::from(self) + } +} + +#[allow(dead_code)] +fn foo<T: A, U: A>(x: T, y: U) -> U { + x.foo(y.to()).to() //~ ERROR overflow evaluating the requirement +} + +fn main() { + let z = foo(8u8, 1u16); +} diff --git a/tests/ui/specialization/issue-39448.stderr b/tests/ui/specialization/issue-39448.stderr new file mode 100644 index 000000000..9ce51d113 --- /dev/null +++ b/tests/ui/specialization/issue-39448.stderr @@ -0,0 +1,35 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-39448.rs:1:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +error[E0275]: overflow evaluating the requirement `T: FromA<U>` + --> $DIR/issue-39448.rs:45:13 + | +LL | x.foo(y.to()).to() + | ^^ + | +note: required for `T` to implement `FromA<U>` + --> $DIR/issue-39448.rs:24:29 + | +LL | impl<T: A, U: A + FromA<T>> FromA<T> for U { + | -------- ^^^^^^^^ ^ + | | + | unsatisfied trait bound introduced here +note: required for `U` to implement `ToA<T>` + --> $DIR/issue-39448.rs:34:12 + | +LL | impl<T, U> ToA<U> for T + | ^^^^^^ ^ +LL | where +LL | U: FromA<T>, + | -------- unsatisfied trait bound introduced here + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/specialization/issue-39618.rs b/tests/ui/specialization/issue-39618.rs new file mode 100644 index 000000000..72630ee9c --- /dev/null +++ b/tests/ui/specialization/issue-39618.rs @@ -0,0 +1,27 @@ +// Regression test for #39618, shouldn't crash. +// FIXME(JohnTitor): Centril pointed out this looks suspicions, we should revisit here. +// More context: https://github.com/rust-lang/rust/pull/69192#discussion_r379846796 + +// check-pass + +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +trait Foo { + fn foo(&self); +} + +trait Bar { + fn bar(&self); +} + +impl<T> Bar for T where T: Foo { + fn bar(&self) {} +} + +impl<T> Foo for T where T: Bar { + fn foo(&self) {} +} + +impl Foo for u64 {} + +fn main() {} diff --git a/tests/ui/specialization/issue-39618.stderr b/tests/ui/specialization/issue-39618.stderr new file mode 100644 index 000000000..19de60c7c --- /dev/null +++ b/tests/ui/specialization/issue-39618.stderr @@ -0,0 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-39618.rs:7:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/specialization/issue-43037.current.stderr b/tests/ui/specialization/issue-43037.current.stderr new file mode 100644 index 000000000..26db9d7c9 --- /dev/null +++ b/tests/ui/specialization/issue-43037.current.stderr @@ -0,0 +1,12 @@ +error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`) + --> $DIR/issue-43037.rs:19:6 + | +LL | impl<T> From<<A<T> as Z>::Assoc> for T {} + | ^ type parameter `T` must be used as the type parameter for some local type + | + = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local + = note: only traits defined in the current crate can be implemented for a type parameter + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0210`. diff --git a/tests/ui/specialization/issue-43037.negative.stderr b/tests/ui/specialization/issue-43037.negative.stderr new file mode 100644 index 000000000..26db9d7c9 --- /dev/null +++ b/tests/ui/specialization/issue-43037.negative.stderr @@ -0,0 +1,12 @@ +error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`) + --> $DIR/issue-43037.rs:19:6 + | +LL | impl<T> From<<A<T> as Z>::Assoc> for T {} + | ^ type parameter `T` must be used as the type parameter for some local type + | + = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local + = note: only traits defined in the current crate can be implemented for a type parameter + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0210`. diff --git a/tests/ui/specialization/issue-43037.rs b/tests/ui/specialization/issue-43037.rs new file mode 100644 index 000000000..a1e3f998b --- /dev/null +++ b/tests/ui/specialization/issue-43037.rs @@ -0,0 +1,22 @@ +// revisions: current negative +#![feature(specialization)] +#![cfg_attr(negative, feature(with_negative_coherence))] +#![allow(incomplete_features)] + +trait X {} +trait Y: X {} +trait Z { + type Assoc: Y; +} +struct A<T>(T); + +impl<T> Y for T where T: X {} +impl<T: X> Z for A<T> { + type Assoc = T; +} + +// this impl is invalid, but causes an ICE anyway +impl<T> From<<A<T> as Z>::Assoc> for T {} +//~^ ERROR type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`) + +fn main() {} diff --git a/tests/ui/specialization/issue-44861.rs b/tests/ui/specialization/issue-44861.rs new file mode 100644 index 000000000..79d9b9490 --- /dev/null +++ b/tests/ui/specialization/issue-44861.rs @@ -0,0 +1,40 @@ +#![crate_type = "lib"] +#![feature(specialization)] +#![feature(unsize, coerce_unsized)] +#![allow(incomplete_features)] + +use std::ops::CoerceUnsized; + +pub struct SmartassPtr<A: Smartass+?Sized>(A::Data); + +pub trait Smartass { + type Data; + type Data2: CoerceUnsized<*const [u8]>; +} + +pub trait MaybeObjectSafe {} + +impl MaybeObjectSafe for () {} + +impl<T> Smartass for T { + type Data = <Self as Smartass>::Data2; + default type Data2 = (); + //~^ ERROR: the trait bound `(): CoerceUnsized<*const [u8]>` is not satisfied +} + +impl Smartass for () { + type Data2 = *const [u8; 1]; +} + +impl Smartass for dyn MaybeObjectSafe { + type Data = *const [u8]; + type Data2 = *const [u8; 0]; +} + +impl<U: Smartass+?Sized, T: Smartass+?Sized> CoerceUnsized<SmartassPtr<T>> for SmartassPtr<U> + where <U as Smartass>::Data: std::ops::CoerceUnsized<<T as Smartass>::Data> +{} + +pub fn conv(s: SmartassPtr<()>) -> SmartassPtr<dyn MaybeObjectSafe> { + s +} diff --git a/tests/ui/specialization/issue-44861.stderr b/tests/ui/specialization/issue-44861.stderr new file mode 100644 index 000000000..1941d40fe --- /dev/null +++ b/tests/ui/specialization/issue-44861.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `(): CoerceUnsized<*const [u8]>` is not satisfied + --> $DIR/issue-44861.rs:21:26 + | +LL | default type Data2 = (); + | ^^ the trait `CoerceUnsized<*const [u8]>` is not implemented for `()` + | +note: required by a bound in `Smartass::Data2` + --> $DIR/issue-44861.rs:12:17 + | +LL | type Data2: CoerceUnsized<*const [u8]>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Smartass::Data2` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/specialization/issue-45814.current.stderr b/tests/ui/specialization/issue-45814.current.stderr new file mode 100644 index 000000000..5013559b8 --- /dev/null +++ b/tests/ui/specialization/issue-45814.current.stderr @@ -0,0 +1,14 @@ +error[E0275]: overflow evaluating the requirement `T: Trait<_>` + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_45814`) +note: required for `T` to implement `Trait<_>` + --> $DIR/issue-45814.rs:9:20 + | +LL | default impl<T, U> Trait<T> for U {} + | ^^^^^^^^ ^ + = note: 128 redundant requirements hidden + = note: required for `T` to implement `Trait<_>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/specialization/issue-45814.negative.stderr b/tests/ui/specialization/issue-45814.negative.stderr new file mode 100644 index 000000000..5013559b8 --- /dev/null +++ b/tests/ui/specialization/issue-45814.negative.stderr @@ -0,0 +1,14 @@ +error[E0275]: overflow evaluating the requirement `T: Trait<_>` + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_45814`) +note: required for `T` to implement `Trait<_>` + --> $DIR/issue-45814.rs:9:20 + | +LL | default impl<T, U> Trait<T> for U {} + | ^^^^^^^^ ^ + = note: 128 redundant requirements hidden + = note: required for `T` to implement `Trait<_>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/specialization/issue-45814.rs b/tests/ui/specialization/issue-45814.rs new file mode 100644 index 000000000..fce236390 --- /dev/null +++ b/tests/ui/specialization/issue-45814.rs @@ -0,0 +1,13 @@ +//~ ERROR overflow evaluating the requirement `T: Trait<_>` +// revisions: current negative +#![feature(specialization)] +#![cfg_attr(negative, feature(with_negative_coherence))] +#![allow(incomplete_features)] + +pub trait Trait<T> {} + +default impl<T, U> Trait<T> for U {} + +impl<T> Trait<<T as Iterator>::Item> for T {} + +fn main() {} diff --git a/tests/ui/specialization/issue-50452-fail.rs b/tests/ui/specialization/issue-50452-fail.rs new file mode 100644 index 000000000..fe21e9b6e --- /dev/null +++ b/tests/ui/specialization/issue-50452-fail.rs @@ -0,0 +1,21 @@ +#![feature(specialization)] +//~^ WARN the feature `specialization` is incomplete + +pub trait Foo { + fn foo(); +} + +impl Foo for i32 {} +impl Foo for i64 { + fn foo() {} + //~^ERROR `foo` specializes an item from a parent `impl` +} +impl<T> Foo for T { + fn foo() {} +} + +fn main() { + i32::foo(); + i64::foo(); + u8::foo(); +} diff --git a/tests/ui/specialization/issue-50452-fail.stderr b/tests/ui/specialization/issue-50452-fail.stderr new file mode 100644 index 000000000..5c136adc4 --- /dev/null +++ b/tests/ui/specialization/issue-50452-fail.stderr @@ -0,0 +1,24 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-50452-fail.rs:1:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +error[E0520]: `foo` specializes an item from a parent `impl`, but that item is not marked `default` + --> $DIR/issue-50452-fail.rs:10:5 + | +LL | fn foo() {} + | ^^^^^^^^^^^ cannot specialize default item `foo` +... +LL | impl<T> Foo for T { + | ----------------- parent `impl` is here + | + = note: to specialize, `foo` in the parent `impl` must be marked `default` + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0520`. diff --git a/tests/ui/specialization/issue-50452.rs b/tests/ui/specialization/issue-50452.rs new file mode 100644 index 000000000..29fc12066 --- /dev/null +++ b/tests/ui/specialization/issue-50452.rs @@ -0,0 +1,19 @@ +// run-pass + +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +pub trait Foo { + fn foo(); +} + +impl Foo for i32 {} +impl Foo for i64 {} +impl<T> Foo for T { + fn foo() {} +} + +fn main() { + i32::foo(); + i64::foo(); + u8::foo(); +} diff --git a/tests/ui/specialization/issue-50452.stderr b/tests/ui/specialization/issue-50452.stderr new file mode 100644 index 000000000..48cab9dcd --- /dev/null +++ b/tests/ui/specialization/issue-50452.stderr @@ -0,0 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-50452.rs:3:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/specialization/issue-51892.rs b/tests/ui/specialization/issue-51892.rs new file mode 100644 index 000000000..5c0625414 --- /dev/null +++ b/tests/ui/specialization/issue-51892.rs @@ -0,0 +1,18 @@ +#![allow(incomplete_features)] +#![feature(generic_const_exprs)] +#![feature(specialization)] + +pub trait Trait { + type Type; +} + +impl<T: ?Sized> Trait for T { + default type Type = [u8; 1]; +} + +impl<T: Trait> Trait for *const T { + type Type = [u8; std::mem::size_of::<<T as Trait>::Type>()]; + //~^ ERROR: unconstrained generic constant +} + +fn main() {} diff --git a/tests/ui/specialization/issue-51892.stderr b/tests/ui/specialization/issue-51892.stderr new file mode 100644 index 000000000..cb46db836 --- /dev/null +++ b/tests/ui/specialization/issue-51892.stderr @@ -0,0 +1,10 @@ +error: unconstrained generic constant + --> $DIR/issue-51892.rs:14:17 + | +LL | type Type = [u8; std::mem::size_of::<<T as Trait>::Type>()]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); std::mem::size_of::<<T as Trait>::Type>()]:` + +error: aborting due to previous error + diff --git a/tests/ui/specialization/issue-52050.rs b/tests/ui/specialization/issue-52050.rs new file mode 100644 index 000000000..804658702 --- /dev/null +++ b/tests/ui/specialization/issue-52050.rs @@ -0,0 +1,32 @@ +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +// Regression test for #52050: when inserting the blanket impl `I` +// into the tree, we had to replace the child node for `Foo`, which +// led to the structure of the tree being messed up. + +use std::iter::Iterator; + +trait IntoPyDictPointer { } + +struct Foo { } + +impl Iterator for Foo { + type Item = (); + fn next(&mut self) -> Option<()> { + None + } +} + +impl IntoPyDictPointer for Foo { } + +impl<I> IntoPyDictPointer for I +where + I: Iterator, +{ +} + +impl IntoPyDictPointer for () //~ ERROR conflicting implementations +{ +} + +fn main() { } diff --git a/tests/ui/specialization/issue-52050.stderr b/tests/ui/specialization/issue-52050.stderr new file mode 100644 index 000000000..c263fe467 --- /dev/null +++ b/tests/ui/specialization/issue-52050.stderr @@ -0,0 +1,24 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-52050.rs:1:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +error[E0119]: conflicting implementations of trait `IntoPyDictPointer` for type `()` + --> $DIR/issue-52050.rs:28:1 + | +LL | impl<I> IntoPyDictPointer for I + | ------------------------------- first implementation here +... +LL | impl IntoPyDictPointer for () + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `()` + | + = note: upstream crates may add a new impl of trait `std::iter::Iterator` for type `()` in future versions + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/specialization/issue-59435.rs b/tests/ui/specialization/issue-59435.rs new file mode 100644 index 000000000..323900256 --- /dev/null +++ b/tests/ui/specialization/issue-59435.rs @@ -0,0 +1,17 @@ +#![feature(specialization)] +#![allow(incomplete_features)] + +struct MyStruct {} + +trait MyTrait { + type MyType: Default; +} + +impl MyTrait for i32 { + default type MyType = MyStruct; + //~^ ERROR: the trait bound `MyStruct: Default` is not satisfied +} + +fn main() { + let _x: <i32 as MyTrait>::MyType = <i32 as MyTrait>::MyType::default(); +} diff --git a/tests/ui/specialization/issue-59435.stderr b/tests/ui/specialization/issue-59435.stderr new file mode 100644 index 000000000..211459406 --- /dev/null +++ b/tests/ui/specialization/issue-59435.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `MyStruct: Default` is not satisfied + --> $DIR/issue-59435.rs:11:27 + | +LL | default type MyType = MyStruct; + | ^^^^^^^^ the trait `Default` is not implemented for `MyStruct` + | +note: required by a bound in `MyTrait::MyType` + --> $DIR/issue-59435.rs:7:18 + | +LL | type MyType: Default; + | ^^^^^^^ required by this bound in `MyTrait::MyType` +help: consider annotating `MyStruct` with `#[derive(Default)]` + | +LL | #[derive(Default)] + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/specialization/issue-63716-parse-async.rs b/tests/ui/specialization/issue-63716-parse-async.rs new file mode 100644 index 000000000..10f185c33 --- /dev/null +++ b/tests/ui/specialization/issue-63716-parse-async.rs @@ -0,0 +1,14 @@ +// Ensure that `default async fn` will parse. +// See issue #63716 for details. + +// check-pass +// edition:2018 + +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +fn main() {} + +#[cfg(FALSE)] +impl Foo for Bar { + default async fn baz() {} +} diff --git a/tests/ui/specialization/issue-63716-parse-async.stderr b/tests/ui/specialization/issue-63716-parse-async.stderr new file mode 100644 index 000000000..a00572da8 --- /dev/null +++ b/tests/ui/specialization/issue-63716-parse-async.stderr @@ -0,0 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-63716-parse-async.rs:7:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/specialization/issue-68830-spurious-diagnostics.rs b/tests/ui/specialization/issue-68830-spurious-diagnostics.rs new file mode 100644 index 000000000..d11ec7983 --- /dev/null +++ b/tests/ui/specialization/issue-68830-spurious-diagnostics.rs @@ -0,0 +1,23 @@ +// A regression test for #68830. This checks we don't emit +// a verbose `conflicting implementations` error. + +#![feature(specialization)] +#![allow(incomplete_features)] + +struct BadStruct { + err: MissingType //~ ERROR: cannot find type `MissingType` in this scope +} + +trait MyTrait<T> { + fn foo(); +} + +impl<T, D> MyTrait<T> for D { + default fn foo() {} +} + +impl<T> MyTrait<T> for BadStruct { + fn foo() {} +} + +fn main() {} diff --git a/tests/ui/specialization/issue-68830-spurious-diagnostics.stderr b/tests/ui/specialization/issue-68830-spurious-diagnostics.stderr new file mode 100644 index 000000000..833f61dca --- /dev/null +++ b/tests/ui/specialization/issue-68830-spurious-diagnostics.stderr @@ -0,0 +1,9 @@ +error[E0412]: cannot find type `MissingType` in this scope + --> $DIR/issue-68830-spurious-diagnostics.rs:8:10 + | +LL | err: MissingType + | ^^^^^^^^^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/specialization/issue-70442.rs b/tests/ui/specialization/issue-70442.rs new file mode 100644 index 000000000..d41b5355c --- /dev/null +++ b/tests/ui/specialization/issue-70442.rs @@ -0,0 +1,23 @@ +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +// check-pass + +trait Trait { + type Assoc; +} + +impl<T> Trait for T { + default type Assoc = bool; +} + +// This impl inherits the `Assoc` definition from above and "locks it in", or finalizes it, making +// child impls unable to further specialize it. However, since the specialization graph didn't +// correctly track this, we would refuse to project `Assoc` from this impl, even though that should +// happen for items that are final. +impl Trait for () {} + +fn foo<X: Trait<Assoc=bool>>() {} + +fn main() { + foo::<()>(); // `<() as Trait>::Assoc` is normalized to `bool` correctly +} diff --git a/tests/ui/specialization/issue-70442.stderr b/tests/ui/specialization/issue-70442.stderr new file mode 100644 index 000000000..aa72c3286 --- /dev/null +++ b/tests/ui/specialization/issue-70442.stderr @@ -0,0 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-70442.rs:1:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/specialization/min_specialization/auxiliary/specialization-trait.rs b/tests/ui/specialization/min_specialization/auxiliary/specialization-trait.rs new file mode 100644 index 000000000..6ec0d261d --- /dev/null +++ b/tests/ui/specialization/min_specialization/auxiliary/specialization-trait.rs @@ -0,0 +1,6 @@ +#![feature(rustc_attrs)] + +#[rustc_specialization_trait] +pub trait SpecTrait { + fn method(&self); +} diff --git a/tests/ui/specialization/min_specialization/dyn-trait-assoc-types.rs b/tests/ui/specialization/min_specialization/dyn-trait-assoc-types.rs new file mode 100644 index 000000000..03cab00b0 --- /dev/null +++ b/tests/ui/specialization/min_specialization/dyn-trait-assoc-types.rs @@ -0,0 +1,32 @@ +// Test that associated types in trait objects are not considered to be +// constrained. + +#![feature(min_specialization)] + +trait Specializable { + fn f(); +} + +trait B<T> { + type Y; +} + +trait C { + type Y; +} + +impl<A: ?Sized> Specializable for A { + default fn f() {} +} + +impl<'a, T> Specializable for dyn B<T, Y = T> + 'a { + //~^ ERROR specializing impl repeats parameter `T` + fn f() {} +} + +impl<'a, T> Specializable for dyn C<Y = (T, T)> + 'a { + //~^ ERROR specializing impl repeats parameter `T` + fn f() {} +} + +fn main() {} diff --git a/tests/ui/specialization/min_specialization/dyn-trait-assoc-types.stderr b/tests/ui/specialization/min_specialization/dyn-trait-assoc-types.stderr new file mode 100644 index 000000000..db5558f16 --- /dev/null +++ b/tests/ui/specialization/min_specialization/dyn-trait-assoc-types.stderr @@ -0,0 +1,14 @@ +error: specializing impl repeats parameter `T` + --> $DIR/dyn-trait-assoc-types.rs:22:1 + | +LL | impl<'a, T> Specializable for dyn B<T, Y = T> + 'a { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: specializing impl repeats parameter `T` + --> $DIR/dyn-trait-assoc-types.rs:27:1 + | +LL | impl<'a, T> Specializable for dyn C<Y = (T, T)> + 'a { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/specialization/min_specialization/impl-on-nonexisting.rs b/tests/ui/specialization/min_specialization/impl-on-nonexisting.rs new file mode 100644 index 000000000..77a64320d --- /dev/null +++ b/tests/ui/specialization/min_specialization/impl-on-nonexisting.rs @@ -0,0 +1,7 @@ +#![feature(min_specialization)] + +trait Trait {} +impl Trait for NonExistent {} +//~^ ERROR cannot find type `NonExistent` in this scope + +fn main() {} diff --git a/tests/ui/specialization/min_specialization/impl-on-nonexisting.stderr b/tests/ui/specialization/min_specialization/impl-on-nonexisting.stderr new file mode 100644 index 000000000..b032ccbe5 --- /dev/null +++ b/tests/ui/specialization/min_specialization/impl-on-nonexisting.stderr @@ -0,0 +1,9 @@ +error[E0412]: cannot find type `NonExistent` in this scope + --> $DIR/impl-on-nonexisting.rs:4:16 + | +LL | impl Trait for NonExistent {} + | ^^^^^^^^^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/specialization/min_specialization/impl_specialization_trait.rs b/tests/ui/specialization/min_specialization/impl_specialization_trait.rs new file mode 100644 index 000000000..723ed71c3 --- /dev/null +++ b/tests/ui/specialization/min_specialization/impl_specialization_trait.rs @@ -0,0 +1,16 @@ +// Check that specialization traits can't be implemented without a feature. + +// gate-test-min_specialization + +// aux-build:specialization-trait.rs + +extern crate specialization_trait; + +struct A {} + +impl specialization_trait::SpecTrait for A { + //~^ ERROR implementing `rustc_specialization_trait` traits is unstable + fn method(&self) {} +} + +fn main() {} diff --git a/tests/ui/specialization/min_specialization/impl_specialization_trait.stderr b/tests/ui/specialization/min_specialization/impl_specialization_trait.stderr new file mode 100644 index 000000000..934103d49 --- /dev/null +++ b/tests/ui/specialization/min_specialization/impl_specialization_trait.stderr @@ -0,0 +1,10 @@ +error: implementing `rustc_specialization_trait` traits is unstable + --> $DIR/impl_specialization_trait.rs:11:1 + | +LL | impl specialization_trait::SpecTrait for A { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(min_specialization)]` to the crate attributes to enable + +error: aborting due to previous error + diff --git a/tests/ui/specialization/min_specialization/implcit-well-formed-bounds.rs b/tests/ui/specialization/min_specialization/implcit-well-formed-bounds.rs new file mode 100644 index 000000000..98d7f9194 --- /dev/null +++ b/tests/ui/specialization/min_specialization/implcit-well-formed-bounds.rs @@ -0,0 +1,30 @@ +// Test that specializing on the well-formed predicates of the trait and +// self-type of an impl is allowed. + +// check-pass + +#![feature(min_specialization)] + +struct OrdOnly<T: Ord>(T); + +trait SpecTrait<U> { + fn f(); +} + +impl<T, U> SpecTrait<U> for T { + default fn f() {} +} + +impl<T: Ord> SpecTrait<()> for OrdOnly<T> { + fn f() {} +} + +impl<T: Ord> SpecTrait<OrdOnly<T>> for () { + fn f() {} +} + +impl<T: Ord, U: Ord, V: Ord> SpecTrait<(OrdOnly<T>, OrdOnly<U>)> for &[OrdOnly<V>] { + fn f() {} +} + +fn main() {} diff --git a/tests/ui/specialization/min_specialization/issue-79224.rs b/tests/ui/specialization/min_specialization/issue-79224.rs new file mode 100644 index 000000000..104bddd07 --- /dev/null +++ b/tests/ui/specialization/min_specialization/issue-79224.rs @@ -0,0 +1,26 @@ +#![feature(min_specialization)] +use std::fmt::{self, Display}; + +pub enum Cow<'a, B: ?Sized + 'a, O = <B as ToOwned>::Owned> +where + B: ToOwned, +{ + Borrowed(&'a B), + Owned(O), +} + +impl ToString for Cow<'_, str> { + fn to_string(&self) -> String { + String::new() + } +} + +impl<B: ?Sized> Display for Cow<'_, B> { + //~^ ERROR: the trait bound `B: Clone` is not satisfied [E0277] + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + //~^ ERROR: the trait bound `B: Clone` is not satisfied [E0277] + write!(f, "foo") + } +} + +fn main() {} diff --git a/tests/ui/specialization/min_specialization/issue-79224.stderr b/tests/ui/specialization/min_specialization/issue-79224.stderr new file mode 100644 index 000000000..505baa23c --- /dev/null +++ b/tests/ui/specialization/min_specialization/issue-79224.stderr @@ -0,0 +1,27 @@ +error[E0277]: the trait bound `B: Clone` is not satisfied + --> $DIR/issue-79224.rs:18:29 + | +LL | impl<B: ?Sized> Display for Cow<'_, B> { + | ^^^^^^^^^^ the trait `Clone` is not implemented for `B` + | + = note: required for `B` to implement `ToOwned` +help: consider further restricting this bound + | +LL | impl<B: ?Sized + std::clone::Clone> Display for Cow<'_, B> { + | +++++++++++++++++++ + +error[E0277]: the trait bound `B: Clone` is not satisfied + --> $DIR/issue-79224.rs:20:12 + | +LL | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + | ^^^^^ the trait `Clone` is not implemented for `B` + | + = note: required for `B` to implement `ToOwned` +help: consider further restricting this bound + | +LL | impl<B: ?Sized + std::clone::Clone> Display for Cow<'_, B> { + | +++++++++++++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/specialization/min_specialization/repeated_projection_type.rs b/tests/ui/specialization/min_specialization/repeated_projection_type.rs new file mode 100644 index 000000000..f21f39f06 --- /dev/null +++ b/tests/ui/specialization/min_specialization/repeated_projection_type.rs @@ -0,0 +1,24 @@ +// Test that projection bounds can't be specialized on. + +#![feature(min_specialization)] + +trait X { + fn f(); +} +trait Id { + type This; +} +impl<T> Id for T { + type This = T; +} + +impl<T: Id> X for T { + default fn f() {} +} + +impl<I, V: Id<This = (I,)>> X for V { + //~^ ERROR cannot specialize on + fn f() {} +} + +fn main() {} diff --git a/tests/ui/specialization/min_specialization/repeated_projection_type.stderr b/tests/ui/specialization/min_specialization/repeated_projection_type.stderr new file mode 100644 index 000000000..a751ba793 --- /dev/null +++ b/tests/ui/specialization/min_specialization/repeated_projection_type.stderr @@ -0,0 +1,8 @@ +error: cannot specialize on associated type `<V as Id>::This == (I,)` + --> $DIR/repeated_projection_type.rs:19:15 + | +LL | impl<I, V: Id<This = (I,)>> X for V { + | ^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/specialization/min_specialization/repeating_lifetimes.rs b/tests/ui/specialization/min_specialization/repeating_lifetimes.rs new file mode 100644 index 000000000..49bfacec0 --- /dev/null +++ b/tests/ui/specialization/min_specialization/repeating_lifetimes.rs @@ -0,0 +1,19 @@ +// Test that directly specializing on repeated lifetime parameters is not +// allowed. + +#![feature(min_specialization)] + +trait X { + fn f(); +} + +impl<T> X for T { + default fn f() {} +} + +impl<'a> X for (&'a u8, &'a u8) { + //~^ ERROR specializing impl repeats parameter `'a` + fn f() {} +} + +fn main() {} diff --git a/tests/ui/specialization/min_specialization/repeating_lifetimes.stderr b/tests/ui/specialization/min_specialization/repeating_lifetimes.stderr new file mode 100644 index 000000000..16dccb10b --- /dev/null +++ b/tests/ui/specialization/min_specialization/repeating_lifetimes.stderr @@ -0,0 +1,8 @@ +error: specializing impl repeats parameter `'a` + --> $DIR/repeating_lifetimes.rs:14:1 + | +LL | impl<'a> X for (&'a u8, &'a u8) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/specialization/min_specialization/repeating_param.rs b/tests/ui/specialization/min_specialization/repeating_param.rs new file mode 100644 index 000000000..5a1c97fd3 --- /dev/null +++ b/tests/ui/specialization/min_specialization/repeating_param.rs @@ -0,0 +1,17 @@ +// Test that specializing on two type parameters being equal is not allowed. + +#![feature(min_specialization)] + +trait X { + fn f(); +} + +impl<T> X for T { + default fn f() {} +} +impl<T> X for (T, T) { + //~^ ERROR specializing impl repeats parameter `T` + fn f() {} +} + +fn main() {} diff --git a/tests/ui/specialization/min_specialization/repeating_param.stderr b/tests/ui/specialization/min_specialization/repeating_param.stderr new file mode 100644 index 000000000..5e6adf723 --- /dev/null +++ b/tests/ui/specialization/min_specialization/repeating_param.stderr @@ -0,0 +1,8 @@ +error: specializing impl repeats parameter `T` + --> $DIR/repeating_param.rs:12:1 + | +LL | impl<T> X for (T, T) { + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/specialization/min_specialization/spec-iter.rs b/tests/ui/specialization/min_specialization/spec-iter.rs new file mode 100644 index 000000000..e17e9dd5f --- /dev/null +++ b/tests/ui/specialization/min_specialization/spec-iter.rs @@ -0,0 +1,20 @@ +// Check that we can specialize on a concrete iterator type. This requires us +// to consider which parameters in the parent impl are constrained. + +// check-pass + +#![feature(min_specialization)] + +trait SpecFromIter<T> { + fn f(&self); +} + +impl<'a, T: 'a, I: Iterator<Item = &'a T>> SpecFromIter<T> for I { + default fn f(&self) {} +} + +impl<'a, T> SpecFromIter<T> for std::slice::Iter<'a, T> { + fn f(&self) {} +} + +fn main() {} diff --git a/tests/ui/specialization/min_specialization/spec-marker-supertraits.rs b/tests/ui/specialization/min_specialization/spec-marker-supertraits.rs new file mode 100644 index 000000000..3bb2480e9 --- /dev/null +++ b/tests/ui/specialization/min_specialization/spec-marker-supertraits.rs @@ -0,0 +1,29 @@ +// Check that supertraits cannot be used to work around min_specialization +// limitations. + +#![feature(min_specialization)] +#![feature(rustc_attrs)] + +trait HasMethod { + fn method(&self); +} + +#[rustc_unsafe_specialization_marker] +trait Marker: HasMethod {} + +trait Spec { + fn spec_me(&self); +} + +impl<T> Spec for T { + default fn spec_me(&self) {} +} + +impl<T: Marker> Spec for T { + //~^ ERROR cannot specialize on trait `HasMethod` + fn spec_me(&self) { + self.method(); + } +} + +fn main() {} diff --git a/tests/ui/specialization/min_specialization/spec-marker-supertraits.stderr b/tests/ui/specialization/min_specialization/spec-marker-supertraits.stderr new file mode 100644 index 000000000..ba9d6bbe3 --- /dev/null +++ b/tests/ui/specialization/min_specialization/spec-marker-supertraits.stderr @@ -0,0 +1,8 @@ +error: cannot specialize on trait `HasMethod` + --> $DIR/spec-marker-supertraits.rs:22:9 + | +LL | impl<T: Marker> Spec for T { + | ^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/specialization/min_specialization/spec-reference.rs b/tests/ui/specialization/min_specialization/spec-reference.rs new file mode 100644 index 000000000..377889e2c --- /dev/null +++ b/tests/ui/specialization/min_specialization/spec-reference.rs @@ -0,0 +1,19 @@ +// Check that lifetime parameters are allowed in specializing impls. + +// check-pass + +#![feature(min_specialization)] + +trait MySpecTrait { + fn f(); +} + +impl<T> MySpecTrait for T { + default fn f() {} +} + +impl<'a, T: ?Sized> MySpecTrait for &'a T { + fn f() {} +} + +fn main() {} diff --git a/tests/ui/specialization/min_specialization/specialization_marker.rs b/tests/ui/specialization/min_specialization/specialization_marker.rs new file mode 100644 index 000000000..93462d02e --- /dev/null +++ b/tests/ui/specialization/min_specialization/specialization_marker.rs @@ -0,0 +1,17 @@ +// Test that `rustc_unsafe_specialization_marker` is only allowed on marker traits. + +#![feature(rustc_attrs)] + +#[rustc_unsafe_specialization_marker] +trait SpecMarker { + fn f(); + //~^ ERROR marker traits +} + +#[rustc_unsafe_specialization_marker] +trait SpecMarker2 { + type X; + //~^ ERROR marker traits +} + +fn main() {} diff --git a/tests/ui/specialization/min_specialization/specialization_marker.stderr b/tests/ui/specialization/min_specialization/specialization_marker.stderr new file mode 100644 index 000000000..b47c14f3c --- /dev/null +++ b/tests/ui/specialization/min_specialization/specialization_marker.stderr @@ -0,0 +1,15 @@ +error[E0714]: marker traits cannot have associated items + --> $DIR/specialization_marker.rs:7:5 + | +LL | fn f(); + | ^^^^^^^ + +error[E0714]: marker traits cannot have associated items + --> $DIR/specialization_marker.rs:13:5 + | +LL | type X; + | ^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0714`. diff --git a/tests/ui/specialization/min_specialization/specialization_super_trait.rs b/tests/ui/specialization/min_specialization/specialization_super_trait.rs new file mode 100644 index 000000000..145f376ed --- /dev/null +++ b/tests/ui/specialization/min_specialization/specialization_super_trait.rs @@ -0,0 +1,18 @@ +// Test that supertraits can't be assumed in impls of +// `rustc_specialization_trait`, as such impls would +// allow specializing on the supertrait. + +#![feature(min_specialization)] +#![feature(rustc_attrs)] + +#[rustc_specialization_trait] +trait SpecMarker: Default { + fn f(); +} + +impl<T: Default> SpecMarker for T { + //~^ ERROR cannot specialize + fn f() {} +} + +fn main() {} diff --git a/tests/ui/specialization/min_specialization/specialization_super_trait.stderr b/tests/ui/specialization/min_specialization/specialization_super_trait.stderr new file mode 100644 index 000000000..e93578662 --- /dev/null +++ b/tests/ui/specialization/min_specialization/specialization_super_trait.stderr @@ -0,0 +1,8 @@ +error: cannot specialize on trait `Default` + --> $DIR/specialization_super_trait.rs:13:9 + | +LL | impl<T: Default> SpecMarker for T { + | ^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/specialization/min_specialization/specialization_trait.rs b/tests/ui/specialization/min_specialization/specialization_trait.rs new file mode 100644 index 000000000..d597278d2 --- /dev/null +++ b/tests/ui/specialization/min_specialization/specialization_trait.rs @@ -0,0 +1,26 @@ +// Test that `rustc_specialization_trait` requires always applicable impls. + +#![feature(min_specialization)] +#![feature(rustc_attrs)] + +#[rustc_specialization_trait] +trait SpecMarker { + fn f(); +} + +impl SpecMarker for &'static u8 { + //~^ ERROR cannot specialize + fn f() {} +} + +impl<T> SpecMarker for (T, T) { + //~^ ERROR specializing impl + fn f() {} +} + +impl<T: Clone> SpecMarker for [T] { + //~^ ERROR cannot specialize + fn f() {} +} + +fn main() {} diff --git a/tests/ui/specialization/min_specialization/specialization_trait.stderr b/tests/ui/specialization/min_specialization/specialization_trait.stderr new file mode 100644 index 000000000..bc87ae0f8 --- /dev/null +++ b/tests/ui/specialization/min_specialization/specialization_trait.stderr @@ -0,0 +1,20 @@ +error: cannot specialize on `'static` lifetime + --> $DIR/specialization_trait.rs:11:1 + | +LL | impl SpecMarker for &'static u8 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: specializing impl repeats parameter `T` + --> $DIR/specialization_trait.rs:16:1 + | +LL | impl<T> SpecMarker for (T, T) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: cannot specialize on trait `Clone` + --> $DIR/specialization_trait.rs:21:9 + | +LL | impl<T: Clone> SpecMarker for [T] { + | ^^^^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/specialization/min_specialization/specialize_on_marker.rs b/tests/ui/specialization/min_specialization/specialize_on_marker.rs new file mode 100644 index 000000000..4219bd13b --- /dev/null +++ b/tests/ui/specialization/min_specialization/specialize_on_marker.rs @@ -0,0 +1,24 @@ +// Test that specializing on a `rustc_unsafe_specialization_marker` trait is +// allowed. + +// check-pass + +#![feature(min_specialization)] +#![feature(rustc_attrs)] + +#[rustc_unsafe_specialization_marker] +trait SpecMarker {} + +trait X { + fn f(); +} + +impl<T> X for T { + default fn f() {} +} + +impl<T: SpecMarker> X for T { + fn f() {} +} + +fn main() {} diff --git a/tests/ui/specialization/min_specialization/specialize_on_spec_trait.rs b/tests/ui/specialization/min_specialization/specialize_on_spec_trait.rs new file mode 100644 index 000000000..abbab5c23 --- /dev/null +++ b/tests/ui/specialization/min_specialization/specialize_on_spec_trait.rs @@ -0,0 +1,27 @@ +// Test that specializing on a `rustc_specialization_trait` trait is allowed. + +// check-pass + +#![feature(min_specialization)] +#![feature(rustc_attrs)] + +#[rustc_specialization_trait] +trait SpecTrait { + fn g(&self); +} + +trait X { + fn f(&self); +} + +impl<T> X for T { + default fn f(&self) {} +} + +impl<T: SpecTrait> X for T { + fn f(&self) { + self.g(); + } +} + +fn main() {} diff --git a/tests/ui/specialization/min_specialization/specialize_on_static.rs b/tests/ui/specialization/min_specialization/specialize_on_static.rs new file mode 100644 index 000000000..dd1b05401 --- /dev/null +++ b/tests/ui/specialization/min_specialization/specialize_on_static.rs @@ -0,0 +1,18 @@ +// Test that directly specializing on `'static` is not allowed. + +#![feature(min_specialization)] + +trait X { + fn f(); +} + +impl<T> X for &'_ T { + default fn f() {} +} + +impl X for &'static u8 { + //~^ ERROR cannot specialize on `'static` lifetime + fn f() {} +} + +fn main() {} diff --git a/tests/ui/specialization/min_specialization/specialize_on_static.stderr b/tests/ui/specialization/min_specialization/specialize_on_static.stderr new file mode 100644 index 000000000..9a16798f1 --- /dev/null +++ b/tests/ui/specialization/min_specialization/specialize_on_static.stderr @@ -0,0 +1,8 @@ +error: cannot specialize on `'static` lifetime + --> $DIR/specialize_on_static.rs:13:1 + | +LL | impl X for &'static u8 { + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/specialization/min_specialization/specialize_on_trait.rs b/tests/ui/specialization/min_specialization/specialize_on_trait.rs new file mode 100644 index 000000000..0588442c3 --- /dev/null +++ b/tests/ui/specialization/min_specialization/specialize_on_trait.rs @@ -0,0 +1,20 @@ +// Test that specializing on a trait is not allowed in general. + +#![feature(min_specialization)] + +trait SpecMarker {} + +trait X { + fn f(); +} + +impl<T> X for T { + default fn f() {} +} + +impl<T: SpecMarker> X for T { + //~^ ERROR cannot specialize on trait `SpecMarker` + fn f() {} +} + +fn main() {} diff --git a/tests/ui/specialization/min_specialization/specialize_on_trait.stderr b/tests/ui/specialization/min_specialization/specialize_on_trait.stderr new file mode 100644 index 000000000..7b79c7eb4 --- /dev/null +++ b/tests/ui/specialization/min_specialization/specialize_on_trait.stderr @@ -0,0 +1,8 @@ +error: cannot specialize on trait `SpecMarker` + --> $DIR/specialize_on_trait.rs:15:9 + | +LL | impl<T: SpecMarker> X for T { + | ^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/specialization/non-defaulted-item-fail.rs b/tests/ui/specialization/non-defaulted-item-fail.rs new file mode 100644 index 000000000..b7d6ac829 --- /dev/null +++ b/tests/ui/specialization/non-defaulted-item-fail.rs @@ -0,0 +1,54 @@ +#![feature(specialization, associated_type_defaults)] +//~^ WARN the feature `specialization` is incomplete + +// Test that attempting to override a non-default method or one not in the +// parent impl causes an error. + +trait Foo { + type Ty = (); + const CONST: u8 = 123; + fn foo(&self) -> bool { true } +} + +// Specialization tree for Foo: +// +// Box<T> Vec<T> +// / \ / \ +// Box<i32> Box<i64> Vec<()> Vec<bool> + +impl<T> Foo for Box<T> { + type Ty = bool; + const CONST: u8 = 0; + fn foo(&self) -> bool { false } +} + +// Allowed +impl Foo for Box<i32> {} + +// Can't override a non-`default` fn +impl Foo for Box<i64> { + type Ty = Vec<()>; +//~^ error: `Ty` specializes an item from a parent `impl`, but that item is not marked `default` + const CONST: u8 = 42; +//~^ error: `CONST` specializes an item from a parent `impl`, but that item is not marked `default` + fn foo(&self) -> bool { true } +//~^ error: `foo` specializes an item from a parent `impl`, but that item is not marked `default` +} + + +// Doesn't mention the item = provided body/value is used and the method is final. +impl<T> Foo for Vec<T> {} + +// Allowed +impl Foo for Vec<()> {} + +impl Foo for Vec<bool> { + type Ty = Vec<()>; +//~^ error: `Ty` specializes an item from a parent `impl`, but that item is not marked `default` + const CONST: u8 = 42; +//~^ error: `CONST` specializes an item from a parent `impl`, but that item is not marked `default` + fn foo(&self) -> bool { true } +//~^ error: `foo` specializes an item from a parent `impl`, but that item is not marked `default` +} + +fn main() {} diff --git a/tests/ui/specialization/non-defaulted-item-fail.stderr b/tests/ui/specialization/non-defaulted-item-fail.stderr new file mode 100644 index 000000000..faa14555a --- /dev/null +++ b/tests/ui/specialization/non-defaulted-item-fail.stderr @@ -0,0 +1,79 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/non-defaulted-item-fail.rs:1:12 + | +LL | #![feature(specialization, associated_type_defaults)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +error[E0520]: `Ty` specializes an item from a parent `impl`, but that item is not marked `default` + --> $DIR/non-defaulted-item-fail.rs:30:5 + | +LL | impl<T> Foo for Box<T> { + | ---------------------- parent `impl` is here +... +LL | type Ty = Vec<()>; + | ^^^^^^^^^^^^^^^^^^ cannot specialize default item `Ty` + | + = note: to specialize, `Ty` in the parent `impl` must be marked `default` + +error[E0520]: `CONST` specializes an item from a parent `impl`, but that item is not marked `default` + --> $DIR/non-defaulted-item-fail.rs:32:5 + | +LL | impl<T> Foo for Box<T> { + | ---------------------- parent `impl` is here +... +LL | const CONST: u8 = 42; + | ^^^^^^^^^^^^^^^^^^^^^ cannot specialize default item `CONST` + | + = note: to specialize, `CONST` in the parent `impl` must be marked `default` + +error[E0520]: `foo` specializes an item from a parent `impl`, but that item is not marked `default` + --> $DIR/non-defaulted-item-fail.rs:34:5 + | +LL | impl<T> Foo for Box<T> { + | ---------------------- parent `impl` is here +... +LL | fn foo(&self) -> bool { true } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot specialize default item `foo` + | + = note: to specialize, `foo` in the parent `impl` must be marked `default` + +error[E0520]: `Ty` specializes an item from a parent `impl`, but that item is not marked `default` + --> $DIR/non-defaulted-item-fail.rs:46:5 + | +LL | impl<T> Foo for Vec<T> {} + | ---------------------- parent `impl` is here +... +LL | type Ty = Vec<()>; + | ^^^^^^^^^^^^^^^^^^ cannot specialize default item `Ty` + | + = note: to specialize, `Ty` in the parent `impl` must be marked `default` + +error[E0520]: `CONST` specializes an item from a parent `impl`, but that item is not marked `default` + --> $DIR/non-defaulted-item-fail.rs:48:5 + | +LL | impl<T> Foo for Vec<T> {} + | ---------------------- parent `impl` is here +... +LL | const CONST: u8 = 42; + | ^^^^^^^^^^^^^^^^^^^^^ cannot specialize default item `CONST` + | + = note: to specialize, `CONST` in the parent `impl` must be marked `default` + +error[E0520]: `foo` specializes an item from a parent `impl`, but that item is not marked `default` + --> $DIR/non-defaulted-item-fail.rs:50:5 + | +LL | impl<T> Foo for Vec<T> {} + | ---------------------- parent `impl` is here +... +LL | fn foo(&self) -> bool { true } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot specialize default item `foo` + | + = note: to specialize, `foo` in the parent `impl` must be marked `default` + +error: aborting due to 6 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0520`. diff --git a/tests/ui/specialization/soundness/partial_eq_range_inclusive.rs b/tests/ui/specialization/soundness/partial_eq_range_inclusive.rs new file mode 100644 index 000000000..923dec892 --- /dev/null +++ b/tests/ui/specialization/soundness/partial_eq_range_inclusive.rs @@ -0,0 +1,35 @@ +// run-pass + +use std::cell::RefCell; +use std::cmp::Ordering; + +struct Evil<'a, 'b> { + values: RefCell<Vec<&'a str>>, + to_insert: &'b String, +} + +impl<'a, 'b> PartialEq for Evil<'a, 'b> { + fn eq(&self, _other: &Self) -> bool { + true + } +} + +impl<'a> PartialOrd for Evil<'a, 'a> { + fn partial_cmp(&self, _other: &Self) -> Option<Ordering> { + self.values.borrow_mut().push(self.to_insert); + None + } +} + +fn main() { + let e; + let values; + { + let to_insert = String::from("Hello, world!"); + e = Evil { values: RefCell::new(Vec::new()), to_insert: &to_insert }; + let range = &e..=&e; + let _ = range == range; + values = e.values; + } + assert_eq!(*values.borrow(), Vec::<&str>::new()); +} diff --git a/tests/ui/specialization/soundness/partial_ord_slice.rs b/tests/ui/specialization/soundness/partial_ord_slice.rs new file mode 100644 index 000000000..b9e80a48d --- /dev/null +++ b/tests/ui/specialization/soundness/partial_ord_slice.rs @@ -0,0 +1,42 @@ +// Check that we aren't using unsound specialization in slice comparisons. + +// run-pass + +use std::cell::Cell; +use std::cmp::Ordering; + +struct Evil<'a, 'b>(Cell<(&'a [i32], &'b [i32])>); + +impl PartialEq for Evil<'_, '_> { + fn eq(&self, _other: &Self) -> bool { + true + } +} + +impl Eq for Evil<'_, '_> {} + +impl PartialOrd for Evil<'_, '_> { + fn partial_cmp(&self, _other: &Self) -> Option<Ordering> { + Some(Ordering::Equal) + } +} + +impl<'a> Ord for Evil<'a, 'a> { + fn cmp(&self, _other: &Self) -> Ordering { + let (a, b) = self.0.get(); + self.0.set((b, a)); + Ordering::Equal + } +} + +fn main() { + let x = &[1, 2, 3, 4]; + let u = { + let a = Box::new([7, 8, 9, 10]); + let y = [Evil(Cell::new((x, &*a)))]; + let _ = &y[..] <= &y[..]; + let [Evil(c)] = y; + c.get().0 + }; + assert_eq!(u, &[1, 2, 3, 4]); +} diff --git a/tests/ui/specialization/specialization-allowed-cross-crate.rs b/tests/ui/specialization/specialization-allowed-cross-crate.rs new file mode 100644 index 000000000..5d67160eb --- /dev/null +++ b/tests/ui/specialization/specialization-allowed-cross-crate.rs @@ -0,0 +1,26 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_variables)] +#![allow(unused_imports)] + +// aux-build:go_trait.rs + +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +extern crate go_trait; + +use go_trait::{Go,GoMut}; +use std::fmt::Debug; +use std::default::Default; + +struct MyThingy; + +impl Go for MyThingy { + fn go(&self, arg: isize) { } +} + +impl GoMut for MyThingy { + fn go_mut(&mut self, arg: isize) { } +} + +fn main() { } diff --git a/tests/ui/specialization/specialization-allowed-cross-crate.stderr b/tests/ui/specialization/specialization-allowed-cross-crate.stderr new file mode 100644 index 000000000..3eea4a53b --- /dev/null +++ b/tests/ui/specialization/specialization-allowed-cross-crate.stderr @@ -0,0 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/specialization-allowed-cross-crate.rs:8:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/specialization/specialization-assoc-fns.rs b/tests/ui/specialization/specialization-assoc-fns.rs new file mode 100644 index 000000000..cbfcb4719 --- /dev/null +++ b/tests/ui/specialization/specialization-assoc-fns.rs @@ -0,0 +1,29 @@ +// run-pass + +// Test that non-method associated functions can be specialized + +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +trait Foo { + fn mk() -> Self; +} + +impl<T: Default> Foo for T { + default fn mk() -> T { + T::default() + } +} + +impl Foo for Vec<u8> { + fn mk() -> Vec<u8> { + vec![0] + } +} + +fn main() { + let v1: Vec<i32> = Foo::mk(); + let v2: Vec<u8> = Foo::mk(); + + assert!(v1.len() == 0); + assert!(v2.len() == 1); +} diff --git a/tests/ui/specialization/specialization-assoc-fns.stderr b/tests/ui/specialization/specialization-assoc-fns.stderr new file mode 100644 index 000000000..69f7cece7 --- /dev/null +++ b/tests/ui/specialization/specialization-assoc-fns.stderr @@ -0,0 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/specialization-assoc-fns.rs:5:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/specialization/specialization-basics.rs b/tests/ui/specialization/specialization-basics.rs new file mode 100644 index 000000000..721c934db --- /dev/null +++ b/tests/ui/specialization/specialization-basics.rs @@ -0,0 +1,98 @@ +// run-pass + +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +// Tests a variety of basic specialization scenarios and method +// dispatch for them. + +trait Foo { + fn foo(&self) -> &'static str; +} + +impl<T> Foo for T { + default fn foo(&self) -> &'static str { + "generic" + } +} + +impl<T: Clone> Foo for T { + default fn foo(&self) -> &'static str { + "generic Clone" + } +} + +impl<T, U> Foo for (T, U) where T: Clone, U: Clone { + default fn foo(&self) -> &'static str { + "generic pair" + } +} + +impl<T: Clone> Foo for (T, T) { + default fn foo(&self) -> &'static str { + "generic uniform pair" + } +} + +impl Foo for (u8, u32) { + default fn foo(&self) -> &'static str { + "(u8, u32)" + } +} + +impl Foo for (u8, u8) { + default fn foo(&self) -> &'static str { + "(u8, u8)" + } +} + +impl<T: Clone> Foo for Vec<T> { + default fn foo(&self) -> &'static str { + "generic Vec" + } +} + +impl Foo for Vec<i32> { + fn foo(&self) -> &'static str { + "Vec<i32>" + } +} + +impl Foo for String { + fn foo(&self) -> &'static str { + "String" + } +} + +impl Foo for i32 { + fn foo(&self) -> &'static str { + "i32" + } +} + +struct NotClone; + +trait MyMarker {} +impl<T: Clone + MyMarker> Foo for T { + default fn foo(&self) -> &'static str { + "generic Clone + MyMarker" + } +} + +#[derive(Clone)] +struct MarkedAndClone; +impl MyMarker for MarkedAndClone {} + +fn main() { + assert!(NotClone.foo() == "generic"); + assert!(0u8.foo() == "generic Clone"); + assert!(vec![NotClone].foo() == "generic"); + assert!(vec![0u8].foo() == "generic Vec"); + assert!(vec![0i32].foo() == "Vec<i32>"); + assert!(0i32.foo() == "i32"); + assert!(String::new().foo() == "String"); + assert!(((), 0).foo() == "generic pair"); + assert!(((), ()).foo() == "generic uniform pair"); + assert!((0u8, 0u32).foo() == "(u8, u32)"); + assert!((0u8, 0u8).foo() == "(u8, u8)"); + assert!(MarkedAndClone.foo() == "generic Clone + MyMarker"); +} diff --git a/tests/ui/specialization/specialization-basics.stderr b/tests/ui/specialization/specialization-basics.stderr new file mode 100644 index 000000000..7714d4af4 --- /dev/null +++ b/tests/ui/specialization/specialization-basics.stderr @@ -0,0 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/specialization-basics.rs:3:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/specialization/specialization-cross-crate-no-gate.rs b/tests/ui/specialization/specialization-cross-crate-no-gate.rs new file mode 100644 index 000000000..f744b16de --- /dev/null +++ b/tests/ui/specialization/specialization-cross-crate-no-gate.rs @@ -0,0 +1,21 @@ +// run-pass + +// Test that specialization works even if only the upstream crate enables it + +// aux-build:specialization_cross_crate.rs + +extern crate specialization_cross_crate; + +use specialization_cross_crate::*; + +fn main() { + assert!(0u8.foo() == "generic Clone"); + assert!(vec![0u8].foo() == "generic Vec"); + assert!(vec![0i32].foo() == "Vec<i32>"); + assert!(0i32.foo() == "i32"); + assert!(String::new().foo() == "String"); + assert!(((), 0).foo() == "generic pair"); + assert!(((), ()).foo() == "generic uniform pair"); + assert!((0u8, 0u32).foo() == "(u8, u32)"); + assert!((0u8, 0u8).foo() == "(u8, u8)"); +} diff --git a/tests/ui/specialization/specialization-cross-crate.rs b/tests/ui/specialization/specialization-cross-crate.rs new file mode 100644 index 000000000..d9381d661 --- /dev/null +++ b/tests/ui/specialization/specialization-cross-crate.rs @@ -0,0 +1,50 @@ +// run-pass + +// aux-build:specialization_cross_crate.rs + +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +extern crate specialization_cross_crate; + +use specialization_cross_crate::*; + +struct NotClone; + +#[derive(Clone)] +struct MarkedAndClone; +impl MyMarker for MarkedAndClone {} + +struct MyType<T>(#[allow(unused_tuple_struct_fields)] T); +impl<T> Foo for MyType<T> { + default fn foo(&self) -> &'static str { + "generic MyType" + } +} + +impl Foo for MyType<u8> { + fn foo(&self) -> &'static str { + "MyType<u8>" + } +} + +struct MyOtherType; +impl Foo for MyOtherType {} + +fn main() { + assert!(NotClone.foo() == "generic"); + assert!(0u8.foo() == "generic Clone"); + assert!(vec![NotClone].foo() == "generic"); + assert!(vec![0u8].foo() == "generic Vec"); + assert!(vec![0i32].foo() == "Vec<i32>"); + assert!(0i32.foo() == "i32"); + assert!(String::new().foo() == "String"); + assert!(((), 0).foo() == "generic pair"); + assert!(((), ()).foo() == "generic uniform pair"); + assert!((0u8, 0u32).foo() == "(u8, u32)"); + assert!((0u8, 0u8).foo() == "(u8, u8)"); + assert!(MarkedAndClone.foo() == "generic Clone + MyMarker"); + + assert!(MyType(()).foo() == "generic MyType"); + assert!(MyType(0u8).foo() == "MyType<u8>"); + assert!(MyOtherType.foo() == "generic"); +} diff --git a/tests/ui/specialization/specialization-cross-crate.stderr b/tests/ui/specialization/specialization-cross-crate.stderr new file mode 100644 index 000000000..06818bb56 --- /dev/null +++ b/tests/ui/specialization/specialization-cross-crate.stderr @@ -0,0 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/specialization-cross-crate.rs:5:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/specialization/specialization-default-methods.rs b/tests/ui/specialization/specialization-default-methods.rs new file mode 100644 index 000000000..dcf68afa9 --- /dev/null +++ b/tests/ui/specialization/specialization-default-methods.rs @@ -0,0 +1,87 @@ +// run-pass + +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +// Test that default methods are cascaded correctly + +// First, test only use of explicit `default` items: + +trait Foo { + fn foo(&self) -> bool; +} + +// Specialization tree for Foo: +// +// T +// / \ +// i32 i64 + +impl<T> Foo for T { + default fn foo(&self) -> bool { false } +} + +impl Foo for i32 {} + +impl Foo for i64 { + fn foo(&self) -> bool { true } +} + +fn test_foo() { + assert!(!0i8.foo()); + assert!(!0i32.foo()); + assert!(0i64.foo()); +} + +// Next, test mixture of explicit `default` and provided methods: + +trait Bar { + fn bar(&self) -> i32 { 0 } +} + +// Specialization tree for Bar. +// Uses of $ designate that method is provided +// +// $Bar (the trait) +// | +// T +// /|\ +// / | \ +// / | \ +// / | \ +// / | \ +// / | \ +// $i32 &str $Vec<T> +// /\ +// / \ +// Vec<i32> $Vec<i64> + +impl<T> Bar for T { + default fn bar(&self) -> i32 { 0 } +} + +impl Bar for i32 { + fn bar(&self) -> i32 { 1 } +} +impl<'a> Bar for &'a str {} + +impl<T> Bar for Vec<T> { + default fn bar(&self) -> i32 { 2 } +} +impl Bar for Vec<i32> {} +impl Bar for Vec<i64> { + fn bar(&self) -> i32 { 3 } +} + +fn test_bar() { + assert!(0u8.bar() == 0); + assert!(0i32.bar() == 1); + assert!("hello".bar() == 0); + assert!(vec![()].bar() == 2); + assert!(vec![0i32].bar() == 2); + assert!(vec![0i64].bar() == 3); +} + +fn main() { + test_foo(); + test_bar(); +} diff --git a/tests/ui/specialization/specialization-default-methods.stderr b/tests/ui/specialization/specialization-default-methods.stderr new file mode 100644 index 000000000..d78d30bd8 --- /dev/null +++ b/tests/ui/specialization/specialization-default-methods.stderr @@ -0,0 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/specialization-default-methods.rs:3:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/specialization/specialization-default-projection.rs b/tests/ui/specialization/specialization-default-projection.rs new file mode 100644 index 000000000..7f3ae9512 --- /dev/null +++ b/tests/ui/specialization/specialization-default-projection.rs @@ -0,0 +1,36 @@ +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +// Make sure we can't project defaulted associated types + +trait Foo { + type Assoc; +} + +impl<T> Foo for T { + default type Assoc = (); +} + +impl Foo for u8 { + type Assoc = String; +} + +fn generic<T>() -> <T as Foo>::Assoc { + // `T` could be some downstream crate type that specializes (or, + // for that matter, `u8`). + + () //~ ERROR mismatched types +} + +fn monomorphic() -> () { + // Even though we know that `()` is not specialized in a + // downstream crate, typeck refuses to project here. + + generic::<()>() //~ ERROR mismatched types +} + +fn main() { + // No error here, we CAN project from `u8`, as there is no `default` + // in that impl. + let s: String = generic::<u8>(); + println!("{}", s); // bad news if this all compiles +} diff --git a/tests/ui/specialization/specialization-default-projection.stderr b/tests/ui/specialization/specialization-default-projection.stderr new file mode 100644 index 000000000..b8b81876d --- /dev/null +++ b/tests/ui/specialization/specialization-default-projection.stderr @@ -0,0 +1,43 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/specialization-default-projection.rs:1:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +error[E0308]: mismatched types + --> $DIR/specialization-default-projection.rs:21:5 + | +LL | fn generic<T>() -> <T as Foo>::Assoc { + | ----------------- expected `<T as Foo>::Assoc` because of return type +... +LL | () + | ^^ expected associated type, found `()` + | + = note: expected associated type `<T as Foo>::Assoc` + found unit type `()` + = help: consider constraining the associated type `<T as Foo>::Assoc` to `()` or calling a method that returns `<T as Foo>::Assoc` + = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html + +error[E0308]: mismatched types + --> $DIR/specialization-default-projection.rs:28:5 + | +LL | fn monomorphic() -> () { + | -- expected `()` because of return type +... +LL | generic::<()>() + | ^^^^^^^^^^^^^^^- help: consider using a semicolon here: `;` + | | + | expected `()`, found associated type + | + = note: expected unit type `()` + found associated type `<() as Foo>::Assoc` + = help: consider constraining the associated type `<() as Foo>::Assoc` to `()` + = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html + +error: aborting due to 2 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/specialization/specialization-default-types.rs b/tests/ui/specialization/specialization-default-types.rs new file mode 100644 index 000000000..346471f11 --- /dev/null +++ b/tests/ui/specialization/specialization-default-types.rs @@ -0,0 +1,35 @@ +// It should not be possible to use the concrete value of a defaulted +// associated type in the impl defining it -- otherwise, what happens +// if it's overridden? + +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +trait Example { + type Output; + fn generate(self) -> Self::Output; +} + +impl<T> Example for T { + default type Output = Box<T>; + default fn generate(self) -> Self::Output { + Box::new(self) //~ ERROR mismatched types + } +} + +impl Example for bool { + type Output = bool; + fn generate(self) -> bool { self } +} + +fn trouble<T>(t: T) -> Box<T> { + Example::generate(t) //~ ERROR mismatched types +} + +fn weaponize() -> bool { + let b: Box<bool> = trouble(true); + *b +} + +fn main() { + weaponize(); +} diff --git a/tests/ui/specialization/specialization-default-types.stderr b/tests/ui/specialization/specialization-default-types.stderr new file mode 100644 index 000000000..61a556a93 --- /dev/null +++ b/tests/ui/specialization/specialization-default-types.stderr @@ -0,0 +1,39 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/specialization-default-types.rs:5:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +error[E0308]: mismatched types + --> $DIR/specialization-default-types.rs:15:9 + | +LL | default type Output = Box<T>; + | ----------------------------- expected this associated type +LL | default fn generate(self) -> Self::Output { + | ------------ expected `<T as Example>::Output` because of return type +LL | Box::new(self) + | ^^^^^^^^^^^^^^ expected associated type, found struct `Box` + | + = note: expected associated type `<T as Example>::Output` + found struct `Box<T>` + +error[E0308]: mismatched types + --> $DIR/specialization-default-types.rs:25:5 + | +LL | fn trouble<T>(t: T) -> Box<T> { + | ------ expected `Box<T>` because of return type +LL | Example::generate(t) + | ^^^^^^^^^^^^^^^^^^^^ expected struct `Box`, found associated type + | + = note: expected struct `Box<T>` + found associated type `<T as Example>::Output` + = help: consider constraining the associated type `<T as Example>::Output` to `Box<T>` + = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html + +error: aborting due to 2 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/specialization/specialization-feature-gate-default.rs b/tests/ui/specialization/specialization-feature-gate-default.rs new file mode 100644 index 000000000..8bad3ac0a --- /dev/null +++ b/tests/ui/specialization/specialization-feature-gate-default.rs @@ -0,0 +1,13 @@ +// Check that specialization must be ungated to use the `default` keyword + +// gate-test-specialization + +trait Foo { + fn foo(&self); +} + +impl<T> Foo for T { + default fn foo(&self) {} //~ ERROR specialization is unstable +} + +fn main() {} diff --git a/tests/ui/specialization/specialization-feature-gate-default.stderr b/tests/ui/specialization/specialization-feature-gate-default.stderr new file mode 100644 index 000000000..42dbb200c --- /dev/null +++ b/tests/ui/specialization/specialization-feature-gate-default.stderr @@ -0,0 +1,12 @@ +error[E0658]: specialization is unstable + --> $DIR/specialization-feature-gate-default.rs:10:5 + | +LL | default fn foo(&self) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information + = help: add `#![feature(specialization)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/specialization/specialization-feature-gate-overlap.rs b/tests/ui/specialization/specialization-feature-gate-overlap.rs new file mode 100644 index 000000000..b83c84ab8 --- /dev/null +++ b/tests/ui/specialization/specialization-feature-gate-overlap.rs @@ -0,0 +1,17 @@ +// Check that writing an overlapping impl is not allow unless specialization is ungated. + +// gate-test-specialization + +trait Foo { + fn foo(&self); +} + +impl<T> Foo for T { + fn foo(&self) {} +} + +impl Foo for u8 { //~ ERROR E0119 + fn foo(&self) {} +} + +fn main() {} diff --git a/tests/ui/specialization/specialization-feature-gate-overlap.stderr b/tests/ui/specialization/specialization-feature-gate-overlap.stderr new file mode 100644 index 000000000..9157ad0d4 --- /dev/null +++ b/tests/ui/specialization/specialization-feature-gate-overlap.stderr @@ -0,0 +1,12 @@ +error[E0119]: conflicting implementations of trait `Foo` for type `u8` + --> $DIR/specialization-feature-gate-overlap.rs:13:1 + | +LL | impl<T> Foo for T { + | ----------------- first implementation here +... +LL | impl Foo for u8 { + | ^^^^^^^^^^^^^^^ conflicting implementation for `u8` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/specialization/specialization-no-default.rs b/tests/ui/specialization/specialization-no-default.rs new file mode 100644 index 000000000..ae739b235 --- /dev/null +++ b/tests/ui/specialization/specialization-no-default.rs @@ -0,0 +1,77 @@ +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +// Check a number of scenarios in which one impl tries to override another, +// without correctly using `default`. + +// Test 1: one layer of specialization, multiple methods, missing `default` + +trait Foo { + fn foo(&self); + fn bar(&self); +} + +impl<T> Foo for T { + fn foo(&self) {} + fn bar(&self) {} +} + +impl Foo for u8 {} +impl Foo for u16 { + fn foo(&self) {} //~ ERROR E0520 +} +impl Foo for u32 { + fn bar(&self) {} //~ ERROR E0520 +} + +// Test 2: one layer of specialization, missing `default` on associated type + +trait Bar { + type T; +} + +impl<T> Bar for T { + type T = u8; +} + +impl Bar for u8 { + type T = (); //~ ERROR E0520 +} + +// Test 3a: multiple layers of specialization, missing interior `default` + +trait Baz { + fn baz(&self); +} + +impl<T> Baz for T { + default fn baz(&self) {} +} + +impl<T: Clone> Baz for T { + fn baz(&self) {} +} + +impl Baz for i32 { + fn baz(&self) {} //~ ERROR E0520 +} + +// Test 3b: multiple layers of specialization, missing interior `default`, +// redundant `default` in bottom layer. + +trait Redundant { + fn redundant(&self); +} + +impl<T> Redundant for T { + default fn redundant(&self) {} +} + +impl<T: Clone> Redundant for T { + fn redundant(&self) {} +} + +impl Redundant for i32 { + default fn redundant(&self) {} //~ ERROR E0520 +} + +fn main() {} diff --git a/tests/ui/specialization/specialization-no-default.stderr b/tests/ui/specialization/specialization-no-default.stderr new file mode 100644 index 000000000..842cec9c7 --- /dev/null +++ b/tests/ui/specialization/specialization-no-default.stderr @@ -0,0 +1,68 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/specialization-no-default.rs:1:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +error[E0520]: `foo` specializes an item from a parent `impl`, but that item is not marked `default` + --> $DIR/specialization-no-default.rs:20:5 + | +LL | impl<T> Foo for T { + | ----------------- parent `impl` is here +... +LL | fn foo(&self) {} + | ^^^^^^^^^^^^^^^^ cannot specialize default item `foo` + | + = note: to specialize, `foo` in the parent `impl` must be marked `default` + +error[E0520]: `bar` specializes an item from a parent `impl`, but that item is not marked `default` + --> $DIR/specialization-no-default.rs:23:5 + | +LL | impl<T> Foo for T { + | ----------------- parent `impl` is here +... +LL | fn bar(&self) {} + | ^^^^^^^^^^^^^^^^ cannot specialize default item `bar` + | + = note: to specialize, `bar` in the parent `impl` must be marked `default` + +error[E0520]: `T` specializes an item from a parent `impl`, but that item is not marked `default` + --> $DIR/specialization-no-default.rs:37:5 + | +LL | impl<T> Bar for T { + | ----------------- parent `impl` is here +... +LL | type T = (); + | ^^^^^^^^^^^^ cannot specialize default item `T` + | + = note: to specialize, `T` in the parent `impl` must be marked `default` + +error[E0520]: `baz` specializes an item from a parent `impl`, but that item is not marked `default` + --> $DIR/specialization-no-default.rs:55:5 + | +LL | impl<T: Clone> Baz for T { + | ------------------------ parent `impl` is here +... +LL | fn baz(&self) {} + | ^^^^^^^^^^^^^^^^ cannot specialize default item `baz` + | + = note: to specialize, `baz` in the parent `impl` must be marked `default` + +error[E0520]: `redundant` specializes an item from a parent `impl`, but that item is not marked `default` + --> $DIR/specialization-no-default.rs:74:5 + | +LL | impl<T: Clone> Redundant for T { + | ------------------------------ parent `impl` is here +... +LL | default fn redundant(&self) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot specialize default item `redundant` + | + = note: to specialize, `redundant` in the parent `impl` must be marked `default` + +error: aborting due to 5 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0520`. diff --git a/tests/ui/specialization/specialization-on-projection.rs b/tests/ui/specialization/specialization-on-projection.rs new file mode 100644 index 000000000..be8dcc423 --- /dev/null +++ b/tests/ui/specialization/specialization-on-projection.rs @@ -0,0 +1,24 @@ +// run-pass +#![allow(dead_code)] + +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +// Ensure that specialization works for impls defined directly on a projection + +trait Foo<T> {} + +trait Assoc { + type Item; +} + +impl<T: Assoc> Foo<T::Item> for T {} + +struct Struct; + +impl Assoc for Struct { + type Item = u8; +} + +impl Foo<u8> for Struct {} + +fn main() {} diff --git a/tests/ui/specialization/specialization-on-projection.stderr b/tests/ui/specialization/specialization-on-projection.stderr new file mode 100644 index 000000000..00fc7ffc5 --- /dev/null +++ b/tests/ui/specialization/specialization-on-projection.stderr @@ -0,0 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/specialization-on-projection.rs:4:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/specialization/specialization-out-of-order.rs b/tests/ui/specialization/specialization-out-of-order.rs new file mode 100644 index 000000000..cb7563e27 --- /dev/null +++ b/tests/ui/specialization/specialization-out-of-order.rs @@ -0,0 +1,19 @@ +// run-pass + +// Test that you can list the more specific impl before the more general one. + +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +trait Foo { + type Out; +} + +impl Foo for bool { + type Out = (); +} + +impl<T> Foo for T { + default type Out = bool; +} + +fn main() {} diff --git a/tests/ui/specialization/specialization-out-of-order.stderr b/tests/ui/specialization/specialization-out-of-order.stderr new file mode 100644 index 000000000..b524e00f0 --- /dev/null +++ b/tests/ui/specialization/specialization-out-of-order.stderr @@ -0,0 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/specialization-out-of-order.rs:5:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/specialization/specialization-overlap-hygiene.rs b/tests/ui/specialization/specialization-overlap-hygiene.rs new file mode 100644 index 000000000..93e7c8325 --- /dev/null +++ b/tests/ui/specialization/specialization-overlap-hygiene.rs @@ -0,0 +1,23 @@ +#![feature(decl_macro)] + +struct X; + +macro_rules! define_f_legacy { () => { + fn f() {} +}} +macro define_g_modern() { + fn g() {} +} + +impl X { + fn f() {} //~ ERROR duplicate definitions with name `f` + fn g() {} // OK +} +impl X { + define_f_legacy!(); +} +impl X { + define_g_modern!(); +} + +fn main() {} diff --git a/tests/ui/specialization/specialization-overlap-hygiene.stderr b/tests/ui/specialization/specialization-overlap-hygiene.stderr new file mode 100644 index 000000000..81efd46cc --- /dev/null +++ b/tests/ui/specialization/specialization-overlap-hygiene.stderr @@ -0,0 +1,12 @@ +error[E0592]: duplicate definitions with name `f` + --> $DIR/specialization-overlap-hygiene.rs:13:4 + | +LL | fn f() {} + | ------ other definition for `f` +... +LL | fn f() {} + | ^^^^^^ duplicate definitions for `f` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0592`. diff --git a/tests/ui/specialization/specialization-overlap-negative.rs b/tests/ui/specialization/specialization-overlap-negative.rs new file mode 100644 index 000000000..550d37082 --- /dev/null +++ b/tests/ui/specialization/specialization-overlap-negative.rs @@ -0,0 +1,11 @@ +#![feature(negative_impls)] +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +trait MyTrait {} + +struct TestType<T>(::std::marker::PhantomData<T>); + +unsafe impl<T: Clone> Send for TestType<T> {} +impl<T: MyTrait> !Send for TestType<T> {} //~ ERROR E0751 + +fn main() {} diff --git a/tests/ui/specialization/specialization-overlap-negative.stderr b/tests/ui/specialization/specialization-overlap-negative.stderr new file mode 100644 index 000000000..1fe4869ff --- /dev/null +++ b/tests/ui/specialization/specialization-overlap-negative.stderr @@ -0,0 +1,21 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/specialization-overlap-negative.rs:2:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +error[E0751]: found both positive and negative implementation of trait `Send` for type `TestType<_>`: + --> $DIR/specialization-overlap-negative.rs:9:1 + | +LL | unsafe impl<T: Clone> Send for TestType<T> {} + | ------------------------------------------ positive implementation here +LL | impl<T: MyTrait> !Send for TestType<T> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ negative implementation here + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0751`. diff --git a/tests/ui/specialization/specialization-overlap-projection.rs b/tests/ui/specialization/specialization-overlap-projection.rs new file mode 100644 index 000000000..b07efb2a5 --- /dev/null +++ b/tests/ui/specialization/specialization-overlap-projection.rs @@ -0,0 +1,25 @@ +// run-pass + +// Test that impls on projected self types can resolve overlap, even when the +// projections involve specialization, so long as the associated type is +// provided by the most specialized impl. + +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +trait Assoc { + type Output; +} + +impl<T> Assoc for T { + default type Output = bool; +} + +impl Assoc for u8 { type Output = u8; } +impl Assoc for u16 { type Output = u16; } + +trait Foo {} +impl Foo for u32 {} +impl Foo for <u8 as Assoc>::Output {} +impl Foo for <u16 as Assoc>::Output {} + +fn main() {} diff --git a/tests/ui/specialization/specialization-overlap-projection.stderr b/tests/ui/specialization/specialization-overlap-projection.stderr new file mode 100644 index 000000000..708c0817f --- /dev/null +++ b/tests/ui/specialization/specialization-overlap-projection.stderr @@ -0,0 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/specialization-overlap-projection.rs:7:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/specialization/specialization-overlap.rs b/tests/ui/specialization/specialization-overlap.rs new file mode 100644 index 000000000..6bee22ceb --- /dev/null +++ b/tests/ui/specialization/specialization-overlap.rs @@ -0,0 +1,19 @@ +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +trait Foo { fn foo() {} } +impl<T: Clone> Foo for T {} +impl<T> Foo for Vec<T> {} //~ ERROR E0119 + +trait Bar { fn bar() {} } +impl<T> Bar for (T, u8) {} +impl<T> Bar for (u8, T) {} //~ ERROR E0119 + +trait Baz<U> { fn baz() {} } +impl<T> Baz<T> for u8 {} +impl<T> Baz<u8> for T {} //~ ERROR E0119 + +trait Qux { fn qux() {} } +impl<T: Clone> Qux for T {} +impl<T: Eq> Qux for T {} //~ ERROR E0119 + +fn main() {} diff --git a/tests/ui/specialization/specialization-overlap.stderr b/tests/ui/specialization/specialization-overlap.stderr new file mode 100644 index 000000000..098bf4a70 --- /dev/null +++ b/tests/ui/specialization/specialization-overlap.stderr @@ -0,0 +1,45 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/specialization-overlap.rs:1:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +error[E0119]: conflicting implementations of trait `Foo` for type `Vec<_>` + --> $DIR/specialization-overlap.rs:5:1 + | +LL | impl<T: Clone> Foo for T {} + | ------------------------ first implementation here +LL | impl<T> Foo for Vec<T> {} + | ^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Vec<_>` + +error[E0119]: conflicting implementations of trait `Bar` for type `(u8, u8)` + --> $DIR/specialization-overlap.rs:9:1 + | +LL | impl<T> Bar for (T, u8) {} + | ----------------------- first implementation here +LL | impl<T> Bar for (u8, T) {} + | ^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(u8, u8)` + +error[E0119]: conflicting implementations of trait `Baz<u8>` for type `u8` + --> $DIR/specialization-overlap.rs:13:1 + | +LL | impl<T> Baz<T> for u8 {} + | --------------------- first implementation here +LL | impl<T> Baz<u8> for T {} + | ^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `u8` + +error[E0119]: conflicting implementations of trait `Qux` + --> $DIR/specialization-overlap.rs:17:1 + | +LL | impl<T: Clone> Qux for T {} + | ------------------------ first implementation here +LL | impl<T: Eq> Qux for T {} + | ^^^^^^^^^^^^^^^^^^^^^ conflicting implementation + +error: aborting due to 4 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/specialization/specialization-polarity.rs b/tests/ui/specialization/specialization-polarity.rs new file mode 100644 index 000000000..b3cd8255b --- /dev/null +++ b/tests/ui/specialization/specialization-polarity.rs @@ -0,0 +1,17 @@ +// Make sure specialization cannot change impl polarity + +#![feature(auto_traits)] +#![feature(negative_impls)] +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +auto trait Foo {} + +impl<T> Foo for T {} +impl !Foo for u8 {} //~ ERROR E0751 + +auto trait Bar {} + +impl<T> !Bar for T {} +impl Bar for u8 {} //~ ERROR E0751 + +fn main() {} diff --git a/tests/ui/specialization/specialization-polarity.stderr b/tests/ui/specialization/specialization-polarity.stderr new file mode 100644 index 000000000..f287018ba --- /dev/null +++ b/tests/ui/specialization/specialization-polarity.stderr @@ -0,0 +1,29 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/specialization-polarity.rs:5:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +error[E0751]: found both positive and negative implementation of trait `Foo` for type `u8`: + --> $DIR/specialization-polarity.rs:10:1 + | +LL | impl<T> Foo for T {} + | ----------------- positive implementation here +LL | impl !Foo for u8 {} + | ^^^^^^^^^^^^^^^^ negative implementation here + +error[E0751]: found both positive and negative implementation of trait `Bar` for type `u8`: + --> $DIR/specialization-polarity.rs:15:1 + | +LL | impl<T> !Bar for T {} + | ------------------ negative implementation here +LL | impl Bar for u8 {} + | ^^^^^^^^^^^^^^^ positive implementation here + +error: aborting due to 2 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0751`. diff --git a/tests/ui/specialization/specialization-projection-alias.rs b/tests/ui/specialization/specialization-projection-alias.rs new file mode 100644 index 000000000..f1f0b47bb --- /dev/null +++ b/tests/ui/specialization/specialization-projection-alias.rs @@ -0,0 +1,26 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_variables)] + +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +// Regression test for ICE when combining specialized associated types and type +// aliases + +trait Id_ { + type Out; +} + +type Id<T> = <T as Id_>::Out; + +impl<T> Id_ for T { + default type Out = T; +} + +fn test_proection() { + let x: Id<bool> = panic!(); +} + +fn main() { + +} diff --git a/tests/ui/specialization/specialization-projection-alias.stderr b/tests/ui/specialization/specialization-projection-alias.stderr new file mode 100644 index 000000000..c94d9ed07 --- /dev/null +++ b/tests/ui/specialization/specialization-projection-alias.stderr @@ -0,0 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/specialization-projection-alias.rs:5:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/specialization/specialization-projection.rs b/tests/ui/specialization/specialization-projection.rs new file mode 100644 index 000000000..78afe7a94 --- /dev/null +++ b/tests/ui/specialization/specialization-projection.rs @@ -0,0 +1,42 @@ +// run-pass +#![allow(dead_code)] + +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +// Make sure we *can* project non-defaulted associated types +// cf ui/specialization/specialization-default-projection.rs + +// First, do so without any use of specialization + +trait Foo { + type Assoc; +} + +impl<T> Foo for T { + type Assoc = (); +} + +fn generic_foo<T>() -> <T as Foo>::Assoc { + () +} + +// Next, allow for one layer of specialization + +trait Bar { + type Assoc; +} + +impl<T> Bar for T { + default type Assoc = (); +} + +impl<T: Clone> Bar for T { + type Assoc = u8; +} + +fn generic_bar_clone<T: Clone>() -> <T as Bar>::Assoc { + 0u8 +} + +fn main() { +} diff --git a/tests/ui/specialization/specialization-projection.stderr b/tests/ui/specialization/specialization-projection.stderr new file mode 100644 index 000000000..bfc4e0a0f --- /dev/null +++ b/tests/ui/specialization/specialization-projection.stderr @@ -0,0 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/specialization-projection.rs:4:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/specialization/specialization-supertraits.rs b/tests/ui/specialization/specialization-supertraits.rs new file mode 100644 index 000000000..fb85d8019 --- /dev/null +++ b/tests/ui/specialization/specialization-supertraits.rs @@ -0,0 +1,17 @@ +// run-pass + +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +// Test that you can specialize via an explicit trait hierarchy + +// FIXME: this doesn't work yet... + +trait Parent {} +trait Child: Parent {} + +trait Foo {} + +impl<T: Parent> Foo for T {} +impl<T: Child> Foo for T {} + +fn main() {} diff --git a/tests/ui/specialization/specialization-supertraits.stderr b/tests/ui/specialization/specialization-supertraits.stderr new file mode 100644 index 000000000..e716bc215 --- /dev/null +++ b/tests/ui/specialization/specialization-supertraits.stderr @@ -0,0 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/specialization-supertraits.rs:3:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/specialization/specialization-translate-projections-with-lifetimes.rs b/tests/ui/specialization/specialization-translate-projections-with-lifetimes.rs new file mode 100644 index 000000000..904aeaa08 --- /dev/null +++ b/tests/ui/specialization/specialization-translate-projections-with-lifetimes.rs @@ -0,0 +1,33 @@ +// run-pass + +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +trait Iterator { + fn next(&self); +} + +trait WithAssoc { + type Item; +} + +impl<'a> WithAssoc for &'a () { + type Item = &'a u32; +} + +struct Cloned<I>(#[allow(unused_tuple_struct_fields)] I); + +impl<'a, I, T: 'a> Iterator for Cloned<I> + where I: WithAssoc<Item=&'a T>, T: Clone +{ + fn next(&self) {} +} + +impl<'a, I, T: 'a> Iterator for Cloned<I> + where I: WithAssoc<Item=&'a T>, T: Copy +{ + +} + +fn main() { + Cloned(&()).next(); +} diff --git a/tests/ui/specialization/specialization-translate-projections-with-lifetimes.stderr b/tests/ui/specialization/specialization-translate-projections-with-lifetimes.stderr new file mode 100644 index 000000000..c7aad3c0f --- /dev/null +++ b/tests/ui/specialization/specialization-translate-projections-with-lifetimes.stderr @@ -0,0 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/specialization-translate-projections-with-lifetimes.rs:3:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/specialization/specialization-translate-projections-with-params.rs b/tests/ui/specialization/specialization-translate-projections-with-params.rs new file mode 100644 index 000000000..62d63590a --- /dev/null +++ b/tests/ui/specialization/specialization-translate-projections-with-params.rs @@ -0,0 +1,32 @@ +// run-pass + +// Ensure that provided items are inherited properly even when impls vary in +// type parameters *and* rely on projections, and the type parameters are input +// types on the trait. + +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +trait Trait<T> { + fn convert(&self) -> T; +} +trait WithAssoc { + type Item; + fn as_item(&self) -> &Self::Item; +} + +impl<T, U> Trait<U> for T where T: WithAssoc<Item=U>, U: Clone { + fn convert(&self) -> U { + self.as_item().clone() + } +} + +impl WithAssoc for u8 { + type Item = u8; + fn as_item(&self) -> &u8 { self } +} + +impl Trait<u8> for u8 {} + +fn main() { + assert!(3u8.convert() == 3u8); +} diff --git a/tests/ui/specialization/specialization-translate-projections-with-params.stderr b/tests/ui/specialization/specialization-translate-projections-with-params.stderr new file mode 100644 index 000000000..1c4fd9325 --- /dev/null +++ b/tests/ui/specialization/specialization-translate-projections-with-params.stderr @@ -0,0 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/specialization-translate-projections-with-params.rs:7:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/specialization/specialization-translate-projections.rs b/tests/ui/specialization/specialization-translate-projections.rs new file mode 100644 index 000000000..92ea9e2b8 --- /dev/null +++ b/tests/ui/specialization/specialization-translate-projections.rs @@ -0,0 +1,33 @@ +// run-pass + +// Ensure that provided items are inherited properly even when impls vary in +// type parameters *and* rely on projections. + +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +use std::convert::Into; + +trait Trait { + fn to_u8(&self) -> u8; +} +trait WithAssoc { + type Item; + fn to_item(&self) -> Self::Item; +} + +impl<T, U> Trait for T where T: WithAssoc<Item=U>, U: Into<u8> { + fn to_u8(&self) -> u8 { + self.to_item().into() + } +} + +impl WithAssoc for u8 { + type Item = u8; + fn to_item(&self) -> u8 { *self } +} + +impl Trait for u8 {} + +fn main() { + assert!(3u8.to_u8() == 3u8); +} diff --git a/tests/ui/specialization/specialization-translate-projections.stderr b/tests/ui/specialization/specialization-translate-projections.stderr new file mode 100644 index 000000000..22bbb12a0 --- /dev/null +++ b/tests/ui/specialization/specialization-translate-projections.stderr @@ -0,0 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/specialization-translate-projections.rs:6:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/specialization/transmute-specialization.rs b/tests/ui/specialization/transmute-specialization.rs new file mode 100644 index 000000000..499334d98 --- /dev/null +++ b/tests/ui/specialization/transmute-specialization.rs @@ -0,0 +1,15 @@ +// run-pass + +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +trait Specializable { type Output; } + +impl<T> Specializable for T { + default type Output = u16; +} + +fn main() { + unsafe { + std::mem::transmute::<u16, <() as Specializable>::Output>(0); + } +} diff --git a/tests/ui/specialization/transmute-specialization.stderr b/tests/ui/specialization/transmute-specialization.stderr new file mode 100644 index 000000000..b1c26d7da --- /dev/null +++ b/tests/ui/specialization/transmute-specialization.stderr @@ -0,0 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/transmute-specialization.rs:3:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + |