diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:02:58 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:02:58 +0000 |
commit | 698f8c2f01ea549d77d7dc3338a12e04c11057b9 (patch) | |
tree | 173a775858bd501c378080a10dca74132f05bc50 /src/test/ui/rfc-2632-const-trait-impl | |
parent | Initial commit. (diff) | |
download | rustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.tar.xz rustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.zip |
Adding upstream version 1.64.0+dfsg1.upstream/1.64.0+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
88 files changed, 2104 insertions, 0 deletions
diff --git a/src/test/ui/rfc-2632-const-trait-impl/assoc-type.rs b/src/test/ui/rfc-2632-const-trait-impl/assoc-type.rs new file mode 100644 index 000000000..99eacaa83 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/assoc-type.rs @@ -0,0 +1,30 @@ +#![feature(const_trait_impl)] + +struct NonConstAdd(i32); + +impl std::ops::Add for NonConstAdd { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + NonConstAdd(self.0 + rhs.0) + } +} + +trait Foo { + type Bar: ~const std::ops::Add; +} + +impl const Foo for NonConstAdd { + type Bar = NonConstAdd; + //~^ ERROR: cannot add `NonConstAdd` to `NonConstAdd` in const contexts +} + +trait Baz { + type Qux: std::ops::Add; +} + +impl const Baz for NonConstAdd { + type Qux = NonConstAdd; // OK +} + +fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/assoc-type.stderr b/src/test/ui/rfc-2632-const-trait-impl/assoc-type.stderr new file mode 100644 index 000000000..64501c523 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/assoc-type.stderr @@ -0,0 +1,25 @@ +error[E0277]: cannot add `NonConstAdd` to `NonConstAdd` in const contexts + --> $DIR/assoc-type.rs:18:16 + | +LL | type Bar = NonConstAdd; + | ^^^^^^^^^^^ no implementation for `NonConstAdd + NonConstAdd` + | + = help: the trait `~const Add` is not implemented for `NonConstAdd` +note: the trait `Add` is implemented for `NonConstAdd`, but that implementation is not `const` + --> $DIR/assoc-type.rs:18:16 + | +LL | type Bar = NonConstAdd; + | ^^^^^^^^^^^ +note: required by a bound in `Foo::Bar` + --> $DIR/assoc-type.rs:14:15 + | +LL | type Bar: ~const std::ops::Add; + | ^^^^^^^^^^^^^^^^^^^^ required by this bound in `Foo::Bar` +help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement + | +LL | impl const Foo for NonConstAdd where NonConstAdd: ~const Add { + | +++++++++++++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/rfc-2632-const-trait-impl/attr-misuse.rs b/src/test/ui/rfc-2632-const-trait-impl/attr-misuse.rs new file mode 100644 index 000000000..01ac74fef --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/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/src/test/ui/rfc-2632-const-trait-impl/attr-misuse.stderr b/src/test/ui/rfc-2632-const-trait-impl/attr-misuse.stderr new file mode 100644 index 000000000..b18f33218 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/attr-misuse.stderr @@ -0,0 +1,14 @@ +error: attribute should be applied to a trait + --> $DIR/attr-misuse.rs:9:1 + | +LL | #[const_trait] + | ^^^^^^^^^^^^^^ + +error: attribute should be applied to a trait + --> $DIR/attr-misuse.rs:5:5 + | +LL | #[const_trait] + | ^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/rfc-2632-const-trait-impl/auxiliary/cross-crate.rs b/src/test/ui/rfc-2632-const-trait-impl/auxiliary/cross-crate.rs new file mode 100644 index 000000000..e73082c11 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/auxiliary/cross-crate.rs @@ -0,0 +1,23 @@ +#![feature(const_trait_impl)] + +#[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/src/test/ui/rfc-2632-const-trait-impl/auxiliary/staged-api.rs b/src/test/ui/rfc-2632-const-trait-impl/auxiliary/staged-api.rs new file mode 100644 index 000000000..19e900609 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/auxiliary/staged-api.rs @@ -0,0 +1,18 @@ +#![feature(const_trait_impl)] +#![feature(staged_api)] +#![stable(feature = "rust1", since = "1.0.0")] + +#[stable(feature = "rust1", since = "1.0.0")] +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/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.rs b/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.rs new file mode 100644 index 000000000..24b9235bb --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.rs @@ -0,0 +1,29 @@ +#![feature(const_trait_impl)] + +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 + //~| ERROR cannot call non-const fn +} + +fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.stderr b/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.stderr new file mode 100644 index 000000000..1fc9db277 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.stderr @@ -0,0 +1,24 @@ +error[E0277]: the trait bound `u32: ~const Plus` is not satisfied + --> $DIR/call-const-trait-method-fail.rs:24:7 + | +LL | a.plus(b) + | ^^^^^^^ the trait `~const Plus` is not implemented for `u32` + | +note: the trait `Plus` is implemented for `u32`, but that implementation is not `const` + --> $DIR/call-const-trait-method-fail.rs:24:7 + | +LL | a.plus(b) + | ^^^^^^^ + +error[E0015]: cannot call non-const fn `<u32 as Plus>::plus` in constant functions + --> $DIR/call-const-trait-method-fail.rs:24:7 + | +LL | a.plus(b) + | ^^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0015, E0277. +For more information about an error, try `rustc --explain E0015`. diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-pass.rs b/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-pass.rs new file mode 100644 index 000000000..cf38bc3c9 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-pass.rs @@ -0,0 +1,42 @@ +// run-pass + +#![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) + } +} + +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/src/test/ui/rfc-2632-const-trait-impl/call-generic-in-impl.rs b/src/test/ui/rfc-2632-const-trait-impl/call-generic-in-impl.rs new file mode 100644 index 000000000..89dc47aad --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/call-generic-in-impl.rs @@ -0,0 +1,14 @@ +// check-pass +#![feature(const_trait_impl)] + +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/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-chain.rs b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-chain.rs new file mode 100644 index 000000000..b00ff1f2f --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-chain.rs @@ -0,0 +1,28 @@ +//! Basic test for calling methods on generic type parameters in `const fn`. + +// check-pass + +#![feature(const_trait_impl)] + +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/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-dup-bound.rs b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-dup-bound.rs new file mode 100644 index 000000000..c8ded0fa7 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-dup-bound.rs @@ -0,0 +1,31 @@ +// check-pass + +#![feature(const_trait_impl)] + +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/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-fail.rs b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-fail.rs new file mode 100644 index 000000000..2bc5ee512 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-fail.rs @@ -0,0 +1,8 @@ +#![feature(const_trait_impl)] + +pub const fn equals_self<T: PartialEq>(t: &T) -> bool { + *t == *t + //~^ ERROR can't compare +} + +fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-fail.stderr b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-fail.stderr new file mode 100644 index 000000000..83d395dda --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-fail.stderr @@ -0,0 +1,16 @@ +error[E0277]: can't compare `T` with `_` in const contexts + --> $DIR/call-generic-method-fail.rs:4:8 + | +LL | *t == *t + | ^^ no implementation for `T == _` + | +note: the trait `PartialEq<_>` is implemented for `T`, but that implementation is not `const` + --> $DIR/call-generic-method-fail.rs:4:8 + | +LL | *t == *t + | ^^ + = help: the trait `PartialEq<&B>` is implemented for `&A` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst-bound.rs b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst-bound.rs new file mode 100644 index 000000000..e197c8b73 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/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/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.rs b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.rs new file mode 100644 index 000000000..d3e14a53a --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.rs @@ -0,0 +1,21 @@ +#![feature(const_trait_impl)] + +struct S; + +impl PartialEq for S { + fn eq(&self, _: &S) -> bool { + true + } +} + +const fn equals_self<T: ~const PartialEq>(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 + +fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr new file mode 100644 index 000000000..0a2a5f0f2 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr @@ -0,0 +1,27 @@ +error[E0277]: can't compare `S` with `S` in const contexts + --> $DIR/call-generic-method-nonconst.rs:18:34 + | +LL | pub const EQ: bool = equals_self(&S); + | ----------- ^^ no implementation for `S == S` + | | + | required by a bound introduced by this call + | + = help: the trait `~const PartialEq` is not implemented for `S` +note: the trait `PartialEq` is implemented for `S`, but that implementation is not `const` + --> $DIR/call-generic-method-nonconst.rs:18:34 + | +LL | pub const EQ: bool = equals_self(&S); + | ^^ +note: required by a bound in `equals_self` + --> $DIR/call-generic-method-nonconst.rs:11:25 + | +LL | const fn equals_self<T: ~const PartialEq>(t: &T) -> bool { + | ^^^^^^^^^^^^^^^^ required by this bound in `equals_self` +help: consider annotating `S` with `#[derive(PartialEq)]` + | +LL | #[derive(PartialEq)] + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-pass.rs b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-pass.rs new file mode 100644 index 000000000..40565d1b7 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-pass.rs @@ -0,0 +1,24 @@ +//! Basic test for calling methods on generic type parameters in `const fn`. + +// check-pass + +#![feature(const_trait_impl)] + +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/src/test/ui/rfc-2632-const-trait-impl/const-and-non-const-impl.rs b/src/test/ui/rfc-2632-const-trait-impl/const-and-non-const-impl.rs new file mode 100644 index 000000000..f66d63da6 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/const-and-non-const-impl.rs @@ -0,0 +1,31 @@ +#![feature(const_trait_impl)] + +pub struct Int(i32); + +impl const std::ops::Add for i32 { + //~^ ERROR only traits defined in the current crate can be implemented for primitive types + 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 { + //~^ ERROR conflicting implementations of trait + type Output = Self; + + fn add(self, rhs: Self) -> Self { + Int(self.0 + rhs.0) + } +} + +fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-and-non-const-impl.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-and-non-const-impl.stderr new file mode 100644 index 000000000..f515ec198 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/const-and-non-const-impl.stderr @@ -0,0 +1,25 @@ +error[E0117]: only traits defined in the current crate can be implemented for primitive types + --> $DIR/const-and-non-const-impl.rs:5: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 + | impl doesn't use only types from inside the current crate + | + = note: define and implement a trait or new type instead + +error[E0119]: conflicting implementations of trait `std::ops::Add` for type `Int` + --> $DIR/const-and-non-const-impl.rs:22:1 + | +LL | impl std::ops::Add for Int { + | -------------------------- first implementation here +... +LL | impl const std::ops::Add for Int { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Int` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0117, E0119. +For more information about an error, try `rustc --explain E0117`. diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.rs b/src/test/ui/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.rs new file mode 100644 index 000000000..b3e3dd62b --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.rs @@ -0,0 +1,15 @@ +#![feature(const_trait_impl)] + +struct S; +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/src/test/ui/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.stderr new file mode 100644 index 000000000..9e49785c5 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.stderr @@ -0,0 +1,11 @@ +error[E0015]: cannot call non-const fn `non_const` in constant functions + --> $DIR/const-check-fns-in-const-impl.rs:11: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 previous error + +For more information about this error, try `rustc --explain E0015`. diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-closures.rs b/src/test/ui/rfc-2632-const-trait-impl/const-closures.rs new file mode 100644 index 000000000..755d85398 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/const-closures.rs @@ -0,0 +1,30 @@ +// run-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/src/test/ui/rfc-2632-const-trait-impl/const-default-method-bodies.rs b/src/test/ui/rfc-2632-const-trait-impl/const-default-method-bodies.rs new file mode 100644 index 000000000..140a06a73 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/const-default-method-bodies.rs @@ -0,0 +1,29 @@ +#![feature(const_trait_impl)] + +#[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 + ConstImpl.a(); +} + +fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-default-method-bodies.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-default-method-bodies.stderr new file mode 100644 index 000000000..ec724cc96 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/const-default-method-bodies.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `NonConstImpl: ~const ConstDefaultFn` is not satisfied + --> $DIR/const-default-method-bodies.rs:24:18 + | +LL | NonConstImpl.a(); + | ^ the trait `~const ConstDefaultFn` is not implemented for `NonConstImpl` + | +note: the trait `ConstDefaultFn` is implemented for `NonConstImpl`, but that implementation is not `const` + --> $DIR/const-default-method-bodies.rs:24:18 + | +LL | NonConstImpl.a(); + | ^ +help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement + | +LL | const fn test() where NonConstImpl: ~const ConstDefaultFn { + | +++++++++++++++++++++++++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-drop-bound.rs b/src/test/ui/rfc-2632-const-trait-impl/const-drop-bound.rs new file mode 100644 index 000000000..948f0efbc --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/const-drop-bound.rs @@ -0,0 +1,25 @@ +// 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/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr new file mode 100644 index 000000000..9dbaffd4c --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr @@ -0,0 +1,78 @@ +error[E0277]: can't drop `NonTrivialDrop` in const contexts + --> $DIR/const-drop-fail.rs:43:5 + | +LL | const _: () = check($exp); + | ----- required by a bound introduced by this call +... +LL | NonTrivialDrop, + | ^^^^^^^^^^^^^^ expected an implementor of trait `~const Destruct` + | + = note: the trait bound `NonTrivialDrop: ~const Destruct` is not satisfied +note: required by a bound in `check` + --> $DIR/const-drop-fail.rs:34:19 + | +LL | const fn check<T: ~const Destruct>(_: T) {} + | ^^^^^^^^^^^^^^^ required by this bound in `check` +help: consider borrowing here + | +LL | &NonTrivialDrop, + | + +LL | &mut NonTrivialDrop, + | ++++ + +error[E0277]: can't drop `NonTrivialDrop` in const contexts + --> $DIR/const-drop-fail.rs:45:5 + | +LL | const _: () = check($exp); + | ----- required by a bound introduced by this call +... +LL | ConstImplWithDropGlue(NonTrivialDrop), + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `ConstImplWithDropGlue`, the trait `~const Destruct` is not implemented for `NonTrivialDrop` + | +note: the trait `Destruct` is implemented for `NonTrivialDrop`, but that implementation is not `const` + --> $DIR/const-drop-fail.rs:45:5 + | +LL | ConstImplWithDropGlue(NonTrivialDrop), + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: required because it appears within the type `ConstImplWithDropGlue` + --> $DIR/const-drop-fail.rs:16:8 + | +LL | struct ConstImplWithDropGlue(NonTrivialDrop); + | ^^^^^^^^^^^^^^^^^^^^^ +note: required by a bound in `check` + --> $DIR/const-drop-fail.rs:34:19 + | +LL | const fn check<T: ~const Destruct>(_: T) {} + | ^^^^^^^^^^^^^^^ required by this bound in `check` + +error[E0277]: the trait bound `ConstDropImplWithBounds<NonTrivialDrop>: ~const Destruct` is not satisfied + --> $DIR/const-drop-fail.rs:47:5 + | +LL | const _: () = check($exp); + | ----- required by a bound introduced by this call +... +LL | ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData), + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected an implementor of trait `~const Destruct` + | +note: required because of the requirements on the impl of `~const Destruct` for `ConstDropImplWithBounds<NonTrivialDrop>` + --> $DIR/const-drop-fail.rs:28:25 + | +LL | impl<T: ~const A> const Drop for ConstDropImplWithBounds<T> { + | ^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: 1 redundant requirement hidden + = note: required because of the requirements on the impl of `~const Destruct` for `ConstDropImplWithBounds<NonTrivialDrop>` +note: required by a bound in `check` + --> $DIR/const-drop-fail.rs:34:19 + | +LL | const fn check<T: ~const Destruct>(_: T) {} + | ^^^^^^^^^^^^^^^ required by this bound in `check` +help: consider borrowing here + | +LL | &ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData), + | + +LL | &mut ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData), + | ++++ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.rs b/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.rs new file mode 100644 index 000000000..001dd430a --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.rs @@ -0,0 +1,51 @@ +// revisions: stock precise +#![feature(const_trait_impl)] +#![feature(const_mut_refs)] +#![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) {} +} + +trait A { fn a() { println!("A"); } } + +impl A for NonTrivialDrop {} + +struct ConstDropImplWithBounds<T: A>(PhantomData<T>); + +impl<T: ~const A> const Drop for ConstDropImplWithBounds<T> { + fn drop(&mut self) { + T::a(); + } +} + +const fn check<T: ~const Destruct>(_: T) {} + +macro_rules! check_all { + ($($exp:expr),*$(,)?) => {$( + const _: () = check($exp); + )*}; +} + +check_all! { + NonTrivialDrop, + //~^ ERROR can't drop + ConstImplWithDropGlue(NonTrivialDrop), + //~^ ERROR can't drop + ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData), + //~^ ERROR the trait bound +} + +fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr new file mode 100644 index 000000000..9dbaffd4c --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr @@ -0,0 +1,78 @@ +error[E0277]: can't drop `NonTrivialDrop` in const contexts + --> $DIR/const-drop-fail.rs:43:5 + | +LL | const _: () = check($exp); + | ----- required by a bound introduced by this call +... +LL | NonTrivialDrop, + | ^^^^^^^^^^^^^^ expected an implementor of trait `~const Destruct` + | + = note: the trait bound `NonTrivialDrop: ~const Destruct` is not satisfied +note: required by a bound in `check` + --> $DIR/const-drop-fail.rs:34:19 + | +LL | const fn check<T: ~const Destruct>(_: T) {} + | ^^^^^^^^^^^^^^^ required by this bound in `check` +help: consider borrowing here + | +LL | &NonTrivialDrop, + | + +LL | &mut NonTrivialDrop, + | ++++ + +error[E0277]: can't drop `NonTrivialDrop` in const contexts + --> $DIR/const-drop-fail.rs:45:5 + | +LL | const _: () = check($exp); + | ----- required by a bound introduced by this call +... +LL | ConstImplWithDropGlue(NonTrivialDrop), + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `ConstImplWithDropGlue`, the trait `~const Destruct` is not implemented for `NonTrivialDrop` + | +note: the trait `Destruct` is implemented for `NonTrivialDrop`, but that implementation is not `const` + --> $DIR/const-drop-fail.rs:45:5 + | +LL | ConstImplWithDropGlue(NonTrivialDrop), + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: required because it appears within the type `ConstImplWithDropGlue` + --> $DIR/const-drop-fail.rs:16:8 + | +LL | struct ConstImplWithDropGlue(NonTrivialDrop); + | ^^^^^^^^^^^^^^^^^^^^^ +note: required by a bound in `check` + --> $DIR/const-drop-fail.rs:34:19 + | +LL | const fn check<T: ~const Destruct>(_: T) {} + | ^^^^^^^^^^^^^^^ required by this bound in `check` + +error[E0277]: the trait bound `ConstDropImplWithBounds<NonTrivialDrop>: ~const Destruct` is not satisfied + --> $DIR/const-drop-fail.rs:47:5 + | +LL | const _: () = check($exp); + | ----- required by a bound introduced by this call +... +LL | ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData), + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected an implementor of trait `~const Destruct` + | +note: required because of the requirements on the impl of `~const Destruct` for `ConstDropImplWithBounds<NonTrivialDrop>` + --> $DIR/const-drop-fail.rs:28:25 + | +LL | impl<T: ~const A> const Drop for ConstDropImplWithBounds<T> { + | ^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: 1 redundant requirement hidden + = note: required because of the requirements on the impl of `~const Destruct` for `ConstDropImplWithBounds<NonTrivialDrop>` +note: required by a bound in `check` + --> $DIR/const-drop-fail.rs:34:19 + | +LL | const fn check<T: ~const Destruct>(_: T) {} + | ^^^^^^^^^^^^^^^ required by this bound in `check` +help: consider borrowing here + | +LL | &ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData), + | + +LL | &mut ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData), + | ++++ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-drop.rs b/src/test/ui/rfc-2632-const-trait-impl/const-drop.rs new file mode 100644 index 000000000..04462c0a1 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/const-drop.rs @@ -0,0 +1,112 @@ +// run-pass +// revisions: stock precise +#![feature(const_trait_impl)] +#![feature(const_mut_refs)] +#![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) {} + +const fn b() -> u8 { + let mut c = 0; + let _ = S(&mut c); + 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); + + pub trait SomeTrait { + fn foo(); + } + impl const SomeTrait for () { + fn foo() {} + } + // non-const impl + impl SomeTrait for i32 { + fn foo() {} + } + + pub struct ConstDropWithBound<T: 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(unused_tuple_struct_fields)] 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/src/test/ui/rfc-2632-const-trait-impl/const-impl-norecover.rs b/src/test/ui/rfc-2632-const-trait-impl/const-impl-norecover.rs new file mode 100644 index 000000000..bed4e9fd1 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/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/src/test/ui/rfc-2632-const-trait-impl/const-impl-norecover.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-impl-norecover.stderr new file mode 100644 index 000000000..603f6b7d2 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/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 previous error + diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-impl-recovery.rs b/src/test/ui/rfc-2632-const-trait-impl/const-impl-recovery.rs new file mode 100644 index 000000000..470c653dd --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/const-impl-recovery.rs @@ -0,0 +1,15 @@ +#![feature(const_trait_impl)] + +trait Foo {} + +const impl Foo for i32 {} //~ ERROR: expected identifier, found keyword + +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/src/test/ui/rfc-2632-const-trait-impl/const-impl-recovery.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-impl-recovery.stderr new file mode 100644 index 000000000..709084c86 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/const-impl-recovery.stderr @@ -0,0 +1,26 @@ +error: expected identifier, found keyword `impl` + --> $DIR/const-impl-recovery.rs:5: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:9: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/src/test/ui/rfc-2632-const-trait-impl/cross-crate-default-method-body-is-const.rs b/src/test/ui/rfc-2632-const-trait-impl/cross-crate-default-method-body-is-const.rs new file mode 100644 index 000000000..bde8bf20f --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/cross-crate-default-method-body-is-const.rs @@ -0,0 +1,18 @@ +// This tests that `const_trait` default methods can +// be called from a const context when used across crates. +// +// check-pass + +#![feature(const_trait_impl)] + +// aux-build: cross-crate.rs +extern crate cross_crate; + +use cross_crate::*; + +const _: () = { + Const.func(); + Const.defaulted_func(); +}; + +fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/cross-crate.gatednc.stderr b/src/test/ui/rfc-2632-const-trait-impl/cross-crate.gatednc.stderr new file mode 100644 index 000000000..174c62912 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/cross-crate.gatednc.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `cross_crate::NonConst: ~const cross_crate::MyTrait` is not satisfied + --> $DIR/cross-crate.rs:17:14 + | +LL | NonConst.func(); + | ^^^^ the trait `~const cross_crate::MyTrait` is not implemented for `cross_crate::NonConst` + | +note: the trait `cross_crate::MyTrait` is implemented for `cross_crate::NonConst`, but that implementation is not `const` + --> $DIR/cross-crate.rs:17:14 + | +LL | NonConst.func(); + | ^^^^ +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: ~const cross_crate::MyTrait { + | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/rfc-2632-const-trait-impl/cross-crate.rs b/src/test/ui/rfc-2632-const-trait-impl/cross-crate.rs new file mode 100644 index 000000000..6df47022c --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/cross-crate.rs @@ -0,0 +1,24 @@ +// revisions: stock gated stocknc gatednc +// [gated] check-pass +#![cfg_attr(any(gated, gatednc), feature(const_trait_impl))] + +// 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: the trait bound + //[gatednc]~^^ ERROR: the trait bound + Const.func(); + //[stock]~^ ERROR: cannot call +} + +fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/cross-crate.stock.stderr b/src/test/ui/rfc-2632-const-trait-impl/cross-crate.stock.stderr new file mode 100644 index 000000000..086547542 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/cross-crate.stock.stderr @@ -0,0 +1,11 @@ +error[E0015]: cannot call non-const fn `<cross_crate::Const as cross_crate::MyTrait>::func` in constant functions + --> $DIR/cross-crate.rs:20:11 + | +LL | Const.func(); + | ^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0015`. diff --git a/src/test/ui/rfc-2632-const-trait-impl/cross-crate.stocknc.stderr b/src/test/ui/rfc-2632-const-trait-impl/cross-crate.stocknc.stderr new file mode 100644 index 000000000..4619dd113 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/cross-crate.stocknc.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `cross_crate::NonConst: cross_crate::MyTrait` is not satisfied + --> $DIR/cross-crate.rs:17:14 + | +LL | NonConst.func(); + | ^^^^ the trait `~const cross_crate::MyTrait` is not implemented for `cross_crate::NonConst` + | +note: the trait `cross_crate::MyTrait` is implemented for `cross_crate::NonConst`, but that implementation is not `const` + --> $DIR/cross-crate.rs:17:14 + | +LL | NonConst.func(); + | ^^^^ +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: ~const cross_crate::MyTrait { + | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-body-checking.rs b/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-body-checking.rs new file mode 100644 index 000000000..d27291231 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-body-checking.rs @@ -0,0 +1,16 @@ +#![feature(const_trait_impl)] + +trait Tr {} +impl Tr for () {} + +const fn foo<T>() where T: ~const Tr {} + +#[const_trait] +pub trait Foo { + fn foo() { + foo::<()>(); + //~^ ERROR the trait bound `(): ~const Tr` is not satisfied + } +} + +fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-body-checking.stderr b/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-body-checking.stderr new file mode 100644 index 000000000..7542b81fe --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-body-checking.stderr @@ -0,0 +1,24 @@ +error[E0277]: the trait bound `(): ~const Tr` is not satisfied + --> $DIR/default-method-body-is-const-body-checking.rs:11:15 + | +LL | foo::<()>(); + | ^^ the trait `~const Tr` is not implemented for `()` + | +note: the trait `Tr` is implemented for `()`, but that implementation is not `const` + --> $DIR/default-method-body-is-const-body-checking.rs:11:15 + | +LL | foo::<()>(); + | ^^ +note: required by a bound in `foo` + --> $DIR/default-method-body-is-const-body-checking.rs:6:28 + | +LL | const fn foo<T>() where T: ~const Tr {} + | ^^^^^^^^^ required by this bound in `foo` +help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement + | +LL | pub trait Foo where (): ~const Tr { + | +++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.rs b/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.rs new file mode 100644 index 000000000..f70ecbc37 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.rs @@ -0,0 +1,15 @@ +#![feature(const_trait_impl)] + +#[const_trait] +pub trait Tr { + fn a(&self) {} + + fn b(&self) { + ().a() + //~^ ERROR the trait bound + } +} + +impl Tr for () {} + +fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.stderr b/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.stderr new file mode 100644 index 000000000..b229053eb --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `(): ~const Tr` is not satisfied + --> $DIR/default-method-body-is-const-same-trait-ck.rs:8:12 + | +LL | ().a() + | ^ the trait `~const Tr` is not implemented for `()` + | +note: the trait `Tr` is implemented for `()`, but that implementation is not `const` + --> $DIR/default-method-body-is-const-same-trait-ck.rs:8:12 + | +LL | ().a() + | ^ +help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement + | +LL | pub trait Tr where (): ~const Tr { + | +++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-with-staged-api.rs b/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-with-staged-api.rs new file mode 100644 index 000000000..1b45cd9aa --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/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(since = "1", feature = "foo")] + +#[const_trait] +trait Tr { + fn a() {} +} + +fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/feature-gate.gated.stderr b/src/test/ui/rfc-2632-const-trait-impl/feature-gate.gated.stderr new file mode 100644 index 000000000..af4d3909e --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/feature-gate.gated.stderr @@ -0,0 +1,8 @@ +error: fatal error triggered by #[rustc_error] + --> $DIR/feature-gate.rs:13:1 + | +LL | fn main() {} + | ^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/rfc-2632-const-trait-impl/feature-gate.rs b/src/test/ui/rfc-2632-const-trait-impl/feature-gate.rs new file mode 100644 index 000000000..7bac72e1b --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/feature-gate.rs @@ -0,0 +1,13 @@ +// revisions: stock gated +// gate-test-const_trait_impl + +#![cfg_attr(gated, feature(const_trait_impl))] +#![feature(rustc_attrs)] + +struct S; +trait T {} +impl const T for S {} +//[stock]~^ ERROR const trait impls are experimental + +#[rustc_error] +fn main() {} //[gated]~ ERROR fatal error triggered by #[rustc_error] diff --git a/src/test/ui/rfc-2632-const-trait-impl/feature-gate.stock.stderr b/src/test/ui/rfc-2632-const-trait-impl/feature-gate.stock.stderr new file mode 100644 index 000000000..91a8bb578 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/feature-gate.stock.stderr @@ -0,0 +1,12 @@ +error[E0658]: const trait impls are experimental + --> $DIR/feature-gate.rs:9: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 + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/rfc-2632-const-trait-impl/generic-bound.rs b/src/test/ui/rfc-2632-const-trait-impl/generic-bound.rs new file mode 100644 index 000000000..5495b531c --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/generic-bound.rs @@ -0,0 +1,30 @@ +// run-pass + +#![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/src/test/ui/rfc-2632-const-trait-impl/hir-const-check.rs b/src/test/ui/rfc-2632-const-trait-impl/hir-const-check.rs new file mode 100644 index 000000000..80a4442de --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/hir-const-check.rs @@ -0,0 +1,16 @@ +// Regression test for #69615. + +#![feature(const_trait_impl)] + +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/src/test/ui/rfc-2632-const-trait-impl/hir-const-check.stderr b/src/test/ui/rfc-2632-const-trait-impl/hir-const-check.stderr new file mode 100644 index 000000000..32df63e44 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/hir-const-check.stderr @@ -0,0 +1,12 @@ +error[E0658]: `?` is not allowed in a `const fn` + --> $DIR/hir-const-check.rs:11: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 + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/rfc-2632-const-trait-impl/impl-tilde-const-trait.rs b/src/test/ui/rfc-2632-const-trait-impl/impl-tilde-const-trait.rs new file mode 100644 index 000000000..05b26465c --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/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/src/test/ui/rfc-2632-const-trait-impl/impl-tilde-const-trait.stderr b/src/test/ui/rfc-2632-const-trait-impl/impl-tilde-const-trait.stderr new file mode 100644 index 000000000..0a91719e1 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/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 previous error + diff --git a/src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn-fail.rs b/src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn-fail.rs new file mode 100644 index 000000000..6df9696f2 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn-fail.rs @@ -0,0 +1,17 @@ +#![feature(const_trait_impl)] + +#[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/src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn-fail.stderr b/src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn-fail.stderr new file mode 100644 index 000000000..6c6ca9f5d --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn-fail.stderr @@ -0,0 +1,12 @@ +error[E0046]: not all trait items implemented, missing: `req` + --> $DIR/impl-with-default-fn-fail.rs:12:1 + | +LL | fn req(&self); + | -------------- `req` from trait +... +LL | impl const Tr for u16 { + | ^^^^^^^^^^^^^^^^^^^^^ missing `req` in implementation + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0046`. diff --git a/src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn-pass.rs b/src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn-pass.rs new file mode 100644 index 000000000..ae81421e9 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn-pass.rs @@ -0,0 +1,26 @@ +// check-pass + +#![feature(const_trait_impl)] + +#[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/src/test/ui/rfc-2632-const-trait-impl/inherent-impl-const-bounds.rs b/src/test/ui/rfc-2632-const-trait-impl/inherent-impl-const-bounds.rs new file mode 100644 index 000000000..2cef803a9 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/inherent-impl-const-bounds.rs @@ -0,0 +1,20 @@ +// check-pass +#![feature(const_trait_impl)] + +struct S; + +trait A {} +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/src/test/ui/rfc-2632-const-trait-impl/inherent-impl.rs b/src/test/ui/rfc-2632-const-trait-impl/inherent-impl.rs new file mode 100644 index 000000000..afd0d137b --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/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/src/test/ui/rfc-2632-const-trait-impl/inherent-impl.stderr b/src/test/ui/rfc-2632-const-trait-impl/inherent-impl.stderr new file mode 100644 index 000000000..8c5562703 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/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/src/test/ui/rfc-2632-const-trait-impl/issue-88155.rs b/src/test/ui/rfc-2632-const-trait-impl/issue-88155.rs new file mode 100644 index 000000000..b132c395a --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/issue-88155.rs @@ -0,0 +1,13 @@ +#![feature(const_trait_impl)] + +pub trait A { + fn assoc() -> bool; +} + +pub const fn foo<T: A>() -> bool { + T::assoc() + //~^ ERROR the trait bound + //~| ERROR cannot call non-const fn +} + +fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/issue-88155.stderr b/src/test/ui/rfc-2632-const-trait-impl/issue-88155.stderr new file mode 100644 index 000000000..955923505 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/issue-88155.stderr @@ -0,0 +1,24 @@ +error[E0277]: the trait bound `T: ~const A` is not satisfied + --> $DIR/issue-88155.rs:8:5 + | +LL | T::assoc() + | ^^^^^^^^^^ the trait `~const A` is not implemented for `T` + | +note: the trait `A` is implemented for `T`, but that implementation is not `const` + --> $DIR/issue-88155.rs:8:5 + | +LL | T::assoc() + | ^^^^^^^^^^ + +error[E0015]: cannot call non-const fn `<T as A>::assoc` in constant functions + --> $DIR/issue-88155.rs:8:5 + | +LL | T::assoc() + | ^^^^^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0015, E0277. +For more information about an error, try `rustc --explain E0015`. diff --git a/src/test/ui/rfc-2632-const-trait-impl/issue-92111.rs b/src/test/ui/rfc-2632-const-trait-impl/issue-92111.rs new file mode 100644 index 000000000..96a3e386e --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/issue-92111.rs @@ -0,0 +1,23 @@ +// Regression test for #92111. +// +// 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/src/test/ui/rfc-2632-const-trait-impl/issue-92230-wf-super-trait-env.rs b/src/test/ui/rfc-2632-const-trait-impl/issue-92230-wf-super-trait-env.rs new file mode 100644 index 000000000..97c27ce1a --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/issue-92230-wf-super-trait-env.rs @@ -0,0 +1,13 @@ +// Regression test for #92230. +// +// check-pass + +#![feature(const_trait_impl)] + +pub trait Super {} +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/src/test/ui/rfc-2632-const-trait-impl/non-const-op-in-closure-in-const.rs b/src/test/ui/rfc-2632-const-trait-impl/non-const-op-in-closure-in-const.rs new file mode 100644 index 000000000..defef9e04 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/non-const-op-in-closure-in-const.rs @@ -0,0 +1,17 @@ +// check-pass + +#![feature(const_trait_impl)] + +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/src/test/ui/rfc-2632-const-trait-impl/staged-api-user-crate.rs b/src/test/ui/rfc-2632-const-trait-impl/staged-api-user-crate.rs new file mode 100644 index 000000000..fc0d82727 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/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/src/test/ui/rfc-2632-const-trait-impl/staged-api-user-crate.stderr b/src/test/ui/rfc-2632-const-trait-impl/staged-api-user-crate.stderr new file mode 100644 index 000000000..61f9840e0 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/staged-api-user-crate.stderr @@ -0,0 +1,11 @@ +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 + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0015`. diff --git a/src/test/ui/rfc-2632-const-trait-impl/staged-api.rs b/src/test/ui/rfc-2632-const-trait-impl/staged-api.rs new file mode 100644 index 000000000..1d79f5adf --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/staged-api.rs @@ -0,0 +1,63 @@ +// revisions: stable unstable + +#![cfg_attr(unstable, feature(unstable))] // The feature from the ./auxiliary/staged-api.rs file. +#![feature(const_trait_impl)] +#![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(); + // ^ This is okay regardless of whether the `unstable` feature is enabled, as this function is + // not const-stable. + 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(); + // ^ This is okay regardless of whether the `unstable` feature is enabled, as this function is + // not const-stable. + 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(); + //[unstable]~^ 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/src/test/ui/rfc-2632-const-trait-impl/staged-api.stable.stderr b/src/test/ui/rfc-2632-const-trait-impl/staged-api.stable.stderr new file mode 100644 index 000000000..a1aca762e --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/staged-api.stable.stderr @@ -0,0 +1,25 @@ +error: trait implementations cannot be const stable yet + --> $DIR/staged-api.rs:19: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:42:1 + | +LL | / pub const fn const_context_not_const_stable() { +LL | | +LL | | Unstable::func(); +LL | | // ^ This is okay regardless of whether the `unstable` feature is enabled, as this function is +... | +LL | | // ^ fails, because the `foo` feature is not active +LL | | } + | |_^ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/rfc-2632-const-trait-impl/staged-api.unstable.stderr b/src/test/ui/rfc-2632-const-trait-impl/staged-api.unstable.stderr new file mode 100644 index 000000000..c38d1a81a --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/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:35: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/src/test/ui/rfc-2632-const-trait-impl/std-impl-gate.rs b/src/test/ui/rfc-2632-const-trait-impl/std-impl-gate.rs new file mode 100644 index 000000000..2f54c09e3 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/std-impl-gate.rs @@ -0,0 +1,21 @@ +// This tests feature gates for const impls in the standard library. + +// revisions: stock gated +//[gated] run-pass + +#![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/src/test/ui/rfc-2632-const-trait-impl/std-impl-gate.stock.stderr b/src/test/ui/rfc-2632-const-trait-impl/std-impl-gate.stock.stderr new file mode 100644 index 000000000..0b450a947 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/std-impl-gate.stock.stderr @@ -0,0 +1,11 @@ +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 + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0015`. diff --git a/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.rs b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.rs new file mode 100644 index 000000000..7b38c15af --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.rs @@ -0,0 +1,14 @@ +#![feature(const_trait_impl)] + +trait Foo { + fn a(&self); +} +trait Bar: ~const Foo {} + +const fn foo<T: Bar>(x: &T) { + x.a(); + //~^ ERROR the trait bound + //~| ERROR cannot call +} + +fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.stderr b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.stderr new file mode 100644 index 000000000..1766cdbee --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.stderr @@ -0,0 +1,24 @@ +error[E0277]: the trait bound `T: ~const Foo` is not satisfied + --> $DIR/super-traits-fail-2.rs:9:7 + | +LL | x.a(); + | ^^^ the trait `~const Foo` is not implemented for `T` + | +note: the trait `Foo` is implemented for `T`, but that implementation is not `const` + --> $DIR/super-traits-fail-2.rs:9:7 + | +LL | x.a(); + | ^^^ + +error[E0015]: cannot call non-const fn `<T as Foo>::a` in constant functions + --> $DIR/super-traits-fail-2.rs:9:7 + | +LL | x.a(); + | ^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0015, E0277. +For more information about an error, try `rustc --explain E0015`. diff --git a/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail.rs b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail.rs new file mode 100644 index 000000000..af465cad3 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail.rs @@ -0,0 +1,16 @@ +#![feature(const_trait_impl)] + +trait Foo { + fn a(&self); +} +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/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail.stderr b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail.stderr new file mode 100644 index 000000000..9e8b8f8c6 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail.stderr @@ -0,0 +1,24 @@ +error[E0277]: the trait bound `S: ~const Foo` is not satisfied + --> $DIR/super-traits-fail.rs:13:12 + | +LL | impl const Bar for S {} + | ^^^ the trait `~const Foo` is not implemented for `S` + | +note: the trait `Foo` is implemented for `S`, but that implementation is not `const` + --> $DIR/super-traits-fail.rs:13:12 + | +LL | impl const Bar for S {} + | ^^^ +note: required by a bound in `Bar` + --> $DIR/super-traits-fail.rs:6:12 + | +LL | trait Bar: ~const Foo {} + | ^^^^^^^^^^ required by this bound in `Bar` +help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement + | +LL | impl const Bar for S where S: ~const Foo {} + | +++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/rfc-2632-const-trait-impl/super-traits.rs b/src/test/ui/rfc-2632-const-trait-impl/super-traits.rs new file mode 100644 index 000000000..aded4ca9a --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/super-traits.rs @@ -0,0 +1,22 @@ +// check-pass +#![feature(const_trait_impl)] + +trait Foo { + fn a(&self); +} +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/src/test/ui/rfc-2632-const-trait-impl/syntax.rs b/src/test/ui/rfc-2632-const-trait-impl/syntax.rs new file mode 100644 index 000000000..7ac2458e3 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/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/src/test/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.rs b/src/test/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.rs new file mode 100644 index 000000000..b4302f3e7 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.rs @@ -0,0 +1,29 @@ +#![feature(const_trait_impl)] +#![feature(associated_type_bounds)] + +trait T {} +struct S; +impl T for S {} + +fn rpit() -> impl ~const T { S } +//~^ ERROR `~const` is not allowed + +fn apit(_: impl ~const T) {} +//~^ ERROR `~const` is not allowed + +fn rpit_assoc_bound() -> impl IntoIterator<Item: ~const T> { Some(S) } +//~^ ERROR `~const` is not allowed + +fn apit_assoc_bound(_: impl IntoIterator<Item: ~const T>) {} +//~^ ERROR `~const` is not allowed + +fn generic<P: ~const T>() {} +//~^ ERROR `~const` is not allowed + +fn where_clause<P>() where P: ~const T {} +//~^ ERROR `~const` is not allowed + +struct TildeQuestion<T: ~const ?Sized>(std::marker::PhantomData<T>); +//~^ ERROR `~const` and `?` are mutually exclusive + +fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.stderr b/src/test/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.stderr new file mode 100644 index 000000000..033ec21ba --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.stderr @@ -0,0 +1,56 @@ +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:8:19 + | +LL | fn rpit() -> impl ~const T { S } + | ^^^^^^^^ + | + = note: only allowed on bounds on traits' associated types and functions, const fns, const impls and its associated functions + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:11:17 + | +LL | fn apit(_: impl ~const T) {} + | ^^^^^^^^ + | + = note: only allowed on bounds on traits' associated types and functions, const fns, const impls and its associated functions + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:14:50 + | +LL | fn rpit_assoc_bound() -> impl IntoIterator<Item: ~const T> { Some(S) } + | ^^^^^^^^ + | + = note: only allowed on bounds on traits' associated types and functions, const fns, const impls and its associated functions + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:17:48 + | +LL | fn apit_assoc_bound(_: impl IntoIterator<Item: ~const T>) {} + | ^^^^^^^^ + | + = note: only allowed on bounds on traits' associated types and functions, const fns, const impls and its associated functions + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:20:15 + | +LL | fn generic<P: ~const T>() {} + | ^^^^^^^^ + | + = note: only allowed on bounds on traits' associated types and functions, const fns, const impls and its associated functions + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:23:31 + | +LL | fn where_clause<P>() where P: ~const T {} + | ^^^^^^^^ + | + = note: only allowed on bounds on traits' associated types and functions, const fns, const impls and its associated functions + +error: `~const` and `?` are mutually exclusive + --> $DIR/tilde-const-invalid-places.rs:26:25 + | +LL | struct TildeQuestion<T: ~const ?Sized>(std::marker::PhantomData<T>); + | ^^^^^^^^^^^^^ + +error: aborting due to 7 previous errors + diff --git a/src/test/ui/rfc-2632-const-trait-impl/tilde-const-syntax.rs b/src/test/ui/rfc-2632-const-trait-impl/tilde-const-syntax.rs new file mode 100644 index 000000000..9b3c2cf2a --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/tilde-const-syntax.rs @@ -0,0 +1,9 @@ +// compile-flags: -Z parse-only +// check-pass + +#![feature(const_trait_impl)] + +struct S< + T: ~const ?for<'a> Tr<'a> + 'static + ~const std::ops::Add, + T: ~const ?for<'a: 'b> m::Trait<'a>, +>; diff --git a/src/test/ui/rfc-2632-const-trait-impl/tilde-twice.rs b/src/test/ui/rfc-2632-const-trait-impl/tilde-twice.rs new file mode 100644 index 000000000..06e4ede8b --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/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/src/test/ui/rfc-2632-const-trait-impl/tilde-twice.stderr b/src/test/ui/rfc-2632-const-trait-impl/tilde-twice.stderr new file mode 100644 index 000000000..928d23e8a --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/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 previous error + diff --git a/src/test/ui/rfc-2632-const-trait-impl/trait-default-body-stability.rs b/src/test/ui/rfc-2632-const-trait-impl/trait-default-body-stability.rs new file mode 100644 index 000000000..334fc4cb8 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/trait-default-body-stability.rs @@ -0,0 +1,50 @@ +// check-pass + +#![feature(staged_api)] +#![feature(const_trait_impl)] +#![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/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause-run.rs b/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause-run.rs new file mode 100644 index 000000000..b7cf9a13b --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause-run.rs @@ -0,0 +1,40 @@ +// run-pass + +#![feature(const_trait_impl)] + +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/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause-self-referential.rs b/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause-self-referential.rs new file mode 100644 index 000000000..acea58eae --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause-self-referential.rs @@ -0,0 +1,23 @@ +// check-pass + +#![feature(const_trait_impl)] + +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/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause.rs b/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause.rs new file mode 100644 index 000000000..d37ed3bb8 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause.rs @@ -0,0 +1,39 @@ +#![feature(const_trait_impl)] + +trait Bar {} + +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 the trait bound + T::c::<T>(); + //~^ ERROR the trait bound +} + +const fn test2<T: ~const Foo + ~const Bar>() { + T::a(); + T::b(); + T::c::<T>(); +} + +fn test3<T: Foo>() { + T::a(); + T::b(); + //~^ ERROR the trait bound + T::c::<T>(); + //~^ ERROR the trait bound +} + +fn test4<T: Foo + Bar>() { + T::a(); + T::b(); + T::c::<T>(); +} + +fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause.stderr b/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause.stderr new file mode 100644 index 000000000..d5b2d2697 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause.stderr @@ -0,0 +1,77 @@ +error[E0277]: the trait bound `T: ~const Bar` is not satisfied + --> $DIR/trait-where-clause.rs:13:5 + | +LL | T::b(); + | ^^^^ the trait `~const Bar` is not implemented for `T` + | +note: the trait `Bar` is implemented for `T`, but that implementation is not `const` + --> $DIR/trait-where-clause.rs:13:5 + | +LL | T::b(); + | ^^^^ +note: required by a bound in `Foo::b` + --> $DIR/trait-where-clause.rs:7:24 + | +LL | fn b() where Self: ~const Bar; + | ^^^^^^^^^^ required by this bound in `Foo::b` +help: consider further restricting this bound + | +LL | const fn test1<T: ~const Foo + Bar + ~const Bar>() { + | ++++++++++++ + +error[E0277]: the trait bound `T: ~const Bar` is not satisfied + --> $DIR/trait-where-clause.rs:15:5 + | +LL | T::c::<T>(); + | ^^^^^^^^^ the trait `~const Bar` is not implemented for `T` + | +note: the trait `Bar` is implemented for `T`, but that implementation is not `const` + --> $DIR/trait-where-clause.rs:15:5 + | +LL | T::c::<T>(); + | ^^^^^^^^^ +note: required by a bound in `Foo::c` + --> $DIR/trait-where-clause.rs:8:13 + | +LL | fn c<T: ~const Bar>(); + | ^^^^^^^^^^ required by this bound in `Foo::c` +help: consider further restricting this bound + | +LL | const fn test1<T: ~const Foo + Bar + ~const Bar>() { + | ++++++++++++ + +error[E0277]: the trait bound `T: Bar` is not satisfied + --> $DIR/trait-where-clause.rs:27: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:7:24 + | +LL | fn b() where Self: ~const Bar; + | ^^^^^^^^^^ required by this bound in `Foo::b` +help: consider further restricting this bound + | +LL | fn test3<T: Foo + Bar>() { + | +++++ + +error[E0277]: the trait bound `T: Bar` is not satisfied + --> $DIR/trait-where-clause.rs:29:5 + | +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:8:13 + | +LL | fn c<T: ~const Bar>(); + | ^^^^^^^^^^ required by this bound in `Foo::c` +help: consider further restricting this bound + | +LL | fn test3<T: Foo + Bar>() { + | +++++ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/rfc-2632-const-trait-impl/without-tilde.rs b/src/test/ui/rfc-2632-const-trait-impl/without-tilde.rs new file mode 100644 index 000000000..e8b261545 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/without-tilde.rs @@ -0,0 +1,6 @@ +// compile-flags: -Z parse-only + +#![feature(const_trait_impl)] + +struct S<T: const Tr>; +//~^ ERROR expected one of `!`, `(`, `,`, `=`, `>`, `?`, `for`, `~`, lifetime, or path diff --git a/src/test/ui/rfc-2632-const-trait-impl/without-tilde.stderr b/src/test/ui/rfc-2632-const-trait-impl/without-tilde.stderr new file mode 100644 index 000000000..b6b77ac4a --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/without-tilde.stderr @@ -0,0 +1,8 @@ +error: expected one of `!`, `(`, `,`, `=`, `>`, `?`, `for`, `~`, lifetime, or path, found keyword `const` + --> $DIR/without-tilde.rs:5:13 + | +LL | struct S<T: const Tr>; + | ^^^^^ expected one of 10 possible tokens + +error: aborting due to previous error + |