From d13924caa729c14131ee4dd88f35c080095e1b05 Mon Sep 17 00:00:00 2001 From: Redddy Date: Wed, 25 Feb 2026 03:16:17 +0000 Subject: [PATCH 1/3] mGCA: Reject negated non-integer literals in const args --- compiler/rustc_ast_lowering/src/lib.rs | 21 ++++---- .../mgca/array-expr-complex.stderr | 8 ++-- .../mgca/explicit_anon_consts.stderr | 16 +++---- .../mgca/nonsensical-negated-literal.rs | 17 ++++--- .../mgca/nonsensical-negated-literal.stderr | 48 +++++++++++-------- 5 files changed, 61 insertions(+), 49 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 24a7215ddb385..ee21f0df5e217 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -2521,16 +2521,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ExprKind::Block(block, _) => { if let [stmt] = block.stmts.as_slice() && let StmtKind::Expr(expr) = &stmt.kind - && matches!( - expr.kind, - ExprKind::Block(..) - | ExprKind::Path(..) - | ExprKind::Struct(..) - | ExprKind::Call(..) - | ExprKind::Tup(..) - | ExprKind::Array(..) - | ExprKind::ConstBlock(..) - ) { return self.lower_expr_to_const_arg_direct(expr); } @@ -2553,6 +2543,17 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let span = expr.span; let literal = self.lower_lit(literal, span); + if !matches!(literal.node, LitKind::Int(..)) { + let err = + self.dcx().struct_span_err(expr.span, "negated literal must be an integer"); + + return ConstArg { + hir_id: self.next_id(), + kind: hir::ConstArgKind::Error(err.emit()), + span, + }; + } + ConstArg { hir_id: self.lower_node_id(expr.id), kind: hir::ConstArgKind::Literal { lit: literal.node, negated: true }, diff --git a/tests/ui/const-generics/mgca/array-expr-complex.stderr b/tests/ui/const-generics/mgca/array-expr-complex.stderr index beac1aa232f2f..544b0f05b4e44 100644 --- a/tests/ui/const-generics/mgca/array-expr-complex.stderr +++ b/tests/ui/const-generics/mgca/array-expr-complex.stderr @@ -5,16 +5,16 @@ LL | takes_array::<{ [1, 2, 1 + 2] }>(); | ^^^^^ error: complex const arguments must be placed inside of a `const` block - --> $DIR/array-expr-complex.rs:10:19 + --> $DIR/array-expr-complex.rs:10:21 | LL | takes_array::<{ [X; 3] }>(); - | ^^^^^^^^^^ + | ^^^^^^ error: complex const arguments must be placed inside of a `const` block - --> $DIR/array-expr-complex.rs:12:19 + --> $DIR/array-expr-complex.rs:12:21 | LL | takes_array::<{ [0; Y] }>(); - | ^^^^^^^^^^ + | ^^^^^^ error: aborting due to 3 previous errors diff --git a/tests/ui/const-generics/mgca/explicit_anon_consts.stderr b/tests/ui/const-generics/mgca/explicit_anon_consts.stderr index 714d7a804d111..1c72afce52c7d 100644 --- a/tests/ui/const-generics/mgca/explicit_anon_consts.stderr +++ b/tests/ui/const-generics/mgca/explicit_anon_consts.stderr @@ -1,8 +1,8 @@ error: complex const arguments must be placed inside of a `const` block - --> $DIR/explicit_anon_consts.rs:13:33 + --> $DIR/explicit_anon_consts.rs:13:35 | LL | type Adt4 = Foo<{ 1 + 1 }>; - | ^^^^^^^^^ + | ^^^^^ error: complex const arguments must be placed inside of a `const` block --> $DIR/explicit_anon_consts.rs:21:34 @@ -17,22 +17,22 @@ LL | let _4 = [(); 1 + 1]; | ^^^^^ error: complex const arguments must be placed inside of a `const` block - --> $DIR/explicit_anon_consts.rs:45:43 + --> $DIR/explicit_anon_consts.rs:45:45 | LL | type const ITEM4: usize = { 1 + 1 }; - | ^^^^^^^^^ + | ^^^^^ error: complex const arguments must be placed inside of a `const` block - --> $DIR/explicit_anon_consts.rs:62:23 + --> $DIR/explicit_anon_consts.rs:62:25 | LL | T4: Trait, - | ^^^^^^^^^ + | ^^^^^ error: complex const arguments must be placed inside of a `const` block - --> $DIR/explicit_anon_consts.rs:71:50 + --> $DIR/explicit_anon_consts.rs:71:52 | LL | struct Default4; - | ^^^^^^^^^ + | ^^^^^ error: generic parameters may not be used in const operations --> $DIR/explicit_anon_consts.rs:42:51 diff --git a/tests/ui/const-generics/mgca/nonsensical-negated-literal.rs b/tests/ui/const-generics/mgca/nonsensical-negated-literal.rs index cd68a2c0d4301..4a3efb801cb01 100644 --- a/tests/ui/const-generics/mgca/nonsensical-negated-literal.rs +++ b/tests/ui/const-generics/mgca/nonsensical-negated-literal.rs @@ -1,4 +1,4 @@ -#![feature(adt_const_params, min_generic_const_args)] +#![feature(adt_const_params, min_generic_const_args, unsized_const_params)] #![expect(incomplete_features)] use std::marker::ConstParamTy; @@ -10,17 +10,22 @@ struct Foo { fn foo() {} +fn bar() {} + fn main() { foo::<{ Foo { field: -1_usize } }>(); //~^ ERROR: type annotations needed for the literal foo::<{ Foo { field: { -1_usize } } }>(); - //~^ ERROR: complex const arguments must be placed inside of a `const` block + //~^ ERROR: type annotations needed for the literal foo::<{ Foo { field: -true } }>(); - //~^ ERROR: the constant `true` is not of type `isize` + //~^ ERROR negated literal must be an integer foo::<{ Foo { field: { -true } } }>(); - //~^ ERROR: complex const arguments must be placed inside of a `const` block + //~^ ERROR negated literal must be an integer foo::<{ Foo { field: -"<3" } }>(); - //~^ ERROR: the constant `"<3"` is not of type `isize` + //~^ ERROR negated literal must be an integer foo::<{ Foo { field: { -"<3" } } }>(); - //~^ ERROR: complex const arguments must be placed inside of a `const` block + //~^ ERROR negated literal must be an integer + + bar::<{ -"hi" }>(); + //~^ ERROR: negated literal must be an integer } diff --git a/tests/ui/const-generics/mgca/nonsensical-negated-literal.stderr b/tests/ui/const-generics/mgca/nonsensical-negated-literal.stderr index 43ed4b71e33e7..60c559d1d5ba9 100644 --- a/tests/ui/const-generics/mgca/nonsensical-negated-literal.stderr +++ b/tests/ui/const-generics/mgca/nonsensical-negated-literal.stderr @@ -1,38 +1,44 @@ -error: complex const arguments must be placed inside of a `const` block - --> $DIR/nonsensical-negated-literal.rs:16:26 +error: negated literal must be an integer + --> $DIR/nonsensical-negated-literal.rs:20:26 | -LL | foo::<{ Foo { field: { -1_usize } } }>(); - | ^^^^^^^^^^^^ +LL | foo::<{ Foo { field: -true } }>(); + | ^^^^^ -error: complex const arguments must be placed inside of a `const` block - --> $DIR/nonsensical-negated-literal.rs:20:26 +error: negated literal must be an integer + --> $DIR/nonsensical-negated-literal.rs:22:28 | LL | foo::<{ Foo { field: { -true } } }>(); - | ^^^^^^^^^ + | ^^^^^ -error: complex const arguments must be placed inside of a `const` block +error: negated literal must be an integer --> $DIR/nonsensical-negated-literal.rs:24:26 | +LL | foo::<{ Foo { field: -"<3" } }>(); + | ^^^^^ + +error: negated literal must be an integer + --> $DIR/nonsensical-negated-literal.rs:26:28 + | LL | foo::<{ Foo { field: { -"<3" } } }>(); - | ^^^^^^^^^ + | ^^^^^ + +error: negated literal must be an integer + --> $DIR/nonsensical-negated-literal.rs:29:13 + | +LL | bar::<{ -"hi" }>(); + | ^^^^^ error: type annotations needed for the literal - --> $DIR/nonsensical-negated-literal.rs:14:26 + --> $DIR/nonsensical-negated-literal.rs:16:26 | LL | foo::<{ Foo { field: -1_usize } }>(); | ^^^^^^^^ -error: the constant `true` is not of type `isize` - --> $DIR/nonsensical-negated-literal.rs:18:13 - | -LL | foo::<{ Foo { field: -true } }>(); - | ^^^^^^^^^^^^^^^^^^^^ expected `isize`, found `bool` - -error: the constant `"<3"` is not of type `isize` - --> $DIR/nonsensical-negated-literal.rs:22:13 +error: type annotations needed for the literal + --> $DIR/nonsensical-negated-literal.rs:18:28 | -LL | foo::<{ Foo { field: -"<3" } }>(); - | ^^^^^^^^^^^^^^^^^^^^ expected `isize`, found `&'static str` +LL | foo::<{ Foo { field: { -1_usize } } }>(); + | ^^^^^^^^ -error: aborting due to 6 previous errors +error: aborting due to 7 previous errors From 51271084000fc9bcf1dc39be1c528767da6aa95c Mon Sep 17 00:00:00 2001 From: Redddy Date: Wed, 25 Feb 2026 04:05:12 +0000 Subject: [PATCH 2/3] mGCA: drop literal anon-const special case in parser --- compiler/rustc_parse/src/parser/path.rs | 22 ++++-------------- ...const-projections-in-assoc-const-ty.stderr | 21 ++++------------- ...array-expr-type-mismatch-in-where-bound.rs | 2 +- ...y-expr-type-mismatch-in-where-bound.stderr | 5 ++-- .../type_const-inherent-const-omitted-type.rs | 1 + ...e_const-inherent-const-omitted-type.stderr | 8 ++++++- .../mgca/type_const-mismatched-types.rs | 3 +-- .../mgca/type_const-mismatched-types.stderr | 23 ++++--------------- .../type_const-only-in-impl-omitted-type.rs | 1 + ...ype_const-only-in-impl-omitted-type.stderr | 10 ++++++-- 10 files changed, 34 insertions(+), 62 deletions(-) diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs index 9196d8d156d8e..f9a882c371d59 100644 --- a/compiler/rustc_parse/src/parser/path.rs +++ b/compiler/rustc_parse/src/parser/path.rs @@ -919,24 +919,10 @@ impl<'a> Parser<'a> { Ok((expr, mgca_disambiguation)) } - /// Under `min_generic_const_args` we still allow *some* anon consts to be written without - /// a `const` block as it makes things quite a lot nicer. This function is useful for contexts - /// where we would like to use `MgcaDisambiguation::Direct` but need to fudge it to be `AnonConst` - /// in the presence of literals. - // - /// FIXME(min_generic_const_args): In the long term it would be nice to have a way to directly - /// represent literals in `hir::ConstArgKind` so that we can remove this special case by not - /// needing an anon const. - pub fn mgca_direct_lit_hack(&self, expr: &Expr) -> MgcaDisambiguation { - match &expr.kind { - ast::ExprKind::Lit(_) => MgcaDisambiguation::AnonConst, - ast::ExprKind::Unary(ast::UnOp::Neg, expr) - if matches!(expr.kind, ast::ExprKind::Lit(_)) => - { - MgcaDisambiguation::AnonConst - } - _ => MgcaDisambiguation::Direct, - } + /// Under `min_generic_const_args`, prefer direct const arguments rather than + /// wrapping literals in anon consts. + pub fn mgca_direct_lit_hack(&self, _expr: &Expr) -> MgcaDisambiguation { + MgcaDisambiguation::Direct } /// Parse a generic argument in a path segment. diff --git a/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-const-projections-in-assoc-const-ty.stderr b/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-const-projections-in-assoc-const-ty.stderr index cc08c25906b66..7443c2977d54d 100644 --- a/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-const-projections-in-assoc-const-ty.stderr +++ b/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-const-projections-in-assoc-const-ty.stderr @@ -1,27 +1,14 @@ -error[E0277]: the trait bound `FreshTy(0): A` is not satisfied +error: type annotations needed for the literal --> $DIR/dyn-compat-self-const-projections-in-assoc-const-ty.rs:32:33 | LL | let _: dyn A; - | ^ the trait `A` is not implemented for `FreshTy(0)` - | -help: the trait `A` is implemented for `()` - --> $DIR/dyn-compat-self-const-projections-in-assoc-const-ty.rs:20:1 - | -LL | impl A for () { - | ^^^^^^^^^^^^^ + | ^ -error[E0277]: the trait bound `FreshTy(0): A` is not satisfied +error: type annotations needed for the literal --> $DIR/dyn-compat-self-const-projections-in-assoc-const-ty.rs:34:34 | LL | let _: &dyn A = &(); - | ^ the trait `A` is not implemented for `FreshTy(0)` - | -help: the trait `A` is implemented for `()` - --> $DIR/dyn-compat-self-const-projections-in-assoc-const-ty.rs:20:1 - | -LL | impl A for () { - | ^^^^^^^^^^^^^ + | ^ error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/const-generics/mgca/array-expr-type-mismatch-in-where-bound.rs b/tests/ui/const-generics/mgca/array-expr-type-mismatch-in-where-bound.rs index cda519b96d4d8..98feccfc99c74 100644 --- a/tests/ui/const-generics/mgca/array-expr-type-mismatch-in-where-bound.rs +++ b/tests/ui/const-generics/mgca/array-expr-type-mismatch-in-where-bound.rs @@ -14,7 +14,7 @@ where fn bar() where - T: Trait2<3>, //~ ERROR: mismatched types + T: Trait2<3>, //~ ERROR: type annotations needed for the literal { } diff --git a/tests/ui/const-generics/mgca/array-expr-type-mismatch-in-where-bound.stderr b/tests/ui/const-generics/mgca/array-expr-type-mismatch-in-where-bound.stderr index be40e44742267..169282547fc1d 100644 --- a/tests/ui/const-generics/mgca/array-expr-type-mismatch-in-where-bound.stderr +++ b/tests/ui/const-generics/mgca/array-expr-type-mismatch-in-where-bound.stderr @@ -4,12 +4,11 @@ error: expected `usize`, found const array LL | T: Trait1<{ [] }>, | ^^ -error[E0308]: mismatched types +error: type annotations needed for the literal --> $DIR/array-expr-type-mismatch-in-where-bound.rs:17:15 | LL | T: Trait2<3>, - | ^ expected `[u8; 3]`, found integer + | ^ error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/mgca/type_const-inherent-const-omitted-type.rs b/tests/ui/const-generics/mgca/type_const-inherent-const-omitted-type.rs index 3262e79478bdb..c57121a4a26a0 100644 --- a/tests/ui/const-generics/mgca/type_const-inherent-const-omitted-type.rs +++ b/tests/ui/const-generics/mgca/type_const-inherent-const-omitted-type.rs @@ -6,6 +6,7 @@ struct A; impl A { type const B = 4; //~^ ERROR: missing type for `const` item + //~| ERROR: type annotations needed for the literal } fn main() {} diff --git a/tests/ui/const-generics/mgca/type_const-inherent-const-omitted-type.stderr b/tests/ui/const-generics/mgca/type_const-inherent-const-omitted-type.stderr index 77e54ab2f2e93..7fbb7461a4911 100644 --- a/tests/ui/const-generics/mgca/type_const-inherent-const-omitted-type.stderr +++ b/tests/ui/const-generics/mgca/type_const-inherent-const-omitted-type.stderr @@ -9,5 +9,11 @@ help: provide a type for the item LL | type const B: = 4; | ++++++++ -error: aborting due to 1 previous error +error: type annotations needed for the literal + --> $DIR/type_const-inherent-const-omitted-type.rs:7:20 + | +LL | type const B = 4; + | ^ + +error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/mgca/type_const-mismatched-types.rs b/tests/ui/const-generics/mgca/type_const-mismatched-types.rs index c73785f9a3e38..b17a5b2b978a6 100644 --- a/tests/ui/const-generics/mgca/type_const-mismatched-types.rs +++ b/tests/ui/const-generics/mgca/type_const-mismatched-types.rs @@ -3,7 +3,6 @@ type const FREE: u32 = 5_usize; //~^ ERROR the constant `5` is not of type `u32` -//~| ERROR mismatched types type const FREE2: isize = FREE; //~^ ERROR the constant `5` is not of type `isize` @@ -14,7 +13,7 @@ trait Tr { impl Tr for () { type const N: usize = false; - //~^ ERROR mismatched types + //~^ ERROR the constant `false` is not of type `usize` } fn main() {} diff --git a/tests/ui/const-generics/mgca/type_const-mismatched-types.stderr b/tests/ui/const-generics/mgca/type_const-mismatched-types.stderr index f7f64c535f602..e2c916cf6d05a 100644 --- a/tests/ui/const-generics/mgca/type_const-mismatched-types.stderr +++ b/tests/ui/const-generics/mgca/type_const-mismatched-types.stderr @@ -5,29 +5,16 @@ LL | type const FREE: u32 = 5_usize; | ^^^^^^^^^^^^^^^^^^^^ expected `u32`, found `usize` error: the constant `5` is not of type `isize` - --> $DIR/type_const-mismatched-types.rs:8:1 + --> $DIR/type_const-mismatched-types.rs:7:1 | LL | type const FREE2: isize = FREE; | ^^^^^^^^^^^^^^^^^^^^^^^ expected `isize`, found `usize` -error[E0308]: mismatched types - --> $DIR/type_const-mismatched-types.rs:16:27 +error: the constant `false` is not of type `usize` + --> $DIR/type_const-mismatched-types.rs:15:5 | LL | type const N: usize = false; - | ^^^^^ expected `usize`, found `bool` + | ^^^^^^^^^^^^^^^^^^^ expected `usize`, found `bool` -error[E0308]: mismatched types - --> $DIR/type_const-mismatched-types.rs:4:24 - | -LL | type const FREE: u32 = 5_usize; - | ^^^^^^^ expected `u32`, found `usize` - | -help: change the type of the numeric literal from `usize` to `u32` - | -LL - type const FREE: u32 = 5_usize; -LL + type const FREE: u32 = 5_u32; - | - -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/mgca/type_const-only-in-impl-omitted-type.rs b/tests/ui/const-generics/mgca/type_const-only-in-impl-omitted-type.rs index a7ff9f0ce03f7..c8c7788eb135a 100644 --- a/tests/ui/const-generics/mgca/type_const-only-in-impl-omitted-type.rs +++ b/tests/ui/const-generics/mgca/type_const-only-in-impl-omitted-type.rs @@ -10,6 +10,7 @@ struct GoodS; impl BadTr for GoodS { type const NUM: = 84; //~^ ERROR: missing type for `const` item + //~| ERROR: type annotations needed for the literal } diff --git a/tests/ui/const-generics/mgca/type_const-only-in-impl-omitted-type.stderr b/tests/ui/const-generics/mgca/type_const-only-in-impl-omitted-type.stderr index 11a60246f6a68..99dc6398170db 100644 --- a/tests/ui/const-generics/mgca/type_const-only-in-impl-omitted-type.stderr +++ b/tests/ui/const-generics/mgca/type_const-only-in-impl-omitted-type.stderr @@ -5,12 +5,18 @@ LL | type const NUM: = 84; | ^ help: provide a type for the associated constant: `usize` error: use of trait associated const not defined as `type const` - --> $DIR/type_const-only-in-impl-omitted-type.rs:16:43 + --> $DIR/type_const-only-in-impl-omitted-type.rs:17:43 | LL | fn accept_bad_tr>(_x: &T) {} | ^^^^^^^^^^^ | = note: the declaration in the trait must begin with `type const` not just `const` alone -error: aborting due to 2 previous errors +error: type annotations needed for the literal + --> $DIR/type_const-only-in-impl-omitted-type.rs:11:23 + | +LL | type const NUM: = 84; + | ^^ + +error: aborting due to 3 previous errors From d2619b5dcfdcef4ad55d73cbb21ed2d031c128cd Mon Sep 17 00:00:00 2001 From: Redddy Date: Wed, 25 Feb 2026 04:19:38 +0000 Subject: [PATCH 3/3] Remove mgca_direct_lit_hack indirection --- compiler/rustc_parse/src/parser/expr.rs | 3 +-- compiler/rustc_parse/src/parser/item.rs | 4 +--- compiler/rustc_parse/src/parser/path.rs | 9 +-------- compiler/rustc_parse/src/parser/ty.rs | 3 +-- 4 files changed, 4 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 52dcade91aeaf..44e8f13dd2364 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1628,8 +1628,7 @@ impl<'a> Parser<'a> { let first_expr = self.parse_expr()?; if self.eat(exp!(Semi)) { // Repeating array syntax: `[ 0; 512 ]` - let count = - self.parse_expr_anon_const(|this, expr| this.mgca_direct_lit_hack(expr))?; + let count = self.parse_expr_anon_const(|_, _| MgcaDisambiguation::Direct)?; self.expect(close)?; ExprKind::Repeat(first_expr, count) } else if self.eat(exp!(Comma)) { diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 69610d062919d..2ca4fac7fc46b 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -1587,9 +1587,7 @@ impl<'a> Parser<'a> { let rhs = match (self.eat(exp!(Eq)), const_arg) { (true, true) => ConstItemRhsKind::TypeConst { - rhs: Some( - self.parse_expr_anon_const(|this, expr| this.mgca_direct_lit_hack(expr))?, - ), + rhs: Some(self.parse_expr_anon_const(|_, _| MgcaDisambiguation::Direct)?), }, (true, false) => ConstItemRhsKind::Body { rhs: Some(self.parse_expr()?) }, (false, true) => ConstItemRhsKind::TypeConst { rhs: None }, diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs index f9a882c371d59..e514a08c8fb3a 100644 --- a/compiler/rustc_parse/src/parser/path.rs +++ b/compiler/rustc_parse/src/parser/path.rs @@ -915,14 +915,7 @@ impl<'a> Parser<'a> { }); } - let mgca_disambiguation = self.mgca_direct_lit_hack(&expr); - Ok((expr, mgca_disambiguation)) - } - - /// Under `min_generic_const_args`, prefer direct const arguments rather than - /// wrapping literals in anon consts. - pub fn mgca_direct_lit_hack(&self, _expr: &Expr) -> MgcaDisambiguation { - MgcaDisambiguation::Direct + Ok((expr, MgcaDisambiguation::Direct)) } /// Parse a generic argument in a path segment. diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index 6ff165eb22b71..40335ef1b1bc7 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -658,8 +658,7 @@ impl<'a> Parser<'a> { }; let ty = if self.eat(exp!(Semi)) { - let mut length = - self.parse_expr_anon_const(|this, expr| this.mgca_direct_lit_hack(expr))?; + let mut length = self.parse_expr_anon_const(|_, _| MgcaDisambiguation::Direct)?; if let Err(e) = self.expect(exp!(CloseBracket)) { // Try to recover from `X` when `X::` works