Skip to content

Commit 4cb0ebd

Browse files
Rollup merge of #144741 - ShoyuVanilla:tilde-const-in-block, r=fee1-dead
fix: Error on illegal `[const]`s inside blocks within legal positions Fixes #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: https://github.com/rust-lang/rust/blob/3fb1b53a9dbfcdf37a4b67d35cde373316829930/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.
2 parents 58b00b0 + 7d78968 commit 4cb0ebd

File tree

7 files changed

+140
-42
lines changed

7 files changed

+140
-42
lines changed

compiler/rustc_ast_passes/messages.ftl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,10 @@ ast_passes_tilde_const_disallowed = `[const]` is not allowed here
241241
.trait_assoc_ty = associated types in non-`const` traits cannot have `[const]` trait bounds
242242
.trait_impl_assoc_ty = associated types in non-const impls cannot have `[const]` trait bounds
243243
.inherent_assoc_ty = inherent associated types cannot have `[const]` trait bounds
244+
.struct = structs cannot have `[const]` trait bounds
245+
.enum = enums cannot have `[const]` trait bounds
246+
.union = unions cannot have `[const]` trait bounds
247+
.anon_const = anonymous constants cannot have `[const]` trait bounds
244248
.object = trait objects cannot have `[const]` trait bounds
245249
.item = this item cannot have `[const]` trait bounds
246250

compiler/rustc_ast_passes/src/ast_validation.rs

Lines changed: 31 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1124,7 +1124,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
11241124
);
11251125
}
11261126
}
1127-
visit::walk_item(self, item)
1127+
self.with_tilde_const(Some(TildeConstReason::Enum { span: item.span }), |this| {
1128+
visit::walk_item(this, item)
1129+
});
11281130
}
11291131
ItemKind::Trait(box Trait {
11301132
constness,
@@ -1175,26 +1177,32 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
11751177
}
11761178
visit::walk_item(self, item)
11771179
}
1178-
ItemKind::Struct(ident, generics, vdata) => match vdata {
1179-
VariantData::Struct { fields, .. } => {
1180-
self.visit_attrs_vis_ident(&item.attrs, &item.vis, ident);
1181-
self.visit_generics(generics);
1182-
walk_list!(self, visit_field_def, fields);
1183-
}
1184-
_ => visit::walk_item(self, item),
1185-
},
1180+
ItemKind::Struct(ident, generics, vdata) => {
1181+
self.with_tilde_const(Some(TildeConstReason::Struct { span: item.span }), |this| {
1182+
match vdata {
1183+
VariantData::Struct { fields, .. } => {
1184+
this.visit_attrs_vis_ident(&item.attrs, &item.vis, ident);
1185+
this.visit_generics(generics);
1186+
walk_list!(this, visit_field_def, fields);
1187+
}
1188+
_ => visit::walk_item(this, item),
1189+
}
1190+
})
1191+
}
11861192
ItemKind::Union(ident, generics, vdata) => {
11871193
if vdata.fields().is_empty() {
11881194
self.dcx().emit_err(errors::FieldlessUnion { span: item.span });
11891195
}
1190-
match vdata {
1191-
VariantData::Struct { fields, .. } => {
1192-
self.visit_attrs_vis_ident(&item.attrs, &item.vis, ident);
1193-
self.visit_generics(generics);
1194-
walk_list!(self, visit_field_def, fields);
1196+
self.with_tilde_const(Some(TildeConstReason::Union { span: item.span }), |this| {
1197+
match vdata {
1198+
VariantData::Struct { fields, .. } => {
1199+
this.visit_attrs_vis_ident(&item.attrs, &item.vis, ident);
1200+
this.visit_generics(generics);
1201+
walk_list!(this, visit_field_def, fields);
1202+
}
1203+
_ => visit::walk_item(this, item),
11951204
}
1196-
_ => visit::walk_item(self, item),
1197-
}
1205+
});
11981206
}
11991207
ItemKind::Const(box ConstItem { defaultness, expr, .. }) => {
12001208
self.check_defaultness(item.span, *defaultness);
@@ -1623,6 +1631,13 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
16231631
_ => self.with_in_trait_impl(None, |this| visit::walk_assoc_item(this, item, ctxt)),
16241632
}
16251633
}
1634+
1635+
fn visit_anon_const(&mut self, anon_const: &'a AnonConst) {
1636+
self.with_tilde_const(
1637+
Some(TildeConstReason::AnonConst { span: anon_const.value.span }),
1638+
|this| visit::walk_anon_const(this, anon_const),
1639+
)
1640+
}
16261641
}
16271642

16281643
/// When encountering an equality constraint in a `where` clause, emit an error. If the code seems

