parse array lengths without mgca shenanigans

This commit is contained in:
Boxy 2026-02-06 16:18:10 +00:00
parent 23a44d3c70
commit 01703e30c0
11 changed files with 21 additions and 243 deletions

View file

@ -1622,16 +1622,8 @@ impl<'a> Parser<'a> {
let first_expr = self.parse_expr()?;
if self.eat(exp!(Semi)) {
// Repeating array syntax: `[ 0; 512 ]`
let count = if self.eat_keyword(exp!(Const)) {
// While we could just disambiguate `Direct` from `AnonConst` by
// treating all const block exprs as `AnonConst`, that would
// complicate the DefCollector and likely all other visitors.
// So we strip the const blockiness and just store it as a block
// in the AST with the extra disambiguator on the AnonConst
self.parse_mgca_const_block(false)?
} else {
self.parse_expr_anon_const(|this, expr| this.mgca_direct_lit_hack(expr))?
};
let count =
self.parse_expr_anon_const(|this, expr| this.mgca_direct_lit_hack(expr))?;
self.expect(close)?;
ExprKind::Repeat(first_expr, count)
} else if self.eat(exp!(Comma)) {

View file

@ -658,16 +658,8 @@ impl<'a> Parser<'a> {
};
let ty = if self.eat(exp!(Semi)) {
let mut length = if self.eat_keyword(exp!(Const)) {
// While we could just disambiguate `Direct` from `AnonConst` by
// treating all const block exprs as `AnonConst`, that would
// complicate the DefCollector and likely all other visitors.
// So we strip the const blockiness and just store it as a block
// in the AST with the extra disambiguator on the AnonConst
self.parse_mgca_const_block(false)?
} else {
self.parse_expr_anon_const(|this, expr| this.mgca_direct_lit_hack(expr))?
};
let mut length =
self.parse_expr_anon_const(|this, expr| this.mgca_direct_lit_hack(expr))?;
if let Err(e) = self.expect(exp!(CloseBracket)) {
// Try to recover from `X<Y, ...>` when `X::<Y, ...>` works

View file

@ -0,0 +1,7 @@
fn foo() {
let a = [(); const { let x = 1; x }];
}
fn foo() {
let x = [(); const { 1 }];
}

View file

@ -0,0 +1,10 @@
fn foo() {
let a = [(); const {
let x = 1;
x
}];
}
fn foo() {
let x = [(); const { 1 }];
}

View file

@ -1,73 +0,0 @@
#![feature(generic_const_items, min_generic_const_args)]
#![expect(incomplete_features)]
// library crates exercise weirder code paths around
// DefIds which were created for const args.
#![crate_type = "lib"]
struct Foo<const N: usize>;
type Adt1<const N: usize> = Foo<N>;
type Adt2<const N: usize> = Foo<{ N }>;
type Adt3<const N: usize> = Foo<const { N }>;
//~^ ERROR: generic parameters may not be used in const operations
type Adt4<const N: usize> = Foo<{ 1 + 1 }>;
//~^ ERROR: complex const arguments must be placed inside of a `const` block
type Adt5<const N: usize> = Foo<const { 1 + 1 }>;
type Arr<const N: usize> = [(); N];
type Arr2<const N: usize> = [(); { N }];
type Arr3<const N: usize> = [(); const { N }];
//~^ ERROR: generic parameters may not be used in const operations
type Arr4<const N: usize> = [(); 1 + 1];
//~^ ERROR: complex const arguments must be placed inside of a `const` block
type Arr5<const N: usize> = [(); const { 1 + 1 }];
fn repeats<const N: usize>() -> [(); N] {
let _1 = [(); N];
let _2 = [(); { N }];
let _3 = [(); const { N }];
//~^ ERROR: generic parameters may not be used in const operations
let _4 = [(); 1 + 1];
//~^ ERROR: complex const arguments must be placed inside of a `const` block
let _5 = [(); const { 1 + 1 }];
let _6: [(); const { N }] = todo!();
//~^ ERROR: generic parameters may not be used in const operations
}
#[type_const]
const ITEM1<const N: usize>: usize = N;
#[type_const]
const ITEM2<const N: usize>: usize = { N };
#[type_const]
const ITEM3<const N: usize>: usize = const { N };
//~^ ERROR: generic parameters may not be used in const operations
#[type_const]
const ITEM4<const N: usize>: usize = { 1 + 1 };
//~^ ERROR: complex const arguments must be placed inside of a `const` block
#[type_const]
const ITEM5<const N: usize>: usize = const { 1 + 1};
trait Trait {
#[type_const]
const ASSOC: usize;
}
fn ace_bounds<
const N: usize,
// We skip the T1 case because it doesn't resolve
// T1: Trait<ASSOC = N>,
T2: Trait<ASSOC = { N }>,
T3: Trait<ASSOC = const { N }>,
//~^ ERROR: generic parameters may not be used in const operations
T4: Trait<ASSOC = { 1 + 1 }>,
//~^ ERROR: complex const arguments must be placed inside of a `const` block
T5: Trait<ASSOC = const { 1 + 1 }>,
>() {}
struct Default1<const N: usize, const M: usize = N>;
struct Default2<const N: usize, const M: usize = { N }>;
struct Default3<const N: usize, const M: usize = const { N }>;
//~^ ERROR: generic parameters may not be used in const operations
struct Default4<const N: usize, const M: usize = { 1 + 1 }>;
//~^ ERROR: complex const arguments must be placed inside of a `const` block
struct Default5<const N: usize, const M: usize = const { 1 + 1}>;

View file

@ -1,80 +0,0 @@
error: complex const arguments must be placed inside of a `const` block
--> $DIR/explicit_anon_consts.rs:13:33
|
LL | type Adt4<const N: usize> = Foo<{ 1 + 1 }>;
| ^^^^^^^^^
error: complex const arguments must be placed inside of a `const` block
--> $DIR/explicit_anon_consts.rs:21:34
|
LL | type Arr4<const N: usize> = [(); 1 + 1];
| ^^^^^
error: complex const arguments must be placed inside of a `const` block
--> $DIR/explicit_anon_consts.rs:30:19
|
LL | let _4 = [(); 1 + 1];
| ^^^^^
error: complex const arguments must be placed inside of a `const` block
--> $DIR/explicit_anon_consts.rs:45:38
|
LL | const ITEM4<const N: usize>: usize = { 1 + 1 };
| ^^^^^^^^^
error: complex const arguments must be placed inside of a `const` block
--> $DIR/explicit_anon_consts.rs:62:23
|
LL | T4: Trait<ASSOC = { 1 + 1 }>,
| ^^^^^^^^^
error: complex const arguments must be placed inside of a `const` block
--> $DIR/explicit_anon_consts.rs:71:50
|
LL | struct Default4<const N: usize, const M: usize = { 1 + 1 }>;
| ^^^^^^^^^
error: generic parameters may not be used in const operations
--> $DIR/explicit_anon_consts.rs:42:46
|
LL | const ITEM3<const N: usize>: usize = const { N };
| ^
error: generic parameters may not be used in const operations
--> $DIR/explicit_anon_consts.rs:60:31
|
LL | T3: Trait<ASSOC = const { N }>,
| ^
error: generic parameters may not be used in const operations
--> $DIR/explicit_anon_consts.rs:69:58
|
LL | struct Default3<const N: usize, const M: usize = const { N }>;
| ^
error: generic parameters may not be used in const operations
--> $DIR/explicit_anon_consts.rs:28:27
|
LL | let _3 = [(); const { N }];
| ^
error: generic parameters may not be used in const operations
--> $DIR/explicit_anon_consts.rs:33:26
|
LL | let _6: [(); const { N }] = todo!();
| ^
error: generic parameters may not be used in const operations
--> $DIR/explicit_anon_consts.rs:11:41
|
LL | type Adt3<const N: usize> = Foo<const { N }>;
| ^
error: generic parameters may not be used in const operations
--> $DIR/explicit_anon_consts.rs:19:42
|
LL | type Arr3<const N: usize> = [(); const { N }];
| ^
error: aborting due to 13 previous errors

View file

@ -1,13 +0,0 @@
#![feature(min_generic_const_args)]
#![expect(incomplete_features)]
struct S<const N: usize>([(); N]);
impl<const N: usize> S<N> {
fn foo() -> [(); const { let _: Self = loop {}; 1 }] {
//~^ ERROR generic `Self`
todo!()
}
}
fn main() {}

View file

@ -1,14 +0,0 @@
error: generic `Self` types are currently not permitted in anonymous constants
--> $DIR/selftyalias-containing-param.rs:7:37
|
LL | fn foo() -> [(); const { let _: Self = loop {}; 1 }] {
| ^^^^
|
note: not a concrete type
--> $DIR/selftyalias-containing-param.rs:6:22
|
LL | impl<const N: usize> S<N> {
| ^^^^
error: aborting due to 1 previous error

View file

@ -1,9 +0,0 @@
#![feature(min_generic_const_args)]
#![expect(incomplete_features)]
trait Tr<const N: usize> {
fn foo() -> [(); const { let _: Self; 1 }];
//~^ ERROR generic parameters
}
fn main() {}

View file

@ -1,8 +0,0 @@
error: generic parameters may not be used in const operations
--> $DIR/selftyparam.rs:5:37
|
LL | fn foo() -> [(); const { let _: Self; 1 }];
| ^^^^
error: aborting due to 1 previous error

View file

@ -1,26 +0,0 @@
//@ check-pass
// This test should compile without an ICE.
#![expect(incomplete_features)]
#![feature(min_generic_const_args)]
pub struct A;
pub trait Array {
#[type_const]
const LEN: usize;
fn arr() -> [u8; Self::LEN];
}
impl Array for A {
#[type_const]
const LEN: usize = 4;
#[allow(unused_braces)]
fn arr() -> [u8; const { Self::LEN }] {
return [0u8; const { Self::LEN }];
}
}
fn main() {
let _ = A::arr();
}