From 523490e94ad6aabcc53a30919889ce60b4f327ee Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Sat, 28 Aug 2021 07:37:30 +0000 Subject: [PATCH 1/2] Allow `~const` bounds on trait assoc functions --- .../rustc_ast_passes/src/ast_validation.rs | 4 +-- .../tilde-const-invalid-places.stderr | 12 +++---- .../trait-where-clause.rs | 33 +++++++++++++++++ .../trait-where-clause.stderr | 35 +++++++++++++++++++ 4 files changed, 76 insertions(+), 8 deletions(-) create mode 100644 src/test/ui/rfc-2632-const-trait-impl/trait-where-clause.rs create mode 100644 src/test/ui/rfc-2632-const-trait-impl/trait-where-clause.stderr diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index c0ea710fdcb4e..5153f1861eaf1 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -1442,7 +1442,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { if !self.is_tilde_const_allowed { self.err_handler() .struct_span_err(bound.span(), "`~const` is not allowed here") - .note("only allowed on bounds on traits' associated types, const fns, const impls and its associated functions") + .note("only allowed on bounds on traits' associated types and functions, const fns, const impls and its associated functions") .emit(); } } @@ -1616,7 +1616,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { walk_list!(self, visit_ty, ty); } AssocItemKind::Fn(box FnKind(_, ref sig, ref generics, ref body)) - if self.in_const_trait_impl => + if self.in_const_trait_impl || ctxt == AssocCtxt::Trait => { self.visit_vis(&item.vis); self.visit_ident(item.ident); 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 index b026099f6829b..033ec21ba8408 100644 --- 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 @@ -4,7 +4,7 @@ error: `~const` is not allowed here LL | fn rpit() -> impl ~const T { S } | ^^^^^^^^ | - = note: only allowed on bounds on traits' associated types, const fns, const impls and its associated functions + = 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 @@ -12,7 +12,7 @@ error: `~const` is not allowed here LL | fn apit(_: impl ~const T) {} | ^^^^^^^^ | - = note: only allowed on bounds on traits' associated types, const fns, const impls and its associated functions + = 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 @@ -20,7 +20,7 @@ error: `~const` is not allowed here LL | fn rpit_assoc_bound() -> impl IntoIterator { Some(S) } | ^^^^^^^^ | - = note: only allowed on bounds on traits' associated types, const fns, const impls and its associated functions + = 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 @@ -28,7 +28,7 @@ error: `~const` is not allowed here LL | fn apit_assoc_bound(_: impl IntoIterator) {} | ^^^^^^^^ | - = note: only allowed on bounds on traits' associated types, const fns, const impls and its associated functions + = 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 @@ -36,7 +36,7 @@ error: `~const` is not allowed here LL | fn generic() {} | ^^^^^^^^ | - = note: only allowed on bounds on traits' associated types, const fns, const impls and its associated functions + = 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 @@ -44,7 +44,7 @@ error: `~const` is not allowed here LL | fn where_clause

() where P: ~const T {} | ^^^^^^^^ | - = note: only allowed on bounds on traits' associated types, const fns, const impls and its associated functions + = 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 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 0000000000000..7fcd791e722d4 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause.rs @@ -0,0 +1,33 @@ +#![feature(const_fn_trait_bound)] +#![feature(const_trait_impl)] + +trait Bar {} + +trait Foo { + fn a(); + fn b() where Self: ~const Bar; +} + +const fn test1() { + T::a(); + T::b(); + //~^ ERROR the trait bound +} + +const fn test2() { + T::a(); + T::b(); +} + +fn test3() { + T::a(); + T::b(); + //~^ ERROR the trait bound +} + +fn test4() { + T::a(); + T::b(); +} + +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 0000000000000..f70792ba55a4b --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause.stderr @@ -0,0 +1,35 @@ +error[E0277]: the trait bound `T: Bar` is not satisfied + --> $DIR/trait-where-clause.rs:13:5 + | +LL | T::b(); + | ^^^^ the trait `Bar` is not implemented for `T` + | +note: required by `Foo::b` + --> $DIR/trait-where-clause.rs:8:5 + | +LL | fn b() where Self: ~const Bar; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: consider further restricting this bound + | +LL | const fn test1() { + | +++++ + +error[E0277]: the trait bound `T: Bar` is not satisfied + --> $DIR/trait-where-clause.rs:24:5 + | +LL | T::b(); + | ^^^^ the trait `Bar` is not implemented for `T` + | +note: required by `Foo::b` + --> $DIR/trait-where-clause.rs:8:5 + | +LL | fn b() where Self: ~const Bar; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: consider further restricting this bound + | +LL | fn test3() { + | +++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. From ee02c8e20a5098e77251bb07cca5fe9b932c84d7 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Sat, 28 Aug 2021 15:53:26 +0000 Subject: [PATCH 2/2] Add test cases --- .../trait-where-clause-run.rs | 41 +++++++++++++++++++ .../trait-where-clause-self-referential.rs | 24 +++++++++++ .../trait-where-clause.rs | 7 ++++ .../trait-where-clause.stderr | 38 +++++++++++++++-- 4 files changed, 107 insertions(+), 3 deletions(-) create mode 100644 src/test/ui/rfc-2632-const-trait-impl/trait-where-clause-run.rs create mode 100644 src/test/ui/rfc-2632-const-trait-impl/trait-where-clause-self-referential.rs 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 0000000000000..0cde5b6f84218 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause-run.rs @@ -0,0 +1,41 @@ +// run-pass + +#![feature(const_trait_impl)] +#![feature(const_fn_trait_bound)] + +trait Bar { + fn bar() -> u8; +} + +trait Foo { + #[default_method_body_is_const] + fn foo() -> u8 where Self: ~const 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 0000000000000..ae9ab26cdc04a --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause-self-referential.rs @@ -0,0 +1,24 @@ +// check-pass + +#![feature(const_trait_impl)] +#![feature(const_fn_trait_bound)] + +trait Foo { + fn bar() where Self: ~const Foo; +} + +struct S; + +impl Foo for S { + fn bar() {} +} + +fn baz() { + T::bar(); +} + +const fn qux() { + 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 index 7fcd791e722d4..d64822d7ce8af 100644 --- 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 @@ -6,28 +6,35 @@ trait Bar {} trait Foo { fn a(); fn b() where Self: ~const Bar; + fn c(); } const fn test1() { T::a(); T::b(); //~^ ERROR the trait bound + T::c::(); + //~^ ERROR the trait bound } const fn test2() { T::a(); T::b(); + T::c::(); } fn test3() { T::a(); T::b(); //~^ ERROR the trait bound + T::c::(); + //~^ ERROR the trait bound } fn test4() { T::a(); T::b(); + T::c::(); } 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 index f70792ba55a4b..fffb91f98700b 100644 --- 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 @@ -1,5 +1,5 @@ error[E0277]: the trait bound `T: Bar` is not satisfied - --> $DIR/trait-where-clause.rs:13:5 + --> $DIR/trait-where-clause.rs:14:5 | LL | T::b(); | ^^^^ the trait `Bar` is not implemented for `T` @@ -15,7 +15,23 @@ LL | const fn test1() { | +++++ error[E0277]: the trait bound `T: Bar` is not satisfied - --> $DIR/trait-where-clause.rs:24:5 + --> $DIR/trait-where-clause.rs:16:5 + | +LL | T::c::(); + | ^^^^^^^^^ the trait `Bar` is not implemented for `T` + | +note: required by `Foo::c` + --> $DIR/trait-where-clause.rs:9:5 + | +LL | fn c(); + | ^^^^^^^^^^^^^^^^^^^^^^ +help: consider further restricting this bound + | +LL | const fn test1() { + | +++++ + +error[E0277]: the trait bound `T: Bar` is not satisfied + --> $DIR/trait-where-clause.rs:28:5 | LL | T::b(); | ^^^^ the trait `Bar` is not implemented for `T` @@ -30,6 +46,22 @@ help: consider further restricting this bound LL | fn test3() { | +++++ -error: aborting due to 2 previous errors +error[E0277]: the trait bound `T: Bar` is not satisfied + --> $DIR/trait-where-clause.rs:30:5 + | +LL | T::c::(); + | ^^^^^^^^^ the trait `Bar` is not implemented for `T` + | +note: required by `Foo::c` + --> $DIR/trait-where-clause.rs:9:5 + | +LL | fn c(); + | ^^^^^^^^^^^^^^^^^^^^^^ +help: consider further restricting this bound + | +LL | fn test3() { + | +++++ + +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0277`.