compiler/rustc_ast_passes/src/errors.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -623,6 +623,26 @@ pub(crate) enum TildeConstReason {
623623
#[primary_span]
624624
span: Span,
625625
},
626+
#[note(ast_passes_struct)]
627+
Struct {
628+
#[primary_span]
629+
span: Span,
630+
},
631+
#[note(ast_passes_enum)]
632+
Enum {
633+
#[primary_span]
634+
span: Span,
635+
},
636+
#[note(ast_passes_union)]
637+
Union {
638+
#[primary_span]
639+
span: Span,
640+
},
641+
#[note(ast_passes_anon_const)]
642+
AnonConst {
643+
#[primary_span]
644+
span: Span,
645+
},
626646
#[note(ast_passes_object)]
627647
TraitObject,
628648
#[note(ast_passes_item)]
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#![feature(const_trait_impl, impl_trait_in_bindings)]
2+
3+
struct S;
4+
#[const_trait]
5+
trait Trait<const N: u32> {}
6+
7+
impl const Trait<0> for () {}
8+
9+
const fn f<
10+
T: Trait<
11+
{
12+
const fn g<U: [const] Trait<0>>() {}
13+
14+
struct I<U: [const] Trait<0>>(U);
15+
//~^ ERROR `[const]` is not allowed here
16+
17+
let x: &impl [const] Trait<0> = &();
18+
//~^ ERROR `[const]` is not allowed here
19+
20+
0
21+
},
22+
>,
23+
>(x: &T) {
24+
// Should be allowed here
25+
let y: &impl [const] Trait<0> = x;
26+
}
27+
28+
pub fn main() {}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
error: `[const]` is not allowed here
2+
--> $DIR/conditionally-const-in-anon-const.rs:14:25
3+
|
4+
LL | struct I<U: [const] Trait<0>>(U);
5+
| ^^^^^^^
6+
|
7+
note: structs cannot have `[const]` trait bounds
8+
--> $DIR/conditionally-const-in-anon-const.rs:14:13
9+
|
10+
LL | struct I<U: [const] Trait<0>>(U);
11+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
12+
13+
error: `[const]` is not allowed here
14+
--> $DIR/conditionally-const-in-anon-const.rs:17:26
15+
|
16+
LL | let x: &impl [const] Trait<0> = &();
17+
| ^^^^^^^
18+
|
19+
note: anonymous constants cannot have `[const]` trait bounds
20+
--> $DIR/conditionally-const-in-anon-const.rs:11:9
21+
|
22+
LL | / {
23+
LL | | const fn g<U: [const] Trait<0>>() {}
24+
LL | |
25+
LL | | struct I<U: [const] Trait<0>>(U);
26+
... |
27+
LL | | 0
28+
LL | | },
29+
| |_________^
30+
31+
error: aborting due to 2 previous errors
32+

tests/ui/traits/const-traits/conditionally-const-in-struct-args.rs

Lines changed: 0 additions & 21 deletions
This file was deleted.

tests/ui/traits/const-traits/conditionally-const-invalid-places.stderr

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,39 +16,59 @@ error: `[const]` is not allowed here
1616
LL | struct Struct<T: [const] Trait> { field: T }
1717
| ^^^^^^^
1818
|
19-
= note: this item cannot have `[const]` trait bounds
19+
note: structs cannot have `[const]` trait bounds
20+
--> $DIR/conditionally-const-invalid-places.rs:9:1
21+
|
22+
LL | struct Struct<T: [const] Trait> { field: T }
23+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2024

2125
error: `[const]` is not allowed here
2226
--> $DIR/conditionally-const-invalid-places.rs:10:23
2327
|
2428
LL | struct TupleStruct<T: [const] Trait>(T);
2529
| ^^^^^^^
2630
|
27-
= note: this item cannot have `[const]` trait bounds
31+
note: structs cannot have `[const]` trait bounds
32+
--> $DIR/conditionally-const-invalid-places.rs:10:1
33+
|
34+
LL | struct TupleStruct<T: [const] Trait>(T);
35+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2836

2937
error: `[const]` is not allowed here
3038
--> $DIR/conditionally-const-invalid-places.rs:11:22
3139
|
3240
LL | struct UnitStruct<T: [const] Trait>;
3341
| ^^^^^^^
3442
|
35-
= note: this item cannot have `[const]` trait bounds
43+
note: structs cannot have `[const]` trait bounds
44+
--> $DIR/conditionally-const-invalid-places.rs:11:1
45+
|
46+
LL | struct UnitStruct<T: [const] Trait>;
47+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
3648

3749
error: `[const]` is not allowed here
3850
--> $DIR/conditionally-const-invalid-places.rs:14:14
3951
|
4052
LL | enum Enum<T: [const] Trait> { Variant(T) }
4153
| ^^^^^^^
4254
|
43-
= note: this item cannot have `[const]` trait bounds
55+
note: enums cannot have `[const]` trait bounds
56+
--> $DIR/conditionally-const-invalid-places.rs:14:1
57+
|
58+
LL | enum Enum<T: [const] Trait> { Variant(T) }
59+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
4460

4561
error: `[const]` is not allowed here
4662
--> $DIR/conditionally-const-invalid-places.rs:16:16
4763
|
4864
LL | union Union<T: [const] Trait> { field: T }
4965
| ^^^^^^^
5066
|
51-
= note: this item cannot have `[const]` trait bounds
67+
note: unions cannot have `[const]` trait bounds
68+
--> $DIR/conditionally-const-invalid-places.rs:16:1
69+
|
70+
LL | union Union<T: [const] Trait> { field: T }
71+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
5272

5373
error: `[const]` is not allowed here
5474
--> $DIR/conditionally-const-invalid-places.rs:19:14

0 commit comments

Comments
 (0)