diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index b497c6beeb984..cde8b8f9fe2e9 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -827,7 +827,10 @@ impl<'hir> LoweringContext<'_, 'hir> { hir_id, def_id: self.local_def_id(v.id), data: self.lower_variant_data(hir_id, item_kind, &v.data), - disr_expr: v.disr_expr.as_ref().map(|e| self.lower_anon_const_to_anon_const(e)), + disr_expr: v + .disr_expr + .as_ref() + .map(|e| self.lower_anon_const_to_anon_const(e, e.value.span)), ident: self.lower_ident(v.ident), span: self.lower_span(v.span), } @@ -917,7 +920,10 @@ impl<'hir> LoweringContext<'_, 'hir> { None => Ident::new(sym::integer(index), self.lower_span(f.span)), }, vis_span: self.lower_span(f.vis.span), - default: f.default.as_ref().map(|v| self.lower_anon_const_to_anon_const(v)), + default: f + .default + .as_ref() + .map(|v| self.lower_anon_const_to_anon_const(v, v.value.span)), ty, safety: self.lower_safety(f.safety, hir::Safety::Safe), } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index e4f431fd2431c..adf4ffd88101f 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -2425,15 +2425,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ); let lowered_args = self.arena.alloc_from_iter(args.iter().map(|arg| { - let const_arg = if let ExprKind::ConstBlock(anon_const) = &arg.kind { - let def_id = self.local_def_id(anon_const.id); - let def_kind = self.tcx.def_kind(def_id); - assert_eq!(DefKind::AnonConst, def_kind); - self.lower_anon_const_to_const_arg(anon_const) - } else { - self.lower_expr_to_const_arg_direct(arg) - }; - + let const_arg = self.lower_expr_to_const_arg_direct(arg); &*self.arena.alloc(const_arg) })); @@ -2445,16 +2437,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } ExprKind::Tup(exprs) => { let exprs = self.arena.alloc_from_iter(exprs.iter().map(|expr| { - let expr = if let ExprKind::ConstBlock(anon_const) = &expr.kind { - let def_id = self.local_def_id(anon_const.id); - let def_kind = self.tcx.def_kind(def_id); - assert_eq!(DefKind::AnonConst, def_kind); - - self.lower_anon_const_to_const_arg(anon_const) - } else { - self.lower_expr_to_const_arg_direct(&expr) - }; - + let expr = self.lower_expr_to_const_arg_direct(&expr); &*self.arena.alloc(expr) })); @@ -2494,16 +2477,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // then go unused as the `Target::ExprField` is not actually // corresponding to `Node::ExprField`. self.lower_attrs(hir_id, &f.attrs, f.span, Target::ExprField); - - let expr = if let ExprKind::ConstBlock(anon_const) = &f.expr.kind { - let def_id = self.local_def_id(anon_const.id); - let def_kind = self.tcx.def_kind(def_id); - assert_eq!(DefKind::AnonConst, def_kind); - - self.lower_anon_const_to_const_arg(anon_const) - } else { - self.lower_expr_to_const_arg_direct(&f.expr) - }; + let expr = self.lower_expr_to_const_arg_direct(&f.expr); &*self.arena.alloc(hir::ConstArgExprField { hir_id, @@ -2521,13 +2495,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } ExprKind::Array(elements) => { let lowered_elems = self.arena.alloc_from_iter(elements.iter().map(|element| { - let const_arg = if let ExprKind::ConstBlock(anon_const) = &element.kind { - let def_id = self.local_def_id(anon_const.id); - assert_eq!(DefKind::AnonConst, self.tcx.def_kind(def_id)); - self.lower_anon_const_to_const_arg(anon_const) - } else { - self.lower_expr_to_const_arg_direct(element) - }; + let const_arg = self.lower_expr_to_const_arg_direct(element); &*self.arena.alloc(const_arg) })); let array_expr = self.arena.alloc(hir::ConstArgArrayExpr { @@ -2557,6 +2525,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { | ExprKind::Call(..) | ExprKind::Tup(..) | ExprKind::Array(..) + | ExprKind::ConstBlock(..) ) { return self.lower_expr_to_const_arg_direct(expr); @@ -2574,6 +2543,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { span, } } + ExprKind::ConstBlock(anon_const) => { + let def_id = self.local_def_id(anon_const.id); + assert_eq!(DefKind::AnonConst, self.tcx.def_kind(def_id)); + self.lower_anon_const_to_const_arg(anon_const, span) + } _ => overly_complex_const(self), } } @@ -2584,11 +2558,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { &mut self, anon: &AnonConst, ) -> &'hir hir::ConstArg<'hir> { - self.arena.alloc(self.lower_anon_const_to_const_arg(anon)) + self.arena.alloc(self.lower_anon_const_to_const_arg(anon, anon.value.span)) } #[instrument(level = "debug", skip(self))] - fn lower_anon_const_to_const_arg(&mut self, anon: &AnonConst) -> hir::ConstArg<'hir> { + fn lower_anon_const_to_const_arg( + &mut self, + anon: &AnonConst, + span: Span, + ) -> hir::ConstArg<'hir> { let tcx = self.tcx; // We cannot change parsing depending on feature gates available, @@ -2599,7 +2577,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { if tcx.features().min_generic_const_args() { return match anon.mgca_disambiguation { MgcaDisambiguation::AnonConst => { - let lowered_anon = self.lower_anon_const_to_anon_const(anon); + let lowered_anon = self.lower_anon_const_to_anon_const(anon, span); ConstArg { hir_id: self.next_id(), kind: hir::ConstArgKind::Anon(lowered_anon), @@ -2645,7 +2623,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { }; } - let lowered_anon = self.lower_anon_const_to_anon_const(anon); + let lowered_anon = self.lower_anon_const_to_anon_const(anon, anon.value.span); ConstArg { hir_id: self.next_id(), kind: hir::ConstArgKind::Anon(lowered_anon), @@ -2655,7 +2633,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { /// See [`hir::ConstArg`] for when to use this function vs /// [`Self::lower_anon_const_to_const_arg`]. - fn lower_anon_const_to_anon_const(&mut self, c: &AnonConst) -> &'hir hir::AnonConst { + fn lower_anon_const_to_anon_const( + &mut self, + c: &AnonConst, + span: Span, + ) -> &'hir hir::AnonConst { self.arena.alloc(self.with_new_scopes(c.value.span, |this| { let def_id = this.local_def_id(c.id); let hir_id = this.lower_node_id(c.id); @@ -2663,7 +2645,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { def_id, hir_id, body: this.lower_const_body(c.value.span, Some(&c.value)), - span: this.lower_span(c.value.span), + span: this.lower_span(span), } })) } diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 84fe6770be583..11cde35fab17f 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1627,16 +1627,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)) { diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 0ff0b66229366..a6b956b09bc16 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -33,9 +33,9 @@ use rustc_ast::tokenstream::{ }; use rustc_ast::util::case::Case; use rustc_ast::{ - self as ast, AnonConst, AttrArgs, AttrId, BlockCheckMode, ByRef, Const, CoroutineKind, - DUMMY_NODE_ID, DelimArgs, Expr, ExprKind, Extern, HasAttrs, HasTokens, MgcaDisambiguation, - Mutability, Recovered, Safety, StrLit, Visibility, VisibilityKind, + self as ast, AnonConst, AttrArgs, AttrId, ByRef, Const, CoroutineKind, DUMMY_NODE_ID, + DelimArgs, Expr, ExprKind, Extern, HasAttrs, HasTokens, MgcaDisambiguation, Mutability, + Recovered, Safety, StrLit, Visibility, VisibilityKind, }; use rustc_ast_pretty::pprust; use rustc_data_structures::debug_assert_matches; @@ -1269,19 +1269,6 @@ impl<'a> Parser<'a> { } } - fn parse_mgca_const_block(&mut self, gate_syntax: bool) -> PResult<'a, AnonConst> { - let kw_span = self.prev_token.span; - let value = self.parse_expr_block(None, kw_span, BlockCheckMode::Default)?; - if gate_syntax { - self.psess.gated_spans.gate(sym::min_generic_const_args, kw_span.to(value.span)); - } - Ok(AnonConst { - id: ast::DUMMY_NODE_ID, - value, - mgca_disambiguation: MgcaDisambiguation::AnonConst, - }) - } - /// Parses inline const expressions. fn parse_const_block(&mut self, span: Span) -> PResult<'a, Box> { self.expect_keyword(exp!(Const))?; diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs index dd190707c42b4..9196d8d156d8e 100644 --- a/compiler/rustc_parse/src/parser/path.rs +++ b/compiler/rustc_parse/src/parser/path.rs @@ -847,6 +847,7 @@ impl<'a> Parser<'a> { /// - A literal. /// - A numeric literal prefixed by `-`. /// - A single-segment path. + /// - A const block (under mGCA) pub(super) fn expr_is_valid_const_arg(&self, expr: &Box) -> bool { match &expr.kind { ast::ExprKind::Block(_, _) @@ -863,6 +864,10 @@ impl<'a> Parser<'a> { { true } + ast::ExprKind::ConstBlock(_) => { + self.psess.gated_spans.gate(sym::min_generic_const_args, expr.span); + true + } _ => false, } } @@ -874,14 +879,6 @@ impl<'a> Parser<'a> { let (value, mgca_disambiguation) = if self.token.kind == token::OpenBrace { let value = self.parse_expr_block(None, self.token.span, BlockCheckMode::Default)?; (value, MgcaDisambiguation::Direct) - } else 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 - let value = self.parse_mgca_const_block(true)?; - (value.value, MgcaDisambiguation::AnonConst) } else { self.parse_unambiguous_unbraced_const_arg()? }; diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index 380b6a2148461..6ff165eb22b71 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -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` when `X::` works diff --git a/src/tools/rustfmt/tests/source/issue-6788.rs b/src/tools/rustfmt/tests/source/issue-6788.rs new file mode 100644 index 0000000000000..0e63ab53a1ac9 --- /dev/null +++ b/src/tools/rustfmt/tests/source/issue-6788.rs @@ -0,0 +1,7 @@ +fn foo() { + let a = [(); const { let x = 1; x }]; +} + +fn foo() { + let x = [(); const { 1 }]; +} diff --git a/src/tools/rustfmt/tests/target/issue-6788.rs b/src/tools/rustfmt/tests/target/issue-6788.rs new file mode 100644 index 0000000000000..c559438b2d52b --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-6788.rs @@ -0,0 +1,10 @@ +fn foo() { + let a = [(); const { + let x = 1; + x + }]; +} + +fn foo() { + let x = [(); const { 1 }]; +}