Rollup merge of #144741 - ShoyuVanilla:tilde-const-in-block, r=fee1-dead
fix: Error on illegal `[const]`s inside blocks within legal positions
Fixes rust-lang/rust#132067
I initially considered moving `[const]` validations to `rustc_ast_lowering`, but that approach would require adding constness information to `AssocCtxt`, which introduces significant changes - especially within `rustc_expand` - just to support a single use case here:
3fb1b53a9d/compiler/rustc_ast_passes/src/ast_validation.rs (L1596-L1610)
Instead, I believe it's sufficient to simply "reset" `[const]` allowness whenever we enter a new block.
This commit is contained in:
@@ -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_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
|
.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
|
.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
|
.object = trait objects cannot have `[const]` trait bounds
|
||||||
.item = this item cannot have `[const]` trait bounds
|
.item = this item cannot have `[const]` trait bounds
|
||||||
|
|
||||||
|
|||||||
@@ -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 {
|
ItemKind::Trait(box Trait {
|
||||||
constness,
|
constness,
|
||||||
@@ -1175,26 +1177,32 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||||||
}
|
}
|
||||||
visit::walk_item(self, item)
|
visit::walk_item(self, item)
|
||||||
}
|
}
|
||||||
ItemKind::Struct(ident, generics, vdata) => match vdata {
|
ItemKind::Struct(ident, generics, vdata) => {
|
||||||
|
self.with_tilde_const(Some(TildeConstReason::Struct { span: item.span }), |this| {
|
||||||
|
match vdata {
|
||||||
VariantData::Struct { fields, .. } => {
|
VariantData::Struct { fields, .. } => {
|
||||||
self.visit_attrs_vis_ident(&item.attrs, &item.vis, ident);
|
this.visit_attrs_vis_ident(&item.attrs, &item.vis, ident);
|
||||||
self.visit_generics(generics);
|
this.visit_generics(generics);
|
||||||
walk_list!(self, visit_field_def, fields);
|
walk_list!(this, visit_field_def, fields);
|
||||||
|
}
|
||||||
|
_ => visit::walk_item(this, item),
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
_ => visit::walk_item(self, item),
|
|
||||||
},
|
|
||||||
ItemKind::Union(ident, generics, vdata) => {
|
ItemKind::Union(ident, generics, vdata) => {
|
||||||
if vdata.fields().is_empty() {
|
if vdata.fields().is_empty() {
|
||||||
self.dcx().emit_err(errors::FieldlessUnion { span: item.span });
|
self.dcx().emit_err(errors::FieldlessUnion { span: item.span });
|
||||||
}
|
}
|
||||||
|
self.with_tilde_const(Some(TildeConstReason::Union { span: item.span }), |this| {
|
||||||
match vdata {
|
match vdata {
|
||||||
VariantData::Struct { fields, .. } => {
|
VariantData::Struct { fields, .. } => {
|
||||||
self.visit_attrs_vis_ident(&item.attrs, &item.vis, ident);
|
this.visit_attrs_vis_ident(&item.attrs, &item.vis, ident);
|
||||||
self.visit_generics(generics);
|
this.visit_generics(generics);
|
||||||
walk_list!(self, visit_field_def, fields);
|
walk_list!(this, visit_field_def, fields);
|
||||||
}
|
}
|
||||||
_ => visit::walk_item(self, item),
|
_ => visit::walk_item(this, item),
|
||||||
}
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
ItemKind::Const(box ConstItem { defaultness, expr, .. }) => {
|
ItemKind::Const(box ConstItem { defaultness, expr, .. }) => {
|
||||||
self.check_defaultness(item.span, *defaultness);
|
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)),
|
_ => 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
|
/// When encountering an equality constraint in a `where` clause, emit an error. If the code seems
|
||||||
|
|||||||
@@ -623,6 +623,26 @@ pub(crate) enum TildeConstReason {
|
|||||||
#[primary_span]
|
#[primary_span]
|
||||||
span: 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)]
|
#[note(ast_passes_object)]
|
||||||
TraitObject,
|
TraitObject,
|
||||||
#[note(ast_passes_item)]
|
#[note(ast_passes_item)]
|
||||||
|
|||||||
@@ -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() {}
|
||||||
@@ -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
|
||||||
|
|
||||||
@@ -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() {}
|
|
||||||
@@ -16,7 +16,11 @@ error: `[const]` is not allowed here
|
|||||||
LL | struct Struct<T: [const] Trait> { field: T }
|
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
|
error: `[const]` is not allowed here
|
||||||
--> $DIR/conditionally-const-invalid-places.rs:10:23
|
--> $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);
|
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
|
error: `[const]` is not allowed here
|
||||||
--> $DIR/conditionally-const-invalid-places.rs:11:22
|
--> $DIR/conditionally-const-invalid-places.rs:11:22
|
||||||
@@ -32,7 +40,11 @@ error: `[const]` is not allowed here
|
|||||||
LL | struct UnitStruct<T: [const] Trait>;
|
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
|
error: `[const]` is not allowed here
|
||||||
--> $DIR/conditionally-const-invalid-places.rs:14:14
|
--> $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) }
|
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
|
error: `[const]` is not allowed here
|
||||||
--> $DIR/conditionally-const-invalid-places.rs:16:16
|
--> $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 }
|
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
|
error: `[const]` is not allowed here
|
||||||
--> $DIR/conditionally-const-invalid-places.rs:19:14
|
--> $DIR/conditionally-const-invalid-places.rs:19:14
|
||||||
|
|||||||
Reference in New Issue
Block a user