fix: Error on illegal [const]s inside blocks within legal positions

This commit is contained in:
Shoyu Vanilla 2025-08-01 00:23:36 +09:00
parent 7cd950546b
commit 7d78968bd0
7 changed files with 140 additions and 42 deletions

View file

@ -241,6 +241,10 @@ ast_passes_tilde_const_disallowed = `[const]` is not allowed here
.trait_assoc_ty = associated types in non-`const` traits cannot have `[const]` trait bounds
.trait_impl_assoc_ty = associated types in non-const impls cannot have `[const]` trait bounds
.inherent_assoc_ty = inherent associated types cannot have `[const]` trait bounds
.struct = structs cannot have `[const]` trait bounds
.enum = enums cannot have `[const]` trait bounds
.union = unions cannot have `[const]` trait bounds
.anon_const = anonymous constants cannot have `[const]` trait bounds
.object = trait objects cannot have `[const]` trait bounds
.item = this item cannot have `[const]` trait bounds

View file

@ -1124,7 +1124,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
);
}
}
visit::walk_item(self, item)
self.with_tilde_const(Some(TildeConstReason::Enum { span: item.span }), |this| {
visit::walk_item(this, item)
});
}
ItemKind::Trait(box Trait {
constness,
@ -1175,26 +1177,32 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
}
visit::walk_item(self, item)
}
ItemKind::Struct(ident, generics, vdata) => match vdata {
VariantData::Struct { fields, .. } => {
self.visit_attrs_vis_ident(&item.attrs, &item.vis, ident);
self.visit_generics(generics);
walk_list!(self, visit_field_def, fields);
}
_ => visit::walk_item(self, item),
},
ItemKind::Struct(ident, generics, vdata) => {
self.with_tilde_const(Some(TildeConstReason::Struct { span: item.span }), |this| {
match vdata {
VariantData::Struct { fields, .. } => {
this.visit_attrs_vis_ident(&item.attrs, &item.vis, ident);
this.visit_generics(generics);
walk_list!(this, visit_field_def, fields);
}
_ => visit::walk_item(this, item),
}
})
}
ItemKind::Union(ident, generics, vdata) => {
if vdata.fields().is_empty() {
self.dcx().emit_err(errors::FieldlessUnion { span: item.span });
}
match vdata {
VariantData::Struct { fields, .. } => {
self.visit_attrs_vis_ident(&item.attrs, &item.vis, ident);
self.visit_generics(generics);
walk_list!(self, visit_field_def, fields);
self.with_tilde_const(Some(TildeConstReason::Union { span: item.span }), |this| {
match vdata {
VariantData::Struct { fields, .. } => {
this.visit_attrs_vis_ident(&item.attrs, &item.vis, ident);
this.visit_generics(generics);
walk_list!(this, visit_field_def, fields);
}
_ => visit::walk_item(this, item),
}
_ => visit::walk_item(self, item),
}
});
}
ItemKind::Const(box ConstItem { defaultness, expr, .. }) => {
self.check_defaultness(item.span, *defaultness);
@ -1623,6 +1631,13 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
_ => self.with_in_trait_impl(None, |this| visit::walk_assoc_item(this, item, ctxt)),
}
}
fn visit_anon_const(&mut self, anon_const: &'a AnonConst) {
self.with_tilde_const(
Some(TildeConstReason::AnonConst { span: anon_const.value.span }),
|this| visit::walk_anon_const(this, anon_const),
)
}
}
/// When encountering an equality constraint in a `where` clause, emit an error. If the code seems

View file

@ -623,6 +623,26 @@ pub(crate) enum TildeConstReason {
#[primary_span]
span: Span,
},
#[note(ast_passes_struct)]
Struct {
#[primary_span]
span: Span,
},
#[note(ast_passes_enum)]
Enum {
#[primary_span]
span: Span,
},
#[note(ast_passes_union)]
Union {
#[primary_span]
span: Span,
},
#[note(ast_passes_anon_const)]
AnonConst {
#[primary_span]
span: Span,
},
#[note(ast_passes_object)]
TraitObject,
#[note(ast_passes_item)]

View file

