diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 73abd2bb83b9e6c82d672a7a9a2513b5384bb3d6..a243300edd9d2be480e3581bdcc970fe0edb3dff 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -1442,7 +1442,7 @@ fn visit_param_bound(&mut self, bound: &'a GenericBound) { 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 @@ fn visit_assoc_item(&mut self, item: &'a AssocItem, ctxt: AssocCtxt) { 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 b026099f6829b5e3b04099e5a23641dcb82fd1a0..033ec21ba8408defa7bc509cef0053531482df2c 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-run.rs b/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause-run.rs new file mode 100644 index 0000000000000000000000000000000000000000..0cde5b6f84218951370ff4b47730b7659be77ef8 --- /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 0000000000000000000000000000000000000000..ae9ab26cdc04ad708706007e9bc19e9dc742f512 --- /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 new file mode 100644 index 0000000000000000000000000000000000000000..d64822d7ce8af77a4d5296a668dfffe0c8551f5d --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause.rs @@ -0,0 +1,40 @@ +#![feature(const_fn_trait_bound)] +#![feature(const_trait_impl)] + +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 new file mode 100644 index 0000000000000000000000000000000000000000..fffb91f98700bdf8f9c9210468645a851944d9ca --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause.stderr @@ -0,0 +1,67 @@ +error[E0277]: the trait bound `T: Bar` is not satisfied + --> $DIR/trait-where-clause.rs:14: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: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` + | +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[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`.