mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 14:55:26 +00:00
Improve "~const
is not allowed here" message
This commit is contained in:
parent
542febd2d3
commit
ebf5028574
@ -38,6 +38,13 @@ enum SelfSemantic {
|
|||||||
No,
|
No,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// What is the context that prevents using `~const`?
|
||||||
|
enum DisallowTildeConstContext<'a> {
|
||||||
|
TraitObject,
|
||||||
|
ImplTrait,
|
||||||
|
Fn(FnKind<'a>),
|
||||||
|
}
|
||||||
|
|
||||||
struct AstValidator<'a> {
|
struct AstValidator<'a> {
|
||||||
session: &'a Session,
|
session: &'a Session,
|
||||||
|
|
||||||
@ -56,7 +63,7 @@ struct AstValidator<'a> {
|
|||||||
/// e.g., `impl Iterator<Item = impl Debug>`.
|
/// e.g., `impl Iterator<Item = impl Debug>`.
|
||||||
outer_impl_trait: Option<Span>,
|
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`
|
/// Used to ban `impl Trait` in path projections like `<impl Iterator>::Item`
|
||||||
/// or `Foo::Bar<impl Trait>`
|
/// or `Foo::Bar<impl Trait>`
|
||||||
@ -93,18 +100,26 @@ impl<'a> AstValidator<'a> {
|
|||||||
self.is_impl_trait_banned = old;
|
self.is_impl_trait_banned = old;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with_tilde_const(&mut self, allowed: bool, f: impl FnOnce(&mut Self)) {
|
fn with_tilde_const(
|
||||||
let old = mem::replace(&mut self.is_tilde_const_allowed, allowed);
|
&mut self,
|
||||||
|
disallowed: Option<DisallowTildeConstContext<'a>>,
|
||||||
|
f: impl FnOnce(&mut Self),
|
||||||
|
) {
|
||||||
|
let old = mem::replace(&mut self.disallow_tilde_const, disallowed);
|
||||||
f(self);
|
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)) {
|
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)) {
|
fn with_banned_tilde_const(
|
||||||
self.with_tilde_const(false, f)
|
&mut self,
|
||||||
|
ctx: DisallowTildeConstContext<'a>,
|
||||||
|
f: impl FnOnce(&mut Self),
|
||||||
|
) {
|
||||||
|
self.with_tilde_const(Some(ctx), f)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with_let_management(
|
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)) {
|
fn with_impl_trait(&mut self, outer: Option<Span>, f: impl FnOnce(&mut Self)) {
|
||||||
let old = mem::replace(&mut self.outer_impl_trait, outer);
|
let old = mem::replace(&mut self.outer_impl_trait, outer);
|
||||||
if outer.is_some() {
|
if outer.is_some() {
|
||||||
self.with_banned_tilde_const(f);
|
self.with_banned_tilde_const(DisallowTildeConstContext::ImplTrait, f);
|
||||||
} else {
|
} else {
|
||||||
f(self);
|
f(self);
|
||||||
}
|
}
|
||||||
@ -197,7 +212,10 @@ impl<'a> AstValidator<'a> {
|
|||||||
TyKind::ImplTrait(..) => {
|
TyKind::ImplTrait(..) => {
|
||||||
self.with_impl_trait(Some(t.span), |this| visit::walk_ty(this, t))
|
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) => {
|
TyKind::Path(ref qself, ref path) => {
|
||||||
// We allow these:
|
// We allow these:
|
||||||
// - `Option<impl Trait>`
|
// - `Option<impl Trait>`
|
||||||
@ -1411,13 +1429,15 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||||||
);
|
);
|
||||||
err.emit();
|
err.emit();
|
||||||
}
|
}
|
||||||
(_, TraitBoundModifier::MaybeConst) => {
|
(_, TraitBoundModifier::MaybeConst) if let Some(reason) = &self.disallow_tilde_const => {
|
||||||
if !self.is_tilde_const_allowed {
|
let mut err = self.err_handler().struct_span_err(bound.span(), "`~const` is not allowed here");
|
||||||
self.err_handler()
|
match reason {
|
||||||
.struct_span_err(bound.span(), "`~const` is not allowed here")
|
DisallowTildeConstContext::TraitObject => err.note("trait objects cannot have `~const` trait bounds"),
|
||||||
.note("only allowed on bounds on functions, traits' associated types and functions, const impls and its associated functions")
|
DisallowTildeConstContext::ImplTrait => err.note("`impl Trait`s cannot have `~const` trait bounds"),
|
||||||
.emit();
|
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) => {
|
(_, TraitBoundModifier::MaybeConstMaybe) => {
|
||||||
self.err_handler()
|
self.err_handler()
|
||||||
@ -1523,10 +1543,13 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let tilde_const_allowed = matches!(fk.header(), Some(FnHeader { .. }))
|
let tilde_const_allowed =
|
||||||
|| matches!(fk.ctxt(), Some(FnCtxt::Assoc(_)));
|
matches!(fk.header(), Some(FnHeader { constness: ast::Const::Yes(_), .. }))
|
||||||
|
|| matches!(fk.ctxt(), Some(FnCtxt::Assoc(_)));
|
||||||
|
|
||||||
self.with_tilde_const(tilde_const_allowed, |this| visit::walk_fn(this, fk));
|
let disallowed = (!tilde_const_allowed).then(|| DisallowTildeConstContext::Fn(fk));
|
||||||
|
|
||||||
|
self.with_tilde_const(disallowed, |this| visit::walk_fn(this, fk));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_assoc_item(&mut self, item: &'a AssocItem, ctxt: AssocCtxt) {
|
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,
|
in_const_trait_impl: false,
|
||||||
has_proc_macro_decls: false,
|
has_proc_macro_decls: false,
|
||||||
outer_impl_trait: None,
|
outer_impl_trait: None,
|
||||||
is_tilde_const_allowed: false,
|
disallow_tilde_const: None,
|
||||||
is_impl_trait_banned: false,
|
is_impl_trait_banned: false,
|
||||||
is_assoc_ty_bound_banned: false,
|
is_assoc_ty_bound_banned: false,
|
||||||
forbidden_let_reason: Some(ForbiddenLetReason::GenericForbidden),
|
forbidden_let_reason: Some(ForbiddenLetReason::GenericForbidden),
|
||||||
|
9
src/test/ui/rfc-2632-const-trait-impl/issue-90052.rs
Normal file
9
src/test/ui/rfc-2632-const-trait-impl/issue-90052.rs
Normal file
@ -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
src/test/ui/rfc-2632-const-trait-impl/issue-90052.stderr
Normal file
14
src/test/ui/rfc-2632-const-trait-impl/issue-90052.stderr
Normal file
@ -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
|
||||||
|
|
@ -1,4 +1,3 @@
|
|||||||
// check-pass
|
|
||||||
#![feature(const_trait_impl)]
|
#![feature(const_trait_impl)]
|
||||||
#![feature(generic_arg_infer)]
|
#![feature(generic_arg_infer)]
|
||||||
#![feature(generic_const_exprs)]
|
#![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) }> {
|
fn bar<A: ~const Add42, const N: usize>(_: Foo<N>) -> Foo<{ A::add(N) }> {
|
||||||
|
//~^ ERROR `~const` is not allowed here
|
||||||
Foo
|
Foo
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
|
@ -4,7 +4,7 @@ error: `~const` is not allowed here
|
|||||||
LL | fn rpit() -> impl ~const T { S }
|
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
|
error: `~const` is not allowed here
|
||||||
--> $DIR/tilde-const-invalid-places.rs:12:17
|
--> $DIR/tilde-const-invalid-places.rs:12:17
|
||||||
@ -12,7 +12,7 @@ error: `~const` is not allowed here
|
|||||||
LL | fn apit(_: impl ~const T) {}
|
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
|
error: `~const` is not allowed here
|
||||||
--> $DIR/tilde-const-invalid-places.rs:15:50
|
--> $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) }
|
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
|
error: `~const` is not allowed here
|
||||||
--> $DIR/tilde-const-invalid-places.rs:18:48
|
--> $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>) {}
|
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
|
error: `~const` and `?` are mutually exclusive
|
||||||
--> $DIR/tilde-const-invalid-places.rs:21:25
|
--> $DIR/tilde-const-invalid-places.rs:21:25
|
||||||
|
Loading…
Reference in New Issue
Block a user