diff options
| author | Michael Goulet <michael@errs.io> | 2024-10-22 00:03:09 +0000 |
|---|---|---|
| committer | Michael Goulet <michael@errs.io> | 2024-10-22 00:03:09 +0000 |
| commit | e91267f3f094a6f5d16aef0abb864fca4bc8c9f4 (patch) | |
| tree | ba5ce9ae085572e299066b12a06da711416eea87 /tests/ui/traits | |
| parent | edbd9398dcc0e3b6ffe0dd0cd4578d37d1d36974 (diff) | |
| download | rust-e91267f3f094a6f5d16aef0abb864fca4bc8c9f4.tar.gz rust-e91267f3f094a6f5d16aef0abb864fca4bc8c9f4.zip | |
Move tests
Diffstat (limited to 'tests/ui/traits')
238 files changed, 7896 insertions, 0 deletions
diff --git a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-0.rs b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-0.rs new file mode 100644 index 00000000000..4399ae2d1be --- /dev/null +++ b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-0.rs @@ -0,0 +1,20 @@ +//@ known-bug: unknown + +#![allow(incomplete_features)] +#![feature(const_trait_impl, effects)] + +#[const_trait] +trait Trait { + type Assoc: ~const Trait; + fn func() -> i32; +} + +const fn unqualified<T: ~const Trait>() -> i32 { + T::Assoc::func() +} + +const fn qualified<T: ~const Trait>() -> i32 { + <T as Trait>::Assoc::func() +} + +fn main() {} diff --git a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-0.stderr b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-0.stderr new file mode 100644 index 00000000000..8288c660ce7 --- /dev/null +++ b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-0.stderr @@ -0,0 +1,46 @@ +error: using `#![feature(effects)]` without enabling next trait solver globally + | + = note: the next trait solver must be enabled globally for the effects feature to work correctly + = help: use `-Znext-solver` to enable + +error[E0277]: the trait bound `<T as Trait>::Assoc: Trait` is not satisfied + --> $DIR/assoc-type-const-bound-usage-0.rs:13:5 + | +LL | T::Assoc::func() + | ^^^^^^^^ the trait `Trait` is not implemented for `<T as Trait>::Assoc` + | +note: required by a bound in `Trait::func` + --> $DIR/assoc-type-const-bound-usage-0.rs:6:1 + | +LL | #[const_trait] + | ^^^^^^^^^^^^^^ required by this bound in `Trait::func` +... +LL | fn func() -> i32; + | ---- required by a bound in this associated function +help: consider further restricting the associated type + | +LL | const fn unqualified<T: ~const Trait>() -> i32 where <T as Trait>::Assoc: Trait { + | ++++++++++++++++++++++++++++++++ + +error[E0277]: the trait bound `<T as Trait>::Assoc: Trait` is not satisfied + --> $DIR/assoc-type-const-bound-usage-0.rs:17:5 + | +LL | <T as Trait>::Assoc::func() + | ^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `<T as Trait>::Assoc` + | +note: required by a bound in `Trait::func` + --> $DIR/assoc-type-const-bound-usage-0.rs:6:1 + | +LL | #[const_trait] + | ^^^^^^^^^^^^^^ required by this bound in `Trait::func` +... +LL | fn func() -> i32; + | ---- required by a bound in this associated function +help: consider further restricting the associated type + | +LL | const fn qualified<T: ~const Trait>() -> i32 where <T as Trait>::Assoc: Trait { + | ++++++++++++++++++++++++++++++++ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-1.rs b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-1.rs new file mode 100644 index 00000000000..8a1bf75f87e --- /dev/null +++ b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-1.rs @@ -0,0 +1,23 @@ +//@ known-bug: unknown +// FIXME(effects) + +#![feature(const_trait_impl, effects, generic_const_exprs)] +#![allow(incomplete_features)] + +#[const_trait] +trait Trait { + type Assoc: ~const Trait; + fn func() -> i32; +} + +struct Type<const N: i32>; + +fn unqualified<T: const Trait>() -> Type<{ T::Assoc::func() }> { + Type +} + +fn qualified<T: const Trait>() -> Type<{ <T as Trait>::Assoc::func() }> { + Type +} + +fn main() {} diff --git a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-1.stderr b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-1.stderr new file mode 100644 index 00000000000..0792d090321 --- /dev/null +++ b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-1.stderr @@ -0,0 +1,46 @@ +error: using `#![feature(effects)]` without enabling next trait solver globally + | + = note: the next trait solver must be enabled globally for the effects feature to work correctly + = help: use `-Znext-solver` to enable + +error[E0277]: the trait bound `<T as Trait>::Assoc: Trait` is not satisfied + --> $DIR/assoc-type-const-bound-usage-1.rs:15:44 + | +LL | fn unqualified<T: const Trait>() -> Type<{ T::Assoc::func() }> { + | ^^^^^^^^ the trait `Trait` is not implemented for `<T as Trait>::Assoc` + | +note: required by a bound in `Trait::func` + --> $DIR/assoc-type-const-bound-usage-1.rs:7:1 + | +LL | #[const_trait] + | ^^^^^^^^^^^^^^ required by this bound in `Trait::func` +... +LL | fn func() -> i32; + | ---- required by a bound in this associated function +help: consider further restricting the associated type + | +LL | fn unqualified<T: const Trait>() -> Type<{ T::Assoc::func() }> where <T as Trait>::Assoc: Trait { + | ++++++++++++++++++++++++++++++++ + +error[E0277]: the trait bound `<T as Trait>::Assoc: Trait` is not satisfied + --> $DIR/assoc-type-const-bound-usage-1.rs:19:42 + | +LL | fn qualified<T: const Trait>() -> Type<{ <T as Trait>::Assoc::func() }> { + | ^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `<T as Trait>::Assoc` + | +note: required by a bound in `Trait::func` + --> $DIR/assoc-type-const-bound-usage-1.rs:7:1 + | +LL | #[const_trait] + | ^^^^^^^^^^^^^^ required by this bound in `Trait::func` +... +LL | fn func() -> i32; + | ---- required by a bound in this associated function +help: consider further restricting the associated type + | +LL | fn qualified<T: const Trait>() -> Type<{ <T as Trait>::Assoc::func() }> where <T as Trait>::Assoc: Trait { + | ++++++++++++++++++++++++++++++++ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/const-traits/assoc-type.rs b/tests/ui/traits/const-traits/assoc-type.rs new file mode 100644 index 00000000000..ea3cbabf302 --- /dev/null +++ b/tests/ui/traits/const-traits/assoc-type.rs @@ -0,0 +1,48 @@ +// FIXME(effects): Replace `Add` with `std::ops::Add` once the latter a `#[const_trait]` again. +#![feature(const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete + +#[const_trait] +trait Add<Rhs = Self> { + type Output; + + fn add(self, other: Rhs) -> Self::Output; +} + +impl const Add for i32 { + type Output = Self; + + fn add(self, other: Self) -> Self::Output { + self + other + } +} + +struct NonConstAdd(i32); + +impl Add for NonConstAdd { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + NonConstAdd(self.0.add(rhs.0)) + } +} + +#[const_trait] +trait Foo { + type Bar: ~const Add; +} + +impl const Foo for NonConstAdd { + type Bar = NonConstAdd; + // FIXME(effects) ERROR the trait bound `NonConstAdd: ~const Add` is not satisfied +} + +#[const_trait] +trait Baz { + type Qux: Add; +} + +impl const Baz for NonConstAdd { + type Qux = NonConstAdd; // OK +} + +fn main() {} diff --git a/tests/ui/traits/const-traits/assoc-type.stderr b/tests/ui/traits/const-traits/assoc-type.stderr new file mode 100644 index 00000000000..c20b53c210f --- /dev/null +++ b/tests/ui/traits/const-traits/assoc-type.stderr @@ -0,0 +1,16 @@ +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/assoc-type.rs:2:30 + | +LL | #![feature(const_trait_impl, effects)] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + +error: using `#![feature(effects)]` without enabling next trait solver globally + | + = note: the next trait solver must be enabled globally for the effects feature to work correctly + = help: use `-Znext-solver` to enable + +error: aborting due to 1 previous error; 1 warning emitted + diff --git a/tests/ui/traits/const-traits/attr-misuse.rs b/tests/ui/traits/const-traits/attr-misuse.rs new file mode 100644 index 00000000000..01ac74feff7 --- /dev/null +++ b/tests/ui/traits/const-traits/attr-misuse.rs @@ -0,0 +1,10 @@ +#![feature(const_trait_impl)] + +#[const_trait] +trait A { + #[const_trait] //~ ERROR attribute should be applied + fn foo(self); +} + +#[const_trait] //~ ERROR attribute should be applied +fn main() {} diff --git a/tests/ui/traits/const-traits/attr-misuse.stderr b/tests/ui/traits/const-traits/attr-misuse.stderr new file mode 100644 index 00000000000..998958cedf7 --- /dev/null +++ b/tests/ui/traits/const-traits/attr-misuse.stderr @@ -0,0 +1,18 @@ +error: attribute should be applied to a trait + --> $DIR/attr-misuse.rs:9:1 + | +LL | #[const_trait] + | ^^^^^^^^^^^^^^ +LL | fn main() {} + | ------------ not a trait + +error: attribute should be applied to a trait + --> $DIR/attr-misuse.rs:5:5 + | +LL | #[const_trait] + | ^^^^^^^^^^^^^^ +LL | fn foo(self); + | ------------- not a trait + +error: aborting due to 2 previous errors + diff --git a/tests/ui/traits/const-traits/auxiliary/cross-crate.rs b/tests/ui/traits/const-traits/auxiliary/cross-crate.rs new file mode 100644 index 00000000000..8f63cd1d521 --- /dev/null +++ b/tests/ui/traits/const-traits/auxiliary/cross-crate.rs @@ -0,0 +1,25 @@ +//@ compile-flags: -Znext-solver +#![allow(incomplete_features)] +#![feature(const_trait_impl, effects)] + +#[const_trait] +pub trait MyTrait { + fn defaulted_func(&self) {} + fn func(self); +} + +pub struct NonConst; + +impl MyTrait for NonConst { + fn func(self) { + + } +} + +pub struct Const; + +impl const MyTrait for Const { + fn func(self) { + + } +} diff --git a/tests/ui/traits/const-traits/auxiliary/staged-api.rs b/tests/ui/traits/const-traits/auxiliary/staged-api.rs new file mode 100644 index 00000000000..986165ef91e --- /dev/null +++ b/tests/ui/traits/const-traits/auxiliary/staged-api.rs @@ -0,0 +1,21 @@ +//@ compile-flags: -Znext-solver +#![allow(incomplete_features)] +#![feature(const_trait_impl, effects)] +#![feature(staged_api)] +#![stable(feature = "rust1", since = "1.0.0")] + +#[stable(feature = "rust1", since = "1.0.0")] +#[const_trait] +pub trait MyTrait { + #[stable(feature = "rust1", since = "1.0.0")] + fn func(); +} + +#[stable(feature = "rust1", since = "1.0.0")] +pub struct Unstable; + +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_const_unstable(feature = "unstable", issue = "none")] +impl const MyTrait for Unstable { + fn func() {} +} diff --git a/tests/ui/traits/const-traits/call-const-trait-method-fail.rs b/tests/ui/traits/const-traits/call-const-trait-method-fail.rs new file mode 100644 index 00000000000..878f9a713a0 --- /dev/null +++ b/tests/ui/traits/const-traits/call-const-trait-method-fail.rs @@ -0,0 +1,31 @@ +//@ compile-flags: -Znext-solver +#![allow(incomplete_features)] +#![feature(const_trait_impl, effects)] + +#[const_trait] +pub trait Plus { + fn plus(self, rhs: Self) -> Self; +} + +impl const Plus for i32 { + fn plus(self, rhs: Self) -> Self { + self + rhs + } +} + +impl Plus for u32 { + fn plus(self, rhs: Self) -> Self { + self + rhs + } +} + +pub const fn add_i32(a: i32, b: i32) -> i32 { + a.plus(b) // ok +} + +pub const fn add_u32(a: u32, b: u32) -> u32 { + a.plus(b) + //~^ ERROR the trait bound `u32: ~const Plus` +} + +fn main() {} diff --git a/tests/ui/traits/const-traits/call-const-trait-method-fail.stderr b/tests/ui/traits/const-traits/call-const-trait-method-fail.stderr new file mode 100644 index 00000000000..5d2333d94fe --- /dev/null +++ b/tests/ui/traits/const-traits/call-const-trait-method-fail.stderr @@ -0,0 +1,22 @@ +error[E0277]: the trait bound `u32: ~const Plus` is not satisfied + --> $DIR/call-const-trait-method-fail.rs:27:5 + | +LL | a.plus(b) + | ^ the trait `Plus` is not implemented for `u32` + | +note: required by a bound in `Plus::plus` + --> $DIR/call-const-trait-method-fail.rs:5:1 + | +LL | #[const_trait] + | ^^^^^^^^^^^^^^ required by this bound in `Plus::plus` +LL | pub trait Plus { +LL | fn plus(self, rhs: Self) -> Self; + | ---- required by a bound in this associated function +help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement + | +LL | pub const fn add_u32(a: u32, b: u32) -> u32 where u32: Plus { + | +++++++++++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/const-traits/call-const-trait-method-pass.rs b/tests/ui/traits/const-traits/call-const-trait-method-pass.rs new file mode 100644 index 00000000000..b854b422b3a --- /dev/null +++ b/tests/ui/traits/const-traits/call-const-trait-method-pass.rs @@ -0,0 +1,43 @@ +//@ known-bug: #110395 + +#![feature(const_trait_impl)] + +struct Int(i32); + +impl const std::ops::Add for Int { + type Output = Int; + + fn add(self, rhs: Self) -> Self { + Int(self.0.plus(rhs.0)) + } +} + +impl const PartialEq for Int { + fn eq(&self, rhs: &Self) -> bool { + self.0 == rhs.0 + } + fn ne(&self, other: &Self) -> bool { + !self.eq(other) + } +} + +#[const_trait] +pub trait Plus { + fn plus(self, rhs: Self) -> Self; +} + +impl const Plus for i32 { + fn plus(self, rhs: Self) -> Self { + self + rhs + } +} + +pub const fn add_i32(a: i32, b: i32) -> i32 { + a.plus(b) +} + +const ADD_INT: Int = Int(1i32) + Int(2i32); + +fn main() { + assert!(ADD_INT == Int(3i32)); +} diff --git a/tests/ui/traits/const-traits/call-const-trait-method-pass.stderr b/tests/ui/traits/const-traits/call-const-trait-method-pass.stderr new file mode 100644 index 00000000000..bf455a714a3 --- /dev/null +++ b/tests/ui/traits/const-traits/call-const-trait-method-pass.stderr @@ -0,0 +1,79 @@ +error: const `impl` for trait `Add` which is not marked with `#[const_trait]` + --> $DIR/call-const-trait-method-pass.rs:7:12 + | +LL | impl const std::ops::Add for Int { + | ^^^^^^^^^^^^^ + | + = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: adding a non-const method body in the future would be a breaking change + +error: const `impl` for trait `PartialEq` which is not marked with `#[const_trait]` + --> $DIR/call-const-trait-method-pass.rs:15:12 + | +LL | impl const PartialEq for Int { + | ^^^^^^^^^ + | + = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: adding a non-const method body in the future would be a breaking change + +error[E0049]: method `plus` has 1 const parameter but its trait declaration has 0 const parameters + --> $DIR/call-const-trait-method-pass.rs:24:1 + | +LL | #[const_trait] + | ^^^^^^^^^^^^^^ found 1 const parameter +LL | pub trait Plus { +LL | fn plus(self, rhs: Self) -> Self; + | - expected 0 const parameters + +error[E0015]: cannot call non-const operator in constants + --> $DIR/call-const-trait-method-pass.rs:39:22 + | +LL | const ADD_INT: Int = Int(1i32) + Int(2i32); + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: calls in constants are limited to constant functions, tuple structs and tuple variants +help: add `#![feature(effects)]` to the crate attributes to enable + | +LL + #![feature(effects)] + | + +error[E0015]: cannot call non-const fn `<i32 as Plus>::plus` in constant functions + --> $DIR/call-const-trait-method-pass.rs:11:20 + | +LL | Int(self.0.plus(rhs.0)) + | ^^^^^^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants +help: add `#![feature(effects)]` to the crate attributes to enable + | +LL + #![feature(effects)] + | + +error[E0015]: cannot call non-const fn `<Int as PartialEq>::eq` in constant functions + --> $DIR/call-const-trait-method-pass.rs:20:15 + | +LL | !self.eq(other) + | ^^^^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants +help: add `#![feature(effects)]` to the crate attributes to enable + | +LL + #![feature(effects)] + | + +error[E0015]: cannot call non-const fn `<i32 as Plus>::plus` in constant functions + --> $DIR/call-const-trait-method-pass.rs:36:7 + | +LL | a.plus(b) + | ^^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants +help: add `#![feature(effects)]` to the crate attributes to enable + | +LL + #![feature(effects)] + | + +error: aborting due to 7 previous errors + +Some errors have detailed explanations: E0015, E0049. +For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/call-generic-in-impl.rs b/tests/ui/traits/const-traits/call-generic-in-impl.rs new file mode 100644 index 00000000000..6b3a4ae1b95 --- /dev/null +++ b/tests/ui/traits/const-traits/call-generic-in-impl.rs @@ -0,0 +1,16 @@ +//@ known-bug: #110395 +// FIXME(effects) check-pass +#![feature(const_trait_impl)] + +#[const_trait] +trait MyPartialEq { + fn eq(&self, other: &Self) -> bool; +} + +impl<T: ~const PartialEq> const MyPartialEq for T { + fn eq(&self, other: &Self) -> bool { + PartialEq::eq(self, other) + } +} + +fn main() {} diff --git a/tests/ui/traits/const-traits/call-generic-in-impl.stderr b/tests/ui/traits/const-traits/call-generic-in-impl.stderr new file mode 100644 index 00000000000..5cd274c6c5a --- /dev/null +++ b/tests/ui/traits/const-traits/call-generic-in-impl.stderr @@ -0,0 +1,31 @@ +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/call-generic-in-impl.rs:10:16 + | +LL | impl<T: ~const PartialEq> const MyPartialEq for T { + | ^^^^^^^^^ + +error[E0049]: method `eq` has 1 const parameter but its trait declaration has 0 const parameters + --> $DIR/call-generic-in-impl.rs:5:1 + | +LL | #[const_trait] + | ^^^^^^^^^^^^^^ found 1 const parameter +LL | trait MyPartialEq { +LL | fn eq(&self, other: &Self) -> bool; + | - expected 0 const parameters + +error[E0015]: cannot call non-const fn `<T as PartialEq>::eq` in constant functions + --> $DIR/call-generic-in-impl.rs:12:9 + | +LL | PartialEq::eq(self, other) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants +help: add `#![feature(effects)]` to the crate attributes to enable + | +LL + #![feature(effects)] + | + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0015, E0049. +For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/call-generic-method-chain.rs b/tests/ui/traits/const-traits/call-generic-method-chain.rs new file mode 100644 index 00000000000..9df694a02f5 --- /dev/null +++ b/tests/ui/traits/const-traits/call-generic-method-chain.rs @@ -0,0 +1,29 @@ +//! Basic test for calling methods on generic type parameters in `const fn`. + +//@ known-bug: #110395 +// FIXME(effects) check-pass + +#![feature(const_trait_impl, effects)] + +struct S; + +impl const PartialEq for S { + fn eq(&self, _: &S) -> bool { + true + } + fn ne(&self, other: &S) -> bool { + !self.eq(other) + } +} + +const fn equals_self<T: ~const PartialEq>(t: &T) -> bool { + *t == *t +} + +const fn equals_self_wrapper<T: ~const PartialEq>(t: &T) -> bool { + equals_self(t) +} + +pub const EQ: bool = equals_self_wrapper(&S); + +fn main() {} diff --git a/tests/ui/traits/const-traits/call-generic-method-chain.stderr b/tests/ui/traits/const-traits/call-generic-method-chain.stderr new file mode 100644 index 00000000000..57d57dfd5b9 --- /dev/null +++ b/tests/ui/traits/const-traits/call-generic-method-chain.stderr @@ -0,0 +1,37 @@ +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/call-generic-method-chain.rs:6:30 + | +LL | #![feature(const_trait_impl, effects)] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + +error: using `#![feature(effects)]` without enabling next trait solver globally + | + = note: the next trait solver must be enabled globally for the effects feature to work correctly + = help: use `-Znext-solver` to enable + +error: const `impl` for trait `PartialEq` which is not marked with `#[const_trait]` + --> $DIR/call-generic-method-chain.rs:10:12 + | +LL | impl const PartialEq for S { + | ^^^^^^^^^ + | + = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: adding a non-const method body in the future would be a breaking change + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/call-generic-method-chain.rs:19:32 + | +LL | const fn equals_self<T: ~const PartialEq>(t: &T) -> bool { + | ^^^^^^^^^ + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/call-generic-method-chain.rs:23:40 + | +LL | const fn equals_self_wrapper<T: ~const PartialEq>(t: &T) -> bool { + | ^^^^^^^^^ + +error: aborting due to 4 previous errors; 1 warning emitted + diff --git a/tests/ui/traits/const-traits/call-generic-method-dup-bound.rs b/tests/ui/traits/const-traits/call-generic-method-dup-bound.rs new file mode 100644 index 00000000000..f46a34911f1 --- /dev/null +++ b/tests/ui/traits/const-traits/call-generic-method-dup-bound.rs @@ -0,0 +1,32 @@ +//@ known-bug: #110395 +// FIXME(effects) check-pass + +#![feature(const_trait_impl, effects)] + +struct S; + +impl const PartialEq for S { + fn eq(&self, _: &S) -> bool { + true + } + fn ne(&self, other: &S) -> bool { + !self.eq(other) + } +} + +// This duplicate bound should not result in ambiguities. It should be equivalent to a single ~const +// bound. +const fn equals_self<T: PartialEq + ~const PartialEq>(t: &T) -> bool { + *t == *t +} + +trait A: PartialEq {} +impl<T: PartialEq> A for T {} + +const fn equals_self2<T: A + ~const PartialEq>(t: &T) -> bool { + *t == *t +} + +pub const EQ: bool = equals_self(&S) && equals_self2(&S); + +fn main() {} diff --git a/tests/ui/traits/const-traits/call-generic-method-dup-bound.stderr b/tests/ui/traits/const-traits/call-generic-method-dup-bound.stderr new file mode 100644 index 00000000000..0088ed2eb13 --- /dev/null +++ b/tests/ui/traits/const-traits/call-generic-method-dup-bound.stderr @@ -0,0 +1,37 @@ +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/call-generic-method-dup-bound.rs:4:30 + | +LL | #![feature(const_trait_impl, effects)] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + +error: using `#![feature(effects)]` without enabling next trait solver globally + | + = note: the next trait solver must be enabled globally for the effects feature to work correctly + = help: use `-Znext-solver` to enable + +error: const `impl` for trait `PartialEq` which is not marked with `#[const_trait]` + --> $DIR/call-generic-method-dup-bound.rs:8:12 + | +LL | impl const PartialEq for S { + | ^^^^^^^^^ + | + = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: adding a non-const method body in the future would be a breaking change + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/call-generic-method-dup-bound.rs:19:44 + | +LL | const fn equals_self<T: PartialEq + ~const PartialEq>(t: &T) -> bool { + | ^^^^^^^^^ + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/call-generic-method-dup-bound.rs:26:37 + | +LL | const fn equals_self2<T: A + ~const PartialEq>(t: &T) -> bool { + | ^^^^^^^^^ + +error: aborting due to 4 previous errors; 1 warning emitted + diff --git a/tests/ui/traits/const-traits/call-generic-method-fail.rs b/tests/ui/traits/const-traits/call-generic-method-fail.rs new file mode 100644 index 00000000000..86e0eae61c9 --- /dev/null +++ b/tests/ui/traits/const-traits/call-generic-method-fail.rs @@ -0,0 +1,12 @@ +//@ check-pass +//@ compile-flags: -Znext-solver +#![allow(incomplete_features)] +#![feature(const_trait_impl, effects)] + +pub const fn equals_self<T: PartialEq>(t: &T) -> bool { + *t == *t + // FIXME(effects) ~^ ERROR mismatched types + // FIXME(effects): diagnostic +} + +fn main() {} diff --git a/tests/ui/traits/const-traits/call-generic-method-nonconst-bound.rs b/tests/ui/traits/const-traits/call-generic-method-nonconst-bound.rs new file mode 100644 index 00000000000..9dbc2b95626 --- /dev/null +++ b/tests/ui/traits/const-traits/call-generic-method-nonconst-bound.rs @@ -0,0 +1,17 @@ +//@ check-pass + +struct S; + +impl PartialEq for S { + fn eq(&self, _: &S) -> bool { + true + } +} + +const fn equals_self<T: PartialEq>(t: &T) -> bool { + true +} + +pub const EQ: bool = equals_self(&S); + +fn main() {} diff --git a/tests/ui/traits/const-traits/call-generic-method-nonconst.rs b/tests/ui/traits/const-traits/call-generic-method-nonconst.rs new file mode 100644 index 00000000000..f9e79d41752 --- /dev/null +++ b/tests/ui/traits/const-traits/call-generic-method-nonconst.rs @@ -0,0 +1,28 @@ +//@ compile-flags: -Znext-solver +#![allow(incomplete_features)] +#![feature(const_trait_impl, effects)] + +struct S; + +#[const_trait] +trait Foo { + fn eq(&self, _: &Self) -> bool; +} + +impl Foo for S { + fn eq(&self, _: &S) -> bool { + true + } +} + +const fn equals_self<T: ~const Foo>(t: &T) -> bool { + true +} + +// Calling `equals_self` with something that has a non-const impl should throw an error, despite +// it not using the impl. + +pub const EQ: bool = equals_self(&S); +//~^ ERROR: the trait bound `S: const Foo` is not satisfied + +fn main() {} diff --git a/tests/ui/traits/const-traits/call-generic-method-nonconst.stderr b/tests/ui/traits/const-traits/call-generic-method-nonconst.stderr new file mode 100644 index 00000000000..68c9fc40010 --- /dev/null +++ b/tests/ui/traits/const-traits/call-generic-method-nonconst.stderr @@ -0,0 +1,21 @@ +error[E0277]: the trait bound `S: const Foo` is not satisfied + --> $DIR/call-generic-method-nonconst.rs:25:34 + | +LL | pub const EQ: bool = equals_self(&S); + | ----------- ^^ the trait `Foo` is not implemented for `S` + | | + | required by a bound introduced by this call + | +note: required by a bound in `equals_self` + --> $DIR/call-generic-method-nonconst.rs:18:25 + | +LL | const fn equals_self<T: ~const Foo>(t: &T) -> bool { + | ^^^^^^^^^^ required by this bound in `equals_self` +help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement + | +LL | pub const EQ: bool where S: Foo = equals_self(&S); + | ++++++++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/const-traits/call-generic-method-pass.rs b/tests/ui/traits/const-traits/call-generic-method-pass.rs new file mode 100644 index 00000000000..413685d8b34 --- /dev/null +++ b/tests/ui/traits/const-traits/call-generic-method-pass.rs @@ -0,0 +1,25 @@ +//! Basic test for calling methods on generic type parameters in `const fn`. + +//@ known-bug: #110395 +// FIXME(effects) check-pass + +#![feature(const_trait_impl, effects)] + +struct S; + +impl const PartialEq for S { + fn eq(&self, _: &S) -> bool { + true + } + fn ne(&self, other: &S) -> bool { + !self.eq(other) + } +} + +const fn equals_self<T: ~const PartialEq>(t: &T) -> bool { + *t == *t +} + +pub const EQ: bool = equals_self(&S); + +fn main() {} diff --git a/tests/ui/traits/const-traits/call-generic-method-pass.stderr b/tests/ui/traits/const-traits/call-generic-method-pass.stderr new file mode 100644 index 00000000000..4a6100c3c1a --- /dev/null +++ b/tests/ui/traits/const-traits/call-generic-method-pass.stderr @@ -0,0 +1,31 @@ +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/call-generic-method-pass.rs:6:30 + | +LL | #![feature(const_trait_impl, effects)] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + +error: using `#![feature(effects)]` without enabling next trait solver globally + | + = note: the next trait solver must be enabled globally for the effects feature to work correctly + = help: use `-Znext-solver` to enable + +error: const `impl` for trait `PartialEq` which is not marked with `#[const_trait]` + --> $DIR/call-generic-method-pass.rs:10:12 + | +LL | impl const PartialEq for S { + | ^^^^^^^^^ + | + = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: adding a non-const method body in the future would be a breaking change + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/call-generic-method-pass.rs:19:32 + | +LL | const fn equals_self<T: ~const PartialEq>(t: &T) -> bool { + | ^^^^^^^^^ + +error: aborting due to 3 previous errors; 1 warning emitted + diff --git a/tests/ui/traits/const-traits/call.rs b/tests/ui/traits/const-traits/call.rs new file mode 100644 index 00000000000..af2f7caf88c --- /dev/null +++ b/tests/ui/traits/const-traits/call.rs @@ -0,0 +1,10 @@ +//@ check-pass +//@ compile-flags: -Znext-solver +#![feature(const_closures, const_trait_impl, effects)] +#![allow(incomplete_features)] + +pub const _: () = { + assert!((const || true)()); +}; + +fn main() {} diff --git a/tests/ui/traits/const-traits/const-and-non-const-impl.rs b/tests/ui/traits/const-traits/const-and-non-const-impl.rs new file mode 100644 index 00000000000..6b96fcf0ae3 --- /dev/null +++ b/tests/ui/traits/const-traits/const-and-non-const-impl.rs @@ -0,0 +1,31 @@ +//@ known-bug: #110395 + +#![feature(const_trait_impl)] + +pub struct Int(i32); + +impl const std::ops::Add for i32 { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + self + rhs + } +} + +impl std::ops::Add for Int { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + Int(self.0 + rhs.0) + } +} + +impl const std::ops::Add for Int { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + Int(self.0 + rhs.0) + } +} + +fn main() {} diff --git a/tests/ui/traits/const-traits/const-and-non-const-impl.stderr b/tests/ui/traits/const-traits/const-and-non-const-impl.stderr new file mode 100644 index 00000000000..cf7af41cd4e --- /dev/null +++ b/tests/ui/traits/const-traits/const-and-non-const-impl.stderr @@ -0,0 +1,44 @@ +error: const `impl` for trait `Add` which is not marked with `#[const_trait]` + --> $DIR/const-and-non-const-impl.rs:7:12 + | +LL | impl const std::ops::Add for i32 { + | ^^^^^^^^^^^^^ + | + = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: adding a non-const method body in the future would be a breaking change + +error: const `impl` for trait `Add` which is not marked with `#[const_trait]` + --> $DIR/const-and-non-const-impl.rs:23:12 + | +LL | impl const std::ops::Add for Int { + | ^^^^^^^^^^^^^ + | + = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: adding a non-const method body in the future would be a breaking change + +error[E0119]: conflicting implementations of trait `Add` for type `Int` + --> $DIR/const-and-non-const-impl.rs:23:1 + | +LL | impl std::ops::Add for Int { + | -------------------------- first implementation here +... +LL | impl const std::ops::Add for Int { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Int` + +error[E0117]: only traits defined in the current crate can be implemented for primitive types + --> $DIR/const-and-non-const-impl.rs:7:1 + | +LL | impl const std::ops::Add for i32 { + | ^^^^^^^^^^^-------------^^^^^--- + | | | + | | `i32` is not defined in the current crate + | `i32` is not defined in the current crate + | + = note: impl doesn't have any local type before any uncovered type parameters + = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules + = note: define and implement a trait or new type instead + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0117, E0119. +For more information about an error, try `rustc --explain E0117`. diff --git a/tests/ui/traits/const-traits/const-bound-on-not-const-associated-fn.rs b/tests/ui/traits/const-traits/const-bound-on-not-const-associated-fn.rs new file mode 100644 index 00000000000..099cf0b00d3 --- /dev/null +++ b/tests/ui/traits/const-traits/const-bound-on-not-const-associated-fn.rs @@ -0,0 +1,29 @@ +#![allow(incomplete_features)] +#![feature(const_trait_impl, effects)] + +#[const_trait] +trait MyTrait { + fn do_something(&self); +} + +trait OtherTrait { + fn do_something_else() where Self: ~const MyTrait; + //~^ ERROR `~const` is not allowed here +} + +struct MyStruct<T>(T); + +impl const MyTrait for u32 { + fn do_something(&self) {} +} + +impl<T> MyStruct<T> { + pub fn foo(&self) where T: ~const MyTrait { + //~^ ERROR `~const` is not allowed here + self.0.do_something(); + } +} + +fn main() { + MyStruct(0u32).foo(); +} diff --git a/tests/ui/traits/const-traits/const-bound-on-not-const-associated-fn.stderr b/tests/ui/traits/const-traits/const-bound-on-not-const-associated-fn.stderr new file mode 100644 index 00000000000..b5d9b1fff8a --- /dev/null +++ b/tests/ui/traits/const-traits/const-bound-on-not-const-associated-fn.stderr @@ -0,0 +1,31 @@ +error: `~const` is not allowed here + --> $DIR/const-bound-on-not-const-associated-fn.rs:10:40 + | +LL | fn do_something_else() where Self: ~const MyTrait; + | ^^^^^^ + | +note: this function is not `const`, so it cannot have `~const` trait bounds + --> $DIR/const-bound-on-not-const-associated-fn.rs:10:8 + | +LL | fn do_something_else() where Self: ~const MyTrait; + | ^^^^^^^^^^^^^^^^^ + +error: `~const` is not allowed here + --> $DIR/const-bound-on-not-const-associated-fn.rs:21:32 + | +LL | pub fn foo(&self) where T: ~const MyTrait { + | ^^^^^^ + | +note: this function is not `const`, so it cannot have `~const` trait bounds + --> $DIR/const-bound-on-not-const-associated-fn.rs:21:12 + | +LL | pub fn foo(&self) where T: ~const MyTrait { + | ^^^ + +error: using `#![feature(effects)]` without enabling next trait solver globally + | + = note: the next trait solver must be enabled globally for the effects feature to work correctly + = help: use `-Znext-solver` to enable + +error: aborting due to 3 previous errors + diff --git a/tests/ui/traits/const-traits/const-bounds-non-const-trait.rs b/tests/ui/traits/const-traits/const-bounds-non-const-trait.rs new file mode 100644 index 00000000000..db446f8bc2e --- /dev/null +++ b/tests/ui/traits/const-traits/const-bounds-non-const-trait.rs @@ -0,0 +1,12 @@ +// Regression test for issue #117244. +#![feature(const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete + +trait NonConst {} + +const fn perform<T: ~const NonConst>() {} +//~^ ERROR `~const` can only be applied to `#[const_trait]` traits + +fn operate<T: const NonConst>() {} +//~^ ERROR `const` can only be applied to `#[const_trait]` traits + +fn main() {} diff --git a/tests/ui/traits/const-traits/const-bounds-non-const-trait.stderr b/tests/ui/traits/const-traits/const-bounds-non-const-trait.stderr new file mode 100644 index 00000000000..e1a85fc5414 --- /dev/null +++ b/tests/ui/traits/const-traits/const-bounds-non-const-trait.stderr @@ -0,0 +1,28 @@ +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/const-bounds-non-const-trait.rs:2:30 + | +LL | #![feature(const_trait_impl, effects)] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + +error: using `#![feature(effects)]` without enabling next trait solver globally + | + = note: the next trait solver must be enabled globally for the effects feature to work correctly + = help: use `-Znext-solver` to enable + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-bounds-non-const-trait.rs:6:28 + | +LL | const fn perform<T: ~const NonConst>() {} + | ^^^^^^^^ + +error: `const` can only be applied to `#[const_trait]` traits + --> $DIR/const-bounds-non-const-trait.rs:9:21 + | +LL | fn operate<T: const NonConst>() {} + | ^^^^^^^^ + +error: aborting due to 3 previous errors; 1 warning emitted + diff --git a/tests/ui/traits/const-traits/const-check-fns-in-const-impl.rs b/tests/ui/traits/const-traits/const-check-fns-in-const-impl.rs new file mode 100644 index 00000000000..a1710e65252 --- /dev/null +++ b/tests/ui/traits/const-traits/const-check-fns-in-const-impl.rs @@ -0,0 +1,16 @@ +#![feature(const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete + +struct S; +#[const_trait] +trait T { + fn foo(); +} + +fn non_const() {} + +impl const T for S { + fn foo() { non_const() } + //~^ ERROR cannot call non-const fn +} + +fn main() {} diff --git a/tests/ui/traits/const-traits/const-check-fns-in-const-impl.stderr b/tests/ui/traits/const-traits/const-check-fns-in-const-impl.stderr new file mode 100644 index 00000000000..49cd1725c8c --- /dev/null +++ b/tests/ui/traits/const-traits/const-check-fns-in-const-impl.stderr @@ -0,0 +1,25 @@ +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/const-check-fns-in-const-impl.rs:1:30 + | +LL | #![feature(const_trait_impl, effects)] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + +error: using `#![feature(effects)]` without enabling next trait solver globally + | + = note: the next trait solver must be enabled globally for the effects feature to work correctly + = help: use `-Znext-solver` to enable + +error[E0015]: cannot call non-const fn `non_const` in constant functions + --> $DIR/const-check-fns-in-const-impl.rs:12:16 + | +LL | fn foo() { non_const() } + | ^^^^^^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + +error: aborting due to 2 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/const-closure-parse-not-item.rs b/tests/ui/traits/const-traits/const-closure-parse-not-item.rs new file mode 100644 index 00000000000..b1b0e68b90d --- /dev/null +++ b/tests/ui/traits/const-traits/const-closure-parse-not-item.rs @@ -0,0 +1,11 @@ +//@ known-bug: #110395 +// FIXME check-pass + +#![feature(const_trait_impl, const_closures)] +#![allow(incomplete_features)] + +const fn test() -> impl ~const Fn() { + const move || {} +} + +fn main() {} diff --git a/tests/ui/traits/const-traits/const-closure-parse-not-item.stderr b/tests/ui/traits/const-traits/const-closure-parse-not-item.stderr new file mode 100644 index 00000000000..12cc79f5961 --- /dev/null +++ b/tests/ui/traits/const-traits/const-closure-parse-not-item.stderr @@ -0,0 +1,16 @@ +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-closure-parse-not-item.rs:7:32 + | +LL | const fn test() -> impl ~const Fn() { + | ^^^^ + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-closure-parse-not-item.rs:7:32 + | +LL | const fn test() -> impl ~const Fn() { + | ^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/traits/const-traits/const-closure-trait-method-fail.rs b/tests/ui/traits/const-traits/const-closure-trait-method-fail.rs new file mode 100644 index 00000000000..8c6286426d3 --- /dev/null +++ b/tests/ui/traits/const-traits/const-closure-trait-method-fail.rs @@ -0,0 +1,20 @@ +//@ known-bug: #110395 + +#![feature(const_trait_impl)] + +#[const_trait] +trait Tr { + fn a(self) -> i32; +} + +impl Tr for () { + fn a(self) -> i32 { 42 } +} + +const fn need_const_closure<T: ~const FnOnce(()) -> i32>(x: T) -> i32 { + x(()) +} + +const _: () = assert!(need_const_closure(Tr::a) == 42); + +fn main() {} diff --git a/tests/ui/traits/const-traits/const-closure-trait-method-fail.stderr b/tests/ui/traits/const-traits/const-closure-trait-method-fail.stderr new file mode 100644 index 00000000000..507ceaae2ea --- /dev/null +++ b/tests/ui/traits/const-traits/const-closure-trait-method-fail.stderr @@ -0,0 +1,35 @@ +error[E0049]: method `a` has 1 const parameter but its trait declaration has 0 const parameters + --> $DIR/const-closure-trait-method-fail.rs:5:1 + | +LL | #[const_trait] + | ^^^^^^^^^^^^^^ found 1 const parameter +LL | trait Tr { +LL | fn a(self) -> i32; + | - expected 0 const parameters + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-closure-trait-method-fail.rs:14:39 + | +LL | const fn need_const_closure<T: ~const FnOnce(()) -> i32>(x: T) -> i32 { + | ^^^^^^^^^^^^^^^^^ + +error[E0015]: cannot call non-const closure in constant functions + --> $DIR/const-closure-trait-method-fail.rs:15:5 + | +LL | x(()) + | ^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants +help: consider further restricting this bound + | +LL | const fn need_const_closure<T: ~const FnOnce(()) -> i32 + ~const FnOnce(())>(x: T) -> i32 { + | +++++++++++++++++++ +help: add `#![feature(effects)]` to the crate attributes to enable + | +LL + #![feature(effects)] + | + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0015, E0049. +For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/const-closure-trait-method.rs b/tests/ui/traits/const-traits/const-closure-trait-method.rs new file mode 100644 index 00000000000..ebee4daefbe --- /dev/null +++ b/tests/ui/traits/const-traits/const-closure-trait-method.rs @@ -0,0 +1,20 @@ +//@ known-bug: #110395 +// FIXME check-pass +#![feature(const_trait_impl)] + +#[const_trait] +trait Tr { + fn a(self) -> i32; +} + +impl const Tr for () { + fn a(self) -> i32 { 42 } +} + +const fn need_const_closure<T: ~const FnOnce(()) -> i32>(x: T) -> i32 { + x(()) +} + +const _: () = assert!(need_const_closure(Tr::a) == 42); + +fn main() {} diff --git a/tests/ui/traits/const-traits/const-closure-trait-method.stderr b/tests/ui/traits/const-traits/const-closure-trait-method.stderr new file mode 100644 index 00000000000..2a54cd5d7f6 --- /dev/null +++ b/tests/ui/traits/const-traits/const-closure-trait-method.stderr @@ -0,0 +1,35 @@ +error[E0049]: method `a` has 1 const parameter but its trait declaration has 0 const parameters + --> $DIR/const-closure-trait-method.rs:5:1 + | +LL | #[const_trait] + | ^^^^^^^^^^^^^^ found 1 const parameter +LL | trait Tr { +LL | fn a(self) -> i32; + | - expected 0 const parameters + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-closure-trait-method.rs:14:39 + | +LL | const fn need_const_closure<T: ~const FnOnce(()) -> i32>(x: T) -> i32 { + | ^^^^^^^^^^^^^^^^^ + +error[E0015]: cannot call non-const closure in constant functions + --> $DIR/const-closure-trait-method.rs:15:5 + | +LL | x(()) + | ^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants +help: consider further restricting this bound + | +LL | const fn need_const_closure<T: ~const FnOnce(()) -> i32 + ~const FnOnce(())>(x: T) -> i32 { + | +++++++++++++++++++ +help: add `#![feature(effects)]` to the crate attributes to enable + | +LL + #![feature(effects)] + | + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0015, E0049. +For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/const-closures.rs b/tests/ui/traits/const-traits/const-closures.rs new file mode 100644 index 00000000000..98f8d039cd6 --- /dev/null +++ b/tests/ui/traits/const-traits/const-closures.rs @@ -0,0 +1,31 @@ +//@ known-bug: #110395 +// FIXME check-pass + +#![feature(const_trait_impl)] + +const fn answer_p1<F>(f: &F) -> u8 + where + F: ~const FnOnce() -> u8, + F: ~const FnMut() -> u8, + F: ~const Fn() -> u8, +{ + f() * 7 +} + +const fn three() -> u8 { + 3 +} + +const fn answer_p2() -> u8 { + answer_p1(&three) +} + +const fn answer<F: ~const Fn() -> u8>(f: &F) -> u8 { + f() + f() +} + +const ANSWER: u8 = answer(&answer_p2); + +fn main() { + assert_eq!(ANSWER, 42) +} diff --git a/tests/ui/traits/const-traits/const-closures.stderr b/tests/ui/traits/const-traits/const-closures.stderr new file mode 100644 index 00000000000..a0f05325389 --- /dev/null +++ b/tests/ui/traits/const-traits/const-closures.stderr @@ -0,0 +1,75 @@ +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-closures.rs:8:19 + | +LL | F: ~const FnOnce() -> u8, + | ^^^^^^^^^^^^^^ + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-closures.rs:9:19 + | +LL | F: ~const FnMut() -> u8, + | ^^^^^^^^^^^^^ + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-closures.rs:10:19 + | +LL | F: ~const Fn() -> u8, + | ^^^^^^^^^^ + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-closures.rs:23:27 + | +LL | const fn answer<F: ~const Fn() -> u8>(f: &F) -> u8 { + | ^^^^^^^^^^ + +error[E0015]: cannot call non-const closure in constant functions + --> $DIR/const-closures.rs:24:5 + | +LL | f() + f() + | ^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants +help: consider further restricting this bound + | +LL | const fn answer<F: ~const Fn() -> u8 + ~const Fn()>(f: &F) -> u8 { + | +++++++++++++ +help: add `#![feature(effects)]` to the crate attributes to enable + | +LL + #![feature(effects)] + | + +error[E0015]: cannot call non-const closure in constant functions + --> $DIR/const-closures.rs:24:11 + | +LL | f() + f() + | ^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants +help: consider further restricting this bound + | +LL | const fn answer<F: ~const Fn() -> u8 + ~const Fn()>(f: &F) -> u8 { + | +++++++++++++ +help: add `#![feature(effects)]` to the crate attributes to enable + | +LL + #![feature(effects)] + | + +error[E0015]: cannot call non-const closure in constant functions + --> $DIR/const-closures.rs:12:5 + | +LL | f() * 7 + | ^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants +help: consider further restricting this bound + | +LL | F: ~const FnOnce() -> u8 + ~const Fn(), + | +++++++++++++ +help: add `#![feature(effects)]` to the crate attributes to enable + | +LL + #![feature(effects)] + | + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/const-default-method-bodies.rs b/tests/ui/traits/const-traits/const-default-method-bodies.rs new file mode 100644 index 00000000000..a0333153f85 --- /dev/null +++ b/tests/ui/traits/const-traits/const-default-method-bodies.rs @@ -0,0 +1,31 @@ +//@ compile-flags: -Znext-solver +#![allow(incomplete_features)] +#![feature(const_trait_impl, effects)] + +#[const_trait] +trait ConstDefaultFn: Sized { + fn b(self); + + fn a(self) { + self.b(); + } +} + +struct NonConstImpl; +struct ConstImpl; + +impl ConstDefaultFn for NonConstImpl { + fn b(self) {} +} + +impl const ConstDefaultFn for ConstImpl { + fn b(self) {} +} + +const fn test() { + NonConstImpl.a(); + //~^ ERROR the trait bound `NonConstImpl: ~const ConstDefaultFn` is not satisfied + ConstImpl.a(); +} + +fn main() {} diff --git a/tests/ui/traits/const-traits/const-default-method-bodies.stderr b/tests/ui/traits/const-traits/const-default-method-bodies.stderr new file mode 100644 index 00000000000..0809d9c1e1d --- /dev/null +++ b/tests/ui/traits/const-traits/const-default-method-bodies.stderr @@ -0,0 +1,22 @@ +error[E0277]: the trait bound `NonConstImpl: ~const ConstDefaultFn` is not satisfied + --> $DIR/const-default-method-bodies.rs:26:18 + | +LL | NonConstImpl.a(); + | ^ the trait `ConstDefaultFn` is not implemented for `NonConstImpl` + | +note: required by a bound in `ConstDefaultFn::a` + --> $DIR/const-default-method-bodies.rs:5:1 + | +LL | #[const_trait] + | ^^^^^^^^^^^^^^ required by this bound in `ConstDefaultFn::a` +... +LL | fn a(self) { + | - required by a bound in this associated function +help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement + | +LL | const fn test() where NonConstImpl: ConstDefaultFn { + | ++++++++++++++++++++++++++++++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/const-traits/const-drop-bound.rs b/tests/ui/traits/const-traits/const-drop-bound.rs new file mode 100644 index 00000000000..b0790f86ef5 --- /dev/null +++ b/tests/ui/traits/const-traits/const-drop-bound.rs @@ -0,0 +1,26 @@ +//@ known-bug: #110395 +// FIXME check-pass + +#![feature(const_trait_impl)] +#![feature(const_precise_live_drops)] + +use std::marker::Destruct; + +const fn foo<T, E>(res: Result<T, E>) -> Option<T> where E: ~const Destruct { + match res { + Ok(t) => Some(t), + Err(_e) => None, + } +} + +pub struct Foo<T>(T); + +const fn baz<T, E>(res: Result<Foo<T>, Foo<E>>) -> Option<Foo<T>> +where + T: ~const Destruct, + E: ~const Destruct, +{ + foo(res) +} + +fn main() {} diff --git a/tests/ui/traits/const-traits/const-drop-bound.stderr b/tests/ui/traits/const-traits/const-drop-bound.stderr new file mode 100644 index 00000000000..be197006f02 --- /dev/null +++ b/tests/ui/traits/const-traits/const-drop-bound.stderr @@ -0,0 +1,27 @@ +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-drop-bound.rs:9:68 + | +LL | const fn foo<T, E>(res: Result<T, E>) -> Option<T> where E: ~const Destruct { + | ^^^^^^^^ + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-drop-bound.rs:20:15 + | +LL | T: ~const Destruct, + | ^^^^^^^^ + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-drop-bound.rs:21:15 + | +LL | E: ~const Destruct, + | ^^^^^^^^ + +error[E0493]: destructor of `E` cannot be evaluated at compile-time + --> $DIR/const-drop-bound.rs:12:13 + | +LL | Err(_e) => None, + | ^^ the destructor for this type cannot be evaluated in constant functions + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0493`. diff --git a/tests/ui/traits/const-traits/const-drop-fail-2.precise.stderr b/tests/ui/traits/const-traits/const-drop-fail-2.precise.stderr new file mode 100644 index 00000000000..7529af9293d --- /dev/null +++ b/tests/ui/traits/const-traits/const-drop-fail-2.precise.stderr @@ -0,0 +1,26 @@ +error: const `impl` for trait `Drop` which is not marked with `#[const_trait]` + --> $DIR/const-drop-fail-2.rs:23:25 + | +LL | impl<T: ~const A> const Drop for ConstDropImplWithBounds<T> { + | ^^^^ + | + = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: adding a non-const method body in the future would be a breaking change + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-drop-fail-2.rs:29:26 + | +LL | const fn check<T: ~const Destruct>(_: T) {} + | ^^^^^^^^ + +error: const `impl` for trait `Drop` which is not marked with `#[const_trait]` + --> $DIR/const-drop-fail-2.rs:39:25 + | +LL | impl<T: ~const A> const Drop for ConstDropImplWithNonConstBounds<T> { + | ^^^^ + | + = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: adding a non-const method body in the future would be a breaking change + +error: aborting due to 3 previous errors + diff --git a/tests/ui/traits/const-traits/const-drop-fail-2.rs b/tests/ui/traits/const-traits/const-drop-fail-2.rs new file mode 100644 index 00000000000..7b57e0405af --- /dev/null +++ b/tests/ui/traits/const-traits/const-drop-fail-2.rs @@ -0,0 +1,45 @@ +//@ known-bug: #110395 +#![feature(const_trait_impl)] +// #![cfg_attr(precise, feature(const_precise_live_drops))] + +use std::marker::{Destruct, PhantomData}; + +struct NonTrivialDrop; + +impl Drop for NonTrivialDrop { + fn drop(&mut self) { + println!("Non trivial drop"); + } +} + +#[const_trait] +trait A { fn a() { } } + +impl A for NonTrivialDrop {} + +const fn check<T: ~const Destruct>(_: T) {} + + +/* FIXME(effects) +struct ConstDropImplWithBounds<T: ~const A>(PhantomData<T>); + +impl<T: ~const A> const Drop for ConstDropImplWithBounds<T> { + fn drop(&mut self) { + T::a(); + } +} + +const _: () = check::<ConstDropImplWithBounds<NonTrivialDrop>>( + ConstDropImplWithBounds(PhantomData) +); +*/ + +struct ConstDropImplWithNonConstBounds<T: A>(PhantomData<T>); + +impl<T: ~const A> const Drop for ConstDropImplWithNonConstBounds<T> { + fn drop(&mut self) { + T::a(); + } +} + +fn main() {} diff --git a/tests/ui/traits/const-traits/const-drop-fail-2.stderr b/tests/ui/traits/const-traits/const-drop-fail-2.stderr new file mode 100644 index 00000000000..faf24c6d911 --- /dev/null +++ b/tests/ui/traits/const-traits/const-drop-fail-2.stderr @@ -0,0 +1,39 @@ +error: const `impl` for trait `Drop` which is not marked with `#[const_trait]` + --> $DIR/const-drop-fail-2.rs:39:25 + | +LL | impl<T: ~const A> const Drop for ConstDropImplWithNonConstBounds<T> { + | ^^^^ + | + = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: adding a non-const method body in the future would be a breaking change + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-drop-fail-2.rs:20:26 + | +LL | const fn check<T: ~const Destruct>(_: T) {} + | ^^^^^^^^ + +error[E0493]: destructor of `T` cannot be evaluated at compile-time + --> $DIR/const-drop-fail-2.rs:20:36 + | +LL | const fn check<T: ~const Destruct>(_: T) {} + | ^ - value is dropped here + | | + | the destructor for this type cannot be evaluated in constant functions + +error[E0015]: cannot call non-const fn `<T as A>::a` in constant functions + --> $DIR/const-drop-fail-2.rs:41:9 + | +LL | T::a(); + | ^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants +help: add `#![feature(effects)]` to the crate attributes to enable + | +LL + #![feature(effects)] + | + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0015, E0493. +For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/const-drop-fail-2.stock.stderr b/tests/ui/traits/const-traits/const-drop-fail-2.stock.stderr new file mode 100644 index 00000000000..7529af9293d --- /dev/null +++ b/tests/ui/traits/const-traits/const-drop-fail-2.stock.stderr @@ -0,0 +1,26 @@ +error: const `impl` for trait `Drop` which is not marked with `#[const_trait]` + --> $DIR/const-drop-fail-2.rs:23:25 + | +LL | impl<T: ~const A> const Drop for ConstDropImplWithBounds<T> { + | ^^^^ + | + = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: adding a non-const method body in the future would be a breaking change + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-drop-fail-2.rs:29:26 + | +LL | const fn check<T: ~const Destruct>(_: T) {} + | ^^^^^^^^ + +error: const `impl` for trait `Drop` which is not marked with `#[const_trait]` + --> $DIR/const-drop-fail-2.rs:39:25 + | +LL | impl<T: ~const A> const Drop for ConstDropImplWithNonConstBounds<T> { + | ^^^^ + | + = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: adding a non-const method body in the future would be a breaking change + +error: aborting due to 3 previous errors + diff --git a/tests/ui/traits/const-traits/const-drop-fail.precise.stderr b/tests/ui/traits/const-traits/const-drop-fail.precise.stderr new file mode 100644 index 00000000000..3d400bf0158 --- /dev/null +++ b/tests/ui/traits/const-traits/const-drop-fail.precise.stderr @@ -0,0 +1,77 @@ +error: const `impl` for trait `Drop` which is not marked with `#[const_trait]` + --> $DIR/const-drop-fail.rs:19:12 + | +LL | impl const Drop for ConstImplWithDropGlue { + | ^^^^ + | + = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: adding a non-const method body in the future would be a breaking change + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-drop-fail.rs:23:26 + | +LL | const fn check<T: ~const Destruct>(_: T) {} + | ^^^^^^^^ + +error[E0493]: destructor of `T` cannot be evaluated at compile-time + --> $DIR/const-drop-fail.rs:23:36 + | +LL | const fn check<T: ~const Destruct>(_: T) {} + | ^ the destructor for this type cannot be evaluated in constant functions + +error[E0080]: evaluation of constant value failed + --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL + | + = note: calling non-const function `<NonTrivialDrop as Drop>::drop` + | +note: inside `std::ptr::drop_in_place::<NonTrivialDrop> - shim(Some(NonTrivialDrop))` + --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL +note: inside `check::<NonTrivialDrop>` + --> $DIR/const-drop-fail.rs:23:43 + | +LL | const fn check<T: ~const Destruct>(_: T) {} + | ^ +note: inside `_` + --> $DIR/const-drop-fail.rs:27:23 + | +LL | const _: () = check($exp); + | ^^^^^^^^^^^ +... +LL | / check_all! { +LL | | NonTrivialDrop, +LL | | ConstImplWithDropGlue(NonTrivialDrop), +LL | | } + | |_- in this macro invocation + = note: this error originates in the macro `check_all` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0080]: evaluation of constant value failed + --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL + | + = note: calling non-const function `<NonTrivialDrop as Drop>::drop` + | +note: inside `std::ptr::drop_in_place::<NonTrivialDrop> - shim(Some(NonTrivialDrop))` + --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL +note: inside `std::ptr::drop_in_place::<ConstImplWithDropGlue> - shim(Some(ConstImplWithDropGlue))` + --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL +note: inside `check::<ConstImplWithDropGlue>` + --> $DIR/const-drop-fail.rs:23:43 + | +LL | const fn check<T: ~const Destruct>(_: T) {} + | ^ +note: inside `_` + --> $DIR/const-drop-fail.rs:27:23 + | +LL | const _: () = check($exp); + | ^^^^^^^^^^^ +... +LL | / check_all! { +LL | | NonTrivialDrop, +LL | | ConstImplWithDropGlue(NonTrivialDrop), +LL | | } + | |_- in this macro invocation + = note: this error originates in the macro `check_all` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0080, E0493. +For more information about an error, try `rustc --explain E0080`. diff --git a/tests/ui/traits/const-traits/const-drop-fail.rs b/tests/ui/traits/const-traits/const-drop-fail.rs new file mode 100644 index 00000000000..5a98c32e838 --- /dev/null +++ b/tests/ui/traits/const-traits/const-drop-fail.rs @@ -0,0 +1,36 @@ +//@ known-bug: #110395 + +//@ revisions: stock precise +#![feature(const_trait_impl)] +#![cfg_attr(precise, feature(const_precise_live_drops))] + +use std::marker::{Destruct, PhantomData}; + +struct NonTrivialDrop; + +impl Drop for NonTrivialDrop { + fn drop(&mut self) { + println!("Non trivial drop"); + } +} + +struct ConstImplWithDropGlue(NonTrivialDrop); + +impl const Drop for ConstImplWithDropGlue { + fn drop(&mut self) {} +} + +const fn check<T: ~const Destruct>(_: T) {} + +macro_rules! check_all { + ($($exp:expr),*$(,)?) => {$( + const _: () = check($exp); + )*}; +} + +check_all! { + NonTrivialDrop, + ConstImplWithDropGlue(NonTrivialDrop), +} + +fn main() {} diff --git a/tests/ui/traits/const-traits/const-drop-fail.stock.stderr b/tests/ui/traits/const-traits/const-drop-fail.stock.stderr new file mode 100644 index 00000000000..fd0f6d02684 --- /dev/null +++ b/tests/ui/traits/const-traits/const-drop-fail.stock.stderr @@ -0,0 +1,26 @@ +error: const `impl` for trait `Drop` which is not marked with `#[const_trait]` + --> $DIR/const-drop-fail.rs:19:12 + | +LL | impl const Drop for ConstImplWithDropGlue { + | ^^^^ + | + = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: adding a non-const method body in the future would be a breaking change + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-drop-fail.rs:23:26 + | +LL | const fn check<T: ~const Destruct>(_: T) {} + | ^^^^^^^^ + +error[E0493]: destructor of `T` cannot be evaluated at compile-time + --> $DIR/const-drop-fail.rs:23:36 + | +LL | const fn check<T: ~const Destruct>(_: T) {} + | ^ - value is dropped here + | | + | the destructor for this type cannot be evaluated in constant functions + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0493`. diff --git a/tests/ui/traits/const-traits/const-drop.precise.stderr b/tests/ui/traits/const-traits/const-drop.precise.stderr new file mode 100644 index 00000000000..dd3ea5d241d --- /dev/null +++ b/tests/ui/traits/const-traits/const-drop.precise.stderr @@ -0,0 +1,84 @@ +error: const `impl` for trait `Drop` which is not marked with `#[const_trait]` + --> $DIR/const-drop.rs:12:16 + | +LL | impl<'a> const Drop for S<'a> { + | ^^^^ + | + = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: adding a non-const method body in the future would be a breaking change + +error: const `impl` for trait `Drop` which is not marked with `#[const_trait]` + --> $DIR/const-drop.rs:46:16 + | +LL | impl const Drop for ConstDrop { + | ^^^^ + | + = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: adding a non-const method body in the future would be a breaking change + +error: const `impl` for trait `Drop` which is not marked with `#[const_trait]` + --> $DIR/const-drop.rs:67:37 + | +LL | impl<T: ~const SomeTrait> const Drop for ConstDropWithBound<T> { + | ^^^^ + | + = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: adding a non-const method body in the future would be a breaking change + +error: const `impl` for trait `Drop` which is not marked with `#[const_trait]` + --> $DIR/const-drop.rs:75:30 + | +LL | impl<T: SomeTrait> const Drop for ConstDropWithNonconstBound<T> { + | ^^^^ + | + = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: adding a non-const method body in the future would be a breaking change + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-drop.rs:18:22 + | +LL | const fn a<T: ~const Destruct>(_: T) {} + | ^^^^^^^^ + +error[E0049]: associated function `foo` has 1 const parameter but its trait declaration has 0 const parameters + --> $DIR/const-drop.rs:53:5 + | +LL | #[const_trait] + | ^^^^^^^^^^^^^^ found 1 const parameter +LL | pub trait SomeTrait { +LL | fn foo(); + | - expected 0 const parameters + +error[E0049]: associated function `foo` has 1 const parameter but its trait declaration has 0 const parameters + --> $DIR/const-drop.rs:53:5 + | +LL | #[const_trait] + | ^^^^^^^^^^^^^^ found 1 const parameter +LL | pub trait SomeTrait { +LL | fn foo(); + | - expected 0 const parameters + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0493]: destructor of `T` cannot be evaluated at compile-time + --> $DIR/const-drop.rs:18:32 + | +LL | const fn a<T: ~const Destruct>(_: T) {} + | ^ the destructor for this type cannot be evaluated in constant functions + +error[E0015]: cannot call non-const fn `<T as SomeTrait>::foo` in constant functions + --> $DIR/const-drop.rs:69:13 + | +LL | T::foo(); + | ^^^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants +help: add `#![feature(effects)]` to the crate attributes to enable + | +LL + #![feature(effects)] + | + +error: aborting due to 9 previous errors + +Some errors have detailed explanations: E0015, E0049, E0493. +For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/const-drop.rs b/tests/ui/traits/const-traits/const-drop.rs new file mode 100644 index 00000000000..5bd81fb3ab6 --- /dev/null +++ b/tests/ui/traits/const-traits/const-drop.rs @@ -0,0 +1,115 @@ +// FIXME run-pass +//@ known-bug: #110395 +//@ revisions: stock precise +#![feature(const_trait_impl)] +#![feature(never_type)] +#![cfg_attr(precise, feature(const_precise_live_drops))] + +use std::marker::Destruct; + +struct S<'a>(&'a mut u8); + +impl<'a> const Drop for S<'a> { + fn drop(&mut self) { + *self.0 += 1; + } +} + +const fn a<T: ~const Destruct>(_: T) {} +//FIXME ~^ ERROR destructor of + +const fn b() -> u8 { + let mut c = 0; + let _ = S(&mut c); + //FIXME ~^ ERROR destructor of + a(S(&mut c)); + c +} + +const C: u8 = b(); + +macro_rules! implements_const_drop { + ($($exp:expr),*$(,)?) => { + $( + const _: () = a($exp); + )* + } +} + +#[allow(dead_code)] +mod t { + pub struct Foo; + pub enum Bar { A } + pub fn foo() {} + pub struct ConstDrop; + + impl const Drop for ConstDrop { + fn drop(&mut self) {} + } + + pub struct HasConstDrop(pub ConstDrop); + pub struct TrivialFields(pub u8, pub i8, pub usize, pub isize); + + #[const_trait] + pub trait SomeTrait { + fn foo(); + } + impl const SomeTrait for () { + fn foo() {} + } + // non-const impl + impl SomeTrait for i32 { + fn foo() {} + } + + pub struct ConstDropWithBound<T: const SomeTrait>(pub core::marker::PhantomData<T>); + + impl<T: ~const SomeTrait> const Drop for ConstDropWithBound<T> { + fn drop(&mut self) { + T::foo(); + } + } + + pub struct ConstDropWithNonconstBound<T: SomeTrait>(pub core::marker::PhantomData<T>); + + impl<T: SomeTrait> const Drop for ConstDropWithNonconstBound<T> { + fn drop(&mut self) { + // Note: we DON'T use the `T: SomeTrait` bound + } + } +} + +use t::*; + +implements_const_drop! { + 1u8, + 2, + 3.0, + Foo, + Bar::A, + foo, + ConstDrop, + HasConstDrop(ConstDrop), + TrivialFields(1, 2, 3, 4), + &1, + &1 as *const i32, + ConstDropWithBound::<()>, + ConstDropWithNonconstBound::<i32>, + Result::<i32, !>::Ok(1), +} + +fn main() { + struct HasDropGlue(#[allow(dead_code)] Box<u8>); + struct HasDropImpl; + impl Drop for HasDropImpl { + fn drop(&mut self) { + println!("not trivial drop"); + } + } + + // These types should pass because ~const in a non-const context should have no effect. + a(HasDropGlue(Box::new(0))); + a(HasDropImpl); + + assert_eq!(C, 2); +} diff --git a/tests/ui/traits/const-traits/const-drop.stock.stderr b/tests/ui/traits/const-traits/const-drop.stock.stderr new file mode 100644 index 00000000000..aa59e1c8dc4 --- /dev/null +++ b/tests/ui/traits/const-traits/const-drop.stock.stderr @@ -0,0 +1,86 @@ +error: const `impl` for trait `Drop` which is not marked with `#[const_trait]` + --> $DIR/const-drop.rs:12:16 + | +LL | impl<'a> const Drop for S<'a> { + | ^^^^ + | + = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: adding a non-const method body in the future would be a breaking change + +error: const `impl` for trait `Drop` which is not marked with `#[const_trait]` + --> $DIR/const-drop.rs:46:16 + | +LL | impl const Drop for ConstDrop { + | ^^^^ + | + = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: adding a non-const method body in the future would be a breaking change + +error: const `impl` for trait `Drop` which is not marked with `#[const_trait]` + --> $DIR/const-drop.rs:67:37 + | +LL | impl<T: ~const SomeTrait> const Drop for ConstDropWithBound<T> { + | ^^^^ + | + = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: adding a non-const method body in the future would be a breaking change + +error: const `impl` for trait `Drop` which is not marked with `#[const_trait]` + --> $DIR/const-drop.rs:75:30 + | +LL | impl<T: SomeTrait> const Drop for ConstDropWithNonconstBound<T> { + | ^^^^ + | + = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: adding a non-const method body in the future would be a breaking change + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-drop.rs:18:22 + | +LL | const fn a<T: ~const Destruct>(_: T) {} + | ^^^^^^^^ + +error[E0049]: associated function `foo` has 1 const parameter but its trait declaration has 0 const parameters + --> $DIR/const-drop.rs:53:5 + | +LL | #[const_trait] + | ^^^^^^^^^^^^^^ found 1 const parameter +LL | pub trait SomeTrait { +LL | fn foo(); + | - expected 0 const parameters + +error[E0049]: associated function `foo` has 1 const parameter but its trait declaration has 0 const parameters + --> $DIR/const-drop.rs:53:5 + | +LL | #[const_trait] + | ^^^^^^^^^^^^^^ found 1 const parameter +LL | pub trait SomeTrait { +LL | fn foo(); + | - expected 0 const parameters + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0493]: destructor of `T` cannot be evaluated at compile-time + --> $DIR/const-drop.rs:18:32 + | +LL | const fn a<T: ~const Destruct>(_: T) {} + | ^ - value is dropped here + | | + | the destructor for this type cannot be evaluated in constant functions + +error[E0015]: cannot call non-const fn `<T as SomeTrait>::foo` in constant functions + --> $DIR/const-drop.rs:69:13 + | +LL | T::foo(); + | ^^^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants +help: add `#![feature(effects)]` to the crate attributes to enable + | +LL + #![feature(effects)] + | + +error: aborting due to 9 previous errors + +Some errors have detailed explanations: E0015, E0049, E0493. +For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/const-fns-are-early-bound.rs b/tests/ui/traits/const-traits/const-fns-are-early-bound.rs new file mode 100644 index 00000000000..b3087349e4d --- /dev/null +++ b/tests/ui/traits/const-traits/const-fns-are-early-bound.rs @@ -0,0 +1,136 @@ +//@ known-bug: #110395 +// FIXME(effects) check-pass +//@ compile-flags: -Znext-solver + +#![crate_type = "lib"] +#![allow(internal_features, incomplete_features)] +#![no_std] +#![no_core] +#![feature( + auto_traits, + const_trait_impl, + effects, + lang_items, + no_core, + staged_api, + unboxed_closures, + rustc_attrs, + marker_trait_attr, +)] +#![stable(feature = "minicore", since = "1.0.0")] + +fn test() { + fn is_const_fn<F>(_: F) + where + F: const FnOnce<()>, + { + } + + const fn foo() {} + + is_const_fn(foo); +} + +/// ---------------------------------------------------------------------- /// +/// Const fn trait definitions + +#[const_trait] +#[lang = "fn"] +#[rustc_paren_sugar] +trait Fn<Args: Tuple>: ~const FnMut<Args> { + extern "rust-call" fn call(&self, args: Args) -> Self::Output; +} + +#[const_trait] +#[lang = "fn_mut"] +#[rustc_paren_sugar] +trait FnMut<Args: Tuple>: ~const FnOnce<Args> { + extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output; +} + +#[const_trait] +#[lang = "fn_once"] +#[rustc_paren_sugar] +trait FnOnce<Args: Tuple> { + #[lang = "fn_once_output"] + type Output; + + extern "rust-call" fn call_once(self, args: Args) -> Self::Output; +} + +/// ---------------------------------------------------------------------- /// +/// All this other stuff needed for core. Unrelated to test. + +#[lang = "destruct"] +#[const_trait] +trait Destruct {} + +#[lang = "freeze"] +unsafe auto trait Freeze {} + +#[lang = "drop"] +#[const_trait] +trait Drop { + fn drop(&mut self); +} + +#[lang = "sized"] +trait Sized {} +#[lang = "copy"] +trait Copy {} + +#[lang = "tuple_trait"] +trait Tuple {} + +#[lang = "receiver"] +trait Receiver {} + +impl<T: ?Sized> Receiver for &T {} + +impl<T: ?Sized> Receiver for &mut T {} + +#[stable(feature = "minicore", since = "1.0.0")] +pub mod effects { + use super::Sized; + + #[lang = "EffectsNoRuntime"] + #[stable(feature = "minicore", since = "1.0.0")] + pub struct NoRuntime; + #[lang = "EffectsMaybe"] + #[stable(feature = "minicore", since = "1.0.0")] + pub struct Maybe; + #[lang = "EffectsRuntime"] + #[stable(feature = "minicore", since = "1.0.0")] + pub struct Runtime; + + #[lang = "EffectsCompat"] + #[stable(feature = "minicore", since = "1.0.0")] + pub trait Compat<#[rustc_runtime] const RUNTIME: bool> {} + + #[stable(feature = "minicore", since = "1.0.0")] + impl Compat<false> for NoRuntime {} + #[stable(feature = "minicore", since = "1.0.0")] + impl Compat<true> for Runtime {} + #[stable(feature = "minicore", since = "1.0.0")] + impl<#[rustc_runtime] const RUNTIME: bool> Compat<RUNTIME> for Maybe {} + + #[lang = "EffectsTyCompat"] + #[marker] + #[stable(feature = "minicore", since = "1.0.0")] + pub trait TyCompat<T: ?Sized> {} + + #[stable(feature = "minicore", since = "1.0.0")] + impl<T: ?Sized> TyCompat<T> for T {} + #[stable(feature = "minicore", since = "1.0.0")] + impl<T: ?Sized> TyCompat<T> for Maybe {} + #[stable(feature = "minicore", since = "1.0.0")] + impl<T: ?Sized> TyCompat<Maybe> for T {} + + #[lang = "EffectsIntersection"] + #[stable(feature = "minicore", since = "1.0.0")] + pub trait Intersection { + #[lang = "EffectsIntersectionOutput"] + #[stable(feature = "minicore", since = "1.0.0")] + type Output: ?Sized; + } +} diff --git a/tests/ui/traits/const-traits/const-fns-are-early-bound.stderr b/tests/ui/traits/const-traits/const-fns-are-early-bound.stderr new file mode 100644 index 00000000000..9eda9d98ec5 --- /dev/null +++ b/tests/ui/traits/const-traits/const-fns-are-early-bound.stderr @@ -0,0 +1,20 @@ +error[E0277]: the trait bound `fn() {foo}: const FnOnce()` is not satisfied + --> $DIR/const-fns-are-early-bound.rs:31:17 + | +LL | is_const_fn(foo); + | ----------- ^^^ the trait `FnOnce()` is not implemented for fn item `fn() {foo}` + | | + | required by a bound introduced by this call + | +note: required by a bound in `is_const_fn` + --> $DIR/const-fns-are-early-bound.rs:25:12 + | +LL | fn is_const_fn<F>(_: F) + | ----------- required by a bound in this function +LL | where +LL | F: const FnOnce<()>, + | ^^^^^^^^^^^^^^^^ required by this bound in `is_const_fn` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/const-traits/const-impl-norecover.rs b/tests/ui/traits/const-traits/const-impl-norecover.rs new file mode 100644 index 00000000000..bed4e9fd1e6 --- /dev/null +++ b/tests/ui/traits/const-traits/const-impl-norecover.rs @@ -0,0 +1,12 @@ +#![feature(const_trait_impl)] + +struct Foo; + +const impl Foo { //~ ERROR: expected identifier, found keyword + fn bar() {} +} + +fn main() { + // shouldn't error here because we shouldn't have been able to recover above + Foo::bar(); +} diff --git a/tests/ui/traits/const-traits/const-impl-norecover.stderr b/tests/ui/traits/const-traits/const-impl-norecover.stderr new file mode 100644 index 00000000000..efa72463c5e --- /dev/null +++ b/tests/ui/traits/const-traits/const-impl-norecover.stderr @@ -0,0 +1,8 @@ +error: expected identifier, found keyword `impl` + --> $DIR/const-impl-norecover.rs:5:7 + | +LL | const impl Foo { + | ^^^^ expected identifier, found keyword + +error: aborting due to 1 previous error + diff --git a/tests/ui/traits/const-traits/const-impl-recovery.rs b/tests/ui/traits/const-traits/const-impl-recovery.rs new file mode 100644 index 00000000000..837124db04e --- /dev/null +++ b/tests/ui/traits/const-traits/const-impl-recovery.rs @@ -0,0 +1,17 @@ +#![feature(const_trait_impl)] + +#[const_trait] +trait Foo {} + +const impl Foo for i32 {} //~ ERROR: expected identifier, found keyword + +#[const_trait] +trait Bar {} + +const impl<T: Foo> Bar for T {} //~ ERROR: expected identifier, found keyword + +const fn still_implements<T: Bar>() {} + +const _: () = still_implements::<i32>(); + +fn main() {} diff --git a/tests/ui/traits/const-traits/const-impl-recovery.stderr b/tests/ui/traits/const-traits/const-impl-recovery.stderr new file mode 100644 index 00000000000..7217fc85543 --- /dev/null +++ b/tests/ui/traits/const-traits/const-impl-recovery.stderr @@ -0,0 +1,26 @@ +error: expected identifier, found keyword `impl` + --> $DIR/const-impl-recovery.rs:6:7 + | +LL | const impl Foo for i32 {} + | ^^^^ expected identifier, found keyword + | +help: you might have meant to write a const trait impl + | +LL - const impl Foo for i32 {} +LL + impl const Foo for i32 {} + | + +error: expected identifier, found keyword `impl` + --> $DIR/const-impl-recovery.rs:11:7 + | +LL | const impl<T: Foo> Bar for T {} + | ^^^^ expected identifier, found keyword + | +help: you might have meant to write a const trait impl + | +LL - const impl<T: Foo> Bar for T {} +LL + impl<T: Foo> const Bar for T {} + | + +error: aborting due to 2 previous errors + diff --git a/tests/ui/traits/const-traits/const-impl-requires-const-trait.rs b/tests/ui/traits/const-traits/const-impl-requires-const-trait.rs new file mode 100644 index 00000000000..bd6f476f879 --- /dev/null +++ b/tests/ui/traits/const-traits/const-impl-requires-const-trait.rs @@ -0,0 +1,11 @@ +//@ known-bug: #110395 + +#![feature(const_trait_impl, effects)] + +pub trait A {} +// FIXME ~^ HELP: mark `A` as const + +impl const A for () {} +// FIXME ~^ ERROR: const `impl` for trait `A` which is not marked with `#[const_trait]` + +fn main() {} diff --git a/tests/ui/traits/const-traits/const-impl-requires-const-trait.stderr b/tests/ui/traits/const-traits/const-impl-requires-const-trait.stderr new file mode 100644 index 00000000000..2a030369093 --- /dev/null +++ b/tests/ui/traits/const-traits/const-impl-requires-const-trait.stderr @@ -0,0 +1,28 @@ +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/const-impl-requires-const-trait.rs:3:30 + | +LL | #![feature(const_trait_impl, effects)] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + +error: using `#![feature(effects)]` without enabling next trait solver globally + | + = note: the next trait solver must be enabled globally for the effects feature to work correctly + = help: use `-Znext-solver` to enable + +error: const `impl` for trait `A` which is not marked with `#[const_trait]` + --> $DIR/const-impl-requires-const-trait.rs:8:12 + | +LL | pub trait A {} + | - help: mark `A` as const: `#[const_trait]` +... +LL | impl const A for () {} + | ^ + | + = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: adding a non-const method body in the future would be a breaking change + +error: aborting due to 2 previous errors; 1 warning emitted + diff --git a/tests/ui/traits/const-traits/const-impl-trait.rs b/tests/ui/traits/const-traits/const-impl-trait.rs new file mode 100644 index 00000000000..51dfe29b829 --- /dev/null +++ b/tests/ui/traits/const-traits/const-impl-trait.rs @@ -0,0 +1,56 @@ +//@ known-bug: #110395 +// Broken until we have `&T: const Deref` impl in stdlib + +#![allow(incomplete_features)] +#![feature( + const_trait_impl, + effects, + const_cmp, +)] + +use std::marker::Destruct; + +const fn cmp(a: &impl ~const PartialEq) -> bool { + a == a +} + +const fn wrap(x: impl ~const PartialEq + ~const Destruct) + -> impl ~const PartialEq + ~const Destruct +{ + x +} + +#[const_trait] +trait Foo { + fn huh() -> impl ~const PartialEq + ~const Destruct + Copy; +} + +impl const Foo for () { + fn huh() -> impl ~const PartialEq + ~const Destruct + Copy { + 123 + } +} + +const _: () = { + assert!(cmp(&0xDEADBEEFu32)); + assert!(cmp(&())); + assert!(wrap(123) == wrap(123)); + assert!(wrap(123) != wrap(456)); + let x = <() as Foo>::huh(); + assert!(x == x); +}; + +#[const_trait] +trait T {} +struct S; +impl const T for S {} + +const fn rpit() -> impl ~const T { S } + +const fn apit(_: impl ~const T + ~const Destruct) {} + +const fn rpit_assoc_bound() -> impl IntoIterator<Item: ~const T> { Some(S) } + +const fn apit_assoc_bound(_: impl IntoIterator<Item: ~const T> + ~const Destruct) {} + +fn main() {} diff --git a/tests/ui/traits/const-traits/const-impl-trait.stderr b/tests/ui/traits/const-traits/const-impl-trait.stderr new file mode 100644 index 00000000000..1040af7541c --- /dev/null +++ b/tests/ui/traits/const-traits/const-impl-trait.stderr @@ -0,0 +1,249 @@ +error[E0635]: unknown feature `const_cmp` + --> $DIR/const-impl-trait.rs:8:5 + | +LL | const_cmp, + | ^^^^^^^^^ + +error: using `#![feature(effects)]` without enabling next trait solver globally + | + = note: the next trait solver must be enabled globally for the effects feature to work correctly + = help: use `-Znext-solver` to enable + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-impl-trait.rs:13:30 + | +LL | const fn cmp(a: &impl ~const PartialEq) -> bool { + | ^^^^^^^^^ + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-impl-trait.rs:17:30 + | +LL | const fn wrap(x: impl ~const PartialEq + ~const Destruct) + | ^^^^^^^^^ + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-impl-trait.rs:17:49 + | +LL | const fn wrap(x: impl ~const PartialEq + ~const Destruct) + | ^^^^^^^^ + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-impl-trait.rs:18:20 + | +LL | -> impl ~const PartialEq + ~const Destruct + | ^^^^^^^^^ + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-impl-trait.rs:18:39 + | +LL | -> impl ~const PartialEq + ~const Destruct + | ^^^^^^^^ + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-impl-trait.rs:18:20 + | +LL | -> impl ~const PartialEq + ~const Destruct + | ^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-impl-trait.rs:18:39 + | +LL | -> impl ~const PartialEq + ~const Destruct + | ^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-impl-trait.rs:25:29 + | +LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy; + | ^^^^^^^^^ + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-impl-trait.rs:25:48 + | +LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy; + | ^^^^^^^^ + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-impl-trait.rs:29:29 + | +LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy { + | ^^^^^^^^^ + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-impl-trait.rs:29:48 + | +LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy { + | ^^^^^^^^ + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-impl-trait.rs:29:29 + | +LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy { + | ^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-impl-trait.rs:29:48 + | +LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy { + | ^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-impl-trait.rs:50:41 + | +LL | const fn apit(_: impl ~const T + ~const Destruct) {} + | ^^^^^^^^ + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-impl-trait.rs:54:73 + | +LL | const fn apit_assoc_bound(_: impl IntoIterator<Item: ~const T> + ~const Destruct) {} + | ^^^^^^^^ + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-impl-trait.rs:25:29 + | +LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy; + | ^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-impl-trait.rs:25:48 + | +LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy; + | ^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-impl-trait.rs:25:29 + | +LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy; + | ^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-impl-trait.rs:25:48 + | +LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy; + | ^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-impl-trait.rs:25:29 + | +LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy; + | ^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-impl-trait.rs:25:48 + | +LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy; + | ^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0493]: destructor of `impl PartialEq + Destruct` cannot be evaluated at compile-time + --> $DIR/const-impl-trait.rs:37:26 + | +LL | assert!(wrap(123) == wrap(123)); + | ^^^^^^^^^- value is dropped here + | | + | the destructor for this type cannot be evaluated in constants + +error[E0493]: destructor of `impl PartialEq + Destruct` cannot be evaluated at compile-time + --> $DIR/const-impl-trait.rs:37:26 + | +LL | assert!(wrap(123) == wrap(123)); + | ^^^^^^^^^- value is dropped here + | | + | the destructor for this type cannot be evaluated in constants + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0493]: destructor of `impl PartialEq + Destruct` cannot be evaluated at compile-time + --> $DIR/const-impl-trait.rs:37:13 + | +LL | assert!(wrap(123) == wrap(123)); + | ^^^^^^^^^ - value is dropped here + | | + | the destructor for this type cannot be evaluated in constants + +error[E0493]: destructor of `impl PartialEq + Destruct` cannot be evaluated at compile-time + --> $DIR/const-impl-trait.rs:37:13 + | +LL | assert!(wrap(123) == wrap(123)); + | ^^^^^^^^^ - value is dropped here + | | + | the destructor for this type cannot be evaluated in constants + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0493]: destructor of `impl PartialEq + Destruct` cannot be evaluated at compile-time + --> $DIR/const-impl-trait.rs:38:26 + | +LL | assert!(wrap(123) != wrap(456)); + | ^^^^^^^^^- value is dropped here + | | + | the destructor for this type cannot be evaluated in constants + +error[E0493]: destructor of `impl PartialEq + Destruct` cannot be evaluated at compile-time + --> $DIR/const-impl-trait.rs:38:26 + | +LL | assert!(wrap(123) != wrap(456)); + | ^^^^^^^^^- value is dropped here + | | + | the destructor for this type cannot be evaluated in constants + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0493]: destructor of `impl PartialEq + Destruct` cannot be evaluated at compile-time + --> $DIR/const-impl-trait.rs:38:13 + | +LL | assert!(wrap(123) != wrap(456)); + | ^^^^^^^^^ - value is dropped here + | | + | the destructor for this type cannot be evaluated in constants + +error[E0493]: destructor of `impl PartialEq + Destruct` cannot be evaluated at compile-time + --> $DIR/const-impl-trait.rs:38:13 + | +LL | assert!(wrap(123) != wrap(456)); + | ^^^^^^^^^ - value is dropped here + | | + | the destructor for this type cannot be evaluated in constants + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0493]: destructor of `impl ~const T + ~const Destruct` cannot be evaluated at compile-time + --> $DIR/const-impl-trait.rs:50:15 + | +LL | const fn apit(_: impl ~const T + ~const Destruct) {} + | ^ - value is dropped here + | | + | the destructor for this type cannot be evaluated in constant functions + +error[E0493]: destructor of `impl IntoIterator<Item : ~const T> + ~const Destruct` cannot be evaluated at compile-time + --> $DIR/const-impl-trait.rs:54:27 + | +LL | const fn apit_assoc_bound(_: impl IntoIterator<Item: ~const T> + ~const Destruct) {} + | ^ - value is dropped here + | | + | the destructor for this type cannot be evaluated in constant functions + +error: aborting due to 33 previous errors + +Some errors have detailed explanations: E0493, E0635. +For more information about an error, try `rustc --explain E0493`. diff --git a/tests/ui/traits/const-traits/const-trait-bounds-trait-objects.rs b/tests/ui/traits/const-traits/const-trait-bounds-trait-objects.rs new file mode 100644 index 00000000000..691bce19dc2 --- /dev/null +++ b/tests/ui/traits/const-traits/const-trait-bounds-trait-objects.rs @@ -0,0 +1,18 @@ +#![feature(const_trait_impl)] +// FIXME(effects) add effects +//@ edition: 2021 + +#[const_trait] +trait Trait {} + +fn main() { + let _: &dyn const Trait; //~ ERROR const trait bounds are not allowed in trait object types + let _: &dyn ~const Trait; //~ ERROR `~const` is not allowed here +} + +// Regression test for issue #119525. +trait NonConst {} +const fn handle(_: &dyn const NonConst) {} +//~^ ERROR const trait bounds are not allowed in trait object types +const fn take(_: &dyn ~const NonConst) {} +//~^ ERROR `~const` is not allowed here diff --git a/tests/ui/traits/const-traits/const-trait-bounds-trait-objects.stderr b/tests/ui/traits/const-traits/const-trait-bounds-trait-objects.stderr new file mode 100644 index 00000000000..bd29b4b860b --- /dev/null +++ b/tests/ui/traits/const-traits/const-trait-bounds-trait-objects.stderr @@ -0,0 +1,30 @@ +error: const trait bounds are not allowed in trait object types + --> $DIR/const-trait-bounds-trait-objects.rs:9:17 + | +LL | let _: &dyn const Trait; + | ^^^^^^^^^^^ + +error: `~const` is not allowed here + --> $DIR/const-trait-bounds-trait-objects.rs:10:17 + | +LL | let _: &dyn ~const Trait; + | ^^^^^^ + | + = note: trait objects cannot have `~const` trait bounds + +error: const trait bounds are not allowed in trait object types + --> $DIR/const-trait-bounds-trait-objects.rs:15:25 + | +LL | const fn handle(_: &dyn const NonConst) {} + | ^^^^^^^^^^^^^^ + +error: `~const` is not allowed here + --> $DIR/const-trait-bounds-trait-objects.rs:17:23 + | +LL | const fn take(_: &dyn ~const NonConst) {} + | ^^^^^^ + | + = note: trait objects cannot have `~const` trait bounds + +error: aborting due to 4 previous errors + diff --git a/tests/ui/traits/const-traits/const-trait-bounds.rs b/tests/ui/traits/const-traits/const-trait-bounds.rs new file mode 100644 index 00000000000..3b4ba6a998f --- /dev/null +++ b/tests/ui/traits/const-traits/const-trait-bounds.rs @@ -0,0 +1,32 @@ +//@ known-bug: #110395 +//@ compile-flags: -Znext-solver +// FIXME(effects): check-pass +#![feature(const_trait_impl, effects, generic_const_exprs)] +#![allow(incomplete_features)] + +fn main() { + let _ = process::<()>([()]); + let _ = Struct::<(), 4> { field: [1, 0] }; +} + +fn process<T: const Trait>(input: [(); T::make(2)]) -> [(); T::make(2)] { + input +} + +struct Struct<T: const Trait, const P: usize> +where + [u32; T::make(P)]:, +{ + field: [u32; T::make(P)], +} + +#[const_trait] +trait Trait { + fn make(input: usize) -> usize; +} + +impl const Trait for () { + fn make(input: usize) -> usize { + input / 2 + } +} diff --git a/tests/ui/traits/const-traits/const-trait-bounds.stderr b/tests/ui/traits/const-traits/const-trait-bounds.stderr new file mode 100644 index 00000000000..698b1b5b578 --- /dev/null +++ b/tests/ui/traits/const-traits/const-trait-bounds.stderr @@ -0,0 +1,29 @@ +error: `-Znext-solver=globally` and `generic_const_exprs` are incompatible, using them at the same time is not allowed + --> $DIR/const-trait-bounds.rs:4:39 + | +LL | #![feature(const_trait_impl, effects, generic_const_exprs)] + | ^^^^^^^^^^^^^^^^^^^ + | + = help: remove one of these features + +error[E0284]: type annotations needed: cannot normalize `process<T>::{constant#0}` + --> $DIR/const-trait-bounds.rs:12:35 + | +LL | fn process<T: const Trait>(input: [(); T::make(2)]) -> [(); T::make(2)] { + | ^^^^^^^^^^^^^^^^ cannot normalize `process<T>::{constant#0}` + +error[E0284]: type annotations needed: cannot normalize `Struct<T, P>::field::{constant#0}` + --> $DIR/const-trait-bounds.rs:20:12 + | +LL | field: [u32; T::make(P)], + | ^^^^^^^^^^^^^^^^^ cannot normalize `Struct<T, P>::field::{constant#0}` + +error[E0284]: type annotations needed: cannot normalize `process<T>::{constant#1}` + --> $DIR/const-trait-bounds.rs:13:5 + | +LL | input + | ^^^^^ cannot normalize `process<T>::{constant#1}` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0284`. diff --git a/tests/ui/traits/const-traits/const_derives/derive-const-gate.rs b/tests/ui/traits/const-traits/const_derives/derive-const-gate.rs new file mode 100644 index 00000000000..a772d69c9e2 --- /dev/null +++ b/tests/ui/traits/const-traits/const_derives/derive-const-gate.rs @@ -0,0 +1,5 @@ +#[derive_const(Default)] //~ ERROR use of unstable library feature +//~^ ERROR const `impl` for trait `Default` which is not marked with `#[const_trait]` +pub struct S; + +fn main() {} diff --git a/tests/ui/traits/const-traits/const_derives/derive-const-gate.stderr b/tests/ui/traits/const-traits/const_derives/derive-const-gate.stderr new file mode 100644 index 00000000000..3ccae5a83e6 --- /dev/null +++ b/tests/ui/traits/const-traits/const_derives/derive-const-gate.stderr @@ -0,0 +1,22 @@ +error[E0658]: use of unstable library feature 'derive_const' + --> $DIR/derive-const-gate.rs:1:3 + | +LL | #[derive_const(Default)] + | ^^^^^^^^^^^^ + | + = help: add `#![feature(derive_const)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: const `impl` for trait `Default` which is not marked with `#[const_trait]` + --> $DIR/derive-const-gate.rs:1:16 + | +LL | #[derive_const(Default)] + | ^^^^^^^ + | + = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: adding a non-const method body in the future would be a breaking change + = note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/traits/const-traits/const_derives/derive-const-non-const-type.rs b/tests/ui/traits/const-traits/const_derives/derive-const-non-const-type.rs new file mode 100644 index 00000000000..5896091f8c4 --- /dev/null +++ b/tests/ui/traits/const-traits/const_derives/derive-const-non-const-type.rs @@ -0,0 +1,13 @@ +//@ known-bug: #110395 +#![feature(derive_const, effects)] + +pub struct A; + +impl Default for A { + fn default() -> A { A } +} + +#[derive_const(Default)] +pub struct S(A); + +fn main() {} diff --git a/tests/ui/traits/const-traits/const_derives/derive-const-non-const-type.stderr b/tests/ui/traits/const-traits/const_derives/derive-const-non-const-type.stderr new file mode 100644 index 00000000000..777b3313da6 --- /dev/null +++ b/tests/ui/traits/const-traits/const_derives/derive-const-non-const-type.stderr @@ -0,0 +1,26 @@ +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/derive-const-non-const-type.rs:2:26 + | +LL | #![feature(derive_const, effects)] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + +error: using `#![feature(effects)]` without enabling next trait solver globally + | + = note: the next trait solver must be enabled globally for the effects feature to work correctly + = help: use `-Znext-solver` to enable + +error: const `impl` for trait `Default` which is not marked with `#[const_trait]` + --> $DIR/derive-const-non-const-type.rs:10:16 + | +LL | #[derive_const(Default)] + | ^^^^^^^ + | + = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: adding a non-const method body in the future would be a breaking change + = note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 2 previous errors; 1 warning emitted + diff --git a/tests/ui/traits/const-traits/const_derives/derive-const-use.rs b/tests/ui/traits/const-traits/const_derives/derive-const-use.rs new file mode 100644 index 00000000000..cb649b1ec79 --- /dev/null +++ b/tests/ui/traits/const-traits/const_derives/derive-const-use.rs @@ -0,0 +1,20 @@ +//@ known-bug: #110395 + +#![feature(const_trait_impl, const_cmp, const_default_impls, derive_const, effects)] + +pub struct A; + +impl const Default for A { + fn default() -> A { A } +} + +impl const PartialEq for A { + fn eq(&self, _: &A) -> bool { true } +} + +#[derive_const(Default, PartialEq)] +pub struct S((), A); + +const _: () = assert!(S((), A) == S::default()); + +fn main() {} diff --git a/tests/ui/traits/const-traits/const_derives/derive-const-use.stderr b/tests/ui/traits/const-traits/const_derives/derive-const-use.stderr new file mode 100644 index 00000000000..ad727fc36cd --- /dev/null +++ b/tests/ui/traits/const-traits/const_derives/derive-const-use.stderr @@ -0,0 +1,90 @@ +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/derive-const-use.rs:3:76 + | +LL | #![feature(const_trait_impl, const_cmp, const_default_impls, derive_const, effects)] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + +error[E0635]: unknown feature `const_cmp` + --> $DIR/derive-const-use.rs:3:30 + | +LL | #![feature(const_trait_impl, const_cmp, const_default_impls, derive_const, effects)] + | ^^^^^^^^^ + +error[E0635]: unknown feature `const_default_impls` + --> $DIR/derive-const-use.rs:3:41 + | +LL | #![feature(const_trait_impl, const_cmp, const_default_impls, derive_const, effects)] + | ^^^^^^^^^^^^^^^^^^^ + +error: using `#![feature(effects)]` without enabling next trait solver globally + | + = note: the next trait solver must be enabled globally for the effects feature to work correctly + = help: use `-Znext-solver` to enable + +error: const `impl` for trait `Default` which is not marked with `#[const_trait]` + --> $DIR/derive-const-use.rs:7:12 + | +LL | impl const Default for A { + | ^^^^^^^ + | + = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: adding a non-const method body in the future would be a breaking change + +error: const `impl` for trait `Default` which is not marked with `#[const_trait]` + --> $DIR/derive-const-use.rs:15:16 + | +LL | #[derive_const(Default, PartialEq)] + | ^^^^^^^ + | + = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: adding a non-const method body in the future would be a breaking change + = note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: const `impl` for trait `PartialEq` which is not marked with `#[const_trait]` + --> $DIR/derive-const-use.rs:11:12 + | +LL | impl const PartialEq for A { + | ^^^^^^^^^ + | + = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: adding a non-const method body in the future would be a breaking change + +error: const `impl` for trait `PartialEq` which is not marked with `#[const_trait]` + --> $DIR/derive-const-use.rs:15:25 + | +LL | #[derive_const(Default, PartialEq)] + | ^^^^^^^^^ + | + = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: adding a non-const method body in the future would be a breaking change + = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0080]: evaluation of constant value failed + --> $DIR/derive-const-use.rs:16:14 + | +LL | #[derive_const(Default, PartialEq)] + | ------- in this derive macro expansion +LL | pub struct S((), A); + | ^^ calling non-const function `<() as Default>::default` + | +note: inside `<S as Default>::default` + --> $DIR/derive-const-use.rs:16:14 + | +LL | #[derive_const(Default, PartialEq)] + | ------- in this derive macro expansion +LL | pub struct S((), A); + | ^^ +note: inside `_` + --> $DIR/derive-const-use.rs:18:35 + | +LL | const _: () = assert!(S((), A) == S::default()); + | ^^^^^^^^^^^^ + = note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 8 previous errors; 1 warning emitted + +Some errors have detailed explanations: E0080, E0635. +For more information about an error, try `rustc --explain E0080`. diff --git a/tests/ui/traits/const-traits/const_derives/derive-const-with-params.rs b/tests/ui/traits/const-traits/const_derives/derive-const-with-params.rs new file mode 100644 index 00000000000..c032c76d38f --- /dev/null +++ b/tests/ui/traits/const-traits/const_derives/derive-const-with-params.rs @@ -0,0 +1,14 @@ +//@ known-bug: #110395 +// FIXME(effects) check-pass + +#![feature(derive_const)] +#![feature(const_trait_impl, effects)] + +#[derive_const(PartialEq)] +pub struct Reverse<T>(T); + +const fn foo(a: Reverse<i32>, b: Reverse<i32>) -> bool { + a == b +} + +fn main() {} diff --git a/tests/ui/traits/const-traits/const_derives/derive-const-with-params.stderr b/tests/ui/traits/const-traits/const_derives/derive-const-with-params.stderr new file mode 100644 index 00000000000..addce8dcd6c --- /dev/null +++ b/tests/ui/traits/const-traits/const_derives/derive-const-with-params.stderr @@ -0,0 +1,34 @@ +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/derive-const-with-params.rs:5:30 + | +LL | #![feature(const_trait_impl, effects)] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + +error: using `#![feature(effects)]` without enabling next trait solver globally + | + = note: the next trait solver must be enabled globally for the effects feature to work correctly + = help: use `-Znext-solver` to enable + +error: const `impl` for trait `PartialEq` which is not marked with `#[const_trait]` + --> $DIR/derive-const-with-params.rs:7:16 + | +LL | #[derive_const(PartialEq)] + | ^^^^^^^^^ + | + = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: adding a non-const method body in the future would be a breaking change + = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/derive-const-with-params.rs:7:16 + | +LL | #[derive_const(PartialEq)] + | ^^^^^^^^^ + | + = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 3 previous errors; 1 warning emitted + diff --git a/tests/ui/traits/const-traits/cross-crate-default-method-body-is-const.rs b/tests/ui/traits/const-traits/cross-crate-default-method-body-is-const.rs new file mode 100644 index 00000000000..9ee5254dbf8 --- /dev/null +++ b/tests/ui/traits/const-traits/cross-crate-default-method-body-is-const.rs @@ -0,0 +1,19 @@ +// This tests that `const_trait` default methods can +// be called from a const context when used across crates. +// +//@ check-pass +//@ compile-flags: -Znext-solver +#![allow(incomplete_features)] +#![feature(const_trait_impl, effects)] + +//@ aux-build: cross-crate.rs +extern crate cross_crate; + +use cross_crate::*; + +const _: () = { + Const.func(); + Const.defaulted_func(); +}; + +fn main() {} diff --git a/tests/ui/traits/const-traits/cross-crate.gatednc.stderr b/tests/ui/traits/const-traits/cross-crate.gatednc.stderr new file mode 100644 index 00000000000..a34bae843c8 --- /dev/null +++ b/tests/ui/traits/const-traits/cross-crate.gatednc.stderr @@ -0,0 +1,22 @@ +error[E0277]: the trait bound `cross_crate::NonConst: ~const cross_crate::MyTrait` is not satisfied + --> $DIR/cross-crate.rs:19:14 + | +LL | NonConst.func(); + | ^^^^ the trait `cross_crate::MyTrait` is not implemented for `cross_crate::NonConst` + | +note: required by a bound in `func` + --> $DIR/auxiliary/cross-crate.rs:5:1 + | +LL | #[const_trait] + | ^^^^^^^^^^^^^^ required by this bound in `MyTrait::func` +... +LL | fn func(self); + | ---- required by a bound in this associated function +help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement + | +LL | const fn const_context() where cross_crate::NonConst: cross_crate::MyTrait { + | +++++++++++++++++++++++++++++++++++++++++++++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/const-traits/cross-crate.rs b/tests/ui/traits/const-traits/cross-crate.rs new file mode 100644 index 00000000000..cfcada9c828 --- /dev/null +++ b/tests/ui/traits/const-traits/cross-crate.rs @@ -0,0 +1,27 @@ +//@ revisions: stock gated stocknc gatednc +//@ [gated] check-pass +//@ compile-flags: -Znext-solver +#![cfg_attr(any(gated, gatednc), feature(const_trait_impl, effects))] +#![allow(incomplete_features)] + +//@ aux-build: cross-crate.rs +extern crate cross_crate; + +use cross_crate::*; + +fn non_const_context() { + NonConst.func(); + Const.func(); +} + +const fn const_context() { + #[cfg(any(stocknc, gatednc))] + NonConst.func(); + //[stocknc]~^ ERROR: cannot call + //[gatednc]~^^ ERROR: the trait bound + Const.func(); + //[stock]~^ ERROR: cannot call + //[stocknc]~^^ ERROR: cannot call +} + +fn main() {} diff --git a/tests/ui/traits/const-traits/cross-crate.stock.stderr b/tests/ui/traits/const-traits/cross-crate.stock.stderr new file mode 100644 index 00000000000..b481bdc470c --- /dev/null +++ b/tests/ui/traits/const-traits/cross-crate.stock.stderr @@ -0,0 +1,15 @@ +error[E0015]: cannot call non-const fn `<cross_crate::Const as cross_crate::MyTrait>::func` in constant functions + --> $DIR/cross-crate.rs:22:11 + | +LL | Const.func(); + | ^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants +help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + | +LL + #![feature(const_trait_impl)] + | + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/cross-crate.stocknc.stderr b/tests/ui/traits/const-traits/cross-crate.stocknc.stderr new file mode 100644 index 00000000000..5c3e3b6ff40 --- /dev/null +++ b/tests/ui/traits/const-traits/cross-crate.stocknc.stderr @@ -0,0 +1,27 @@ +error[E0015]: cannot call non-const fn `<cross_crate::NonConst as cross_crate::MyTrait>::func` in constant functions + --> $DIR/cross-crate.rs:19:14 + | +LL | NonConst.func(); + | ^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants +help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + | +LL + #![feature(const_trait_impl)] + | + +error[E0015]: cannot call non-const fn `<cross_crate::Const as cross_crate::MyTrait>::func` in constant functions + --> $DIR/cross-crate.rs:22:11 + | +LL | Const.func(); + | ^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants +help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + | +LL + #![feature(const_trait_impl)] + | + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/default-method-body-is-const-body-checking.rs b/tests/ui/traits/const-traits/default-method-body-is-const-body-checking.rs new file mode 100644 index 00000000000..b534d23b107 --- /dev/null +++ b/tests/ui/traits/const-traits/default-method-body-is-const-body-checking.rs @@ -0,0 +1,20 @@ +//@ known-bug: #110395 +//@ check-pass + +#![feature(const_trait_impl)] + +#[const_trait] +trait Tr {} +impl Tr for () {} + +const fn foo<T>() where T: ~const Tr {} + +#[const_trait] +pub trait Foo { + fn foo() { + foo::<()>(); + //FIXME ~^ ERROR the trait bound `(): Tr` is not satisfied + } +} + +fn main() {} diff --git a/tests/ui/traits/const-traits/default-method-body-is-const-same-trait-ck.rs b/tests/ui/traits/const-traits/default-method-body-is-const-same-trait-ck.rs new file mode 100644 index 00000000000..0c2d93775a4 --- /dev/null +++ b/tests/ui/traits/const-traits/default-method-body-is-const-same-trait-ck.rs @@ -0,0 +1,17 @@ +//@ compile-flags: -Znext-solver +#![allow(incomplete_features)] +#![feature(const_trait_impl, effects)] + +#[const_trait] +pub trait Tr { + fn a(&self) {} + + fn b(&self) { + ().a() + //~^ ERROR the trait bound `(): ~const Tr` is not satisfied + } +} + +impl Tr for () {} + +fn main() {} diff --git a/tests/ui/traits/const-traits/default-method-body-is-const-same-trait-ck.stderr b/tests/ui/traits/const-traits/default-method-body-is-const-same-trait-ck.stderr new file mode 100644 index 00000000000..d0f22c0b9b6 --- /dev/null +++ b/tests/ui/traits/const-traits/default-method-body-is-const-same-trait-ck.stderr @@ -0,0 +1,22 @@ +error[E0277]: the trait bound `(): ~const Tr` is not satisfied + --> $DIR/default-method-body-is-const-same-trait-ck.rs:10:12 + | +LL | ().a() + | ^ the trait `Tr` is not implemented for `()` + | +note: required by a bound in `Tr::a` + --> $DIR/default-method-body-is-const-same-trait-ck.rs:5:1 + | +LL | #[const_trait] + | ^^^^^^^^^^^^^^ required by this bound in `Tr::a` +LL | pub trait Tr { +LL | fn a(&self) {} + | - required by a bound in this associated function +help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement + | +LL | pub trait Tr where (): Tr { + | ++++++++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/const-traits/default-method-body-is-const-with-staged-api.rs b/tests/ui/traits/const-traits/default-method-body-is-const-with-staged-api.rs new file mode 100644 index 00000000000..8b264ebd0e4 --- /dev/null +++ b/tests/ui/traits/const-traits/default-method-body-is-const-with-staged-api.rs @@ -0,0 +1,17 @@ +//@ check-pass + +// This was an ICE, because the compiler ensures the +// function to be const when performing const checking, +// but functions marked with the attribute are not const +// *and* subject to const checking. + +#![feature(staged_api)] +#![feature(const_trait_impl)] +#![stable(feature = "foo", since = "3.3.3")] + +#[const_trait] +trait Tr { + fn a() {} +} + +fn main() {} diff --git a/tests/ui/traits/const-traits/do-not-const-check-override.rs b/tests/ui/traits/const-traits/do-not-const-check-override.rs new file mode 100644 index 00000000000..71e6375283f --- /dev/null +++ b/tests/ui/traits/const-traits/do-not-const-check-override.rs @@ -0,0 +1,21 @@ +//@ check-pass +//@ compile-flags: -Znext-solver +#![allow(incomplete_features)] +#![feature(const_trait_impl, rustc_attrs, effects)] + +#[const_trait] +trait Foo { + #[rustc_do_not_const_check] + fn into_iter(&self) { println!("FEAR ME!") } +} + + +impl const Foo for () { + fn into_iter(&self) { + // ^_^ + } +} + +const _: () = Foo::into_iter(&()); + +fn main() {} diff --git a/tests/ui/traits/const-traits/do-not-const-check.rs b/tests/ui/traits/const-traits/do-not-const-check.rs new file mode 100644 index 00000000000..443b6385735 --- /dev/null +++ b/tests/ui/traits/const-traits/do-not-const-check.rs @@ -0,0 +1,18 @@ +//@ check-pass +#![feature(const_trait_impl, rustc_attrs)] + +#[const_trait] +trait IntoIter { + fn into_iter(self); +} + +#[const_trait] +trait Hmm: Sized { + #[rustc_do_not_const_check] + fn chain<U>(self, other: U) where U: IntoIter, + { + other.into_iter() + } +} + +fn main() {} diff --git a/tests/ui/traits/const-traits/effects/auxiliary/cross-crate.rs b/tests/ui/traits/const-traits/effects/auxiliary/cross-crate.rs new file mode 100644 index 00000000000..779527e22d4 --- /dev/null +++ b/tests/ui/traits/const-traits/effects/auxiliary/cross-crate.rs @@ -0,0 +1,14 @@ +//@ compile-flags: -Znext-solver +#![allow(incomplete_features)] +#![feature(const_trait_impl, effects)] + +pub const fn foo() {} + +#[const_trait] +pub trait Bar { + fn bar(); +} + +impl Bar for () { + fn bar() {} +} diff --git a/tests/ui/traits/const-traits/effects/const_closure-const_trait_impl-ice-113381.rs b/tests/ui/traits/const-traits/effects/const_closure-const_trait_impl-ice-113381.rs new file mode 100644 index 00000000000..3debc22098a --- /dev/null +++ b/tests/ui/traits/const-traits/effects/const_closure-const_trait_impl-ice-113381.rs @@ -0,0 +1,18 @@ +//@ check-pass +// FIXME(effects) this shouldn't pass +//@ compile-flags: -Znext-solver +#![feature(const_closures, const_trait_impl, effects)] +#![allow(incomplete_features)] + +trait Foo { + fn foo(&self); +} + +impl Foo for () { + fn foo(&self) {} +} + +fn main() { + (const || { (()).foo() })(); + // FIXME(effects) ~^ ERROR: cannot call non-const fn +} diff --git a/tests/ui/traits/const-traits/effects/effect-param-infer.rs b/tests/ui/traits/const-traits/effects/effect-param-infer.rs new file mode 100644 index 00000000000..958b9ac6d57 --- /dev/null +++ b/tests/ui/traits/const-traits/effects/effect-param-infer.rs @@ -0,0 +1,16 @@ +// Ensure that we don't get a mismatch error when inserting the host param +// at the end of generic args when the generics have defaulted params. +// +//@ check-pass +//@ compile-flags: -Znext-solver +#![allow(incomplete_features)] +#![feature(const_trait_impl, effects)] + +#[const_trait] +pub trait Foo<Rhs: ?Sized = Self> { + /* stuff */ +} + +impl const Foo for () {} + +fn main() {} diff --git a/tests/ui/traits/const-traits/effects/fallback.rs b/tests/ui/traits/const-traits/effects/fallback.rs new file mode 100644 index 00000000000..4cfba00526b --- /dev/null +++ b/tests/ui/traits/const-traits/effects/fallback.rs @@ -0,0 +1,17 @@ +//@ check-pass +//@ compile-flags: -Znext-solver +#![allow(incomplete_features)] +#![feature(effects)] + +pub const fn owo() {} + +fn main() { + // make sure falling back ty/int vars doesn't cause const fallback to be skipped... + // See issue: 115791. + let _ = 1; + if false { + let x = panic!(); + } + + let _ = owo; +} diff --git a/tests/ui/traits/const-traits/effects/group-traits.rs b/tests/ui/traits/const-traits/effects/group-traits.rs new file mode 100644 index 00000000000..2c5b6cc40e6 --- /dev/null +++ b/tests/ui/traits/const-traits/effects/group-traits.rs @@ -0,0 +1,14 @@ +//@ check-pass +use std::ops::Add; + +pub trait GroupOpsOwned<Rhs = Self, Output = Self>: for<'r> Add<&'r Rhs, Output = Output> {} + +pub trait Curve: Sized + GroupOpsOwned<Self::AffineRepr> { + type AffineRepr; +} + +pub trait CofactorCurve: Curve<AffineRepr = <Self as CofactorCurve>::Affine> { + type Affine; +} + +fn main() {} diff --git a/tests/ui/traits/const-traits/effects/helloworld.rs b/tests/ui/traits/const-traits/effects/helloworld.rs new file mode 100644 index 00000000000..54f362b4413 --- /dev/null +++ b/tests/ui/traits/const-traits/effects/helloworld.rs @@ -0,0 +1,33 @@ +//@ check-pass +//@ compile-flags: -Znext-solver +// gate-test-effects +// ^ effects doesn't have a gate so we will trick tidy into thinking this is a gate test +#![allow(incomplete_features)] +#![feature( + const_trait_impl, + effects, + core_intrinsics, + const_eval_select +)] + +// ensure we are passing in the correct host effect in always const contexts. + +pub const fn hmm<T>() -> usize { + // FIXME(const_trait_impl): maybe we should have a way to refer to the (hidden) effect param + fn one() -> usize { 1 } + const fn zero() -> usize { 0 } + unsafe { + std::intrinsics::const_eval_select((), zero, one) + } +} + +const _: () = { + let x = hmm::<()>(); + assert!(0 == x); +}; + +pub const fn uwu(x: [u8; hmm::<()>()]) { + let [] = x; +} + +fn main() {} diff --git a/tests/ui/traits/const-traits/effects/ice-112822-expected-type-for-param.rs b/tests/ui/traits/const-traits/effects/ice-112822-expected-type-for-param.rs new file mode 100644 index 00000000000..9a9016de3a0 --- /dev/null +++ b/tests/ui/traits/const-traits/effects/ice-112822-expected-type-for-param.rs @@ -0,0 +1,19 @@ +#![feature(const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete + +const fn test() -> impl ~const Fn() { + //~^ ERROR `~const` can only be applied to `#[const_trait]` traits + //~| ERROR `~const` can only be applied to `#[const_trait]` traits + const move || { //~ ERROR const closures are experimental + let sl: &[u8] = b"foo"; + + match sl { + [first, remainder @ ..] => { + assert_eq!(first, &b'f'); + //~^ ERROR cannot call non-const fn + } + [] => panic!(), + } + } +} + +fn main() {} diff --git a/tests/ui/traits/const-traits/effects/ice-112822-expected-type-for-param.stderr b/tests/ui/traits/const-traits/effects/ice-112822-expected-type-for-param.stderr new file mode 100644 index 00000000000..526746eec73 --- /dev/null +++ b/tests/ui/traits/const-traits/effects/ice-112822-expected-type-for-param.stderr @@ -0,0 +1,51 @@ +error[E0658]: const closures are experimental + --> $DIR/ice-112822-expected-type-for-param.rs:6:5 + | +LL | const move || { + | ^^^^^ + | + = note: see issue #106003 <https://github.com/rust-lang/rust/issues/106003> for more information + = help: add `#![feature(const_closures)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/ice-112822-expected-type-for-param.rs:1:30 + | +LL | #![feature(const_trait_impl, effects)] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + +error: using `#![feature(effects)]` without enabling next trait solver globally + | + = note: the next trait solver must be enabled globally for the effects feature to work correctly + = help: use `-Znext-solver` to enable + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/ice-112822-expected-type-for-param.rs:3:32 + | +LL | const fn test() -> impl ~const Fn() { + | ^^^^ + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/ice-112822-expected-type-for-param.rs:3:32 + | +LL | const fn test() -> impl ~const Fn() { + | ^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0015]: cannot call non-const fn `core::panicking::assert_failed::<&u8, &u8>` in constant functions + --> $DIR/ice-112822-expected-type-for-param.rs:11:17 + | +LL | assert_eq!(first, &b'f'); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 5 previous errors; 1 warning emitted + +Some errors have detailed explanations: E0015, E0658. +For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/effects/ice-113375-index-out-of-bounds-generics.rs b/tests/ui/traits/const-traits/effects/ice-113375-index-out-of-bounds-generics.rs new file mode 100644 index 00000000000..06e3377c5ee --- /dev/null +++ b/tests/ui/traits/const-traits/effects/ice-113375-index-out-of-bounds-generics.rs @@ -0,0 +1,18 @@ +//@ check-pass +//@ compile-flags: -Znext-solver +// effects ice https://github.com/rust-lang/rust/issues/113375 index out of bounds + +#![allow(incomplete_features, unused)] +#![feature(effects, adt_const_params)] + +struct Bar<T>(T); + +impl<T> Bar<T> { + const fn value() -> usize { + 42 + } +} + +struct Foo<const N: [u8; Bar::<u32>::value()]>; + +pub fn main() {} diff --git a/tests/ui/traits/const-traits/effects/infer-fallback.rs b/tests/ui/traits/const-traits/effects/infer-fallback.rs new file mode 100644 index 00000000000..581c3949d38 --- /dev/null +++ b/tests/ui/traits/const-traits/effects/infer-fallback.rs @@ -0,0 +1,13 @@ +//@ check-pass +//@ compile-flags: -Znext-solver +#![allow(incomplete_features)] +#![feature(const_trait_impl, effects)] + +const fn a() {} + +fn foo<F: FnOnce()>(a: F) {} + +fn main() { + let _ = a; + foo(a); +} diff --git a/tests/ui/traits/const-traits/effects/minicore.rs b/tests/ui/traits/const-traits/effects/minicore.rs new file mode 100644 index 00000000000..1c3c66bc3ce --- /dev/null +++ b/tests/ui/traits/const-traits/effects/minicore.rs @@ -0,0 +1,570 @@ +//@ known-bug: #110395 +//@ failure-status: 101 +//@ normalize-stderr-test: ".*note: .*\n\n" -> "" +//@ normalize-stderr-test: "thread 'rustc' panicked.*:\n.*\n" -> "" +//@ rustc-env:RUST_BACKTRACE=0 +// FIXME(effects) check-pass +//@ compile-flags: -Znext-solver + +#![crate_type = "lib"] +#![feature(no_core, lang_items, unboxed_closures, auto_traits, intrinsics, rustc_attrs, staged_api)] +#![feature(fundamental, marker_trait_attr)] +#![feature(const_trait_impl, effects)] +#![allow(internal_features, incomplete_features)] +#![no_std] +#![no_core] +#![stable(feature = "minicore", since = "1.0.0")] + +#[lang = "sized"] +trait Sized {} +#[lang = "copy"] +trait Copy {} + +#[lang = "add"] +#[const_trait] +trait Add<Rhs = Self> { + type Output; + + fn add(self, rhs: Rhs) -> Self::Output; +} + +impl const Add for i32 { + type Output = i32; + fn add(self, rhs: i32) -> i32 { + loop {} + } +} + +fn foo() { + let x = 42_i32 + 43_i32; +} + +const fn bar() { + let x = 42_i32 + 43_i32; +} + + +#[lang = "Try"] +#[const_trait] +trait Try: FromResidual<Self::Residual> { + type Output; + type Residual; + + #[lang = "from_output"] + fn from_output(output: Self::Output) -> Self; + + #[lang = "branch"] + fn branch(self) -> ControlFlow<Self::Residual, Self::Output>; +} + +// FIXME +// #[const_trait] +trait FromResidual<R = <Self as /* FIXME: ~const */ Try>::Residual> { + #[lang = "from_residual"] + fn from_residual(residual: R) -> Self; +} + +enum ControlFlow<B, C = ()> { + #[lang = "Continue"] + Continue(C), + #[lang = "Break"] + Break(B), +} + +#[const_trait] +#[lang = "fn"] +#[rustc_paren_sugar] +trait Fn<Args: Tuple>: ~const FnMut<Args> { + extern "rust-call" fn call(&self, args: Args) -> Self::Output; +} + +#[const_trait] +#[lang = "fn_mut"] +#[rustc_paren_sugar] +trait FnMut<Args: Tuple>: ~const FnOnce<Args> { + extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output; +} + +#[const_trait] +#[lang = "fn_once"] +#[rustc_paren_sugar] +trait FnOnce<Args: Tuple> { + #[lang = "fn_once_output"] + type Output; + + extern "rust-call" fn call_once(self, args: Args) -> Self::Output; +} + +struct ConstFnMutClosure<CapturedData, Function> { + data: CapturedData, + func: Function, +} + +#[lang = "tuple_trait"] +trait Tuple {} + +macro_rules! impl_fn_mut_tuple { + ($($var:ident)*) => { + impl<'a, $($var,)* ClosureArguments: Tuple, Function, ClosureReturnValue> const + FnOnce<ClosureArguments> for ConstFnMutClosure<($(&'a mut $var),*), Function> + where + Function: ~const Fn(($(&mut $var),*), ClosureArguments) -> ClosureReturnValue, + Function: ~const Destruct, + { + type Output = ClosureReturnValue; + + extern "rust-call" fn call_once(mut self, args: ClosureArguments) -> Self::Output { + self.call_mut(args) + } + } + impl<'a, $($var,)* ClosureArguments: Tuple, Function, ClosureReturnValue> const + FnMut<ClosureArguments> for ConstFnMutClosure<($(&'a mut $var),*), Function> + where + Function: ~const Fn(($(&mut $var),*), ClosureArguments)-> ClosureReturnValue, + Function: ~const Destruct, + { + extern "rust-call" fn call_mut(&mut self, args: ClosureArguments) -> Self::Output { + #[allow(non_snake_case)] + let ($($var),*) = &mut self.data; + (self.func)(($($var),*), args) + } + } + }; +} +//impl_fn_mut_tuple!(A); +//impl_fn_mut_tuple!(A B); +//impl_fn_mut_tuple!(A B C); +//impl_fn_mut_tuple!(A B C D); +//impl_fn_mut_tuple!(A B C D E); + +#[lang = "receiver"] +trait Receiver {} + +impl<T: ?Sized> Receiver for &T {} + +impl<T: ?Sized> Receiver for &mut T {} + +#[lang = "destruct"] +#[const_trait] +trait Destruct {} + +#[lang = "freeze"] +unsafe auto trait Freeze {} + +#[lang = "drop"] +#[const_trait] +trait Drop { + fn drop(&mut self); +} + +/* +#[const_trait] +trait Residual<O> { + type TryType: ~const Try<Output = O, Residual = Self> + Try<Output = O, Residual = Self>; +} +*/ + +const fn size_of<T>() -> usize { + 42 +} + +impl Copy for u8 {} + +impl usize { + #[rustc_allow_incoherent_impl] + const fn repeat_u8(x: u8) -> usize { + usize::from_ne_bytes([x; size_of::<usize>()]) + } + #[rustc_allow_incoherent_impl] + const fn from_ne_bytes(bytes: [u8; size_of::<Self>()]) -> Self { + loop {} + } +} + +#[rustc_do_not_const_check] // hooked by const-eval +const fn panic_display() { + panic_fmt(); +} + +fn panic_fmt() {} + +#[lang = "index"] +#[const_trait] +trait Index<Idx: ?Sized> { + type Output: ?Sized; + + fn index(&self, index: Idx) -> &Self::Output; +} + + +#[const_trait] +unsafe trait SliceIndex<T: ?Sized> { + type Output: ?Sized; + fn index(self, slice: &T) -> &Self::Output; +} + +impl<T, I> const Index<I> for [T] +where + I: ~const SliceIndex<[T]>, +{ + type Output = I::Output; + + #[inline] + fn index(&self, index: I) -> &I::Output { + index.index(self) + } +} +/* FIXME +impl<T, I, const N: usize> const Index<I> for [T; N] +where + [T]: ~const Index<I>, +{ + type Output = <[T] as Index<I>>::Output; + + #[inline] + // FIXME: make `Self::Output` act like `<Self as ~const Index<I>>::Output` + fn index(&self, index: I) -> &<[T] as Index<I>>::Output { + Index::index(self as &[T], index) + } +} +*/ + +#[lang = "unsize"] +trait Unsize<T: ?Sized> { +} + +#[lang = "coerce_unsized"] +trait CoerceUnsized<T: ?Sized> { +} + +impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {} + + +#[lang = "deref"] +// #[const_trait] FIXME +trait Deref { + #[lang = "deref_target"] + type Target: ?Sized; + + fn deref(&self) -> &Self::Target; +} + + +impl<T: ?Sized> /* const */ Deref for &T { + type Target = T; + + fn deref(&self) -> &T { + *self + } +} + +impl<T: ?Sized> /* const */ Deref for &mut T { + type Target = T; + + fn deref(&self) -> &T { + *self + } +} + +enum Option<T> { + #[lang = "None"] + None, + #[lang = "Some"] + Some(T), +} + +impl<T> Option<T> { + const fn as_ref(&self) -> Option<&T> { + match *self { + Some(ref x) => Some(x), + None => None, + } + } + + const fn as_mut(&mut self) -> Option<&mut T> { + match *self { + Some(ref mut x) => Some(x), + None => None, + } + } +} + +use Option::*; + +/* +const fn as_deref<T>(opt: &Option<T>) -> Option<&T::Target> +where + T: ~const Deref, +{ + match opt { + Option::Some(t) => Option::Some(t.deref()), + Option::None => Option::None, + } +} +*/ + +#[const_trait] +trait Into<T>: Sized { + fn into(self) -> T; +} + +#[const_trait] +trait From<T>: Sized { + fn from(value: T) -> Self; +} + +impl<T, U> const Into<U> for T +where + U: ~const From<T>, +{ + fn into(self) -> U { + U::from(self) + } +} + +impl<T> const From<T> for T { + fn from(t: T) -> T { + t + } +} + +enum Result<T, E> { + Ok(T), + Err(E), +} +use Result::*; + +fn from_str(s: &str) -> Result<bool, ()> { + match s { + "true" => Ok(true), + "false" => Ok(false), + _ => Err(()), + } +} + +#[lang = "eq"] +#[const_trait] +trait PartialEq<Rhs: ?Sized = Self> { + fn eq(&self, other: &Rhs) -> bool; + fn ne(&self, other: &Rhs) -> bool { + !self.eq(other) + } +} + +impl<A: ?Sized, B: ?Sized> const PartialEq<&B> for &A +where + A: ~const PartialEq<B>, +{ + fn eq(&self, other: &&B) -> bool { + PartialEq::eq(*self, *other) + } +} + +impl PartialEq for str { + fn eq(&self, other: &str) -> bool { + loop {} + } +} + + +#[lang = "not"] +#[const_trait] +trait Not { + type Output; + fn not(self) -> Self::Output; +} + +impl const Not for bool { + type Output = bool; + fn not(self) -> bool { + !self + } +} + +impl Copy for bool {} +impl<'a> Copy for &'a str {} + +#[lang = "pin"] +#[fundamental] +#[repr(transparent)] +struct Pin<P> { + pointer: P, +} + +impl<P> Pin<P> { + #[lang = "new_unchecked"] + const unsafe fn new_unchecked(pointer: P) -> Pin<P> { + Pin { pointer } + } +} + +impl<'a, T: ?Sized> Pin<&'a T> { + const fn get_ref(self) -> &'a T { + self.pointer + } +} + + +impl<P: Deref> Pin<P> { + /* const */ fn as_ref(&self) -> Pin<&P::Target> + where + P: /* ~const */ Deref, + { + unsafe { Pin::new_unchecked(&*self.pointer) } + } +} + + +impl<'a, T: ?Sized> Pin<&'a mut T> { + const unsafe fn get_unchecked_mut(self) -> &'a mut T { + self.pointer + } +} +/* FIXME lol +impl<T> Option<T> { + const fn as_pin_ref(self: Pin<&Self>) -> Option<Pin<&T>> { + match Pin::get_ref(self).as_ref() { + Some(x) => unsafe { Some(Pin::new_unchecked(x)) }, + None => None, + } + } + + const fn as_pin_mut(self: Pin<&mut Self>) -> Option<Pin<&mut T>> { + unsafe { + match Pin::get_unchecked_mut(self).as_mut() { + Some(x) => Some(Pin::new_unchecked(x)), + None => None, + } + } + } +} +*/ + +impl<P: /* ~const */ Deref> /* const */ Deref for Pin<P> { + type Target = P::Target; + fn deref(&self) -> &P::Target { + Pin::get_ref(Pin::as_ref(self)) + } +} + +impl<T> /* const */ Deref for Option<T> { + type Target = T; + fn deref(&self) -> &T { + loop {} + } +} + +impl<P: Receiver> Receiver for Pin<P> {} + +impl<T: Clone> Clone for RefCell<T> { + fn clone(&self) -> RefCell<T> { + RefCell::new(self.borrow().clone()) + } +} + +struct RefCell<T: ?Sized> { + borrow: UnsafeCell<()>, + value: UnsafeCell<T>, +} +impl<T> RefCell<T> { + const fn new(value: T) -> RefCell<T> { + loop {} + } +} +impl<T: ?Sized> RefCell<T> { + fn borrow(&self) -> Ref<'_, T> { + loop {} + } +} + +#[lang = "unsafe_cell"] +#[repr(transparent)] +struct UnsafeCell<T: ?Sized> { + value: T, +} + +struct Ref<'b, T: ?Sized + 'b> { + value: *const T, + borrow: &'b UnsafeCell<()>, +} + +impl<T: ?Sized> Deref for Ref<'_, T> { + type Target = T; + + #[inline] + fn deref(&self) -> &T { + loop {} + } +} + +#[lang = "clone"] +#[rustc_trivial_field_reads] +#[const_trait] +trait Clone: Sized { + fn clone(&self) -> Self; + fn clone_from(&mut self, source: &Self) + where + Self: ~const Destruct, + { + *self = source.clone() + } +} + +#[lang = "structural_peq"] +trait StructuralPartialEq {} + +const fn drop<T: ~const Destruct>(_: T) {} + +#[rustc_const_stable(feature = "const_eval_select", since = "1.0.0")] +#[rustc_intrinsic_must_be_overridden] +#[rustc_intrinsic] +const fn const_eval_select<ARG: Tuple, F, G, RET>( + arg: ARG, + called_in_const: F, + called_at_rt: G, +) -> RET +where + F: const FnOnce<ARG, Output = RET>, + G: FnOnce<ARG, Output = RET>, +{ + loop {} +} + +fn test_const_eval_select() { + const fn const_fn() {} + fn rt_fn() {} + + const_eval_select((), const_fn, rt_fn); +} + +mod effects { + use super::Sized; + + #[lang = "EffectsNoRuntime"] + pub struct NoRuntime; + #[lang = "EffectsMaybe"] + pub struct Maybe; + #[lang = "EffectsRuntime"] + pub struct Runtime; + + #[lang = "EffectsCompat"] + pub trait Compat<#[rustc_runtime] const RUNTIME: bool> {} + + impl Compat<false> for NoRuntime {} + impl Compat<true> for Runtime {} + impl<#[rustc_runtime] const RUNTIME: bool> Compat<RUNTIME> for Maybe {} + + #[lang = "EffectsTyCompat"] + #[marker] + pub trait TyCompat<T: ?Sized> {} + + impl<T: ?Sized> TyCompat<T> for T {} + impl<T: ?Sized> TyCompat<T> for Maybe {} + impl<T: ?Sized> TyCompat<Maybe> for T {} + + #[lang = "EffectsIntersection"] + pub trait Intersection { + #[lang = "EffectsIntersectionOutput"] + type Output: ?Sized; + } +} diff --git a/tests/ui/traits/const-traits/effects/minicore.stderr b/tests/ui/traits/const-traits/effects/minicore.stderr new file mode 100644 index 00000000000..823ab69df9c --- /dev/null +++ b/tests/ui/traits/const-traits/effects/minicore.stderr @@ -0,0 +1,13 @@ +error: the compiler unexpectedly panicked. this is a bug. + +query stack during panic: +#0 [check_well_formed] checking that `<impl at $DIR/minicore.rs:459:1: 459:36>` is well-formed +#1 [check_mod_type_wf] checking that types are well-formed in top-level module +end of query stack + +error: the compiler unexpectedly panicked. this is a bug. + +query stack during panic: +#0 [check_well_formed] checking that `drop` is well-formed +#1 [check_mod_type_wf] checking that types are well-formed in top-level module +end of query stack diff --git a/tests/ui/traits/const-traits/effects/mismatched_generic_args.rs b/tests/ui/traits/const-traits/effects/mismatched_generic_args.rs new file mode 100644 index 00000000000..21e91c731b3 --- /dev/null +++ b/tests/ui/traits/const-traits/effects/mismatched_generic_args.rs @@ -0,0 +1,24 @@ +#![feature(generic_const_exprs)] +//~^ WARN: the feature `generic_const_exprs` is incomplete + +// Regression test for #125770 which would ICE under the old effects desugaring that +// created a const generic parameter for constness on `Add`. + +use std::ops::Add; + +pub struct Dimension; + +pub struct Quantity<S, const D: Dimension>(S); +//~^ ERROR: `Dimension` is forbidden as the type of a const generic parameter + +impl<const D: Dimension, LHS, RHS> Add<LHS, D> for Quantity<LHS, { Dimension }> {} +//~^ ERROR: trait takes at most 1 generic argument +//~| ERROR: `Dimension` is forbidden as the type of a const generic parameter + +pub fn add<const U: Dimension>(x: Quantity<f32, U>) -> Quantity<f32, U> { + //~^ ERROR: `Dimension` is forbidden as the type of a const generic parameter + x + y + //~^ ERROR: cannot find value `y` in this scope +} + +fn main() {} diff --git a/tests/ui/traits/const-traits/effects/mismatched_generic_args.stderr b/tests/ui/traits/const-traits/effects/mismatched_generic_args.stderr new file mode 100644 index 00000000000..8e12b40381f --- /dev/null +++ b/tests/ui/traits/const-traits/effects/mismatched_generic_args.stderr @@ -0,0 +1,64 @@ +error[E0425]: cannot find value `y` in this scope + --> $DIR/mismatched_generic_args.rs:20:9 + | +LL | pub fn add<const U: Dimension>(x: Quantity<f32, U>) -> Quantity<f32, U> { + | - similarly named const parameter `U` defined here +LL | +LL | x + y + | ^ help: a const parameter with a similar name exists: `U` + +warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/mismatched_generic_args.rs:1:12 + | +LL | #![feature(generic_const_exprs)] + | ^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information + = note: `#[warn(incomplete_features)]` on by default + +error: `Dimension` is forbidden as the type of a const generic parameter + --> $DIR/mismatched_generic_args.rs:11:33 + | +LL | pub struct Quantity<S, const D: Dimension>(S); + | ^^^^^^^^^ + | + = note: the only supported types are integers, `bool`, and `char` +help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types + | +LL + #![feature(adt_const_params)] + | + +error[E0107]: trait takes at most 1 generic argument but 2 generic arguments were supplied + --> $DIR/mismatched_generic_args.rs:14:36 + | +LL | impl<const D: Dimension, LHS, RHS> Add<LHS, D> for Quantity<LHS, { Dimension }> {} + | ^^^ expected at most 1 generic argument + +error: `Dimension` is forbidden as the type of a const generic parameter + --> $DIR/mismatched_generic_args.rs:14:15 + | +LL | impl<const D: Dimension, LHS, RHS> Add<LHS, D> for Quantity<LHS, { Dimension }> {} + | ^^^^^^^^^ + | + = note: the only supported types are integers, `bool`, and `char` +help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types + | +LL + #![feature(adt_const_params)] + | + +error: `Dimension` is forbidden as the type of a const generic parameter + --> $DIR/mismatched_generic_args.rs:18:21 + | +LL | pub fn add<const U: Dimension>(x: Quantity<f32, U>) -> Quantity<f32, U> { + | ^^^^^^^^^ + | + = note: the only supported types are integers, `bool`, and `char` +help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types + | +LL + #![feature(adt_const_params)] + | + +error: aborting due to 5 previous errors; 1 warning emitted + +Some errors have detailed explanations: E0107, E0425. +For more information about an error, try `rustc --explain E0107`. diff --git a/tests/ui/traits/const-traits/effects/no-explicit-const-params-cross-crate.rs b/tests/ui/traits/const-traits/effects/no-explicit-const-params-cross-crate.rs new file mode 100644 index 00000000000..97052a1d09a --- /dev/null +++ b/tests/ui/traits/const-traits/effects/no-explicit-const-params-cross-crate.rs @@ -0,0 +1,18 @@ +//@ aux-build: cross-crate.rs +extern crate cross_crate; + +use cross_crate::{Bar, foo}; + +fn main() { + foo::<true>(); + //~^ ERROR: function takes 0 generic arguments but 1 generic argument was supplied + <() as Bar<true>>::bar(); + //~^ ERROR: trait takes 0 generic arguments but 1 generic argument was supplied +} + +const FOO: () = { + foo::<false>(); + //~^ ERROR: function takes 0 generic arguments but 1 generic argument was supplied + <() as Bar<false>>::bar(); + //~^ ERROR: trait takes 0 generic arguments but 1 generic argument was supplied +}; diff --git a/tests/ui/traits/const-traits/effects/no-explicit-const-params-cross-crate.stderr b/tests/ui/traits/const-traits/effects/no-explicit-const-params-cross-crate.stderr new file mode 100644 index 00000000000..8c591edac54 --- /dev/null +++ b/tests/ui/traits/const-traits/effects/no-explicit-const-params-cross-crate.stderr @@ -0,0 +1,63 @@ +error[E0107]: function takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/no-explicit-const-params-cross-crate.rs:14:5 + | +LL | foo::<false>(); + | ^^^--------- help: remove the unnecessary generics + | | + | expected 0 generic arguments + | +note: function defined here, with 0 generic parameters + --> $DIR/auxiliary/cross-crate.rs:5:14 + | +LL | pub const fn foo() {} + | ^^^ + +error[E0107]: trait takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/no-explicit-const-params-cross-crate.rs:16:12 + | +LL | <() as Bar<false>>::bar(); + | ^^^ expected 0 generic arguments + | +note: trait defined here, with 0 generic parameters + --> $DIR/auxiliary/cross-crate.rs:8:11 + | +LL | pub trait Bar { + | ^^^ +help: replace the generic bound with the associated type + | +LL | <() as Bar< = false>>::bar(); + | + + +error[E0107]: function takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/no-explicit-const-params-cross-crate.rs:7:5 + | +LL | foo::<true>(); + | ^^^-------- help: remove the unnecessary generics + | | + | expected 0 generic arguments + | +note: function defined here, with 0 generic parameters + --> $DIR/auxiliary/cross-crate.rs:5:14 + | +LL | pub const fn foo() {} + | ^^^ + +error[E0107]: trait takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/no-explicit-const-params-cross-crate.rs:9:12 + | +LL | <() as Bar<true>>::bar(); + | ^^^ expected 0 generic arguments + | +note: trait defined here, with 0 generic parameters + --> $DIR/auxiliary/cross-crate.rs:8:11 + | +LL | pub trait Bar { + | ^^^ +help: replace the generic bound with the associated type + | +LL | <() as Bar< = true>>::bar(); + | + + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/traits/const-traits/effects/no-explicit-const-params.rs b/tests/ui/traits/const-traits/effects/no-explicit-const-params.rs new file mode 100644 index 00000000000..84f5f2803e1 --- /dev/null +++ b/tests/ui/traits/const-traits/effects/no-explicit-const-params.rs @@ -0,0 +1,27 @@ +#![feature(const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete + +const fn foo() {} + +#[const_trait] +trait Bar { + fn bar(); +} + +impl Bar for () { + fn bar() {} +} + +fn main() { + foo::<true>(); + //~^ ERROR: function takes 0 generic arguments but 1 generic argument was supplied + <() as Bar<true>>::bar(); + //~^ ERROR: trait takes 0 generic arguments but 1 generic argument was supplied +} + +const FOO: () = { + foo::<false>(); + //~^ ERROR: function takes 0 generic arguments but 1 generic argument was supplied + <() as Bar<false>>::bar(); + //~^ ERROR: trait takes 0 generic arguments but 1 generic argument was supplied + //~| ERROR: mismatched types +}; diff --git a/tests/ui/traits/const-traits/effects/no-explicit-const-params.stderr b/tests/ui/traits/const-traits/effects/no-explicit-const-params.stderr new file mode 100644 index 00000000000..cc08114ddb5 --- /dev/null +++ b/tests/ui/traits/const-traits/effects/no-explicit-const-params.stderr @@ -0,0 +1,87 @@ +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/no-explicit-const-params.rs:1:30 + | +LL | #![feature(const_trait_impl, effects)] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + +error: using `#![feature(effects)]` without enabling next trait solver globally + | + = note: the next trait solver must be enabled globally for the effects feature to work correctly + = help: use `-Znext-solver` to enable + +error[E0107]: function takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/no-explicit-const-params.rs:22:5 + | +LL | foo::<false>(); + | ^^^--------- help: remove the unnecessary generics + | | + | expected 0 generic arguments + | +note: function defined here, with 0 generic parameters + --> $DIR/no-explicit-const-params.rs:3:10 + | +LL | const fn foo() {} + | ^^^ + +error[E0107]: trait takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/no-explicit-const-params.rs:24:12 + | +LL | <() as Bar<false>>::bar(); + | ^^^ expected 0 generic arguments + | +note: trait defined here, with 0 generic parameters + --> $DIR/no-explicit-const-params.rs:6:7 + | +LL | trait Bar { + | ^^^ +help: replace the generic bound with the associated type + | +LL | <() as Bar< = false>>::bar(); + | + + +error[E0308]: mismatched types + --> $DIR/no-explicit-const-params.rs:24:5 + | +LL | <() as Bar<false>>::bar(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `false`, found `true` + | + = note: expected constant `false` + found constant `true` + +error[E0107]: function takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/no-explicit-const-params.rs:15:5 + | +LL | foo::<true>(); + | ^^^-------- help: remove the unnecessary generics + | | + | expected 0 generic arguments + | +note: function defined here, with 0 generic parameters + --> $DIR/no-explicit-const-params.rs:3:10 + | +LL | const fn foo() {} + | ^^^ + +error[E0107]: trait takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/no-explicit-const-params.rs:17:12 + | +LL | <() as Bar<true>>::bar(); + | ^^^ expected 0 generic arguments + | +note: trait defined here, with 0 generic parameters + --> $DIR/no-explicit-const-params.rs:6:7 + | +LL | trait Bar { + | ^^^ +help: replace the generic bound with the associated type + | +LL | <() as Bar< = true>>::bar(); + | + + +error: aborting due to 6 previous errors; 1 warning emitted + +Some errors have detailed explanations: E0107, E0308. +For more information about an error, try `rustc --explain E0107`. diff --git a/tests/ui/traits/const-traits/effects/project.rs b/tests/ui/traits/const-traits/effects/project.rs new file mode 100644 index 00000000000..9f6ca1f294f --- /dev/null +++ b/tests/ui/traits/const-traits/effects/project.rs @@ -0,0 +1,14 @@ +//@ check-pass +//@ compile-flags: -Znext-solver +#![feature(const_trait_impl, effects)] +#![allow(incomplete_features)] + +#[const_trait] +pub trait Owo<X = <Self as Uwu>::T> {} + +#[const_trait] +pub trait Uwu: Owo { + type T; +} + +fn main() {} diff --git a/tests/ui/traits/const-traits/effects/span-bug-issue-121418.rs b/tests/ui/traits/const-traits/effects/span-bug-issue-121418.rs new file mode 100644 index 00000000000..e6e41c472bd --- /dev/null +++ b/tests/ui/traits/const-traits/effects/span-bug-issue-121418.rs @@ -0,0 +1,14 @@ +#![feature(const_trait_impl)] +#![feature(effects)] //~ WARN the feature `effects` is incomplete + +struct S; +trait T {} + +impl const dyn T { + //~^ ERROR inherent impls cannot be `const` + pub const fn new() -> std::sync::Mutex<dyn T> {} + //~^ ERROR mismatched types + //~| ERROR cannot be known at compilation time +} + +fn main() {} diff --git a/tests/ui/traits/const-traits/effects/span-bug-issue-121418.stderr b/tests/ui/traits/const-traits/effects/span-bug-issue-121418.stderr new file mode 100644 index 00000000000..5ff1c6c5b9f --- /dev/null +++ b/tests/ui/traits/const-traits/effects/span-bug-issue-121418.stderr @@ -0,0 +1,50 @@ +error: inherent impls cannot be `const` + --> $DIR/span-bug-issue-121418.rs:7:12 + | +LL | impl const dyn T { + | ----- ^^^^^ inherent impl for this type + | | + | `const` because of this + | + = note: only trait implementations may be annotated with `const` + +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/span-bug-issue-121418.rs:2:12 + | +LL | #![feature(effects)] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + +error: using `#![feature(effects)]` without enabling next trait solver globally + | + = note: the next trait solver must be enabled globally for the effects feature to work correctly + = help: use `-Znext-solver` to enable + +error[E0308]: mismatched types + --> $DIR/span-bug-issue-121418.rs:9:27 + | +LL | pub const fn new() -> std::sync::Mutex<dyn T> {} + | --- ^^^^^^^^^^^^^^^^^^^^^^^ expected `Mutex<dyn T>`, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression + | + = note: expected struct `Mutex<(dyn T + 'static)>` + found unit type `()` + +error[E0277]: the size for values of type `(dyn T + 'static)` cannot be known at compilation time + --> $DIR/span-bug-issue-121418.rs:9:27 + | +LL | pub const fn new() -> std::sync::Mutex<dyn T> {} + | ^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: within `Mutex<(dyn T + 'static)>`, the trait `Sized` is not implemented for `(dyn T + 'static)`, which is required by `Mutex<(dyn T + 'static)>: Sized` +note: required because it appears within the type `Mutex<(dyn T + 'static)>` + --> $SRC_DIR/std/src/sync/mutex.rs:LL:COL + = note: the return type of a function must have a statically known size + +error: aborting due to 4 previous errors; 1 warning emitted + +Some errors have detailed explanations: E0277, E0308. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/const-traits/effects/spec-effectvar-ice.rs b/tests/ui/traits/const-traits/effects/spec-effectvar-ice.rs new file mode 100644 index 00000000000..0508b1c5e26 --- /dev/null +++ b/tests/ui/traits/const-traits/effects/spec-effectvar-ice.rs @@ -0,0 +1,21 @@ +//@ check-fail +// Fixes #119830 + +#![feature(effects)] //~ WARN the feature `effects` is incomplete +#![feature(min_specialization)] +#![feature(const_trait_impl)] + +trait Specialize {} + +trait Foo {} + +impl<T> const Foo for T {} +//~^ error: const `impl` for trait `Foo` which is not marked with `#[const_trait]` + +impl<T> const Foo for T where T: const Specialize {} +//~^ error: const `impl` for trait `Foo` which is not marked with `#[const_trait]` +//~| error: `const` can only be applied to `#[const_trait]` traits +//~| error: specialization impl does not specialize any associated items +//~| error: cannot specialize on trait `Specialize` + +fn main() {} diff --git a/tests/ui/traits/const-traits/effects/spec-effectvar-ice.stderr b/tests/ui/traits/const-traits/effects/spec-effectvar-ice.stderr new file mode 100644 index 00000000000..e97a9615ae1 --- /dev/null +++ b/tests/ui/traits/const-traits/effects/spec-effectvar-ice.stderr @@ -0,0 +1,64 @@ +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/spec-effectvar-ice.rs:4:12 + | +LL | #![feature(effects)] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + +error: using `#![feature(effects)]` without enabling next trait solver globally + | + = note: the next trait solver must be enabled globally for the effects feature to work correctly + = help: use `-Znext-solver` to enable + +error: const `impl` for trait `Foo` which is not marked with `#[const_trait]` + --> $DIR/spec-effectvar-ice.rs:12:15 + | +LL | trait Foo {} + | - help: mark `Foo` as const: `#[const_trait]` +LL | +LL | impl<T> const Foo for T {} + | ^^^ + | + = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: adding a non-const method body in the future would be a breaking change + +error: const `impl` for trait `Foo` which is not marked with `#[const_trait]` + --> $DIR/spec-effectvar-ice.rs:15:15 + | +LL | trait Foo {} + | - help: mark `Foo` as const: `#[const_trait]` +... +LL | impl<T> const Foo for T where T: const Specialize {} + | ^^^ + | + = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: adding a non-const method body in the future would be a breaking change + +error: `const` can only be applied to `#[const_trait]` traits + --> $DIR/spec-effectvar-ice.rs:15:40 + | +LL | impl<T> const Foo for T where T: const Specialize {} + | ^^^^^^^^^^ + +error: specialization impl does not specialize any associated items + --> $DIR/spec-effectvar-ice.rs:15:1 + | +LL | impl<T> const Foo for T where T: const Specialize {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: impl is a specialization of this impl + --> $DIR/spec-effectvar-ice.rs:12:1 + | +LL | impl<T> const Foo for T {} + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: cannot specialize on trait `Specialize` + --> $DIR/spec-effectvar-ice.rs:15:34 + | +LL | impl<T> const Foo for T where T: const Specialize {} + | ^^^^^^^^^^^^^^^^ + +error: aborting due to 6 previous errors; 1 warning emitted + diff --git a/tests/ui/traits/const-traits/effects/trait-fn-const.rs b/tests/ui/traits/const-traits/effects/trait-fn-const.rs new file mode 100644 index 00000000000..d63dbfbf57d --- /dev/null +++ b/tests/ui/traits/const-traits/effects/trait-fn-const.rs @@ -0,0 +1,21 @@ +// Regression test for issue #113378. +#![feature(const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete + +#[const_trait] +trait Trait { + const fn fun(); //~ ERROR functions in traits cannot be declared const +} + +impl const Trait for () { + const fn fun() {} //~ ERROR functions in trait impls cannot be declared const +} + +impl Trait for u32 { + const fn fun() {} //~ ERROR functions in trait impls cannot be declared const +} + +trait NonConst { + const fn fun(); //~ ERROR functions in traits cannot be declared const +} + +fn main() {} diff --git a/tests/ui/traits/const-traits/effects/trait-fn-const.stderr b/tests/ui/traits/const-traits/effects/trait-fn-const.stderr new file mode 100644 index 00000000000..15cb84026e4 --- /dev/null +++ b/tests/ui/traits/const-traits/effects/trait-fn-const.stderr @@ -0,0 +1,73 @@ +error[E0379]: functions in traits cannot be declared const + --> $DIR/trait-fn-const.rs:6:5 + | +LL | #[const_trait] + | -------------- this declares all associated functions implicitly const +LL | trait Trait { +LL | const fn fun(); + | ^^^^^- + | | + | functions in traits cannot be const + | help: remove the `const` + +error[E0379]: functions in trait impls cannot be declared const + --> $DIR/trait-fn-const.rs:10:5 + | +LL | impl const Trait for () { + | ----- this declares all associated functions implicitly const +LL | const fn fun() {} + | ^^^^^- + | | + | functions in trait impls cannot be const + | help: remove the `const` + +error[E0379]: functions in trait impls cannot be declared const + --> $DIR/trait-fn-const.rs:14:5 + | +LL | const fn fun() {} + | ^^^^^ functions in trait impls cannot be const + | +help: remove the `const` ... + | +LL - const fn fun() {} +LL + fn fun() {} + | +help: ... and declare the impl to be const instead + | +LL | impl const Trait for u32 { + | +++++ + +error[E0379]: functions in traits cannot be declared const + --> $DIR/trait-fn-const.rs:18:5 + | +LL | const fn fun(); + | ^^^^^ functions in traits cannot be const + | +help: remove the `const` ... + | +LL - const fn fun(); +LL + fn fun(); + | +help: ... and declare the trait to be a `#[const_trait]` instead + | +LL + #[const_trait] +LL | trait NonConst { + | + +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/trait-fn-const.rs:2:30 + | +LL | #![feature(const_trait_impl, effects)] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + +error: using `#![feature(effects)]` without enabling next trait solver globally + | + = note: the next trait solver must be enabled globally for the effects feature to work correctly + = help: use `-Znext-solver` to enable + +error: aborting due to 5 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0379`. diff --git a/tests/ui/traits/const-traits/effects/with-without-next-solver.coherence.stderr b/tests/ui/traits/const-traits/effects/with-without-next-solver.coherence.stderr new file mode 100644 index 00000000000..20448f51de2 --- /dev/null +++ b/tests/ui/traits/const-traits/effects/with-without-next-solver.coherence.stderr @@ -0,0 +1,7 @@ +error: using `#![feature(effects)]` without enabling next trait solver globally + | + = note: the next trait solver must be enabled globally for the effects feature to work correctly + = help: use `-Znext-solver` to enable + +error: aborting due to 1 previous error + diff --git a/tests/ui/traits/const-traits/effects/with-without-next-solver.rs b/tests/ui/traits/const-traits/effects/with-without-next-solver.rs new file mode 100644 index 00000000000..f022af05c50 --- /dev/null +++ b/tests/ui/traits/const-traits/effects/with-without-next-solver.rs @@ -0,0 +1,10 @@ +// test that we error correctly when effects is used without the next-solver flag. +//@ revisions: stock coherence full +//@[coherence] compile-flags: -Znext-solver=coherence +//@[full] compile-flags: -Znext-solver +//@[full] check-pass + +#![feature(effects)] +#![allow(incomplete_features)] + +fn main() {} diff --git a/tests/ui/traits/const-traits/effects/with-without-next-solver.stock.stderr b/tests/ui/traits/const-traits/effects/with-without-next-solver.stock.stderr new file mode 100644 index 00000000000..20448f51de2 --- /dev/null +++ b/tests/ui/traits/const-traits/effects/with-without-next-solver.stock.stderr @@ -0,0 +1,7 @@ +error: using `#![feature(effects)]` without enabling next trait solver globally + | + = note: the next trait solver must be enabled globally for the effects feature to work correctly + = help: use `-Znext-solver` to enable + +error: aborting due to 1 previous error + diff --git a/tests/ui/traits/const-traits/feature-gate.gated.stderr b/tests/ui/traits/const-traits/feature-gate.gated.stderr new file mode 100644 index 00000000000..12f9355e41d --- /dev/null +++ b/tests/ui/traits/const-traits/feature-gate.gated.stderr @@ -0,0 +1,8 @@ +error: fatal error triggered by #[rustc_error] + --> $DIR/feature-gate.rs:22:1 + | +LL | fn main() {} + | ^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/traits/const-traits/feature-gate.rs b/tests/ui/traits/const-traits/feature-gate.rs new file mode 100644 index 00000000000..c36ec3538c3 --- /dev/null +++ b/tests/ui/traits/const-traits/feature-gate.rs @@ -0,0 +1,22 @@ +//@ revisions: stock gated +// gate-test-const_trait_impl + +#![cfg_attr(gated, feature(const_trait_impl))] +#![feature(rustc_attrs)] + +struct S; +#[const_trait] //[stock]~ ERROR `const_trait` is a temporary placeholder +trait T {} +impl const T for S {} +//[stock]~^ ERROR const trait impls are experimental + +const fn f<A: ~const T>() {} //[stock]~ ERROR const trait impls are experimental +fn g<A: const T>() {} //[stock]~ ERROR const trait impls are experimental + +macro_rules! discard { ($ty:ty) => {} } + +discard! { impl ~const T } //[stock]~ ERROR const trait impls are experimental +discard! { impl const T } //[stock]~ ERROR const trait impls are experimental + +#[rustc_error] +fn main() {} //[gated]~ ERROR fatal error triggered by #[rustc_error] diff --git a/tests/ui/traits/const-traits/feature-gate.stock.stderr b/tests/ui/traits/const-traits/feature-gate.stock.stderr new file mode 100644 index 00000000000..78157d57056 --- /dev/null +++ b/tests/ui/traits/const-traits/feature-gate.stock.stderr @@ -0,0 +1,63 @@ +error[E0658]: const trait impls are experimental + --> $DIR/feature-gate.rs:10:6 + | +LL | impl const T for S {} + | ^^^^^ + | + = note: see issue #67792 <https://github.com/rust-lang/rust/issues/67792> for more information + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: const trait impls are experimental + --> $DIR/feature-gate.rs:13:15 + | +LL | const fn f<A: ~const T>() {} + | ^^^^^^ + | + = note: see issue #67792 <https://github.com/rust-lang/rust/issues/67792> for more information + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: const trait impls are experimental + --> $DIR/feature-gate.rs:14:9 + | +LL | fn g<A: const T>() {} + | ^^^^^ + | + = note: see issue #67792 <https://github.com/rust-lang/rust/issues/67792> for more information + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: const trait impls are experimental + --> $DIR/feature-gate.rs:18:17 + | +LL | discard! { impl ~const T } + | ^^^^^^ + | + = note: see issue #67792 <https://github.com/rust-lang/rust/issues/67792> for more information + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: const trait impls are experimental + --> $DIR/feature-gate.rs:19:17 + | +LL | discard! { impl const T } + | ^^^^^ + | + = note: see issue #67792 <https://github.com/rust-lang/rust/issues/67792> for more information + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: `const_trait` is a temporary placeholder for marking a trait that is suitable for `const` `impls` and all default bodies as `const`, which may be removed or renamed in the future. + --> $DIR/feature-gate.rs:8:1 + | +LL | #[const_trait] + | ^^^^^^^^^^^^^^ + | + = note: see issue #67792 <https://github.com/rust-lang/rust/issues/67792> for more information + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/traits/const-traits/function-pointer-does-not-require-const.rs b/tests/ui/traits/const-traits/function-pointer-does-not-require-const.rs new file mode 100644 index 00000000000..61826e9977e --- /dev/null +++ b/tests/ui/traits/const-traits/function-pointer-does-not-require-const.rs @@ -0,0 +1,15 @@ +//@ check-pass +#![feature(const_trait_impl)] + +#[const_trait] +pub trait Test {} + +impl Test for () {} + +pub const fn test<T: ~const Test>() {} + +pub const fn min_by_i32() -> fn() { + test::<()> +} + +fn main() {} diff --git a/tests/ui/traits/const-traits/gate.rs b/tests/ui/traits/const-traits/gate.rs new file mode 100644 index 00000000000..d1c93ab9f95 --- /dev/null +++ b/tests/ui/traits/const-traits/gate.rs @@ -0,0 +1,13 @@ +// gate-test-const_closures + +fn main() { + (const || {})(); + //~^ ERROR: const closures are experimental +} + +macro_rules! e { + ($e:expr) => {} +} + +e!((const || {})); +//~^ ERROR const closures are experimental diff --git a/tests/ui/traits/const-traits/gate.stderr b/tests/ui/traits/const-traits/gate.stderr new file mode 100644 index 00000000000..19fd54ff369 --- /dev/null +++ b/tests/ui/traits/const-traits/gate.stderr @@ -0,0 +1,23 @@ +error[E0658]: const closures are experimental + --> $DIR/gate.rs:4:6 + | +LL | (const || {})(); + | ^^^^^ + | + = note: see issue #106003 <https://github.com/rust-lang/rust/issues/106003> for more information + = help: add `#![feature(const_closures)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: const closures are experimental + --> $DIR/gate.rs:12:5 + | +LL | e!((const || {})); + | ^^^^^ + | + = note: see issue #106003 <https://github.com/rust-lang/rust/issues/106003> for more information + = help: add `#![feature(const_closures)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/traits/const-traits/generic-bound.rs b/tests/ui/traits/const-traits/generic-bound.rs new file mode 100644 index 00000000000..620e3259917 --- /dev/null +++ b/tests/ui/traits/const-traits/generic-bound.rs @@ -0,0 +1,30 @@ +//@ known-bug: #110395 + +#![feature(const_trait_impl)] + +use std::marker::PhantomData; + +struct S<T>(PhantomData<T>); + +impl<T> Copy for S<T> {} +impl<T> Clone for S<T> { + fn clone(&self) -> Self { + S(PhantomData) + } +} + +impl<T> const std::ops::Add for S<T> { + type Output = Self; + + fn add(self, _: Self) -> Self { + S(std::marker::PhantomData) + } +} + +const fn twice<T: std::ops::Add>(arg: S<T>) -> S<T> { + arg + arg +} + +fn main() { + let _ = twice(S(PhantomData::<i32>)); +} diff --git a/tests/ui/traits/const-traits/generic-bound.stderr b/tests/ui/traits/const-traits/generic-bound.stderr new file mode 100644 index 00000000000..2baac1d2a16 --- /dev/null +++ b/tests/ui/traits/const-traits/generic-bound.stderr @@ -0,0 +1,24 @@ +error: const `impl` for trait `Add` which is not marked with `#[const_trait]` + --> $DIR/generic-bound.rs:16:15 + | +LL | impl<T> const std::ops::Add for S<T> { + | ^^^^^^^^^^^^^ + | + = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: adding a non-const method body in the future would be a breaking change + +error[E0015]: cannot call non-const operator in constant functions + --> $DIR/generic-bound.rs:25:5 + | +LL | arg + arg + | ^^^^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants +help: add `#![feature(effects)]` to the crate attributes to enable + | +LL + #![feature(effects)] + | + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/hir-const-check.rs b/tests/ui/traits/const-traits/hir-const-check.rs new file mode 100644 index 00000000000..f5fb0fd516a --- /dev/null +++ b/tests/ui/traits/const-traits/hir-const-check.rs @@ -0,0 +1,17 @@ +// Regression test for #69615. + +#![feature(const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete + +#[const_trait] +pub trait MyTrait { + fn method(&self) -> Option<()>; +} + +impl const MyTrait for () { + fn method(&self) -> Option<()> { + Some(())?; //~ ERROR `?` is not allowed in a `const fn` + None + } +} + +fn main() {} diff --git a/tests/ui/traits/const-traits/hir-const-check.stderr b/tests/ui/traits/const-traits/hir-const-check.stderr new file mode 100644 index 00000000000..598129d8694 --- /dev/null +++ b/tests/ui/traits/const-traits/hir-const-check.stderr @@ -0,0 +1,27 @@ +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/hir-const-check.rs:3:30 + | +LL | #![feature(const_trait_impl, effects)] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + +error[E0658]: `?` is not allowed in a `const fn` + --> $DIR/hir-const-check.rs:12:9 + | +LL | Some(())?; + | ^^^^^^^^^ + | + = note: see issue #74935 <https://github.com/rust-lang/rust/issues/74935> for more information + = help: add `#![feature(const_try)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: using `#![feature(effects)]` without enabling next trait solver globally + | + = note: the next trait solver must be enabled globally for the effects feature to work correctly + = help: use `-Znext-solver` to enable + +error: aborting due to 2 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/traits/const-traits/ice-119717-constant-lifetime.rs b/tests/ui/traits/const-traits/ice-119717-constant-lifetime.rs new file mode 100644 index 00000000000..c2f452a9925 --- /dev/null +++ b/tests/ui/traits/const-traits/ice-119717-constant-lifetime.rs @@ -0,0 +1,15 @@ +#![allow(incomplete_features)] +#![feature(const_trait_impl, effects, try_trait_v2)] + +use std::ops::FromResidual; + +impl<T> const FromResidual for T { + //~^ ERROR const `impl` for trait `FromResidual` which is not marked with `#[const_trait]` + //~| type parameter `T` must be used as the type parameter for some local type + fn from_residual(t: T) -> _ { + //~^ the placeholder `_` is not allowed + t + } +} + +fn main() {} diff --git a/tests/ui/traits/const-traits/ice-119717-constant-lifetime.stderr b/tests/ui/traits/const-traits/ice-119717-constant-lifetime.stderr new file mode 100644 index 00000000000..50cdded8d51 --- /dev/null +++ b/tests/ui/traits/const-traits/ice-119717-constant-lifetime.stderr @@ -0,0 +1,38 @@ +error: using `#![feature(effects)]` without enabling next trait solver globally + | + = note: the next trait solver must be enabled globally for the effects feature to work correctly + = help: use `-Znext-solver` to enable + +error: const `impl` for trait `FromResidual` which is not marked with `#[const_trait]` + --> $DIR/ice-119717-constant-lifetime.rs:6:15 + | +LL | impl<T> const FromResidual for T { + | ^^^^^^^^^^^^ + | + = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: adding a non-const method body in the future would be a breaking change + +error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`) + --> $DIR/ice-119717-constant-lifetime.rs:6:6 + | +LL | impl<T> const FromResidual 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[E0121]: the placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/ice-119717-constant-lifetime.rs:9:31 + | +LL | fn from_residual(t: T) -> _ { + | ^ not allowed in type signatures + | +help: try replacing `_` with the type in the corresponding trait method signature + | +LL | fn from_residual(t: T) -> T { + | ~ + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0121, E0210. +For more information about an error, try `rustc --explain E0121`. diff --git a/tests/ui/traits/const-traits/ice-120503-async-const-method.rs b/tests/ui/traits/const-traits/ice-120503-async-const-method.rs new file mode 100644 index 00000000000..9cd18d4566d --- /dev/null +++ b/tests/ui/traits/const-traits/ice-120503-async-const-method.rs @@ -0,0 +1,17 @@ +//@ edition: 2021 +#![feature(effects)] //~ WARN the feature `effects` is incomplete + +trait MyTrait {} + +impl MyTrait for i32 { + async const fn bar(&self) { + //~^ ERROR expected one of `extern` + //~| ERROR functions in trait impls cannot be declared const + //~| ERROR functions cannot be both `const` and `async` + //~| ERROR method `bar` is not a member + main8().await; + //~^ ERROR cannot find function + } +} + +fn main() {} diff --git a/tests/ui/traits/const-traits/ice-120503-async-const-method.stderr b/tests/ui/traits/const-traits/ice-120503-async-const-method.stderr new file mode 100644 index 00000000000..90771c344b5 --- /dev/null +++ b/tests/ui/traits/const-traits/ice-120503-async-const-method.stderr @@ -0,0 +1,75 @@ +error: expected one of `extern`, `fn`, `safe`, or `unsafe`, found keyword `const` + --> $DIR/ice-120503-async-const-method.rs:7:11 + | +LL | async const fn bar(&self) { + | ------^^^^^ + | | | + | | expected one of `extern`, `fn`, `safe`, or `unsafe` + | help: `const` must come before `async`: `const async` + | + = note: keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern` + +error[E0379]: functions in trait impls cannot be declared const + --> $DIR/ice-120503-async-const-method.rs:7:11 + | +LL | async const fn bar(&self) { + | ^^^^^- + | | + | functions in trait impls cannot be const + | help: remove the `const` + +error: functions cannot be both `const` and `async` + --> $DIR/ice-120503-async-const-method.rs:7:5 + | +LL | async const fn bar(&self) { + | -^^^^ ^^^^^ `const` because of this + | | + | _____`async` because of this + | | +LL | | +LL | | +LL | | +... | +LL | | +LL | | } + | |_____- + +error[E0407]: method `bar` is not a member of trait `MyTrait` + --> $DIR/ice-120503-async-const-method.rs:7:5 + | +LL | / async const fn bar(&self) { +LL | | +LL | | +LL | | +... | +LL | | +LL | | } + | |_____^ not a member of trait `MyTrait` + +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/ice-120503-async-const-method.rs:2:12 + | +LL | #![feature(effects)] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + +error: using `#![feature(effects)]` without enabling next trait solver globally + | + = note: the next trait solver must be enabled globally for the effects feature to work correctly + = help: use `-Znext-solver` to enable + +error[E0425]: cannot find function `main8` in this scope + --> $DIR/ice-120503-async-const-method.rs:12:9 + | +LL | main8().await; + | ^^^^^ help: a function with a similar name exists: `main` +... +LL | fn main() {} + | --------- similarly named function `main` defined here + +error: aborting due to 6 previous errors; 1 warning emitted + +Some errors have detailed explanations: E0379, E0407, E0425. +For more information about an error, try `rustc --explain E0379`. diff --git a/tests/ui/traits/const-traits/ice-121536-const-method.rs b/tests/ui/traits/const-traits/ice-121536-const-method.rs new file mode 100644 index 00000000000..a01329278d7 --- /dev/null +++ b/tests/ui/traits/const-traits/ice-121536-const-method.rs @@ -0,0 +1,17 @@ +#![feature(const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete + +pub struct Vec3; + +#[const_trait] +pub trait Add { + fn add(self) -> Vec3; +} + +impl Add for Vec3 { + const fn add(self) -> Vec3 { + //~^ ERROR functions in trait impls cannot be declared const + self + } +} + +fn main() {} diff --git a/tests/ui/traits/const-traits/ice-121536-const-method.stderr b/tests/ui/traits/const-traits/ice-121536-const-method.stderr new file mode 100644 index 00000000000..29187654c3c --- /dev/null +++ b/tests/ui/traits/const-traits/ice-121536-const-method.stderr @@ -0,0 +1,33 @@ +error[E0379]: functions in trait impls cannot be declared const + --> $DIR/ice-121536-const-method.rs:11:5 + | +LL | const fn add(self) -> Vec3 { + | ^^^^^ functions in trait impls cannot be const + | +help: remove the `const` ... + | +LL - const fn add(self) -> Vec3 { +LL + fn add(self) -> Vec3 { + | +help: ... and declare the impl to be const instead + | +LL | impl const Add for Vec3 { + | +++++ + +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/ice-121536-const-method.rs:1:30 + | +LL | #![feature(const_trait_impl, effects)] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + +error: using `#![feature(effects)]` without enabling next trait solver globally + | + = note: the next trait solver must be enabled globally for the effects feature to work correctly + = help: use `-Znext-solver` to enable + +error: aborting due to 2 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0379`. diff --git a/tests/ui/traits/const-traits/ice-123664-unexpected-bound-var.rs b/tests/ui/traits/const-traits/ice-123664-unexpected-bound-var.rs new file mode 100644 index 00000000000..64634e7b7ac --- /dev/null +++ b/tests/ui/traits/const-traits/ice-123664-unexpected-bound-var.rs @@ -0,0 +1,7 @@ +#![allow(incomplete_features)] +#![feature(generic_const_exprs, const_trait_impl, effects)] + +const fn with_positive<F: ~const Fn()>() {} +//~^ ERROR `~const` can only be applied to `#[const_trait]` traits + +pub fn main() {} diff --git a/tests/ui/traits/const-traits/ice-123664-unexpected-bound-var.stderr b/tests/ui/traits/const-traits/ice-123664-unexpected-bound-var.stderr new file mode 100644 index 00000000000..c937430a1ca --- /dev/null +++ b/tests/ui/traits/const-traits/ice-123664-unexpected-bound-var.stderr @@ -0,0 +1,13 @@ +error: using `#![feature(effects)]` without enabling next trait solver globally + | + = note: the next trait solver must be enabled globally for the effects feature to work correctly + = help: use `-Znext-solver` to enable + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/ice-123664-unexpected-bound-var.rs:4:34 + | +LL | const fn with_positive<F: ~const Fn()>() {} + | ^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/traits/const-traits/ice-124857-combine-effect-const-infer-vars.rs b/tests/ui/traits/const-traits/ice-124857-combine-effect-const-infer-vars.rs new file mode 100644 index 00000000000..d4fcbfb1b83 --- /dev/null +++ b/tests/ui/traits/const-traits/ice-124857-combine-effect-const-infer-vars.rs @@ -0,0 +1,14 @@ +//@ compile-flags: -Znext-solver=coherence + +#![allow(incomplete_features)] +#![feature(const_trait_impl, effects)] + +#[const_trait] +trait Foo {} + +impl const Foo for i32 {} + +impl<T> const Foo for T where T: ~const Foo {} +//~^ ERROR conflicting implementations of trait `Foo` for type `i32` + +fn main() {} diff --git a/tests/ui/traits/const-traits/ice-124857-combine-effect-const-infer-vars.stderr b/tests/ui/traits/const-traits/ice-124857-combine-effect-const-infer-vars.stderr new file mode 100644 index 00000000000..284757c1a89 --- /dev/null +++ b/tests/ui/traits/const-traits/ice-124857-combine-effect-const-infer-vars.stderr @@ -0,0 +1,17 @@ +error: using `#![feature(effects)]` without enabling next trait solver globally + | + = note: the next trait solver must be enabled globally for the effects feature to work correctly + = help: use `-Znext-solver` to enable + +error[E0119]: conflicting implementations of trait `Foo` for type `i32` + --> $DIR/ice-124857-combine-effect-const-infer-vars.rs:11:1 + | +LL | impl const Foo for i32 {} + | ---------------------- first implementation here +LL | +LL | impl<T> const Foo for T where T: ~const Foo {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `i32` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/traits/const-traits/ice-126148-failed-to-normalize.rs b/tests/ui/traits/const-traits/ice-126148-failed-to-normalize.rs new file mode 100644 index 00000000000..717c0e7c088 --- /dev/null +++ b/tests/ui/traits/const-traits/ice-126148-failed-to-normalize.rs @@ -0,0 +1,28 @@ +#![allow(incomplete_features)] +#![feature(const_trait_impl, effects, try_trait_v2, const_try)] +use std::ops::{FromResidual, Try}; + +struct TryMe; +struct Error; + +impl const FromResidual<Error> for TryMe {} +//~^ ERROR const `impl` for trait `FromResidual` which is not marked with `#[const_trait]` +//~| ERROR not all trait items implemented + +impl const Try for TryMe { + //~^ ERROR const `impl` for trait `Try` which is not marked with `#[const_trait]` + //~| ERROR not all trait items implemented + type Output = (); + type Residual = Error; +} + +const fn t() -> TryMe { + TryMe?; + TryMe +} + +const _: () = { + t(); +}; + +fn main() {} diff --git a/tests/ui/traits/const-traits/ice-126148-failed-to-normalize.stderr b/tests/ui/traits/const-traits/ice-126148-failed-to-normalize.stderr new file mode 100644 index 00000000000..e49436c8f0f --- /dev/null +++ b/tests/ui/traits/const-traits/ice-126148-failed-to-normalize.stderr @@ -0,0 +1,43 @@ +error: using `#![feature(effects)]` without enabling next trait solver globally + | + = note: the next trait solver must be enabled globally for the effects feature to work correctly + = help: use `-Znext-solver` to enable + +error: const `impl` for trait `FromResidual` which is not marked with `#[const_trait]` + --> $DIR/ice-126148-failed-to-normalize.rs:8:12 + | +LL | impl const FromResidual<Error> for TryMe {} + | ^^^^^^^^^^^^^^^^^^^ + | + = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: adding a non-const method body in the future would be a breaking change + +error[E0046]: not all trait items implemented, missing: `from_residual` + --> $DIR/ice-126148-failed-to-normalize.rs:8:1 + | +LL | impl const FromResidual<Error> for TryMe {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `from_residual` in implementation + | + = help: implement the missing item: `fn from_residual(_: Error) -> Self { todo!() }` + +error: const `impl` for trait `Try` which is not marked with `#[const_trait]` + --> $DIR/ice-126148-failed-to-normalize.rs:12:12 + | +LL | impl const Try for TryMe { + | ^^^ + | + = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: adding a non-const method body in the future would be a breaking change + +error[E0046]: not all trait items implemented, missing: `from_output`, `branch` + --> $DIR/ice-126148-failed-to-normalize.rs:12:1 + | +LL | impl const Try for TryMe { + | ^^^^^^^^^^^^^^^^^^^^^^^^ missing `from_output`, `branch` in implementation + | + = help: implement the missing item: `fn from_output(_: <Self as Try>::Output) -> Self { todo!() }` + = help: implement the missing item: `fn branch(self) -> ControlFlow<<Self as Try>::Residual, <Self as Try>::Output> { todo!() }` + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0046`. diff --git a/tests/ui/traits/const-traits/impl-tilde-const-trait.rs b/tests/ui/traits/const-traits/impl-tilde-const-trait.rs new file mode 100644 index 00000000000..05b26465c5b --- /dev/null +++ b/tests/ui/traits/const-traits/impl-tilde-const-trait.rs @@ -0,0 +1,9 @@ +#![feature(const_trait_impl)] + +struct S; +trait T {} + +impl ~const T for S {} +//~^ ERROR expected a trait, found type + +fn main() {} diff --git a/tests/ui/traits/const-traits/impl-tilde-const-trait.stderr b/tests/ui/traits/const-traits/impl-tilde-const-trait.stderr new file mode 100644 index 00000000000..4695728f8ca --- /dev/null +++ b/tests/ui/traits/const-traits/impl-tilde-const-trait.stderr @@ -0,0 +1,8 @@ +error: expected a trait, found type + --> $DIR/impl-tilde-const-trait.rs:6:6 + | +LL | impl ~const T for S {} + | ^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/traits/const-traits/impl-with-default-fn-fail.rs b/tests/ui/traits/const-traits/impl-with-default-fn-fail.rs new file mode 100644 index 00000000000..49741ca24c7 --- /dev/null +++ b/tests/ui/traits/const-traits/impl-with-default-fn-fail.rs @@ -0,0 +1,18 @@ +#![allow(incomplete_features)] +#![feature(const_trait_impl, effects)] + +#[const_trait] +trait Tr { + fn req(&self); + + fn default() {} +} + +struct S; + +impl const Tr for u16 { + fn default() {} +} //~^^ ERROR not all trait items implemented + + +fn main() {} diff --git a/tests/ui/traits/const-traits/impl-with-default-fn-fail.stderr b/tests/ui/traits/const-traits/impl-with-default-fn-fail.stderr new file mode 100644 index 00000000000..2ea203627f4 --- /dev/null +++ b/tests/ui/traits/const-traits/impl-with-default-fn-fail.stderr @@ -0,0 +1,17 @@ +error: using `#![feature(effects)]` without enabling next trait solver globally + | + = note: the next trait solver must be enabled globally for the effects feature to work correctly + = help: use `-Znext-solver` to enable + +error[E0046]: not all trait items implemented, missing: `req` + --> $DIR/impl-with-default-fn-fail.rs:13:1 + | +LL | fn req(&self); + | -------------- `req` from trait +... +LL | impl const Tr for u16 { + | ^^^^^^^^^^^^^^^^^^^^^ missing `req` in implementation + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0046`. diff --git a/tests/ui/traits/const-traits/impl-with-default-fn-pass.rs b/tests/ui/traits/const-traits/impl-with-default-fn-pass.rs new file mode 100644 index 00000000000..2c375036941 --- /dev/null +++ b/tests/ui/traits/const-traits/impl-with-default-fn-pass.rs @@ -0,0 +1,27 @@ +//@ check-pass +//@ compile-flags: -Znext-solver +#![allow(incomplete_features)] +#![feature(const_trait_impl, effects)] + +#[const_trait] +trait Tr { + fn req(&self); + + fn default() {} +} + +impl const Tr for u8 { + fn req(&self) {} +} + +macro_rules! impl_tr { + ($ty: ty) => { + impl const Tr for $ty { + fn req(&self) {} + } + } +} + +impl_tr!(u64); + +fn main() {} diff --git a/tests/ui/traits/const-traits/inherent-impl-const-bounds.rs b/tests/ui/traits/const-traits/inherent-impl-const-bounds.rs new file mode 100644 index 00000000000..5ead1353bcd --- /dev/null +++ b/tests/ui/traits/const-traits/inherent-impl-const-bounds.rs @@ -0,0 +1,22 @@ +//@ check-pass +#![feature(const_trait_impl)] + +struct S; + +#[const_trait] +trait A {} +#[const_trait] +trait B {} + +impl const A for S {} +impl const B for S {} + +impl S { + const fn a<T: ~const A>() where T: ~const B { + + } +} + +const _: () = S::a::<S>(); + +fn main() {} diff --git a/tests/ui/traits/const-traits/inherent-impl.rs b/tests/ui/traits/const-traits/inherent-impl.rs new file mode 100644 index 00000000000..afd0d137bb4 --- /dev/null +++ b/tests/ui/traits/const-traits/inherent-impl.rs @@ -0,0 +1,13 @@ +#![feature(const_trait_impl)] +#![allow(bare_trait_objects)] + +struct S; +trait T {} + +impl const S {} +//~^ ERROR inherent impls cannot be `const` + +impl const T {} +//~^ ERROR inherent impls cannot be `const` + +fn main() {} diff --git a/tests/ui/traits/const-traits/inherent-impl.stderr b/tests/ui/traits/const-traits/inherent-impl.stderr new file mode 100644 index 00000000000..8c55627031d --- /dev/null +++ b/tests/ui/traits/const-traits/inherent-impl.stderr @@ -0,0 +1,22 @@ +error: inherent impls cannot be `const` + --> $DIR/inherent-impl.rs:7:12 + | +LL | impl const S {} + | ----- ^ inherent impl for this type + | | + | `const` because of this + | + = note: only trait implementations may be annotated with `const` + +error: inherent impls cannot be `const` + --> $DIR/inherent-impl.rs:10:12 + | +LL | impl const T {} + | ----- ^ inherent impl for this type + | | + | `const` because of this + | + = note: only trait implementations may be annotated with `const` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/traits/const-traits/inline-incorrect-early-bound-in-ctfe.rs b/tests/ui/traits/const-traits/inline-incorrect-early-bound-in-ctfe.rs new file mode 100644 index 00000000000..e3adcce17b4 --- /dev/null +++ b/tests/ui/traits/const-traits/inline-incorrect-early-bound-in-ctfe.rs @@ -0,0 +1,32 @@ +// This test demonstrates an ICE that may occur when we try to resolve the instance +// of a impl that has different generics than the trait it's implementing. This ensures +// we first check that the args are compatible before resolving the body, just like +// we do in projection before substituting a GAT. +// +// Const traits aren't the only way to achieve this ICE, but it's a convenient way +// to ensure the inliner is called. + +//@ compile-flags: -Znext-solver -Zinline-mir=yes + +#![feature(const_trait_impl, effects)] +//~^ WARN the feature `effects` is incomplete + +trait Trait { + fn foo(self); +} + +impl Trait for () { + #[inline] + fn foo<T>(self) { + //~^ ERROR method `foo` has 1 type parameter but its trait declaration has 0 type parameters + todo!(); + } +} + +const fn foo() { + ().foo(); +} + +const UWU: () = foo(); + +fn main() {} diff --git a/tests/ui/traits/const-traits/inline-incorrect-early-bound-in-ctfe.stderr b/tests/ui/traits/const-traits/inline-incorrect-early-bound-in-ctfe.stderr new file mode 100644 index 00000000000..2e7801c0b8a --- /dev/null +++ b/tests/ui/traits/const-traits/inline-incorrect-early-bound-in-ctfe.stderr @@ -0,0 +1,21 @@ +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/inline-incorrect-early-bound-in-ctfe.rs:11:30 + | +LL | #![feature(const_trait_impl, effects)] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + +error[E0049]: method `foo` has 1 type parameter but its trait declaration has 0 type parameters + --> $DIR/inline-incorrect-early-bound-in-ctfe.rs:20:12 + | +LL | fn foo(self); + | - expected 0 type parameters +... +LL | fn foo<T>(self) { + | ^ found 1 type parameter + +error: aborting due to 1 previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0049`. diff --git a/tests/ui/traits/const-traits/issue-100222.rs b/tests/ui/traits/const-traits/issue-100222.rs new file mode 100644 index 00000000000..13c469d656c --- /dev/null +++ b/tests/ui/traits/const-traits/issue-100222.rs @@ -0,0 +1,42 @@ +//@ revisions: nn ny yn yy +//@ compile-flags: -Znext-solver +//@ check-pass + +#![allow(incomplete_features)] +#![feature(const_trait_impl, effects, associated_type_defaults)] + +#[cfg_attr(any(yn, yy), const_trait)] +pub trait Index { + type Output; +} + +#[cfg_attr(any(ny, yy), const_trait)] +pub trait IndexMut where Self: Index { + const C: <Self as Index>::Output; + type Assoc = <Self as Index>::Output; + fn foo(&mut self, x: <Self as Index>::Output) -> <Self as Index>::Output; +} + +impl Index for () { type Output = (); } + +#[cfg(not(any(nn, yn)))] +impl const IndexMut for <() as Index>::Output { + const C: <Self as Index>::Output = (); + type Assoc = <Self as Index>::Output; + fn foo(&mut self, x: <Self as Index>::Output) -> <Self as Index>::Output + where <Self as Index>::Output:, + {} +} + +#[cfg(any(nn, yn))] +impl IndexMut for <() as Index>::Output { + const C: <Self as Index>::Output = (); + type Assoc = <Self as Index>::Output; + fn foo(&mut self, x: <Self as Index>::Output) -> <Self as Index>::Output + where <Self as Index>::Output:, + {} +} + +const C: <() as Index>::Output = (); + +fn main() {} diff --git a/tests/ui/traits/const-traits/issue-102156.rs b/tests/ui/traits/const-traits/issue-102156.rs new file mode 100644 index 00000000000..fe4e9108130 --- /dev/null +++ b/tests/ui/traits/const-traits/issue-102156.rs @@ -0,0 +1,15 @@ +#![feature(allocator_api)] +#![feature(const_trait_impl)] + +use core::convert::{From, TryFrom}; +//~^ ERROR +//~| ERROR + +use std::pin::Pin; +use std::alloc::Allocator; +impl<T: ?Sized, A: Allocator> const From<Box<T, A>> for Pin<Box<T, A>> +where + A: 'static, +{} + +pub fn main() {} diff --git a/tests/ui/traits/const-traits/issue-102156.stderr b/tests/ui/traits/const-traits/issue-102156.stderr new file mode 100644 index 00000000000..0c836a614f8 --- /dev/null +++ b/tests/ui/traits/const-traits/issue-102156.stderr @@ -0,0 +1,23 @@ +error[E0433]: failed to resolve: you might be missing crate `core` + --> $DIR/issue-102156.rs:4:5 + | +LL | use core::convert::{From, TryFrom}; + | ^^^^ + | | + | you might be missing crate `core` + | help: try using `std` instead of `core`: `std` + +error[E0433]: failed to resolve: you might be missing crate `core` + --> $DIR/issue-102156.rs:4:5 + | +LL | use core::convert::{From, TryFrom}; + | ^^^^ + | | + | you might be missing crate `core` + | help: try using `std` instead of `core`: `std` + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/traits/const-traits/issue-102985.rs b/tests/ui/traits/const-traits/issue-102985.rs new file mode 100644 index 00000000000..e5394ddd688 --- /dev/null +++ b/tests/ui/traits/const-traits/issue-102985.rs @@ -0,0 +1,13 @@ +//@ known-bug: #110395 +#![feature(const_trait_impl)] + +struct Bug { + inner: [(); match || 1 { + n => n(), + //FIXME ~^ ERROR the trait bound + //FIXME ~| ERROR the trait bound + //FIXME ~| ERROR cannot call non-const closure in constants + }], +} + +fn main() {} diff --git a/tests/ui/traits/const-traits/issue-102985.stderr b/tests/ui/traits/const-traits/issue-102985.stderr new file mode 100644 index 00000000000..8401d1bd4f6 --- /dev/null +++ b/tests/ui/traits/const-traits/issue-102985.stderr @@ -0,0 +1,16 @@ +error[E0015]: cannot call non-const closure in constants + --> $DIR/issue-102985.rs:6:14 + | +LL | n => n(), + | ^^^ + | + = note: closures need an RFC before allowed to be called in constants + = note: calls in constants are limited to constant functions, tuple structs and tuple variants +help: add `#![feature(effects)]` to the crate attributes to enable + | +LL + #![feature(effects)] + | + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/issue-103677.rs b/tests/ui/traits/const-traits/issue-103677.rs new file mode 100644 index 00000000000..c032cc7a688 --- /dev/null +++ b/tests/ui/traits/const-traits/issue-103677.rs @@ -0,0 +1,5 @@ +//@ check-pass + +const _: fn(&String) = |s| { &*s as &str; }; + +fn main() {} diff --git a/tests/ui/traits/const-traits/issue-79450.rs b/tests/ui/traits/const-traits/issue-79450.rs new file mode 100644 index 00000000000..b8b9e07b3bd --- /dev/null +++ b/tests/ui/traits/const-traits/issue-79450.rs @@ -0,0 +1,22 @@ +//@ compile-flags: -Znext-solver +#![allow(incomplete_features)] +#![feature(const_fmt_arguments_new)] +#![feature(const_trait_impl, effects)] + +#[const_trait] +trait Tr { + fn req(&self); + + fn prov(&self) { + println!("lul"); //~ ERROR: cannot call non-const fn `_print` in constant functions + self.req(); + } +} + +struct S; + +impl const Tr for S { + fn req(&self) {} +} + +fn main() {} diff --git a/tests/ui/traits/const-traits/issue-79450.stderr b/tests/ui/traits/const-traits/issue-79450.stderr new file mode 100644 index 00000000000..9e6348d37ed --- /dev/null +++ b/tests/ui/traits/const-traits/issue-79450.stderr @@ -0,0 +1,12 @@ +error[E0015]: cannot call non-const fn `_print` in constant functions + --> $DIR/issue-79450.rs:11:9 + | +LL | println!("lul"); + | ^^^^^^^^^^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = note: this error originates in the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/issue-88155.rs b/tests/ui/traits/const-traits/issue-88155.rs new file mode 100644 index 00000000000..08739de8313 --- /dev/null +++ b/tests/ui/traits/const-traits/issue-88155.rs @@ -0,0 +1,15 @@ +//@ known-bug: #110395 + +#![feature(const_trait_impl)] + +pub trait A { + fn assoc() -> bool; +} + +pub const fn foo<T: A>() -> bool { + T::assoc() + //FIXME ~^ ERROR the trait bound + //FIXME ~| ERROR cannot call non-const fn +} + +fn main() {} diff --git a/tests/ui/traits/const-traits/issue-88155.stderr b/tests/ui/traits/const-traits/issue-88155.stderr new file mode 100644 index 00000000000..afe1ea3b1b7 --- /dev/null +++ b/tests/ui/traits/const-traits/issue-88155.stderr @@ -0,0 +1,15 @@ +error[E0015]: cannot call non-const fn `<T as A>::assoc` in constant functions + --> $DIR/issue-88155.rs:10:5 + | +LL | T::assoc() + | ^^^^^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants +help: add `#![feature(effects)]` to the crate attributes to enable + | +LL + #![feature(effects)] + | + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/issue-92111.rs b/tests/ui/traits/const-traits/issue-92111.rs new file mode 100644 index 00000000000..64fa32156c3 --- /dev/null +++ b/tests/ui/traits/const-traits/issue-92111.rs @@ -0,0 +1,24 @@ +// Regression test for #92111. +// +//@ known-bug: #110395 +// FIXME check-pass + +#![feature(const_trait_impl)] + +use std::marker::Destruct; + +pub trait Tr {} + +#[allow(drop_bounds)] +impl<T: Drop> Tr for T {} + +#[derive(Debug)] +pub struct S(i32); + +impl Tr for S {} + +const fn a<T: ~const Destruct>(t: T) {} + +fn main() { + a(S(0)); +} diff --git a/tests/ui/traits/const-traits/issue-92111.stderr b/tests/ui/traits/const-traits/issue-92111.stderr new file mode 100644 index 00000000000..ecc994a3fe6 --- /dev/null +++ b/tests/ui/traits/const-traits/issue-92111.stderr @@ -0,0 +1,17 @@ +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/issue-92111.rs:20:22 + | +LL | const fn a<T: ~const Destruct>(t: T) {} + | ^^^^^^^^ + +error[E0493]: destructor of `T` cannot be evaluated at compile-time + --> $DIR/issue-92111.rs:20:32 + | +LL | const fn a<T: ~const Destruct>(t: T) {} + | ^ - value is dropped here + | | + | the destructor for this type cannot be evaluated in constant functions + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0493`. diff --git a/tests/ui/traits/const-traits/issue-92230-wf-super-trait-env.rs b/tests/ui/traits/const-traits/issue-92230-wf-super-trait-env.rs new file mode 100644 index 00000000000..e666355db6f --- /dev/null +++ b/tests/ui/traits/const-traits/issue-92230-wf-super-trait-env.rs @@ -0,0 +1,17 @@ +// Regression test for #92230. +// +//@ check-pass +//@ compile-flags: -Znext-solver + +#![feature(const_trait_impl, effects)] +#![allow(incomplete_features)] + +#[const_trait] +pub trait Super {} +#[const_trait] +pub trait Sub: Super {} + +impl<A> const Super for &A where A: ~const Super {} +impl<A> const Sub for &A where A: ~const Sub {} + +fn main() {} diff --git a/tests/ui/traits/const-traits/match-non-const-eq.gated.stderr b/tests/ui/traits/const-traits/match-non-const-eq.gated.stderr new file mode 100644 index 00000000000..c7d21151661 --- /dev/null +++ b/tests/ui/traits/const-traits/match-non-const-eq.gated.stderr @@ -0,0 +1,16 @@ +error[E0015]: cannot match on `str` in constant functions + --> $DIR/match-non-const-eq.rs:7:9 + | +LL | "a" => (), //FIXME [gated]~ ERROR can't compare `str` with `str` in const contexts + | ^^^ + | + = note: `str` cannot be compared in compile-time, and therefore cannot be used in `match`es + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants +help: add `#![feature(effects)]` to the crate attributes to enable + | +LL + #![feature(effects)] + | + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/match-non-const-eq.rs b/tests/ui/traits/const-traits/match-non-const-eq.rs new file mode 100644 index 00000000000..73f8af86bd0 --- /dev/null +++ b/tests/ui/traits/const-traits/match-non-const-eq.rs @@ -0,0 +1,13 @@ +//@ known-bug: #110395 +//@ revisions: stock gated +#![cfg_attr(gated, feature(const_trait_impl))] + +const fn foo(input: &'static str) { + match input { + "a" => (), //FIXME [gated]~ ERROR can't compare `str` with `str` in const contexts + //FIXME ~^ ERROR cannot match on `str` in constant functions + _ => (), + } +} + +fn main() {} diff --git a/tests/ui/traits/const-traits/match-non-const-eq.stock.stderr b/tests/ui/traits/const-traits/match-non-const-eq.stock.stderr new file mode 100644 index 00000000000..0f5ecac3891 --- /dev/null +++ b/tests/ui/traits/const-traits/match-non-const-eq.stock.stderr @@ -0,0 +1,16 @@ +error[E0015]: cannot match on `str` in constant functions + --> $DIR/match-non-const-eq.rs:7:9 + | +LL | "a" => (), //FIXME [gated]~ ERROR can't compare `str` with `str` in const contexts + | ^^^ + | + = note: `str` cannot be compared in compile-time, and therefore cannot be used in `match`es + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants +help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + | +LL + #![feature(const_trait_impl)] + | + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/mbe-bare-trait-objects-const-trait-bounds.rs b/tests/ui/traits/const-traits/mbe-bare-trait-objects-const-trait-bounds.rs new file mode 100644 index 00000000000..820d3d63b62 --- /dev/null +++ b/tests/ui/traits/const-traits/mbe-bare-trait-objects-const-trait-bounds.rs @@ -0,0 +1,20 @@ +// Ensure that we don't consider `const Trait` and `~const Trait` to +// match the macro fragment specifier `ty` as that would be a breaking +// change theoretically speaking. Syntactically trait object types can +// be "bare", i.e., lack the prefix `dyn`. +// By contrast, `?Trait` *does* match `ty` and therefore an arm like +// `?$Trait:path` would never be reached. +// See `parser/macro/mbe-bare-trait-object-maybe-trait-bound.rs`. + +//@ check-pass + +macro_rules! check { + ($Type:ty) => { compile_error!("ty"); }; + (const $Trait:path) => {}; + (~const $Trait:path) => {}; +} + +check! { const Trait } +check! { ~const Trait } + +fn main() {} diff --git a/tests/ui/traits/const-traits/mbe-const-trait-bound-theoretical-regression.rs b/tests/ui/traits/const-traits/mbe-const-trait-bound-theoretical-regression.rs new file mode 100644 index 00000000000..3dcdb0cad94 --- /dev/null +++ b/tests/ui/traits/const-traits/mbe-const-trait-bound-theoretical-regression.rs @@ -0,0 +1,21 @@ +// Demonstrates and records a theoretical regressions / breaking changes caused by the +// introduction of const trait bounds. + +// Setting the edition to 2018 since we don't regress `demo! { dyn const }` in Rust <2018. +//@ edition:2018 + +macro_rules! demo { + ($ty:ty) => { compile_error!("ty"); }; + //~^ ERROR ty + //~| ERROR ty + (impl $c:ident Trait) => {}; + (dyn $c:ident Trait) => {}; +} + +demo! { impl const Trait } +//~^ ERROR const trait impls are experimental + +demo! { dyn const Trait } +//~^ ERROR const trait impls are experimental + +fn main() {} diff --git a/tests/ui/traits/const-traits/mbe-const-trait-bound-theoretical-regression.stderr b/tests/ui/traits/const-traits/mbe-const-trait-bound-theoretical-regression.stderr new file mode 100644 index 00000000000..f4b401b7386 --- /dev/null +++ b/tests/ui/traits/const-traits/mbe-const-trait-bound-theoretical-regression.stderr @@ -0,0 +1,45 @@ +error: ty + --> $DIR/mbe-const-trait-bound-theoretical-regression.rs:8:19 + | +LL | ($ty:ty) => { compile_error!("ty"); }; + | ^^^^^^^^^^^^^^^^^^^^ +... +LL | demo! { impl const Trait } + | -------------------------- in this macro invocation + | + = note: this error originates in the macro `demo` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: ty + --> $DIR/mbe-const-trait-bound-theoretical-regression.rs:8:19 + | +LL | ($ty:ty) => { compile_error!("ty"); }; + | ^^^^^^^^^^^^^^^^^^^^ +... +LL | demo! { dyn const Trait } + | ------------------------- in this macro invocation + | + = note: this error originates in the macro `demo` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0658]: const trait impls are experimental + --> $DIR/mbe-const-trait-bound-theoretical-regression.rs:15:14 + | +LL | demo! { impl const Trait } + | ^^^^^ + | + = note: see issue #67792 <https://github.com/rust-lang/rust/issues/67792> for more information + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: const trait impls are experimental + --> $DIR/mbe-const-trait-bound-theoretical-regression.rs:18:13 + | +LL | demo! { dyn const Trait } + | ^^^^^ + | + = note: see issue #67792 <https://github.com/rust-lang/rust/issues/67792> for more information + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/traits/const-traits/mbe-dyn-const-2015.rs b/tests/ui/traits/const-traits/mbe-dyn-const-2015.rs new file mode 100644 index 00000000000..9d65a2ac302 --- /dev/null +++ b/tests/ui/traits/const-traits/mbe-dyn-const-2015.rs @@ -0,0 +1,13 @@ +// Ensure that the introduction of const trait bound didn't regress this code in Rust 2015. +// See also `mbe-const-trait-bound-theoretical-regression.rs`. + +//@ check-pass + +macro_rules! check { + ($ty:ty) => { compile_error!("ty"); }; + (dyn $c:ident) => {}; +} + +check! { dyn const } + +fn main() {} diff --git a/tests/ui/traits/const-traits/mutually-exclusive-trait-bound-modifiers.rs b/tests/ui/traits/const-traits/mutually-exclusive-trait-bound-modifiers.rs new file mode 100644 index 00000000000..aaab8e819a3 --- /dev/null +++ b/tests/ui/traits/const-traits/mutually-exclusive-trait-bound-modifiers.rs @@ -0,0 +1,20 @@ +#![feature(const_trait_impl)] + +const fn maybe_const_maybe<T: ~const ?Sized>() {} +//~^ ERROR `~const` trait not allowed with `?` trait polarity modifier + +fn const_maybe<T: const ?Sized>() {} +//~^ ERROR `const` trait not allowed with `?` trait polarity modifier + +const fn maybe_const_negative<T: ~const !Trait>() {} +//~^ ERROR `~const` trait not allowed with `!` trait polarity modifier +//~| ERROR negative bounds are not supported + +fn const_negative<T: const !Trait>() {} +//~^ ERROR `const` trait not allowed with `!` trait polarity modifier +//~| ERROR negative bounds are not supported + +#[const_trait] +trait Trait {} + +fn main() {} diff --git a/tests/ui/traits/const-traits/mutually-exclusive-trait-bound-modifiers.stderr b/tests/ui/traits/const-traits/mutually-exclusive-trait-bound-modifiers.stderr new file mode 100644 index 00000000000..18e4d160f5f --- /dev/null +++ b/tests/ui/traits/const-traits/mutually-exclusive-trait-bound-modifiers.stderr @@ -0,0 +1,46 @@ +error: `~const` trait not allowed with `?` trait polarity modifier + --> $DIR/mutually-exclusive-trait-bound-modifiers.rs:3:38 + | +LL | const fn maybe_const_maybe<T: ~const ?Sized>() {} + | ------ ^ + | | + | there is not a well-defined meaning for a `~const ?` trait + +error: `const` trait not allowed with `?` trait polarity modifier + --> $DIR/mutually-exclusive-trait-bound-modifiers.rs:6:25 + | +LL | fn const_maybe<T: const ?Sized>() {} + | ----- ^ + | | + | there is not a well-defined meaning for a `const ?` trait + +error: `~const` trait not allowed with `!` trait polarity modifier + --> $DIR/mutually-exclusive-trait-bound-modifiers.rs:9:41 + | +LL | const fn maybe_const_negative<T: ~const !Trait>() {} + | ------ ^ + | | + | there is not a well-defined meaning for a `~const !` trait + +error: `const` trait not allowed with `!` trait polarity modifier + --> $DIR/mutually-exclusive-trait-bound-modifiers.rs:13:28 + | +LL | fn const_negative<T: const !Trait>() {} + | ----- ^ + | | + | there is not a well-defined meaning for a `const !` trait + +error: negative bounds are not supported + --> $DIR/mutually-exclusive-trait-bound-modifiers.rs:9:41 + | +LL | const fn maybe_const_negative<T: ~const !Trait>() {} + | ^ + +error: negative bounds are not supported + --> $DIR/mutually-exclusive-trait-bound-modifiers.rs:13:28 + | +LL | fn const_negative<T: const !Trait>() {} + | ^ + +error: aborting due to 6 previous errors + diff --git a/tests/ui/traits/const-traits/nested-closure.rs b/tests/ui/traits/const-traits/nested-closure.rs new file mode 100644 index 00000000000..7bd372c1695 --- /dev/null +++ b/tests/ui/traits/const-traits/nested-closure.rs @@ -0,0 +1,12 @@ +//@ check-pass + +#![feature(const_trait_impl)] + +use std::sync::LazyLock; + +static EXTERN_FLAGS: LazyLock<String> = LazyLock::new(|| { + let x = || String::new(); + x() +}); + +fn main() {} diff --git a/tests/ui/traits/const-traits/non-const-op-const-closure-non-const-outer.rs b/tests/ui/traits/const-traits/non-const-op-const-closure-non-const-outer.rs new file mode 100644 index 00000000000..cd8bb5963ad --- /dev/null +++ b/tests/ui/traits/const-traits/non-const-op-const-closure-non-const-outer.rs @@ -0,0 +1,15 @@ +#![feature(const_closures, const_trait_impl)] +#![allow(incomplete_features)] + +trait Foo { + fn foo(&self); +} + +impl Foo for () { + fn foo(&self) {} +} + +fn main() { + (const || { (()).foo() })(); + //~^ ERROR: cannot call non-const fn +} diff --git a/tests/ui/traits/const-traits/non-const-op-const-closure-non-const-outer.stderr b/tests/ui/traits/const-traits/non-const-op-const-closure-non-const-outer.stderr new file mode 100644 index 00000000000..c362a1077e3 --- /dev/null +++ b/tests/ui/traits/const-traits/non-const-op-const-closure-non-const-outer.stderr @@ -0,0 +1,15 @@ +error[E0015]: cannot call non-const fn `<() as Foo>::foo` in constant functions + --> $DIR/non-const-op-const-closure-non-const-outer.rs:13:22 + | +LL | (const || { (()).foo() })(); + | ^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants +help: add `#![feature(effects)]` to the crate attributes to enable + | +LL + #![feature(effects)] + | + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/non-const-op-in-closure-in-const.rs b/tests/ui/traits/const-traits/non-const-op-in-closure-in-const.rs new file mode 100644 index 00000000000..8f11c8a6e55 --- /dev/null +++ b/tests/ui/traits/const-traits/non-const-op-in-closure-in-const.rs @@ -0,0 +1,18 @@ +//@ known-bug: #110395 + +#![feature(const_trait_impl)] + +#[const_trait] +trait Convert<T> { + fn to(self) -> T; +} + +impl<A, B> const Convert<B> for A where B: ~const From<A> { + fn to(self) -> B { + B::from(self) + } +} + +const FOO: fn() -> String = || "foo".to(); + +fn main() {} diff --git a/tests/ui/traits/const-traits/non-const-op-in-closure-in-const.stderr b/tests/ui/traits/const-traits/non-const-op-in-closure-in-const.stderr new file mode 100644 index 00000000000..de4783bdb3f --- /dev/null +++ b/tests/ui/traits/const-traits/non-const-op-in-closure-in-const.stderr @@ -0,0 +1,31 @@ +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/non-const-op-in-closure-in-const.rs:10:51 + | +LL | impl<A, B> const Convert<B> for A where B: ~const From<A> { + | ^^^^^^^ + +error[E0049]: method `to` has 1 const parameter but its trait declaration has 0 const parameters + --> $DIR/non-const-op-in-closure-in-const.rs:5:1 + | +LL | #[const_trait] + | ^^^^^^^^^^^^^^ found 1 const parameter +LL | trait Convert<T> { +LL | fn to(self) -> T; + | - expected 0 const parameters + +error[E0015]: cannot call non-const fn `<B as From<A>>::from` in constant functions + --> $DIR/non-const-op-in-closure-in-const.rs:12:9 + | +LL | B::from(self) + | ^^^^^^^^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants +help: add `#![feature(effects)]` to the crate attributes to enable + | +LL + #![feature(effects)] + | + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0015, E0049. +For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/specialization/const-default-bound-non-const-specialized-bound.rs b/tests/ui/traits/const-traits/specialization/const-default-bound-non-const-specialized-bound.rs new file mode 100644 index 00000000000..69dcb403aa9 --- /dev/null +++ b/tests/ui/traits/const-traits/specialization/const-default-bound-non-const-specialized-bound.rs @@ -0,0 +1,56 @@ +// Tests that trait bounds on specializing trait impls must be `~const` if the +// same bound is present on the default impl and is `~const` there. +//@ known-bug: #110395 +// FIXME(effects) ^ should error + +#![feature(const_trait_impl)] +#![feature(rustc_attrs)] +#![feature(min_specialization)] + +#[rustc_specialization_trait] +trait Specialize {} + +#[const_trait] +trait Foo {} + +#[const_trait] +trait Bar { + fn bar(); +} + +impl<T> const Bar for T +where + T: ~const Foo, +{ + default fn bar() {} +} + +impl<T> Bar for T +where + T: Foo, //FIXME ~ ERROR missing `~const` qualifier + T: Specialize, +{ + fn bar() {} +} + +#[const_trait] +trait Baz { + fn baz(); +} + +impl<T> const Baz for T +where + T: ~const Foo, +{ + default fn baz() {} +} + +impl<T> const Baz for T //FIXME ~ ERROR conflicting implementations of trait `Baz` +where + T: Foo, + T: Specialize, +{ + fn baz() {} +} + +fn main() {} diff --git a/tests/ui/traits/const-traits/specialization/const-default-bound-non-const-specialized-bound.stderr b/tests/ui/traits/const-traits/specialization/const-default-bound-non-const-specialized-bound.stderr new file mode 100644 index 00000000000..7643697874f --- /dev/null +++ b/tests/ui/traits/const-traits/specialization/const-default-bound-non-const-specialized-bound.stderr @@ -0,0 +1,41 @@ +error[E0049]: associated function `bar` has 1 const parameter but its trait declaration has 0 const parameters + --> $DIR/const-default-bound-non-const-specialized-bound.rs:16:1 + | +LL | #[const_trait] + | ^^^^^^^^^^^^^^ found 1 const parameter +LL | trait Bar { +LL | fn bar(); + | - expected 0 const parameters + +error: cannot specialize on const impl with non-const impl + --> $DIR/const-default-bound-non-const-specialized-bound.rs:28:1 + | +LL | / impl<T> Bar for T +LL | | where +LL | | T: Foo, //FIXME ~ ERROR missing `~const` qualifier +LL | | T: Specialize, + | |__________________^ + +error[E0049]: associated function `baz` has 1 const parameter but its trait declaration has 0 const parameters + --> $DIR/const-default-bound-non-const-specialized-bound.rs:36:1 + | +LL | #[const_trait] + | ^^^^^^^^^^^^^^ found 1 const parameter +LL | trait Baz { +LL | fn baz(); + | - expected 0 const parameters + +error[E0049]: associated function `baz` has 1 const parameter but its trait declaration has 0 const parameters + --> $DIR/const-default-bound-non-const-specialized-bound.rs:36:1 + | +LL | #[const_trait] + | ^^^^^^^^^^^^^^ found 1 const parameter +LL | trait Baz { +LL | fn baz(); + | - expected 0 const parameters + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0049`. diff --git a/tests/ui/traits/const-traits/specialization/const-default-const-specialized.rs b/tests/ui/traits/const-traits/specialization/const-default-const-specialized.rs new file mode 100644 index 00000000000..a48a50b9e5c --- /dev/null +++ b/tests/ui/traits/const-traits/specialization/const-default-const-specialized.rs @@ -0,0 +1,40 @@ +// Tests that a const default trait impl can be specialized by another const +// trait impl and that the specializing impl will be used during const-eval. + +//@ known-bug: #110395 +// FIXME(effects) run-pass + +#![feature(const_trait_impl)] +#![feature(min_specialization)] + +#[const_trait] +trait Value { + fn value() -> u32; +} + +const fn get_value<T: ~const Value>() -> u32 { + T::value() +} + +impl<T> const Value for T { + default fn value() -> u32 { + 0 + } +} + +struct FortyTwo; + +impl const Value for FortyTwo { + fn value() -> u32 { + 42 + } +} + +const ZERO: u32 = get_value::<()>(); + +const FORTY_TWO: u32 = get_value::<FortyTwo>(); + +fn main() { + assert_eq!(ZERO, 0); + assert_eq!(FORTY_TWO, 42); +} diff --git a/tests/ui/traits/const-traits/specialization/const-default-const-specialized.stderr b/tests/ui/traits/const-traits/specialization/const-default-const-specialized.stderr new file mode 100644 index 00000000000..9b2ae8d739c --- /dev/null +++ b/tests/ui/traits/const-traits/specialization/const-default-const-specialized.stderr @@ -0,0 +1,36 @@ +error[E0049]: associated function `value` has 1 const parameter but its trait declaration has 0 const parameters + --> $DIR/const-default-const-specialized.rs:10:1 + | +LL | #[const_trait] + | ^^^^^^^^^^^^^^ found 1 const parameter +LL | trait Value { +LL | fn value() -> u32; + | - expected 0 const parameters + +error[E0049]: associated function `value` has 1 const parameter but its trait declaration has 0 const parameters + --> $DIR/const-default-const-specialized.rs:10:1 + | +LL | #[const_trait] + | ^^^^^^^^^^^^^^ found 1 const parameter +LL | trait Value { +LL | fn value() -> u32; + | - expected 0 const parameters + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0015]: cannot call non-const fn `<T as Value>::value` in constant functions + --> $DIR/const-default-const-specialized.rs:16:5 + | +LL | T::value() + | ^^^^^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants +help: add `#![feature(effects)]` to the crate attributes to enable + | +LL + #![feature(effects)] + | + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0015, E0049. +For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.rs b/tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.rs new file mode 100644 index 00000000000..40fc3b17ae4 --- /dev/null +++ b/tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.rs @@ -0,0 +1,26 @@ +// Tests that specializing trait impls must be at least as const as the default impl. + +#![feature(const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete +#![feature(min_specialization)] + +#[const_trait] +trait Value { + fn value() -> u32; +} + +impl<T> const Value for T { + default fn value() -> u32 { + 0 + } +} + +struct FortyTwo; + +impl Value for FortyTwo { //~ ERROR cannot specialize on const impl with non-const impl + fn value() -> u32 { + println!("You can't do that (constly)"); + 42 + } +} + +fn main() {} diff --git a/tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.stderr b/tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.stderr new file mode 100644 index 00000000000..c51d169dd33 --- /dev/null +++ b/tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.stderr @@ -0,0 +1,22 @@ +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/const-default-impl-non-const-specialized-impl.rs:3:30 + | +LL | #![feature(const_trait_impl, effects)] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + +error: using `#![feature(effects)]` without enabling next trait solver globally + | + = note: the next trait solver must be enabled globally for the effects feature to work correctly + = help: use `-Znext-solver` to enable + +error: cannot specialize on const impl with non-const impl + --> $DIR/const-default-impl-non-const-specialized-impl.rs:19:1 + | +LL | impl Value for FortyTwo { + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors; 1 warning emitted + diff --git a/tests/ui/traits/const-traits/specialization/default-keyword.rs b/tests/ui/traits/const-traits/specialization/default-keyword.rs new file mode 100644 index 00000000000..d9ffd237dce --- /dev/null +++ b/tests/ui/traits/const-traits/specialization/default-keyword.rs @@ -0,0 +1,16 @@ +//@ known-bug: #110395 +// FIXME check-pass + +#![feature(const_trait_impl)] +#![feature(min_specialization)] + +#[const_trait] +trait Foo { + fn foo(); +} + +impl const Foo for u32 { + default fn foo() {} +} + +fn main() {} diff --git a/tests/ui/traits/const-traits/specialization/default-keyword.stderr b/tests/ui/traits/const-traits/specialization/default-keyword.stderr new file mode 100644 index 00000000000..18a25045f4b --- /dev/null +++ b/tests/ui/traits/const-traits/specialization/default-keyword.stderr @@ -0,0 +1,12 @@ +error[E0049]: associated function `foo` has 1 const parameter but its trait declaration has 0 const parameters + --> $DIR/default-keyword.rs:7:1 + | +LL | #[const_trait] + | ^^^^^^^^^^^^^^ found 1 const parameter +LL | trait Foo { +LL | fn foo(); + | - expected 0 const parameters + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0049`. diff --git a/tests/ui/traits/const-traits/specialization/issue-95186-specialize-on-tilde-const.rs b/tests/ui/traits/const-traits/specialization/issue-95186-specialize-on-tilde-const.rs new file mode 100644 index 00000000000..219e5f3a600 --- /dev/null +++ b/tests/ui/traits/const-traits/specialization/issue-95186-specialize-on-tilde-const.rs @@ -0,0 +1,50 @@ +// Tests that `~const` trait bounds can be used to specialize const trait impls. + +//@ known-bug: #110395 +// FIXME check-pass + +#![feature(const_trait_impl)] +#![feature(rustc_attrs)] +#![feature(min_specialization)] + +#[const_trait] +#[rustc_specialization_trait] +trait Specialize {} + +#[const_trait] +trait Foo { + fn foo(); +} + +impl<T> const Foo for T { + default fn foo() {} +} + +impl<T> const Foo for T +where + T: ~const Specialize, +{ + fn foo() {} +} + +#[const_trait] +trait Bar { + fn bar() {} +} + +impl<T> const Bar for T +where + T: ~const Foo, +{ + default fn bar() {} +} + +impl<T> const Bar for T +where + T: ~const Foo, + T: ~const Specialize, +{ + fn bar() {} +} + +fn main() {} diff --git a/tests/ui/traits/const-traits/specialization/issue-95186-specialize-on-tilde-const.stderr b/tests/ui/traits/const-traits/specialization/issue-95186-specialize-on-tilde-const.stderr new file mode 100644 index 00000000000..ecdc7b930e6 --- /dev/null +++ b/tests/ui/traits/const-traits/specialization/issue-95186-specialize-on-tilde-const.stderr @@ -0,0 +1,43 @@ +error[E0049]: associated function `foo` has 1 const parameter but its trait declaration has 0 const parameters + --> $DIR/issue-95186-specialize-on-tilde-const.rs:14:1 + | +LL | #[const_trait] + | ^^^^^^^^^^^^^^ found 1 const parameter +LL | trait Foo { +LL | fn foo(); + | - expected 0 const parameters + +error[E0049]: associated function `foo` has 1 const parameter but its trait declaration has 0 const parameters + --> $DIR/issue-95186-specialize-on-tilde-const.rs:14:1 + | +LL | #[const_trait] + | ^^^^^^^^^^^^^^ found 1 const parameter +LL | trait Foo { +LL | fn foo(); + | - expected 0 const parameters + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0049]: associated function `bar` has 1 const parameter but its trait declaration has 0 const parameters + --> $DIR/issue-95186-specialize-on-tilde-const.rs:30:1 + | +LL | #[const_trait] + | ^^^^^^^^^^^^^^ found 1 const parameter +LL | trait Bar { +LL | fn bar() {} + | - expected 0 const parameters + +error[E0049]: associated function `bar` has 1 const parameter but its trait declaration has 0 const parameters + --> $DIR/issue-95186-specialize-on-tilde-const.rs:30:1 + | +LL | #[const_trait] + | ^^^^^^^^^^^^^^ found 1 const parameter +LL | trait Bar { +LL | fn bar() {} + | - expected 0 const parameters + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0049`. diff --git a/tests/ui/traits/const-traits/specialization/issue-95187-same-trait-bound-different-constness.rs b/tests/ui/traits/const-traits/specialization/issue-95187-same-trait-bound-different-constness.rs new file mode 100644 index 00000000000..7514baa2fd5 --- /dev/null +++ b/tests/ui/traits/const-traits/specialization/issue-95187-same-trait-bound-different-constness.rs @@ -0,0 +1,58 @@ +// Tests that `T: ~const Foo` in a specializing impl is treated as equivalent to +// `T: Foo` in the default impl for the purposes of specialization (i.e., it +// does not think that the user is attempting to specialize on trait `Foo`). + +//@ known-bug: #110395 +// FIXME check-pass + +#![feature(rustc_attrs)] +#![feature(min_specialization)] +#![feature(const_trait_impl)] + +#[rustc_specialization_trait] +trait Specialize {} + +#[const_trait] +trait Foo {} + +#[const_trait] +trait Bar { + fn bar(); +} + +impl<T> Bar for T +where + T: Foo, +{ + default fn bar() {} +} + +impl<T> const Bar for T +where + T: ~const Foo, + T: Specialize, +{ + fn bar() {} +} + +#[const_trait] +trait Baz { + fn baz(); +} + +impl<T> const Baz for T +where + T: Foo, +{ + default fn baz() {} +} + +impl<T> const Baz for T +where + T: ~const Foo, + T: Specialize, +{ + fn baz() {} +} + +fn main() {} diff --git a/tests/ui/traits/const-traits/specialization/issue-95187-same-trait-bound-different-constness.stderr b/tests/ui/traits/const-traits/specialization/issue-95187-same-trait-bound-different-constness.stderr new file mode 100644 index 00000000000..6679bb46537 --- /dev/null +++ b/tests/ui/traits/const-traits/specialization/issue-95187-same-trait-bound-different-constness.stderr @@ -0,0 +1,43 @@ +error[E0049]: associated function `bar` has 1 const parameter but its trait declaration has 0 const parameters + --> $DIR/issue-95187-same-trait-bound-different-constness.rs:18:1 + | +LL | #[const_trait] + | ^^^^^^^^^^^^^^ found 1 const parameter +LL | trait Bar { +LL | fn bar(); + | - expected 0 const parameters + +error[E0049]: associated function `bar` has 1 const parameter but its trait declaration has 0 const parameters + --> $DIR/issue-95187-same-trait-bound-different-constness.rs:18:1 + | +LL | #[const_trait] + | ^^^^^^^^^^^^^^ found 1 const parameter +LL | trait Bar { +LL | fn bar(); + | - expected 0 const parameters + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0049]: associated function `baz` has 1 const parameter but its trait declaration has 0 const parameters + --> $DIR/issue-95187-same-trait-bound-different-constness.rs:38:1 + | +LL | #[const_trait] + | ^^^^^^^^^^^^^^ found 1 const parameter +LL | trait Baz { +LL | fn baz(); + | - expected 0 const parameters + +error[E0049]: associated function `baz` has 1 const parameter but its trait declaration has 0 const parameters + --> $DIR/issue-95187-same-trait-bound-different-constness.rs:38:1 + | +LL | #[const_trait] + | ^^^^^^^^^^^^^^ found 1 const parameter +LL | trait Baz { +LL | fn baz(); + | - expected 0 const parameters + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0049`. diff --git a/tests/ui/traits/const-traits/specialization/non-const-default-const-specialized.rs b/tests/ui/traits/const-traits/specialization/non-const-default-const-specialized.rs new file mode 100644 index 00000000000..912b35095f9 --- /dev/null +++ b/tests/ui/traits/const-traits/specialization/non-const-default-const-specialized.rs @@ -0,0 +1,39 @@ +// Tests that a non-const default impl can be specialized by a const trait impl, +// but that the default impl cannot be used in a const context. +//@ known-bug: #110395 +// FIXME(effects) run-pass + +#![feature(const_trait_impl)] +#![feature(min_specialization)] + +#[const_trait] +trait Value { + fn value() -> u32; +} + +const fn get_value<T: ~const Value>() -> u32 { + T::value() +} + +impl<T> Value for T { + default fn value() -> u32 { + println!("You can't do that (constly)"); + 0 + } +} + +struct FortyTwo; + +impl const Value for FortyTwo { + fn value() -> u32 { + 42 + } +} + +fn main() { + let zero = get_value::<()>(); + assert_eq!(zero, 0); + + const FORTY_TWO: u32 = get_value::<FortyTwo>(); + assert_eq!(FORTY_TWO, 42); +} diff --git a/tests/ui/traits/const-traits/specialization/non-const-default-const-specialized.stderr b/tests/ui/traits/const-traits/specialization/non-const-default-const-specialized.stderr new file mode 100644 index 00000000000..7f363922947 --- /dev/null +++ b/tests/ui/traits/const-traits/specialization/non-const-default-const-specialized.stderr @@ -0,0 +1,36 @@ +error[E0049]: associated function `value` has 1 const parameter but its trait declaration has 0 const parameters + --> $DIR/non-const-default-const-specialized.rs:9:1 + | +LL | #[const_trait] + | ^^^^^^^^^^^^^^ found 1 const parameter +LL | trait Value { +LL | fn value() -> u32; + | - expected 0 const parameters + +error[E0049]: associated function `value` has 1 const parameter but its trait declaration has 0 const parameters + --> $DIR/non-const-default-const-specialized.rs:9:1 + | +LL | #[const_trait] + | ^^^^^^^^^^^^^^ found 1 const parameter +LL | trait Value { +LL | fn value() -> u32; + | - expected 0 const parameters + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0015]: cannot call non-const fn `<T as Value>::value` in constant functions + --> $DIR/non-const-default-const-specialized.rs:15:5 + | +LL | T::value() + | ^^^^^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants +help: add `#![feature(effects)]` to the crate attributes to enable + | +LL + #![feature(effects)] + | + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0015, E0049. +For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/specializing-constness-2.rs b/tests/ui/traits/const-traits/specializing-constness-2.rs new file mode 100644 index 00000000000..c1fe42b9751 --- /dev/null +++ b/tests/ui/traits/const-traits/specializing-constness-2.rs @@ -0,0 +1,31 @@ +#![feature(const_trait_impl, min_specialization, rustc_attrs)] +//@ known-bug: #110395 +#[rustc_specialization_trait] +#[const_trait] +pub trait Sup {} + +impl const Sup for () {} + +#[const_trait] +pub trait A { + fn a() -> u32; +} + +impl<T: Default> A for T { + default fn a() -> u32 { + 2 + } +} + +impl<T: Default + ~const Sup> const A for T { + fn a() -> u32 { + 3 + } +} + +const fn generic<T: Default>() { + <T as A>::a(); + //FIXME ~^ ERROR: the trait bound `T: ~const Sup` is not satisfied +} + +fn main() {} diff --git a/tests/ui/traits/const-traits/specializing-constness-2.stderr b/tests/ui/traits/const-traits/specializing-constness-2.stderr new file mode 100644 index 00000000000..bf273f349b4 --- /dev/null +++ b/tests/ui/traits/const-traits/specializing-constness-2.stderr @@ -0,0 +1,36 @@ +error[E0049]: associated function `a` has 1 const parameter but its trait declaration has 0 const parameters + --> $DIR/specializing-constness-2.rs:9:1 + | +LL | #[const_trait] + | ^^^^^^^^^^^^^^ found 1 const parameter +LL | pub trait A { +LL | fn a() -> u32; + | - expected 0 const parameters + +error[E0049]: associated function `a` has 1 const parameter but its trait declaration has 0 const parameters + --> $DIR/specializing-constness-2.rs:9:1 + | +LL | #[const_trait] + | ^^^^^^^^^^^^^^ found 1 const parameter +LL | pub trait A { +LL | fn a() -> u32; + | - expected 0 const parameters + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0015]: cannot call non-const fn `<T as A>::a` in constant functions + --> $DIR/specializing-constness-2.rs:27:5 + | +LL | <T as A>::a(); + | ^^^^^^^^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants +help: add `#![feature(effects)]` to the crate attributes to enable + | +LL + #![feature(effects)] + | + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0015, E0049. +For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/specializing-constness.rs b/tests/ui/traits/const-traits/specializing-constness.rs new file mode 100644 index 00000000000..4501a218ad7 --- /dev/null +++ b/tests/ui/traits/const-traits/specializing-constness.rs @@ -0,0 +1,33 @@ +#![feature(const_trait_impl, effects, min_specialization, rustc_attrs)] //~ WARN the feature `effects` is incomplete + +#[rustc_specialization_trait] +#[const_trait] +pub trait Sup {} + +impl const Sup for () {} + +#[const_trait] +pub trait A { + fn a() -> u32; +} + +#[const_trait] +pub trait Spec {} + +impl<T: ~const Spec> const A for T { + default fn a() -> u32 { + 2 + } +} + +impl<T: Spec + Sup> A for T { +//~^ ERROR: cannot specialize +//~| ERROR: cannot specialize +//~| ERROR: cannot specialize +//FIXME(effects) ~| ERROR: missing `~const` qualifier + fn a() -> u32 { + 3 + } +} + +fn main() {} diff --git a/tests/ui/traits/const-traits/specializing-constness.stderr b/tests/ui/traits/const-traits/specializing-constness.stderr new file mode 100644 index 00000000000..90721af8e5a --- /dev/null +++ b/tests/ui/traits/const-traits/specializing-constness.stderr @@ -0,0 +1,34 @@ +warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/specializing-constness.rs:1:30 + | +LL | #![feature(const_trait_impl, effects, min_specialization, rustc_attrs)] + | ^^^^^^^ + | + = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information + = note: `#[warn(incomplete_features)]` on by default + +error: using `#![feature(effects)]` without enabling next trait solver globally + | + = note: the next trait solver must be enabled globally for the effects feature to work correctly + = help: use `-Znext-solver` to enable + +error: cannot specialize on const impl with non-const impl + --> $DIR/specializing-constness.rs:23:1 + | +LL | impl<T: Spec + Sup> A for T { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: cannot specialize on trait `Compat` + --> $DIR/specializing-constness.rs:23:16 + | +LL | impl<T: Spec + Sup> A for T { + | ^^^ + +error: cannot specialize on trait `Compat` + --> $DIR/specializing-constness.rs:23:9 + | +LL | impl<T: Spec + Sup> A for T { + | ^^^^ + +error: aborting due to 4 previous errors; 1 warning emitted + diff --git a/tests/ui/traits/const-traits/staged-api-user-crate.rs b/tests/ui/traits/const-traits/staged-api-user-crate.rs new file mode 100644 index 00000000000..c4ecb8f67a1 --- /dev/null +++ b/tests/ui/traits/const-traits/staged-api-user-crate.rs @@ -0,0 +1,16 @@ +//@ aux-build: staged-api.rs +extern crate staged_api; + +use staged_api::*; + +// Const stability has no impact on usage in non-const contexts. +fn non_const_context() { + Unstable::func(); +} + +const fn stable_const_context() { + Unstable::func(); + //~^ ERROR cannot call non-const fn `<staged_api::Unstable as staged_api::MyTrait>::func` in constant functions +} + +fn main() {} diff --git a/tests/ui/traits/const-traits/staged-api-user-crate.stderr b/tests/ui/traits/const-traits/staged-api-user-crate.stderr new file mode 100644 index 00000000000..781191ec97c --- /dev/null +++ b/tests/ui/traits/const-traits/staged-api-user-crate.stderr @@ -0,0 +1,15 @@ +error[E0015]: cannot call non-const fn `<staged_api::Unstable as staged_api::MyTrait>::func` in constant functions + --> $DIR/staged-api-user-crate.rs:12:5 + | +LL | Unstable::func(); + | ^^^^^^^^^^^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants +help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + | +LL + #![feature(const_trait_impl)] + | + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/staged-api.rs b/tests/ui/traits/const-traits/staged-api.rs new file mode 100644 index 00000000000..f87e723472a --- /dev/null +++ b/tests/ui/traits/const-traits/staged-api.rs @@ -0,0 +1,63 @@ +//@ revisions: stable unstable +//@ compile-flags: -Znext-solver + +#![cfg_attr(unstable, feature(unstable))] // The feature from the ./auxiliary/staged-api.rs file. +#![feature(const_trait_impl, effects)] +#![allow(incomplete_features)] +#![feature(staged_api)] +#![stable(feature = "rust1", since = "1.0.0")] + +//@ aux-build: staged-api.rs +extern crate staged_api; + +use staged_api::*; + +#[stable(feature = "rust1", since = "1.0.0")] +pub struct Foo; + +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(unstable, rustc_const_unstable(feature = "foo", issue = "none"))] +#[cfg_attr(stable, rustc_const_stable(feature = "foo", since = "1.0.0"))] +impl const MyTrait for Foo { + //[stable]~^ ERROR trait implementations cannot be const stable yet + fn func() {} +} + +// Const stability has no impact on usage in non-const contexts. +fn non_const_context() { + Unstable::func(); + Foo::func(); +} + +#[unstable(feature = "none", issue = "none")] +const fn const_context() { + Unstable::func(); + //[stable]~^ ERROR not yet stable as a const fn + Foo::func(); + //[unstable]~^ ERROR not yet stable as a const fn + // ^ fails, because the `foo` feature is not active +} + +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(unstable, rustc_const_unstable(feature = "foo", issue = "none"))] +pub const fn const_context_not_const_stable() { + //[stable]~^ ERROR function has missing const stability attribute + Unstable::func(); + //[stable]~^ ERROR not yet stable as a const fn + Foo::func(); + //[unstable]~^ ERROR not yet stable as a const fn + // ^ fails, because the `foo` feature is not active +} + +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_const_stable(feature = "cheese", since = "1.0.0")] +const fn stable_const_context() { + Unstable::func(); + //~^ ERROR not yet stable as a const fn + Foo::func(); + //[unstable]~^ ERROR not yet stable as a const fn + const_context_not_const_stable() + //[unstable]~^ ERROR not yet stable as a const fn +} + +fn main() {} diff --git a/tests/ui/traits/const-traits/staged-api.stable.stderr b/tests/ui/traits/const-traits/staged-api.stable.stderr new file mode 100644 index 00000000000..6c07a253f5b --- /dev/null +++ b/tests/ui/traits/const-traits/staged-api.stable.stderr @@ -0,0 +1,49 @@ +error: trait implementations cannot be const stable yet + --> $DIR/staged-api.rs:21:1 + | +LL | / impl const MyTrait for Foo { +LL | | +LL | | fn func() {} +LL | | } + | |_^ + | + = note: see issue #67792 <https://github.com/rust-lang/rust/issues/67792> for more information + +error: function has missing const stability attribute + --> $DIR/staged-api.rs:43:1 + | +LL | / pub const fn const_context_not_const_stable() { +LL | | +LL | | Unstable::func(); +LL | | +... | +LL | | // ^ fails, because the `foo` feature is not active +LL | | } + | |_^ + +error: `<staged_api::Unstable as staged_api::MyTrait>::func` is not yet stable as a const fn + --> $DIR/staged-api.rs:34:5 + | +LL | Unstable::func(); + | ^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable)]` to the crate attributes to enable + +error: `<staged_api::Unstable as staged_api::MyTrait>::func` is not yet stable as a const fn + --> $DIR/staged-api.rs:45:5 + | +LL | Unstable::func(); + | ^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable)]` to the crate attributes to enable + +error: `<staged_api::Unstable as staged_api::MyTrait>::func` is not yet stable as a const fn + --> $DIR/staged-api.rs:55:5 + | +LL | Unstable::func(); + | ^^^^^^^^^^^^^^^^ + | + = help: const-stable functions can only call other const-stable functions + +error: aborting due to 5 previous errors + diff --git a/tests/ui/traits/const-traits/staged-api.unstable.stderr b/tests/ui/traits/const-traits/staged-api.unstable.stderr new file mode 100644 index 00000000000..1c772f13dd5 --- /dev/null +++ b/tests/ui/traits/const-traits/staged-api.unstable.stderr @@ -0,0 +1,42 @@ +error: `<Foo as staged_api::MyTrait>::func` is not yet stable as a const fn + --> $DIR/staged-api.rs:36:5 + | +LL | Foo::func(); + | ^^^^^^^^^^^ + | + = help: add `#![feature(foo)]` to the crate attributes to enable + +error: `<Foo as staged_api::MyTrait>::func` is not yet stable as a const fn + --> $DIR/staged-api.rs:47:5 + | +LL | Foo::func(); + | ^^^^^^^^^^^ + | + = help: add `#![feature(foo)]` to the crate attributes to enable + +error: `<staged_api::Unstable as staged_api::MyTrait>::func` is not yet stable as a const fn + --> $DIR/staged-api.rs:55:5 + | +LL | Unstable::func(); + | ^^^^^^^^^^^^^^^^ + | + = help: const-stable functions can only call other const-stable functions + +error: `<Foo as staged_api::MyTrait>::func` is not yet stable as a const fn + --> $DIR/staged-api.rs:57:5 + | +LL | Foo::func(); + | ^^^^^^^^^^^ + | + = help: const-stable functions can only call other const-stable functions + +error: `const_context_not_const_stable` is not yet stable as a const fn + --> $DIR/staged-api.rs:59:5 + | +LL | const_context_not_const_stable() + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: const-stable functions can only call other const-stable functions + +error: aborting due to 5 previous errors + diff --git a/tests/ui/traits/const-traits/static-const-trait-bound.rs b/tests/ui/traits/const-traits/static-const-trait-bound.rs new file mode 100644 index 00000000000..062067f8e85 --- /dev/null +++ b/tests/ui/traits/const-traits/static-const-trait-bound.rs @@ -0,0 +1,18 @@ +//@ check-pass +pub struct S<T, F: FnOnce() -> T = fn() -> T> { + f: F, + x: Option<T>, +} + +impl<T, F: FnOnce() -> T> S<T, F> { + pub const fn new(f: F) -> Self { + Self { f, x: None } + } +} + +#[derive(Default)] +pub struct Foo; + +static LOCKED_CALLSITES: S<Foo> = S::new(Default::default); + +fn main() {} diff --git a/tests/ui/traits/const-traits/std-impl-gate.gated.stderr b/tests/ui/traits/const-traits/std-impl-gate.gated.stderr new file mode 100644 index 00000000000..d761fdce4bf --- /dev/null +++ b/tests/ui/traits/const-traits/std-impl-gate.gated.stderr @@ -0,0 +1,22 @@ +error[E0635]: unknown feature `const_default_impls` + --> $DIR/std-impl-gate.rs:6:46 + | +LL | #![cfg_attr(gated, feature(const_trait_impl, const_default_impls))] + | ^^^^^^^^^^^^^^^^^^^ + +error[E0015]: cannot call non-const fn `<Vec<usize> as Default>::default` in constant functions + --> $DIR/std-impl-gate.rs:13:5 + | +LL | Default::default() + | ^^^^^^^^^^^^^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants +help: add `#![feature(effects)]` to the crate attributes to enable + | +LL + #![feature(effects)] + | + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0015, E0635. +For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/std-impl-gate.rs b/tests/ui/traits/const-traits/std-impl-gate.rs new file mode 100644 index 00000000000..a9e2ff06290 --- /dev/null +++ b/tests/ui/traits/const-traits/std-impl-gate.rs @@ -0,0 +1,21 @@ +// This tests feature gates for const impls in the standard library. + +//@ revisions: stock gated +//@[gated] known-bug: #110395 + +#![cfg_attr(gated, feature(const_trait_impl, const_default_impls))] + +fn non_const_context() -> Vec<usize> { + Default::default() +} + +const fn const_context() -> Vec<usize> { + Default::default() + //[stock]~^ ERROR cannot call non-const fn +} + +fn main() { + const VAL: Vec<usize> = const_context(); + + assert_eq!(VAL, non_const_context()); +} diff --git a/tests/ui/traits/const-traits/std-impl-gate.stock.stderr b/tests/ui/traits/const-traits/std-impl-gate.stock.stderr new file mode 100644 index 00000000000..b63ea695fc2 --- /dev/null +++ b/tests/ui/traits/const-traits/std-impl-gate.stock.stderr @@ -0,0 +1,15 @@ +error[E0015]: cannot call non-const fn `<Vec<usize> as Default>::default` in constant functions + --> $DIR/std-impl-gate.rs:13:5 + | +LL | Default::default() + | ^^^^^^^^^^^^^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants +help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + | +LL + #![feature(const_trait_impl)] + | + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/super-traits-fail-2.nn.stderr b/tests/ui/traits/const-traits/super-traits-fail-2.nn.stderr new file mode 100644 index 00000000000..48bb1907be2 --- /dev/null +++ b/tests/ui/traits/const-traits/super-traits-fail-2.nn.stderr @@ -0,0 +1,36 @@ +error: `~const` is not allowed here + --> $DIR/super-traits-fail-2.rs:12:12 + | +LL | trait Bar: ~const Foo {} + | ^^^^^^ + | +note: this trait is not a `#[const_trait]`, so it cannot have `~const` trait bounds + --> $DIR/super-traits-fail-2.rs:12:1 + | +LL | trait Bar: ~const Foo {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/super-traits-fail-2.rs:12:19 + | +LL | trait Bar: ~const Foo {} + | ^^^ + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/super-traits-fail-2.rs:12:19 + | +LL | trait Bar: ~const Foo {} + | ^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/super-traits-fail-2.rs:12:19 + | +LL | trait Bar: ~const Foo {} + | ^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 4 previous errors + diff --git a/tests/ui/traits/const-traits/super-traits-fail-2.ny.stderr b/tests/ui/traits/const-traits/super-traits-fail-2.ny.stderr new file mode 100644 index 00000000000..029c3b4bde3 --- /dev/null +++ b/tests/ui/traits/const-traits/super-traits-fail-2.ny.stderr @@ -0,0 +1,24 @@ +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/super-traits-fail-2.rs:12:19 + | +LL | trait Bar: ~const Foo {} + | ^^^ + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/super-traits-fail-2.rs:12:19 + | +LL | trait Bar: ~const Foo {} + | ^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/super-traits-fail-2.rs:12:19 + | +LL | trait Bar: ~const Foo {} + | ^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 3 previous errors + diff --git a/tests/ui/traits/const-traits/super-traits-fail-2.rs b/tests/ui/traits/const-traits/super-traits-fail-2.rs new file mode 100644 index 00000000000..93a6f385e47 --- /dev/null +++ b/tests/ui/traits/const-traits/super-traits-fail-2.rs @@ -0,0 +1,23 @@ +//@ compile-flags: -Znext-solver +#![allow(incomplete_features)] +#![feature(const_trait_impl, effects)] +//@ revisions: yy yn ny nn + +#[cfg_attr(any(yy, yn), const_trait)] +trait Foo { + fn a(&self); +} + +#[cfg_attr(any(yy, ny), const_trait)] +trait Bar: ~const Foo {} +//[ny,nn]~^ ERROR: `~const` can only be applied to `#[const_trait]` +//[ny,nn]~| ERROR: `~const` can only be applied to `#[const_trait]` +//[ny,nn]~| ERROR: `~const` can only be applied to `#[const_trait]` +//[yn,nn]~^^^^ ERROR: `~const` is not allowed here + +const fn foo<T: Bar>(x: &T) { + x.a(); + //[yy,yn]~^ ERROR the trait bound `T: ~const Foo` +} + +fn main() {} diff --git a/tests/ui/traits/const-traits/super-traits-fail-2.yn.stderr b/tests/ui/traits/const-traits/super-traits-fail-2.yn.stderr new file mode 100644 index 00000000000..873c57ec71f --- /dev/null +++ b/tests/ui/traits/const-traits/super-traits-fail-2.yn.stderr @@ -0,0 +1,34 @@ +error: `~const` is not allowed here + --> $DIR/super-traits-fail-2.rs:12:12 + | +LL | trait Bar: ~const Foo {} + | ^^^^^^ + | +note: this trait is not a `#[const_trait]`, so it cannot have `~const` trait bounds + --> $DIR/super-traits-fail-2.rs:12:1 + | +LL | trait Bar: ~const Foo {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0277]: the trait bound `T: ~const Foo` is not satisfied + --> $DIR/super-traits-fail-2.rs:19:7 + | +LL | x.a(); + | ^ the trait `Foo` is not implemented for `T` + | +note: required by a bound in `Foo::a` + --> $DIR/super-traits-fail-2.rs:6:25 + | +LL | #[cfg_attr(any(yy, yn), const_trait)] + | ^^^^^^^^^^^ required by this bound in `Foo::a` +LL | trait Foo { +LL | fn a(&self); + | - required by a bound in this associated function +help: consider further restricting this bound + | +LL | const fn foo<T: Bar + Foo>(x: &T) { + | +++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/const-traits/super-traits-fail-2.yy.stderr b/tests/ui/traits/const-traits/super-traits-fail-2.yy.stderr new file mode 100644 index 00000000000..bea3aea2f3a --- /dev/null +++ b/tests/ui/traits/const-traits/super-traits-fail-2.yy.stderr @@ -0,0 +1,22 @@ +error[E0277]: the trait bound `T: ~const Foo` is not satisfied + --> $DIR/super-traits-fail-2.rs:19:7 + | +LL | x.a(); + | ^ the trait `Foo` is not implemented for `T` + | +note: required by a bound in `Foo::a` + --> $DIR/super-traits-fail-2.rs:6:25 + | +LL | #[cfg_attr(any(yy, yn), const_trait)] + | ^^^^^^^^^^^ required by this bound in `Foo::a` +LL | trait Foo { +LL | fn a(&self); + | - required by a bound in this associated function +help: consider further restricting this bound + | +LL | const fn foo<T: Bar + Foo>(x: &T) { + | +++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/const-traits/super-traits-fail-3.nn.stderr b/tests/ui/traits/const-traits/super-traits-fail-3.nn.stderr new file mode 100644 index 00000000000..f40583f0ca5 --- /dev/null +++ b/tests/ui/traits/const-traits/super-traits-fail-3.nn.stderr @@ -0,0 +1,42 @@ +error: `~const` is not allowed here + --> $DIR/super-traits-fail-3.rs:14:12 + | +LL | trait Bar: ~const Foo {} + | ^^^^^^ + | +note: this trait is not a `#[const_trait]`, so it cannot have `~const` trait bounds + --> $DIR/super-traits-fail-3.rs:14:1 + | +LL | trait Bar: ~const Foo {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/super-traits-fail-3.rs:14:19 + | +LL | trait Bar: ~const Foo {} + | ^^^ + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/super-traits-fail-3.rs:14:19 + | +LL | trait Bar: ~const Foo {} + | ^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/super-traits-fail-3.rs:14:19 + | +LL | trait Bar: ~const Foo {} + | ^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/super-traits-fail-3.rs:20:24 + | +LL | const fn foo<T: ~const Bar>(x: &T) { + | ^^^ + +error: aborting due to 5 previous errors + diff --git a/tests/ui/traits/const-traits/super-traits-fail-3.ny.stderr b/tests/ui/traits/const-traits/super-traits-fail-3.ny.stderr new file mode 100644 index 00000000000..3f6dfa7b008 --- /dev/null +++ b/tests/ui/traits/const-traits/super-traits-fail-3.ny.stderr @@ -0,0 +1,24 @@ +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/super-traits-fail-3.rs:14:19 + | +LL | trait Bar: ~const Foo {} + | ^^^ + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/super-traits-fail-3.rs:14:19 + | +LL | trait Bar: ~const Foo {} + | ^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/super-traits-fail-3.rs:14:19 + | +LL | trait Bar: ~const Foo {} + | ^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 3 previous errors + diff --git a/tests/ui/traits/const-traits/super-traits-fail-3.rs b/tests/ui/traits/const-traits/super-traits-fail-3.rs new file mode 100644 index 00000000000..b5643b11700 --- /dev/null +++ b/tests/ui/traits/const-traits/super-traits-fail-3.rs @@ -0,0 +1,26 @@ +//@ compile-flags: -Znext-solver +#![allow(incomplete_features)] +#![feature(const_trait_impl, effects)] + +//@ revisions: yy yn ny nn +//@[yy] check-pass + +#[cfg_attr(any(yy, yn), const_trait)] +trait Foo { + fn a(&self); +} + +#[cfg_attr(any(yy, ny), const_trait)] +trait Bar: ~const Foo {} +//[ny,nn]~^ ERROR: `~const` can only be applied to `#[const_trait]` +//[ny,nn]~| ERROR: `~const` can only be applied to `#[const_trait]` +//[ny,nn]~| ERROR: `~const` can only be applied to `#[const_trait]` +//[yn,nn]~^^^^ ERROR: `~const` is not allowed here + +const fn foo<T: ~const Bar>(x: &T) { + //[yn,nn]~^ ERROR: `~const` can only be applied to `#[const_trait]` + x.a(); + //[yn]~^ ERROR: the trait bound `T: ~const Foo` is not satisfied +} + +fn main() {} diff --git a/tests/ui/traits/const-traits/super-traits-fail-3.yn.stderr b/tests/ui/traits/const-traits/super-traits-fail-3.yn.stderr new file mode 100644 index 00000000000..bbc95948a59 --- /dev/null +++ b/tests/ui/traits/const-traits/super-traits-fail-3.yn.stderr @@ -0,0 +1,40 @@ +error: `~const` is not allowed here + --> $DIR/super-traits-fail-3.rs:14:12 + | +LL | trait Bar: ~const Foo {} + | ^^^^^^ + | +note: this trait is not a `#[const_trait]`, so it cannot have `~const` trait bounds + --> $DIR/super-traits-fail-3.rs:14:1 + | +LL | trait Bar: ~const Foo {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/super-traits-fail-3.rs:20:24 + | +LL | const fn foo<T: ~const Bar>(x: &T) { + | ^^^ + +error[E0277]: the trait bound `T: ~const Foo` is not satisfied + --> $DIR/super-traits-fail-3.rs:22:7 + | +LL | x.a(); + | ^ the trait `Foo` is not implemented for `T` + | +note: required by a bound in `Foo::a` + --> $DIR/super-traits-fail-3.rs:8:25 + | +LL | #[cfg_attr(any(yy, yn), const_trait)] + | ^^^^^^^^^^^ required by this bound in `Foo::a` +LL | trait Foo { +LL | fn a(&self); + | - required by a bound in this associated function +help: consider further restricting this bound + | +LL | const fn foo<T: ~const Bar + Foo>(x: &T) { + | +++++ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/const-traits/super-traits-fail.rs b/tests/ui/traits/const-traits/super-traits-fail.rs new file mode 100644 index 00000000000..da41d7fcc72 --- /dev/null +++ b/tests/ui/traits/const-traits/super-traits-fail.rs @@ -0,0 +1,22 @@ +//~ ERROR the trait bound +//@ compile-flags: -Znext-solver + +#![allow(incomplete_features)] +#![feature(const_trait_impl, effects)] + +#[const_trait] +trait Foo { + fn a(&self); +} +#[const_trait] +trait Bar: ~const Foo {} + +struct S; +impl Foo for S { + fn a(&self) {} +} + +impl const Bar for S {} +//~^ ERROR the trait bound + +fn main() {} diff --git a/tests/ui/traits/const-traits/super-traits-fail.stderr b/tests/ui/traits/const-traits/super-traits-fail.stderr new file mode 100644 index 00000000000..3870f0f722f --- /dev/null +++ b/tests/ui/traits/const-traits/super-traits-fail.stderr @@ -0,0 +1,24 @@ +error[E0277]: the trait bound `Bar::{synthetic#0}: TyCompat<Foo::{synthetic#0}>` is not satisfied + --> $DIR/super-traits-fail.rs:19:12 + | +LL | impl const Bar for S {} + | ^^^ the trait `TyCompat<Foo::{synthetic#0}>` is not implemented for `Bar::{synthetic#0}`, which is required by `S: Bar` + | + = help: the trait `Bar` is implemented for `S` +note: required for `S` to implement `Bar` + --> $DIR/super-traits-fail.rs:12:7 + | +LL | trait Bar: ~const Foo {} + | ^^^ + +error[E0277]: the trait bound `Maybe: TyCompat<Foo::{synthetic#0}>` is not satisfied + | +note: required by a bound in `Bar::{synthetic#0}` + --> $DIR/super-traits-fail.rs:12:12 + | +LL | trait Bar: ~const Foo {} + | ^^^^^^^^^^ required by this bound in `Bar::{synthetic#0}` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/const-traits/super-traits.rs b/tests/ui/traits/const-traits/super-traits.rs new file mode 100644 index 00000000000..ff7349bba3c --- /dev/null +++ b/tests/ui/traits/const-traits/super-traits.rs @@ -0,0 +1,27 @@ +//@ check-pass +//@ compile-flags: -Znext-solver +#![allow(incomplete_features)] +#![feature(const_trait_impl, effects)] + +#[const_trait] +trait Foo { + fn a(&self); +} + +#[const_trait] +trait Bar: ~const Foo {} + +struct S; +impl const Foo for S { + fn a(&self) {} +} + +impl const Bar for S {} + +const fn foo<T: ~const Bar>(t: &T) { + t.a(); +} + +const _: () = foo(&S); + +fn main() {} diff --git a/tests/ui/traits/const-traits/syntax.rs b/tests/ui/traits/const-traits/syntax.rs new file mode 100644 index 00000000000..1064713ac59 --- /dev/null +++ b/tests/ui/traits/const-traits/syntax.rs @@ -0,0 +1,8 @@ +//@ compile-flags: -Z parse-only +//@ check-pass + +#![feature(const_trait_bound_opt_out)] +#![feature(const_trait_impl)] + +// For now, this parses since an error does not occur until AST lowering. +impl ~const T {} diff --git a/tests/ui/traits/const-traits/tilde-const-and-const-params.rs b/tests/ui/traits/const-traits/tilde-const-and-const-params.rs new file mode 100644 index 00000000000..4b720b534a4 --- /dev/null +++ b/tests/ui/traits/const-traits/tilde-const-and-const-params.rs @@ -0,0 +1,37 @@ +#![feature(const_trait_impl, effects)] +#![feature(generic_arg_infer)] +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +struct Foo<const N: usize>; + +impl<const N: usize> Foo<N> { + fn add<A: ~const Add42>(self) -> Foo<{ A::add(N) }> { + //~^ ERROR `~const` is not allowed here + //~| ERROR mismatched types + Foo + } +} + +#[const_trait] +trait Add42 { + fn add(a: usize) -> usize; +} + +impl const Add42 for () { + fn add(a: usize) -> usize { + a + 42 + } +} + +fn bar<A: ~const Add42, const N: usize>(_: Foo<N>) -> Foo<{ A::add(N) }> { + //~^ ERROR `~const` is not allowed here + //~| ERROR mismatched types + Foo +} + +fn main() { + let foo = Foo::<0>; + let foo = bar::<(), _>(foo); + let _foo = bar::<(), _>(foo); +} diff --git a/tests/ui/traits/const-traits/tilde-const-and-const-params.stderr b/tests/ui/traits/const-traits/tilde-const-and-const-params.stderr new file mode 100644 index 00000000000..73526a26e08 --- /dev/null +++ b/tests/ui/traits/const-traits/tilde-const-and-const-params.stderr @@ -0,0 +1,50 @@ +error: `~const` is not allowed here + --> $DIR/tilde-const-and-const-params.rs:9:15 + | +LL | fn add<A: ~const Add42>(self) -> Foo<{ A::add(N) }> { + | ^^^^^^ + | +note: this function is not `const`, so it cannot have `~const` trait bounds + --> $DIR/tilde-const-and-const-params.rs:9:8 + | +LL | fn add<A: ~const Add42>(self) -> Foo<{ A::add(N) }> { + | ^^^ + +error: `~const` is not allowed here + --> $DIR/tilde-const-and-const-params.rs:27:11 + | +LL | fn bar<A: ~const Add42, const N: usize>(_: Foo<N>) -> Foo<{ A::add(N) }> { + | ^^^^^^ + | +note: this function is not `const`, so it cannot have `~const` trait bounds + --> $DIR/tilde-const-and-const-params.rs:27:4 + | +LL | fn bar<A: ~const Add42, const N: usize>(_: Foo<N>) -> Foo<{ A::add(N) }> { + | ^^^ + +error: using `#![feature(effects)]` without enabling next trait solver globally + | + = note: the next trait solver must be enabled globally for the effects feature to work correctly + = help: use `-Znext-solver` to enable + +error[E0308]: mismatched types + --> $DIR/tilde-const-and-const-params.rs:27:61 + | +LL | fn bar<A: ~const Add42, const N: usize>(_: Foo<N>) -> Foo<{ A::add(N) }> { + | ^^^^^^^^^ expected `false`, found `true` + | + = note: expected constant `false` + found constant `true` + +error[E0308]: mismatched types + --> $DIR/tilde-const-and-const-params.rs:9:44 + | +LL | fn add<A: ~const Add42>(self) -> Foo<{ A::add(N) }> { + | ^^^^^^^^^ expected `false`, found `true` + | + = note: expected constant `false` + found constant `true` + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/traits/const-traits/tilde-const-assoc-fn-in-trait-impl.rs b/tests/ui/traits/const-traits/tilde-const-assoc-fn-in-trait-impl.rs new file mode 100644 index 00000000000..8e7202ecaa1 --- /dev/null +++ b/tests/ui/traits/const-traits/tilde-const-assoc-fn-in-trait-impl.rs @@ -0,0 +1,30 @@ +// Regression test for issue #119700. +//@ check-pass +//@ compile-flags: -Znext-solver +#![allow(incomplete_features)] +#![feature(const_trait_impl, effects)] + +#[const_trait] +trait Main { + fn compute<T: ~const Aux>() -> u32; +} + +impl const Main for () { + fn compute<T: ~const Aux>() -> u32 { + T::generate() + } +} + +#[const_trait] +trait Aux { + fn generate() -> u32; +} + +impl const Aux for () { + fn generate() -> u32 { 1024 } +} + +fn main() { + const _: u32 = <()>::compute::<()>(); + let _ = <()>::compute::<()>(); +} diff --git a/tests/ui/traits/const-traits/tilde-const-inherent-assoc-const-fn.rs b/tests/ui/traits/const-traits/tilde-const-inherent-assoc-const-fn.rs new file mode 100644 index 00000000000..71c5d8366b2 --- /dev/null +++ b/tests/ui/traits/const-traits/tilde-const-inherent-assoc-const-fn.rs @@ -0,0 +1,19 @@ +//@ check-pass +//@ compile-flags: -Znext-solver +#![allow(incomplete_features)] +#![feature(const_trait_impl, effects)] + +#[const_trait] +trait Foo { + fn foo(&self) {} +} + +struct Bar<T>(T); + +impl<T> Bar<T> { + const fn foo(&self) where T: ~const Foo { + self.0.foo() + } +} + +fn main() {} diff --git a/tests/ui/traits/const-traits/tilde-const-invalid-places.rs b/tests/ui/traits/const-traits/tilde-const-invalid-places.rs new file mode 100644 index 00000000000..9d220686771 --- /dev/null +++ b/tests/ui/traits/const-traits/tilde-const-invalid-places.rs @@ -0,0 +1,61 @@ +#![feature(const_trait_impl)] + +#[const_trait] +trait Trait {} + +// Regression test for issue #90052. +fn non_const_function<T: ~const Trait>() {} //~ ERROR `~const` is not allowed + +struct Struct<T: ~const Trait> { field: T } //~ ERROR `~const` is not allowed here +struct TupleStruct<T: ~const Trait>(T); //~ ERROR `~const` is not allowed here +struct UnitStruct<T: ~const Trait>; //~ ERROR `~const` is not allowed here +//~^ ERROR parameter `T` is never used + +enum Enum<T: ~const Trait> { Variant(T) } //~ ERROR `~const` is not allowed here + +union Union<T: ~const Trait> { field: T } //~ ERROR `~const` is not allowed here +//~^ ERROR field must implement `Copy` + +type Type<T: ~const Trait> = T; //~ ERROR `~const` is not allowed here + +const CONSTANT<T: ~const Trait>: () = (); //~ ERROR `~const` is not allowed here +//~^ ERROR generic const items are experimental + +trait NonConstTrait { + type Type<T: ~const Trait>: ~const Trait; + //~^ ERROR `~const` is not allowed + //~| ERROR `~const` is not allowed + fn non_const_function<T: ~const Trait>(); //~ ERROR `~const` is not allowed + const CONSTANT<T: ~const Trait>: (); //~ ERROR `~const` is not allowed + //~^ ERROR generic const items are experimental +} + +impl NonConstTrait for () { + type Type<T: ~const Trait> = (); //~ ERROR `~const` is not allowed + //~^ ERROR overflow evaluating the requirement `(): Trait` + fn non_const_function<T: ~const Trait>() {} //~ ERROR `~const` is not allowed + const CONSTANT<T: ~const Trait>: () = (); //~ ERROR `~const` is not allowed + //~^ ERROR generic const items are experimental +} + +struct Implementor; + +impl Implementor { + type Type<T: ~const Trait> = (); //~ ERROR `~const` is not allowed + //~^ ERROR inherent associated types are unstable + fn non_const_function<T: ~const Trait>() {} //~ ERROR `~const` is not allowed + const CONSTANT<T: ~const Trait>: () = (); //~ ERROR `~const` is not allowed + //~^ ERROR generic const items are experimental +} + +// non-const traits +trait Child0: ~const Trait {} //~ ERROR `~const` is not allowed +trait Child1 where Self: ~const Trait {} //~ ERROR `~const` is not allowed + +// non-const impl +impl<T: ~const Trait> Trait for T {} //~ ERROR `~const` is not allowed + +// inherent impl (regression test for issue #117004) +impl<T: ~const Trait> Struct<T> {} //~ ERROR `~const` is not allowed + +fn main() {} diff --git a/tests/ui/traits/const-traits/tilde-const-invalid-places.stderr b/tests/ui/traits/const-traits/tilde-const-invalid-places.stderr new file mode 100644 index 00000000000..8151b9aaa23 --- /dev/null +++ b/tests/ui/traits/const-traits/tilde-const-invalid-places.stderr @@ -0,0 +1,310 @@ +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:7:26 + | +LL | fn non_const_function<T: ~const Trait>() {} + | ^^^^^^ + | +note: this function is not `const`, so it cannot have `~const` trait bounds + --> $DIR/tilde-const-invalid-places.rs:7:4 + | +LL | fn non_const_function<T: ~const Trait>() {} + | ^^^^^^^^^^^^^^^^^^ + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:9:18 + | +LL | struct Struct<T: ~const Trait> { field: T } + | ^^^^^^ + | + = note: this item cannot have `~const` trait bounds + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:10:23 + | +LL | struct TupleStruct<T: ~const Trait>(T); + | ^^^^^^ + | + = note: this item cannot have `~const` trait bounds + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:11:22 + | +LL | struct UnitStruct<T: ~const Trait>; + | ^^^^^^ + | + = note: this item cannot have `~const` trait bounds + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:14:14 + | +LL | enum Enum<T: ~const Trait> { Variant(T) } + | ^^^^^^ + | + = note: this item cannot have `~const` trait bounds + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:16:16 + | +LL | union Union<T: ~const Trait> { field: T } + | ^^^^^^ + | + = note: this item cannot have `~const` trait bounds + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:19:14 + | +LL | type Type<T: ~const Trait> = T; + | ^^^^^^ + | + = note: this item cannot have `~const` trait bounds + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:21:19 + | +LL | const CONSTANT<T: ~const Trait>: () = (); + | ^^^^^^ + | + = note: this item cannot have `~const` trait bounds + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:25:18 + | +LL | type Type<T: ~const Trait>: ~const Trait; + | ^^^^^^ + | +note: associated types in non-`#[const_trait]` traits cannot have `~const` trait bounds + --> $DIR/tilde-const-invalid-places.rs:25:5 + | +LL | type Type<T: ~const Trait>: ~const Trait; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:25:33 + | +LL | type Type<T: ~const Trait>: ~const Trait; + | ^^^^^^ + | +note: associated types in non-`#[const_trait]` traits cannot have `~const` trait bounds + --> $DIR/tilde-const-invalid-places.rs:25:5 + | +LL | type Type<T: ~const Trait>: ~const Trait; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:28:30 + | +LL | fn non_const_function<T: ~const Trait>(); + | ^^^^^^ + | +note: this function is not `const`, so it cannot have `~const` trait bounds + --> $DIR/tilde-const-invalid-places.rs:28:8 + | +LL | fn non_const_function<T: ~const Trait>(); + | ^^^^^^^^^^^^^^^^^^ + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:29:23 + | +LL | const CONSTANT<T: ~const Trait>: (); + | ^^^^^^ + | + = note: this item cannot have `~const` trait bounds + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:34:18 + | +LL | type Type<T: ~const Trait> = (); + | ^^^^^^ + | +note: associated types in non-const impls cannot have `~const` trait bounds + --> $DIR/tilde-const-invalid-places.rs:34:5 + | +LL | type Type<T: ~const Trait> = (); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:36:30 + | +LL | fn non_const_function<T: ~const Trait>() {} + | ^^^^^^ + | +note: this function is not `const`, so it cannot have `~const` trait bounds + --> $DIR/tilde-const-invalid-places.rs:36:8 + | +LL | fn non_const_function<T: ~const Trait>() {} + | ^^^^^^^^^^^^^^^^^^ + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:37:23 + | +LL | const CONSTANT<T: ~const Trait>: () = (); + | ^^^^^^ + | + = note: this item cannot have `~const` trait bounds + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:44:18 + | +LL | type Type<T: ~const Trait> = (); + | ^^^^^^ + | +note: inherent associated types cannot have `~const` trait bounds + --> $DIR/tilde-const-invalid-places.rs:44:5 + | +LL | type Type<T: ~const Trait> = (); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:46:30 + | +LL | fn non_const_function<T: ~const Trait>() {} + | ^^^^^^ + | +note: this function is not `const`, so it cannot have `~const` trait bounds + --> $DIR/tilde-const-invalid-places.rs:46:8 + | +LL | fn non_const_function<T: ~const Trait>() {} + | ^^^^^^^^^^^^^^^^^^ + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:47:23 + | +LL | const CONSTANT<T: ~const Trait>: () = (); + | ^^^^^^ + | + = note: this item cannot have `~const` trait bounds + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:52:15 + | +LL | trait Child0: ~const Trait {} + | ^^^^^^ + | +note: this trait is not a `#[const_trait]`, so it cannot have `~const` trait bounds + --> $DIR/tilde-const-invalid-places.rs:52:1 + | +LL | trait Child0: ~const Trait {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:53:26 + | +LL | trait Child1 where Self: ~const Trait {} + | ^^^^^^ + | +note: this trait is not a `#[const_trait]`, so it cannot have `~const` trait bounds + --> $DIR/tilde-const-invalid-places.rs:53:1 + | +LL | trait Child1 where Self: ~const Trait {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:56:9 + | +LL | impl<T: ~const Trait> Trait for T {} + | ^^^^^^ + | +note: this impl is not `const`, so it cannot have `~const` trait bounds + --> $DIR/tilde-const-invalid-places.rs:56:1 + | +LL | impl<T: ~const Trait> Trait for T {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:59:9 + | +LL | impl<T: ~const Trait> Struct<T> {} + | ^^^^^^ + | +note: inherent impls cannot have `~const` trait bounds + --> $DIR/tilde-const-invalid-places.rs:59:1 + | +LL | impl<T: ~const Trait> Struct<T> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0658]: generic const items are experimental + --> $DIR/tilde-const-invalid-places.rs:21:15 + | +LL | const CONSTANT<T: ~const Trait>: () = (); + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #113521 <https://github.com/rust-lang/rust/issues/113521> for more information + = help: add `#![feature(generic_const_items)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: generic const items are experimental + --> $DIR/tilde-const-invalid-places.rs:29:19 + | +LL | const CONSTANT<T: ~const Trait>: (); + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #113521 <https://github.com/rust-lang/rust/issues/113521> for more information + = help: add `#![feature(generic_const_items)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: generic const items are experimental + --> $DIR/tilde-const-invalid-places.rs:37:19 + | +LL | const CONSTANT<T: ~const Trait>: () = (); + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #113521 <https://github.com/rust-lang/rust/issues/113521> for more information + = help: add `#![feature(generic_const_items)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: generic const items are experimental + --> $DIR/tilde-const-invalid-places.rs:47:19 + | +LL | const CONSTANT<T: ~const Trait>: () = (); + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #113521 <https://github.com/rust-lang/rust/issues/113521> for more information + = help: add `#![feature(generic_const_items)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0392]: type parameter `T` is never used + --> $DIR/tilde-const-invalid-places.rs:11:19 + | +LL | struct UnitStruct<T: ~const Trait>; + | ^ unused type parameter + | + = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` + +error[E0740]: field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union + --> $DIR/tilde-const-invalid-places.rs:16:32 + | +LL | union Union<T: ~const Trait> { field: T } + | ^^^^^^^^ + | + = note: union fields must not have drop side-effects, which is currently enforced via either `Copy` or `ManuallyDrop<...>` +help: wrap the field type in `ManuallyDrop<...>` + | +LL | union Union<T: ~const Trait> { field: std::mem::ManuallyDrop<T> } + | +++++++++++++++++++++++ + + +error[E0275]: overflow evaluating the requirement `(): Trait` + --> $DIR/tilde-const-invalid-places.rs:34:34 + | +LL | type Type<T: ~const Trait> = (); + | ^^ + | +note: required by a bound in `NonConstTrait::Type` + --> $DIR/tilde-const-invalid-places.rs:25:33 + | +LL | type Type<T: ~const Trait>: ~const Trait; + | ^^^^^^^^^^^^ required by this bound in `NonConstTrait::Type` + +error[E0658]: inherent associated types are unstable + --> $DIR/tilde-const-invalid-places.rs:44:5 + | +LL | type Type<T: ~const Trait> = (); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #8995 <https://github.com/rust-lang/rust/issues/8995> for more information + = help: add `#![feature(inherent_associated_types)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 30 previous errors + +Some errors have detailed explanations: E0275, E0392, E0658, E0740. +For more information about an error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/const-traits/tilde-const-syntax.rs b/tests/ui/traits/const-traits/tilde-const-syntax.rs new file mode 100644 index 00000000000..d65ecae3d06 --- /dev/null +++ b/tests/ui/traits/const-traits/tilde-const-syntax.rs @@ -0,0 +1,9 @@ +//@ compile-flags: -Z parse-only +//@ check-pass + +#![feature(const_trait_impl)] + +struct S< + T: for<'a> ~const Tr<'a> + 'static + ~const std::ops::Add, + T: for<'a: 'b> ~const m::Trait<'a>, +>; diff --git a/tests/ui/traits/const-traits/tilde-const-trait-assoc-tys.rs b/tests/ui/traits/const-traits/tilde-const-trait-assoc-tys.rs new file mode 100644 index 00000000000..254cf2200d8 --- /dev/null +++ b/tests/ui/traits/const-traits/tilde-const-trait-assoc-tys.rs @@ -0,0 +1,20 @@ +//@ check-pass +//@ compile-flags: -Znext-solver +#![allow(incomplete_features)] +#![feature(const_trait_impl, effects)] + +#[const_trait] +trait Trait { + // FIXME(effects): `~const` bounds in trait associated types (excluding associated type bounds) + // don't look super useful. Should we forbid them again? + type Assoc<T: ~const Bound>; +} + +impl const Trait for () { + type Assoc<T: ~const Bound> = T; +} + +#[const_trait] +trait Bound {} + +fn main() {} diff --git a/tests/ui/traits/const-traits/tilde-twice.rs b/tests/ui/traits/const-traits/tilde-twice.rs new file mode 100644 index 00000000000..c3f9f8e6764 --- /dev/null +++ b/tests/ui/traits/const-traits/tilde-twice.rs @@ -0,0 +1,6 @@ +//@ compile-flags: -Z parse-only + +#![feature(const_trait_impl)] + +struct S<T: ~const ~const Tr>; +//~^ ERROR expected identifier, found `~` diff --git a/tests/ui/traits/const-traits/tilde-twice.stderr b/tests/ui/traits/const-traits/tilde-twice.stderr new file mode 100644 index 00000000000..a809736a4f8 --- /dev/null +++ b/tests/ui/traits/const-traits/tilde-twice.stderr @@ -0,0 +1,8 @@ +error: expected identifier, found `~` + --> $DIR/tilde-twice.rs:5:20 + | +LL | struct S<T: ~const ~const Tr>; + | ^ expected identifier + +error: aborting due to 1 previous error + diff --git a/tests/ui/traits/const-traits/trait-default-body-stability.rs b/tests/ui/traits/const-traits/trait-default-body-stability.rs new file mode 100644 index 00000000000..b36e9535ca1 --- /dev/null +++ b/tests/ui/traits/const-traits/trait-default-body-stability.rs @@ -0,0 +1,51 @@ +//@ known-bug: #110395 +//@ compile-flags: -Znext-solver +#![allow(incomplete_features)] +#![feature(staged_api)] +#![feature(const_trait_impl, effects)] +#![feature(const_t_try)] +#![feature(const_try)] +#![feature(try_trait_v2)] + +#![stable(feature = "foo", since = "1.0")] + +use std::ops::{ControlFlow, FromResidual, Try}; + +#[stable(feature = "foo", since = "1.0")] +pub struct T; + +#[stable(feature = "foo", since = "1.0")] +#[rustc_const_unstable(feature = "const_t_try", issue = "none")] +impl const Try for T { + type Output = T; + type Residual = T; + + fn from_output(t: T) -> T { + t + } + + fn branch(self) -> ControlFlow<T, T> { + ControlFlow::Continue(self) + } +} + +#[stable(feature = "foo", since = "1.0")] +#[rustc_const_unstable(feature = "const_t_try", issue = "none")] +impl const FromResidual for T { + fn from_residual(t: T) -> T { + t + } +} + +#[stable(feature = "foo", since = "1.0")] +#[const_trait] +pub trait Tr { + #[stable(feature = "foo", since = "1.0")] + fn bar() -> T { + T? + // Should be allowed. + // Must enable unstable features to call this trait fn in const contexts. + } +} + +fn main() {} diff --git a/tests/ui/traits/const-traits/trait-default-body-stability.stderr b/tests/ui/traits/const-traits/trait-default-body-stability.stderr new file mode 100644 index 00000000000..49fbef9aaa2 --- /dev/null +++ b/tests/ui/traits/const-traits/trait-default-body-stability.stderr @@ -0,0 +1,20 @@ +error: const `impl` for trait `Try` which is not marked with `#[const_trait]` + --> $DIR/trait-default-body-stability.rs:19:12 + | +LL | impl const Try for T { + | ^^^ + | + = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: adding a non-const method body in the future would be a breaking change + +error: const `impl` for trait `FromResidual` which is not marked with `#[const_trait]` + --> $DIR/trait-default-body-stability.rs:34:12 + | +LL | impl const FromResidual for T { + | ^^^^^^^^^^^^ + | + = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: adding a non-const method body in the future would be a breaking change + +error: aborting due to 2 previous errors + diff --git a/tests/ui/traits/const-traits/trait-method-ptr-in-consts-ice.rs b/tests/ui/traits/const-traits/trait-method-ptr-in-consts-ice.rs new file mode 100644 index 00000000000..8a901cc60fd --- /dev/null +++ b/tests/ui/traits/const-traits/trait-method-ptr-in-consts-ice.rs @@ -0,0 +1,23 @@ +//@ check-pass + +struct LazyLock<T> { + data: (Option<T>, fn() -> T), +} + +impl<T> LazyLock<T> { + pub const fn new(f: fn() -> T) -> LazyLock<T> { + LazyLock { data: (None, f) } + } +} + +struct A<T = i32>(Option<T>); + +impl<T> Default for A<T> { + fn default() -> Self { + A(None) + } +} + +static EMPTY_SET: LazyLock<A<i32>> = LazyLock::new(A::default); + +fn main() {} diff --git a/tests/ui/traits/const-traits/trait-where-clause-const.rs b/tests/ui/traits/const-traits/trait-where-clause-const.rs new file mode 100644 index 00000000000..8ca9b7cc7aa --- /dev/null +++ b/tests/ui/traits/const-traits/trait-where-clause-const.rs @@ -0,0 +1,36 @@ +//@ compile-flags: -Znext-solver +// Like trait-where-clause.rs, but we are calling from a const context. +// Checking the validity of traits' where clauses happen at a later stage. +// (`rustc_const_eval` instead of `rustc_hir_analysis`) Therefore one file as a +// test is not enough. + +#![feature(const_trait_impl, effects)] +#![allow(incomplete_features)] + +#[const_trait] +trait Bar {} + +#[const_trait] +trait Foo { + fn a(); + fn b() where Self: ~const Bar; + fn c<T: ~const Bar>(); +} + +const fn test1<T: ~const Foo + Bar>() { + T::a(); + T::b(); + //~^ ERROR mismatched types + //~| ERROR the trait bound + T::c::<T>(); + //~^ ERROR mismatched types + //~| ERROR the trait bound +} + +const fn test2<T: ~const Foo + ~const Bar>() { + T::a(); + T::b(); + T::c::<T>(); +} + +fn main() {} diff --git a/tests/ui/traits/const-traits/trait-where-clause-const.stderr b/tests/ui/traits/const-traits/trait-where-clause-const.stderr new file mode 100644 index 00000000000..eaa981ec744 --- /dev/null +++ b/tests/ui/traits/const-traits/trait-where-clause-const.stderr @@ -0,0 +1,52 @@ +error[E0277]: the trait bound `T: Foo` is not satisfied + --> $DIR/trait-where-clause-const.rs:22:5 + | +LL | T::b(); + | ^ the trait `Foo` is not implemented for `T` + | +note: required by a bound in `Foo::b` + --> $DIR/trait-where-clause-const.rs:13:1 + | +LL | #[const_trait] + | ^^^^^^^^^^^^^^ required by this bound in `Foo::b` +... +LL | fn b() where Self: ~const Bar; + | - required by a bound in this associated function + +error[E0308]: mismatched types + --> $DIR/trait-where-clause-const.rs:22:5 + | +LL | T::b(); + | ^^^^^^ expected `host`, found `true` + | + = note: expected constant `host` + found constant `true` + +error[E0277]: the trait bound `T: Foo` is not satisfied + --> $DIR/trait-where-clause-const.rs:25:5 + | +LL | T::c::<T>(); + | ^ the trait `Foo` is not implemented for `T` + | +note: required by a bound in `Foo::c` + --> $DIR/trait-where-clause-const.rs:13:1 + | +LL | #[const_trait] + | ^^^^^^^^^^^^^^ required by this bound in `Foo::c` +... +LL | fn c<T: ~const Bar>(); + | - required by a bound in this associated function + +error[E0308]: mismatched types + --> $DIR/trait-where-clause-const.rs:25:5 + | +LL | T::c::<T>(); + | ^^^^^^^^^^^ expected `host`, found `true` + | + = note: expected constant `host` + found constant `true` + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0277, E0308. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/const-traits/trait-where-clause-run.rs b/tests/ui/traits/const-traits/trait-where-clause-run.rs new file mode 100644 index 00000000000..2837c835429 --- /dev/null +++ b/tests/ui/traits/const-traits/trait-where-clause-run.rs @@ -0,0 +1,43 @@ +//@ run-pass +//@ compile-flags: -Znext-solver + +#![feature(const_trait_impl, effects)] +#![allow(incomplete_features)] + +#[const_trait] +trait Bar { + fn bar() -> u8; +} + +#[const_trait] +trait Foo { + fn foo() -> u8 where Self: ~const Bar { + <Self as Bar>::bar() * 6 + } +} + +struct NonConst; +struct Const; + +impl Bar for NonConst { + fn bar() -> u8 { + 3 + } +} + +impl Foo for NonConst {} + +impl const Bar for Const { + fn bar() -> u8 { + 4 + } +} + +impl const Foo for Const {} + +fn main() { + const ANS1: u8 = Const::foo(); + let ans2 = NonConst::foo(); + + assert_eq!(ANS1 + ans2, 42); +} diff --git a/tests/ui/traits/const-traits/trait-where-clause-self-referential.rs b/tests/ui/traits/const-traits/trait-where-clause-self-referential.rs new file mode 100644 index 00000000000..cb5cc924bfd --- /dev/null +++ b/tests/ui/traits/const-traits/trait-where-clause-self-referential.rs @@ -0,0 +1,25 @@ +//@ check-pass +//@ compile-flags: -Znext-solver +#![allow(incomplete_features)] +#![feature(const_trait_impl, effects)] + +#[const_trait] +trait Foo { + fn bar() where Self: ~const Foo; +} + +struct S; + +impl Foo for S { + fn bar() {} +} + +fn baz<T: Foo>() { + T::bar(); +} + +const fn qux<T: ~const Foo>() { + T::bar(); +} + +fn main() {} diff --git a/tests/ui/traits/const-traits/trait-where-clause.rs b/tests/ui/traits/const-traits/trait-where-clause.rs new file mode 100644 index 00000000000..11f353f3f8a --- /dev/null +++ b/tests/ui/traits/const-traits/trait-where-clause.rs @@ -0,0 +1,28 @@ +#![feature(const_trait_impl)] + +#[const_trait] +trait Bar {} + +trait Foo { + fn a(); + fn b() where Self: ~const Bar; + //~^ ERROR `~const` is not allowed here + fn c<T: ~const Bar>(); + //~^ ERROR `~const` is not allowed here +} + +fn test1<T: Foo>() { + T::a(); + T::b(); + //~^ ERROR the trait bound + T::c::<T>(); + //~^ ERROR the trait bound +} + +fn test2<T: Foo + Bar>() { + T::a(); + T::b(); + T::c::<T>(); +} + +fn main() {} diff --git a/tests/ui/traits/const-traits/trait-where-clause.stderr b/tests/ui/traits/const-traits/trait-where-clause.stderr new file mode 100644 index 00000000000..abe24b662a2 --- /dev/null +++ b/tests/ui/traits/const-traits/trait-where-clause.stderr @@ -0,0 +1,59 @@ +error: `~const` is not allowed here + --> $DIR/trait-where-clause.rs:8:24 + | +LL | fn b() where Self: ~const Bar; + | ^^^^^^ + | +note: this function is not `const`, so it cannot have `~const` trait bounds + --> $DIR/trait-where-clause.rs:8:8 + | +LL | fn b() where Self: ~const Bar; + | ^ + +error: `~const` is not allowed here + --> $DIR/trait-where-clause.rs:10:13 + | +LL | fn c<T: ~const Bar>(); + | ^^^^^^ + | +note: this function is not `const`, so it cannot have `~const` trait bounds + --> $DIR/trait-where-clause.rs:10:8 + | +LL | fn c<T: ~const Bar>(); + | ^ + +error[E0277]: the trait bound `T: Bar` is not satisfied + --> $DIR/trait-where-clause.rs:16:5 + | +LL | T::b(); + | ^ the trait `Bar` is not implemented for `T` + | +note: required by a bound in `Foo::b` + --> $DIR/trait-where-clause.rs:8:24 + | +LL | fn b() where Self: ~const Bar; + | ^^^^^^^^^^ required by this bound in `Foo::b` +help: consider further restricting this bound + | +LL | fn test1<T: Foo + Bar>() { + | +++++ + +error[E0277]: the trait bound `T: Bar` is not satisfied + --> $DIR/trait-where-clause.rs:18:12 + | +LL | T::c::<T>(); + | ^ the trait `Bar` is not implemented for `T` + | +note: required by a bound in `Foo::c` + --> $DIR/trait-where-clause.rs:10:13 + | +LL | fn c<T: ~const Bar>(); + | ^^^^^^^^^^ required by this bound in `Foo::c` +help: consider further restricting this bound + | +LL | fn test1<T: Foo + Bar>() { + | +++++ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/const-traits/unsatisfied-const-trait-bound.rs b/tests/ui/traits/const-traits/unsatisfied-const-trait-bound.rs new file mode 100644 index 00000000000..d336719f52e --- /dev/null +++ b/tests/ui/traits/const-traits/unsatisfied-const-trait-bound.rs @@ -0,0 +1,33 @@ +//@ known-bug: unknown +// Ensure that we print unsatisfied always-const trait bounds as `const Trait` in diagnostics. +//@ compile-flags: -Znext-solver + +#![feature(const_trait_impl, effects, generic_const_exprs)] +#![allow(incomplete_features)] + +fn require<T: const Trait>() {} + +#[const_trait] +trait Trait { + fn make() -> u32; +} + +struct Ty; + +impl Trait for Ty { + fn make() -> u32 { 0 } +} + +fn main() { + require::<Ty>(); +} + +struct Container<const N: u32>; + +// FIXME(effects): Somehow emit `the trait bound `T: const Trait` is not satisfied` here instead +// and suggest changing `Trait` to `const Trait`. +fn accept0<T: Trait>(_: Container<{ T::make() }>) {} + +// FIXME(effects): Instead of suggesting `+ const Trait`, suggest +// changing `~const Trait` to `const Trait`. +const fn accept1<T: ~const Trait>(_: Container<{ T::make() }>) {} diff --git a/tests/ui/traits/const-traits/unsatisfied-const-trait-bound.stderr b/tests/ui/traits/const-traits/unsatisfied-const-trait-bound.stderr new file mode 100644 index 00000000000..848aa68689b --- /dev/null +++ b/tests/ui/traits/const-traits/unsatisfied-const-trait-bound.stderr @@ -0,0 +1,46 @@ +error: `-Znext-solver=globally` and `generic_const_exprs` are incompatible, using them at the same time is not allowed + --> $DIR/unsatisfied-const-trait-bound.rs:5:39 + | +LL | #![feature(const_trait_impl, effects, generic_const_exprs)] + | ^^^^^^^^^^^^^^^^^^^ + | + = help: remove one of these features + +error[E0308]: mismatched types + --> $DIR/unsatisfied-const-trait-bound.rs:29:37 + | +LL | fn accept0<T: Trait>(_: Container<{ T::make() }>) {} + | ^^^^^^^^^ expected `false`, found `true` + | + = note: expected constant `false` + found constant `true` + +error[E0308]: mismatched types + --> $DIR/unsatisfied-const-trait-bound.rs:33:50 + | +LL | const fn accept1<T: ~const Trait>(_: Container<{ T::make() }>) {} + | ^^^^^^^^^ expected `false`, found `host` + | + = note: expected constant `false` + found constant `host` + +error[E0277]: the trait bound `Ty: const Trait` is not satisfied + --> $DIR/unsatisfied-const-trait-bound.rs:22:15 + | +LL | require::<Ty>(); + | ^^ the trait `Trait` is not implemented for `Ty` + | +note: required by a bound in `require` + --> $DIR/unsatisfied-const-trait-bound.rs:8:15 + | +LL | fn require<T: const Trait>() {} + | ^^^^^^^^^^^ required by this bound in `require` +help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement + | +LL | fn main() where Ty: Trait { + | +++++++++++++++ + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0277, E0308. +For more information about an error, try `rustc --explain E0277`. |
