about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_ast_passes/src/ast_validation.rs63
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/issue-90052.rs9
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/issue-90052.stderr14
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/tilde-const-and-const-params.rs2
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/tilde-const-and-const-params.stderr14
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.stderr8
6 files changed, 85 insertions, 25 deletions
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index 1a4c60087c3..f42aca685f6 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -38,6 +38,13 @@ enum SelfSemantic {
     No,
 }
 
+/// What is the context that prevents using `~const`?
+enum DisallowTildeConstContext<'a> {
+    TraitObject,
+    ImplTrait,
+    Fn(FnKind<'a>),
+}
+
 struct AstValidator<'a> {
     session: &'a Session,
 
@@ -56,7 +63,7 @@ struct AstValidator<'a> {
     /// e.g., `impl Iterator<Item = impl Debug>`.
     outer_impl_trait: Option<Span>,
 
-    is_tilde_const_allowed: bool,
+    disallow_tilde_const: Option<DisallowTildeConstContext<'a>>,
 
     /// Used to ban `impl Trait` in path projections like `<impl Iterator>::Item`
     /// or `Foo::Bar<impl Trait>`
@@ -93,18 +100,26 @@ impl<'a> AstValidator<'a> {
         self.is_impl_trait_banned = old;
     }
 
-    fn with_tilde_const(&mut self, allowed: bool, f: impl FnOnce(&mut Self)) {
-        let old = mem::replace(&mut self.is_tilde_const_allowed, allowed);
+    fn with_tilde_const(
+        &mut self,
+        disallowed: Option<DisallowTildeConstContext<'a>>,
+        f: impl FnOnce(&mut Self),
+    ) {
+        let old = mem::replace(&mut self.disallow_tilde_const, disallowed);
         f(self);
-        self.is_tilde_const_allowed = old;
+        self.disallow_tilde_const = old;
     }
 
     fn with_tilde_const_allowed(&mut self, f: impl FnOnce(&mut Self)) {
-        self.with_tilde_const(true, f)
+        self.with_tilde_const(None, f)
     }
 
-    fn with_banned_tilde_const(&mut self, f: impl FnOnce(&mut Self)) {
-        self.with_tilde_const(false, f)
+    fn with_banned_tilde_const(
+        &mut self,
+        ctx: DisallowTildeConstContext<'a>,
+        f: impl FnOnce(&mut Self),
+    ) {
+        self.with_tilde_const(Some(ctx), f)
     }
 
     fn with_let_management(
@@ -172,7 +187,7 @@ impl<'a> AstValidator<'a> {
     fn with_impl_trait(&mut self, outer: Option<Span>, f: impl FnOnce(&mut Self)) {
         let old = mem::replace(&mut self.outer_impl_trait, outer);
         if outer.is_some() {
-            self.with_banned_tilde_const(f);
+            self.with_banned_tilde_const(DisallowTildeConstContext::ImplTrait, f);
         } else {
             f(self);
         }
@@ -197,7 +212,10 @@ impl<'a> AstValidator<'a> {
             TyKind::ImplTrait(..) => {
                 self.with_impl_trait(Some(t.span), |this| visit::walk_ty(this, t))
             }
-            TyKind::TraitObject(..) => self.with_banned_tilde_const(|this| visit::walk_ty(this, t)),
+            TyKind::TraitObject(..) => self
+                .with_banned_tilde_const(DisallowTildeConstContext::TraitObject, |this| {
+                    visit::walk_ty(this, t)
+                }),
             TyKind::Path(ref qself, ref path) => {
                 // We allow these:
                 //  - `Option<impl Trait>`
@@ -1411,13 +1429,15 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                     );
                     err.emit();
                 }
-                (_, TraitBoundModifier::MaybeConst) => {
-                    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 functions, traits' associated types and functions, const impls and its associated functions")
-                            .emit();
-                    }
+                (_, TraitBoundModifier::MaybeConst) if let Some(reason) = &self.disallow_tilde_const => {
+                    let mut err = self.err_handler().struct_span_err(bound.span(), "`~const` is not allowed here");
+                    match reason {
+                        DisallowTildeConstContext::TraitObject => err.note("trait objects cannot have `~const` trait bounds"),
+                        DisallowTildeConstContext::ImplTrait => err.note("`impl Trait`s cannot have `~const` trait bounds"),
+                        DisallowTildeConstContext::Fn(FnKind::Closure(..)) => err.note("closures cannot have `~const` trait bounds"),
+                        DisallowTildeConstContext::Fn(FnKind::Fn(_, ident, ..)) => err.span_note(ident.span, "this function is not `const`, so it cannot have `~const` trait bounds"),
+                    };
+                    err.emit();
                 }
                 (_, TraitBoundModifier::MaybeConstMaybe) => {
                     self.err_handler()
@@ -1523,10 +1543,13 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
             });
         }
 
-        let tilde_const_allowed = matches!(fk.header(), Some(FnHeader { .. }))
-            || matches!(fk.ctxt(), Some(FnCtxt::Assoc(_)));
+        let tilde_const_allowed =
+            matches!(fk.header(), Some(FnHeader { constness: ast::Const::Yes(_), .. }))
+                || matches!(fk.ctxt(), Some(FnCtxt::Assoc(_)));
+
+        let disallowed = (!tilde_const_allowed).then(|| DisallowTildeConstContext::Fn(fk));
 
-        self.with_tilde_const(tilde_const_allowed, |this| visit::walk_fn(this, fk));
+        self.with_tilde_const(disallowed, |this| visit::walk_fn(this, fk));
     }
 
     fn visit_assoc_item(&mut self, item: &'a AssocItem, ctxt: AssocCtxt) {
@@ -1770,7 +1793,7 @@ pub fn check_crate(session: &Session, krate: &Crate, lints: &mut LintBuffer) ->
         in_const_trait_impl: false,
         has_proc_macro_decls: false,
         outer_impl_trait: None,
-        is_tilde_const_allowed: false,
+        disallow_tilde_const: None,
         is_impl_trait_banned: false,
         is_assoc_ty_bound_banned: false,
         forbidden_let_reason: Some(ForbiddenLetReason::GenericForbidden),
diff --git a/src/test/ui/rfc-2632-const-trait-impl/issue-90052.rs b/src/test/ui/rfc-2632-const-trait-impl/issue-90052.rs
new file mode 100644
index 00000000000..21ddf4ab4e5
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/issue-90052.rs
@@ -0,0 +1,9 @@
+#![feature(const_trait_impl)]
+
+#[const_trait]
+trait Bar {}
+
+fn foo<T>() where T: ~const Bar {}
+//~^ ERROR `~const` is not allowed
+
+fn main() {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/issue-90052.stderr b/src/test/ui/rfc-2632-const-trait-impl/issue-90052.stderr
new file mode 100644
index 00000000000..b2a9365378b
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/issue-90052.stderr
@@ -0,0 +1,14 @@
+error: `~const` is not allowed here
+  --> $DIR/issue-90052.rs:6:22
+   |
+LL | fn foo<T>() where T: ~const Bar {}
+   |                      ^^^^^^^^^^
+   |
+note: this function is not `const`, so it cannot have `~const` trait bounds
+  --> $DIR/issue-90052.rs:6:4
+   |
+LL | fn foo<T>() where T: ~const Bar {}
+   |    ^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/rfc-2632-const-trait-impl/tilde-const-and-const-params.rs b/src/test/ui/rfc-2632-const-trait-impl/tilde-const-and-const-params.rs
index b29b633cff6..78a64b9018a 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/tilde-const-and-const-params.rs
+++ b/src/test/ui/rfc-2632-const-trait-impl/tilde-const-and-const-params.rs
@@ -1,4 +1,3 @@
-// check-pass
 #![feature(const_trait_impl)]
 #![feature(generic_arg_infer)]
 #![feature(generic_const_exprs)]
@@ -24,6 +23,7 @@ impl const Add42 for () {
 }
 
 fn bar<A: ~const Add42, const N: usize>(_: Foo<N>) -> Foo<{ A::add(N) }> {
+    //~^ ERROR `~const` is not allowed here
     Foo
 }
 
diff --git a/src/test/ui/rfc-2632-const-trait-impl/tilde-const-and-const-params.stderr b/src/test/ui/rfc-2632-const-trait-impl/tilde-const-and-const-params.stderr
new file mode 100644
index 00000000000..aae72f36e57
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/tilde-const-and-const-params.stderr
@@ -0,0 +1,14 @@
+error: `~const` is not allowed here
+  --> $DIR/tilde-const-and-const-params.rs:25:11
+   |
+LL | fn bar<A: ~const Add42, const N: usize>(_: Foo<N>) -> Foo<{ A::add(N) }> {
+   |           ^^^^^^^^^^^^
+   |
+note: this function is not `const`, so it cannot have `~const` trait bounds
+  --> $DIR/tilde-const-and-const-params.rs:25:4
+   |
+LL | fn bar<A: ~const Add42, const N: usize>(_: Foo<N>) -> Foo<{ A::add(N) }> {
+   |    ^^^
+
+error: aborting due to previous error
+
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 5d213315634..84867cb4a53 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 functions, traits' associated types and functions, const impls and its associated functions
+   = note: `impl Trait`s cannot have `~const` trait bounds
 
 error: `~const` is not allowed here
   --> $DIR/tilde-const-invalid-places.rs:12:17
@@ -12,7 +12,7 @@ error: `~const` is not allowed here
 LL | fn apit(_: impl ~const T) {}
    |                 ^^^^^^^^
    |
-   = note: only allowed on bounds on functions, traits' associated types and functions, const impls and its associated functions
+   = note: `impl Trait`s cannot have `~const` trait bounds
 
 error: `~const` is not allowed here
   --> $DIR/tilde-const-invalid-places.rs:15:50
@@ -20,7 +20,7 @@ error: `~const` is not allowed here
 LL | fn rpit_assoc_bound() -> impl IntoIterator<Item: ~const T> { Some(S) }
    |                                                  ^^^^^^^^
    |
-   = note: only allowed on bounds on functions, traits' associated types and functions, const impls and its associated functions
+   = note: `impl Trait`s cannot have `~const` trait bounds
 
 error: `~const` is not allowed here
   --> $DIR/tilde-const-invalid-places.rs:18:48
@@ -28,7 +28,7 @@ error: `~const` is not allowed here
 LL | fn apit_assoc_bound(_: impl IntoIterator<Item: ~const T>) {}
    |                                                ^^^^^^^^
    |
-   = note: only allowed on bounds on functions, traits' associated types and functions, const impls and its associated functions
+   = note: `impl Trait`s cannot have `~const` trait bounds
 
 error: `~const` and `?` are mutually exclusive
   --> $DIR/tilde-const-invalid-places.rs:21:25