Skip to content

Commit

Permalink
Rollup merge of #103319 - fee1-dead-contrib:improve_tilde_const_msg, …
Browse files Browse the repository at this point in the history
…r=oli-obk

Improve "`~const` is not allowed here" message

r? `@oli-obk`
  • Loading branch information
matthiaskrgr authored Oct 20, 2022
2 parents 801e326 + ebf5028 commit f9944a9
Show file tree
Hide file tree
Showing 6 changed files with 85 additions and 25 deletions.
63 changes: 43 additions & 20 deletions compiler/rustc_ast_passes/src/ast_validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,

Expand All @@ -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>`
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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);
}
Expand All @@ -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>`
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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),
Expand Down
9 changes: 9 additions & 0 deletions src/test/ui/rfc-2632-const-trait-impl/issue-90052.rs
Original file line number Diff line number Diff line change
@@ -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() {}
14 changes: 14 additions & 0 deletions src/test/ui/rfc-2632-const-trait-impl/issue-90052.stderr
Original file line number Diff line number Diff line change
@@ -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

Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
// check-pass
#![feature(const_trait_impl)]
#![feature(generic_arg_infer)]
#![feature(generic_const_exprs)]
Expand All @@ -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
}

Expand Down
Original file line number Diff line number Diff line change
@@ -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

Original file line number Diff line number Diff line change
Expand Up @@ -4,31 +4,31 @@ 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
|
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
|
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
|
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
Expand Down

0 comments on commit f9944a9

Please sign in to comment.