@ -0,0 +1,28 @@
#![feature(const_trait_impl, impl_trait_in_bindings)]
struct S;
#[const_trait]
trait Trait<const N: u32> {}
impl const Trait<0> for () {}
const fn f<
T: Trait<
{
const fn g<U: [const] Trait<0>>() {}
struct I<U: [const] Trait<0>>(U);
//~^ ERROR `[const]` is not allowed here
let x: &impl [const] Trait<0> = &();
//~^ ERROR `[const]` is not allowed here
0
},
>,
>(x: &T) {
// Should be allowed here
let y: &impl [const] Trait<0> = x;
}
pub fn main() {}

View file

@ -0,0 +1,32 @@
error: `[const]` is not allowed here
--> $DIR/conditionally-const-in-anon-const.rs:14:25
|
LL | struct I<U: [const] Trait<0>>(U);
| ^^^^^^^
|
note: structs cannot have `[const]` trait bounds
--> $DIR/conditionally-const-in-anon-const.rs:14:13
|
LL | struct I<U: [const] Trait<0>>(U);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: `[const]` is not allowed here
--> $DIR/conditionally-const-in-anon-const.rs:17:26
|
LL | let x: &impl [const] Trait<0> = &();
| ^^^^^^^
|
note: anonymous constants cannot have `[const]` trait bounds
--> $DIR/conditionally-const-in-anon-const.rs:11:9
|
LL | / {
LL | | const fn g<U: [const] Trait<0>>() {}
LL | |
LL | | struct I<U: [const] Trait<0>>(U);
... |
LL | | 0
LL | | },
| |_________^
error: aborting due to 2 previous errors

View file

@ -1,21 +0,0 @@
//@ compile-flags: -Znext-solver
//@ known-bug: #132067
//@ check-pass
#![feature(const_trait_impl)]
struct S;
#[const_trait]
trait Trait<const N: u32> {}
const fn f<
T: Trait<
{
struct I<U: [const] Trait<0>>(U);
0
},
>,
>() {
}
pub fn main() {}

View file

@ -16,7 +16,11 @@ error: `[const]` is not allowed here
LL | struct Struct<T: [const] Trait> { field: T }
| ^^^^^^^
|
= note: this item cannot have `[const]` trait bounds
note: structs cannot have `[const]` trait bounds
--> $DIR/conditionally-const-invalid-places.rs:9:1
|
LL | struct Struct<T: [const] Trait> { field: T }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: `[const]` is not allowed here
--> $DIR/conditionally-const-invalid-places.rs:10:23
@ -24,7 +28,11 @@ error: `[const]` is not allowed here
LL | struct TupleStruct<T: [const] Trait>(T);
| ^^^^^^^
|
= note: this item cannot have `[const]` trait bounds
note: structs cannot have `[const]` trait bounds
--> $DIR/conditionally-const-invalid-places.rs:10:1
|
LL | struct TupleStruct<T: [const] Trait>(T);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: `[const]` is not allowed here
--> $DIR/conditionally-const-invalid-places.rs:11:22
@ -32,7 +40,11 @@ error: `[const]` is not allowed here
LL | struct UnitStruct<T: [const] Trait>;
| ^^^^^^^
|
= note: this item cannot have `[const]` trait bounds
note: structs cannot have `[const]` trait bounds
--> $DIR/conditionally-const-invalid-places.rs:11:1
|
LL | struct UnitStruct<T: [const] Trait>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: `[const]` is not allowed here
--> $DIR/conditionally-const-invalid-places.rs:14:14
@ -40,7 +52,11 @@ error: `[const]` is not allowed here
LL | enum Enum<T: [const] Trait> { Variant(T) }
| ^^^^^^^
|
= note: this item cannot have `[const]` trait bounds
note: enums cannot have `[const]` trait bounds
--> $DIR/conditionally-const-invalid-places.rs:14:1
|
LL | enum Enum<T: [const] Trait> { Variant(T) }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: `[const]` is not allowed here
--> $DIR/conditionally-const-invalid-places.rs:16:16
@ -48,7 +64,11 @@ error: `[const]` is not allowed here
LL | union Union<T: [const] Trait> { field: T }
| ^^^^^^^
|
= note: this item cannot have `[const]` trait bounds
note: unions cannot have `[const]` trait bounds
--> $DIR/conditionally-const-invalid-places.rs:16:1
|
LL | union Union<T: [const] Trait> { field: T }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: `[const]` is not allowed here
--> $DIR/conditionally-const-invalid-places.rs:19:14