diff options
| author | Luca Versari <veluca93@gmail.com> | 2024-09-16 11:56:22 +0200 |
|---|---|---|
| committer | Luca Versari <veluca93@gmail.com> | 2024-11-16 01:07:51 +0100 |
| commit | b462c68aee956602408373975d3ca898e464030b (patch) | |
| tree | fcb0b903238a67ca25d22c8bf7212b99629dc5a2 /compiler/rustc_ast_lowering/src/expr.rs | |
| parent | ce40196577ecc0b72f6de7e2c8e43fdc728fb69a (diff) | |
| download | rust-b462c68aee956602408373975d3ca898e464030b.tar.gz rust-b462c68aee956602408373975d3ca898e464030b.zip | |
Fix ICE when passing DefId-creating args to legacy_const_generics.
Diffstat (limited to 'compiler/rustc_ast_lowering/src/expr.rs')
| -rw-r--r-- | compiler/rustc_ast_lowering/src/expr.rs | 70 |
1 files changed, 67 insertions, 3 deletions
diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index b7cf2d252dc..3af29838b72 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -1,18 +1,22 @@ use std::assert_matches::assert_matches; +use std::ops::ControlFlow; use rustc_ast::ptr::P as AstP; use rustc_ast::*; +use rustc_ast_pretty::pprust::expr_to_string; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_data_structures::sync::Lrc; use rustc_hir as hir; use rustc_hir::HirId; use rustc_hir::def::{DefKind, Res}; use rustc_middle::span_bug; +use rustc_middle::ty::TyCtxt; use rustc_session::errors::report_lit_error; use rustc_span::source_map::{Spanned, respan}; use rustc_span::symbol::{Ident, Symbol, kw, sym}; use rustc_span::{DUMMY_SP, DesugaringKind, Span}; use thin_vec::{ThinVec, thin_vec}; +use visit::{Visitor, walk_expr}; use super::errors::{ AsyncCoroutinesNotSupported, AwaitOnlyInAsyncFnAndBlocks, BaseExpressionDoubleDot, @@ -23,9 +27,32 @@ use super::errors::{ use super::{ GenericArgsMode, ImplTraitContext, LoweringContext, ParamMode, ResolverAstLoweringExt, }; -use crate::errors::YieldInClosure; +use crate::errors::{InvalidLegacyConstGenericArg, UseConstGenericArg, YieldInClosure}; use crate::{AllowReturnTypeNotation, FnDeclKind, ImplTraitPosition, fluent_generated}; +struct WillCreateDefIdsVisitor {} + +impl<'v> rustc_ast::visit::Visitor<'v> for WillCreateDefIdsVisitor { + type Result = ControlFlow<Span>; + + fn visit_anon_const(&mut self, c: &'v AnonConst) -> Self::Result { + ControlFlow::Break(c.value.span) + } + + fn visit_item(&mut self, item: &'v Item) -> Self::Result { + ControlFlow::Break(item.span) + } + + fn visit_expr(&mut self, ex: &'v Expr) -> Self::Result { + match ex.kind { + ExprKind::Gen(..) | ExprKind::ConstBlock(..) | ExprKind::Closure(..) => { + ControlFlow::Break(ex.span) + } + _ => walk_expr(self, ex), + } + } +} + impl<'hir> LoweringContext<'_, 'hir> { fn lower_exprs(&mut self, exprs: &[AstP<Expr>]) -> &'hir [hir::Expr<'hir>] { self.arena.alloc_from_iter(exprs.iter().map(|x| self.lower_expr_mut(x))) @@ -396,10 +423,34 @@ impl<'hir> LoweringContext<'_, 'hir> { unreachable!(); }; + let mut error = None; + let mut invalid_expr_error = |tcx: TyCtxt<'_>, span| { + // Avoid emitting the error multiple times. + if error.is_none() { + let mut const_args = vec![]; + let mut other_args = vec![]; + for (idx, arg) in args.iter().enumerate() { + if legacy_args_idx.contains(&idx) { + const_args.push(format!("{{ {} }}", expr_to_string(arg))); + } else { + other_args.push(expr_to_string(arg)); + } + } + let suggestion = UseConstGenericArg { + end_of_fn: f.span.shrink_to_hi(), + const_args: const_args.join(", "), + other_args: other_args.join(", "), + call_args: args[0].span.to(args.last().unwrap().span), + }; + error = Some(tcx.dcx().emit_err(InvalidLegacyConstGenericArg { span, suggestion })); + } + error.unwrap() + }; + // Split the arguments into const generics and normal arguments let mut real_args = vec![]; let mut generic_args = ThinVec::new(); - for (idx, arg) in args.into_iter().enumerate() { + for (idx, arg) in args.iter().cloned().enumerate() { if legacy_args_idx.contains(&idx) { let parent_def_id = self.current_def_id_parent; let node_id = self.next_node_id(); @@ -410,7 +461,20 @@ impl<'hir> LoweringContext<'_, 'hir> { self.create_def(parent_def_id, node_id, kw::Empty, DefKind::AnonConst, f.span); } - let anon_const = AnonConst { id: node_id, value: arg }; + let mut visitor = WillCreateDefIdsVisitor {}; + let const_value = if let ControlFlow::Break(span) = visitor.visit_expr(&arg) { + AstP(Expr { + id: self.next_node_id(), + kind: ExprKind::Err(invalid_expr_error(self.tcx, span)), + span: f.span, + attrs: [].into(), + tokens: None, + }) + } else { + arg + }; + + let anon_const = AnonConst { id: node_id, value: const_value }; generic_args.push(AngleBracketedArg::Arg(GenericArg::Const(anon_const))); } else { real_args.push(arg); |
