Fix ICE when passing DefId-creating args to legacy_const_generics.

This commit is contained in:
Luca Versari 2024-09-16 11:56:22 +02:00
parent ce40196577
commit b462c68aee
9 changed files with 211 additions and 22 deletions

View File

@ -3270,6 +3270,7 @@ name = "rustc_ast_lowering"
version = "0.0.0" version = "0.0.0"
dependencies = [ dependencies = [
"rustc_ast", "rustc_ast",
"rustc_ast_pretty",
"rustc_data_structures", "rustc_data_structures",
"rustc_errors", "rustc_errors",
"rustc_fluent_macro", "rustc_fluent_macro",

View File

@ -9,6 +9,7 @@ doctest = false
[dependencies] [dependencies]
# tidy-alphabetical-start # tidy-alphabetical-start
rustc_ast = { path = "../rustc_ast" } rustc_ast = { path = "../rustc_ast" }
rustc_ast_pretty = { path = "../rustc_ast_pretty" }
rustc_data_structures = { path = "../rustc_data_structures" } rustc_data_structures = { path = "../rustc_data_structures" }
rustc_errors = { path = "../rustc_errors" } rustc_errors = { path = "../rustc_errors" }
rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_fluent_macro = { path = "../rustc_fluent_macro" }

View File

@ -103,6 +103,12 @@ ast_lowering_invalid_asm_template_modifier_reg_class =
ast_lowering_invalid_asm_template_modifier_sym = ast_lowering_invalid_asm_template_modifier_sym =
asm template modifiers are not allowed for `sym` arguments asm template modifiers are not allowed for `sym` arguments
ast_lowering_invalid_legacy_const_generic_arg =
invalid argument to a legacy const generic: cannot have const blocks, closures, async blocks or items
ast_lowering_invalid_legacy_const_generic_arg_suggestion =
try using a const generic argument instead
ast_lowering_invalid_register = ast_lowering_invalid_register =
invalid register `{$reg}`: {$error} invalid register `{$reg}`: {$error}

View File

@ -451,3 +451,26 @@ pub(crate) struct YieldInClosure {
#[suggestion(code = "#[coroutine] ", applicability = "maybe-incorrect", style = "verbose")] #[suggestion(code = "#[coroutine] ", applicability = "maybe-incorrect", style = "verbose")]
pub suggestion: Option<Span>, pub suggestion: Option<Span>,
} }
#[derive(Diagnostic)]
#[diag(ast_lowering_invalid_legacy_const_generic_arg)]
pub(crate) struct InvalidLegacyConstGenericArg {
#[primary_span]
pub span: Span,
#[subdiagnostic]
pub suggestion: UseConstGenericArg,
}
#[derive(Subdiagnostic)]
#[multipart_suggestion(
ast_lowering_invalid_legacy_const_generic_arg_suggestion,
applicability = "maybe-incorrect"
)]
pub(crate) struct UseConstGenericArg {
#[suggestion_part(code = "::<{const_args}>")]
pub end_of_fn: Span,
pub const_args: String,
pub other_args: String,
#[suggestion_part(code = "{other_args}")]
pub call_args: Span,
}

View File

@ -1,18 +1,22 @@
use std::assert_matches::assert_matches; use std::assert_matches::assert_matches;
use std::ops::ControlFlow;
use rustc_ast::ptr::P as AstP; use rustc_ast::ptr::P as AstP;
use rustc_ast::*; use rustc_ast::*;
use rustc_ast_pretty::pprust::expr_to_string;
use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_data_structures::sync::Lrc; use rustc_data_structures::sync::Lrc;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::HirId; use rustc_hir::HirId;
use rustc_hir::def::{DefKind, Res}; use rustc_hir::def::{DefKind, Res};
use rustc_middle::span_bug; use rustc_middle::span_bug;
use rustc_middle::ty::TyCtxt;
use rustc_session::errors::report_lit_error; use rustc_session::errors::report_lit_error;
use rustc_span::source_map::{Spanned, respan}; use rustc_span::source_map::{Spanned, respan};
use rustc_span::symbol::{Ident, Symbol, kw, sym}; use rustc_span::symbol::{Ident, Symbol, kw, sym};
use rustc_span::{DUMMY_SP, DesugaringKind, Span}; use rustc_span::{DUMMY_SP, DesugaringKind, Span};
use thin_vec::{ThinVec, thin_vec}; use thin_vec::{ThinVec, thin_vec};
use visit::{Visitor, walk_expr};
use super::errors::{ use super::errors::{
AsyncCoroutinesNotSupported, AwaitOnlyInAsyncFnAndBlocks, BaseExpressionDoubleDot, AsyncCoroutinesNotSupported, AwaitOnlyInAsyncFnAndBlocks, BaseExpressionDoubleDot,
@ -23,9 +27,32 @@ use super::errors::{
use super::{ use super::{
GenericArgsMode, ImplTraitContext, LoweringContext, ParamMode, ResolverAstLoweringExt, GenericArgsMode, ImplTraitContext, LoweringContext, ParamMode, ResolverAstLoweringExt,
}; };
use crate::errors::YieldInClosure; use crate::errors::{InvalidLegacyConstGenericArg, UseConstGenericArg, YieldInClosure};
use crate::{AllowReturnTypeNotation, FnDeclKind, ImplTraitPosition, fluent_generated}; 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> { impl<'hir> LoweringContext<'_, 'hir> {
fn lower_exprs(&mut self, exprs: &[AstP<Expr>]) -> &'hir [hir::Expr<'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))) self.arena.alloc_from_iter(exprs.iter().map(|x| self.lower_expr_mut(x)))
@ -396,10 +423,34 @@ impl<'hir> LoweringContext<'_, 'hir> {
unreachable!(); 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 // Split the arguments into const generics and normal arguments
let mut real_args = vec![]; let mut real_args = vec![];
let mut generic_args = ThinVec::new(); 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) { if legacy_args_idx.contains(&idx) {
let parent_def_id = self.current_def_id_parent; let parent_def_id = self.current_def_id_parent;
let node_id = self.next_node_id(); 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); 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))); generic_args.push(AngleBracketedArg::Arg(GenericArg::Const(anon_const)));
} else { } else {
real_args.push(arg); real_args.push(arg);

View File

@ -1,12 +0,0 @@
//@ known-bug: #123077
//@ only-x86_64
use std::arch::x86_64::{__m128, _mm_blend_ps};
pub fn sse41_blend_noinline( ) -> __m128 {
let f = { |x, y| unsafe {
_mm_blend_ps(x, y, { |x, y| unsafe })
}};
f(x, y)
}
pub fn main() {}

View File

@ -1,7 +0,0 @@
//@ known-bug: rust-lang/rust#129150
//@ only-x86_64
use std::arch::x86_64::_mm_blend_ps;
pub fn main() {
_mm_blend_ps(1, 2, &const {} );
}

View File

@ -0,0 +1,31 @@
//@ only-x86_64
const fn foo<const U: i32>() -> i32 {
U
}
fn main() {
std::arch::x86_64::_mm_blend_ps(loop {}, loop {}, || ());
//~^ invalid argument to a legacy const generic
std::arch::x86_64::_mm_blend_ps(loop {}, loop {}, 5 + || ());
//~^ invalid argument to a legacy const generic
std::arch::x86_64::_mm_blend_ps(loop {}, loop {}, foo::<{ 1 + 2 }>());
//~^ invalid argument to a legacy const generic
std::arch::x86_64::_mm_blend_ps(loop {}, loop {}, foo::<3>());
//~^ invalid argument to a legacy const generic
std::arch::x86_64::_mm_blend_ps(loop {}, loop {}, &const {});
//~^ invalid argument to a legacy const generic
std::arch::x86_64::_mm_blend_ps(loop {}, loop {}, {
struct F();
//~^ invalid argument to a legacy const generic
1
});
std::arch::x86_64::_mm_inserti_si64(loop {}, loop {}, || (), 1 + || ());
//~^ invalid argument to a legacy const generic
}

View File

@ -0,0 +1,82 @@
error: invalid argument to a legacy const generic: cannot have const blocks, closures, async blocks or items
--> $DIR/invalid-rustc_legacy_const_generics-issue-123077.rs:8:55
|
LL | std::arch::x86_64::_mm_blend_ps(loop {}, loop {}, || ());
| ^^^^^
|
help: try using a const generic argument instead
|
LL | std::arch::x86_64::_mm_blend_ps::<{ || () }>(loop {}, loop {});
| +++++++++++++ ~~~~~~~~~~~~~~~~
error: invalid argument to a legacy const generic: cannot have const blocks, closures, async blocks or items
--> $DIR/invalid-rustc_legacy_const_generics-issue-123077.rs:11:59
|
LL | std::arch::x86_64::_mm_blend_ps(loop {}, loop {}, 5 + || ());
| ^^^^^
|
help: try using a const generic argument instead
|
LL | std::arch::x86_64::_mm_blend_ps::<{ 5 + (|| ()) }>(loop {}, loop {});
| +++++++++++++++++++ ~~~~~~~~~~~~~~~~
error: invalid argument to a legacy const generic: cannot have const blocks, closures, async blocks or items
--> $DIR/invalid-rustc_legacy_const_generics-issue-123077.rs:14:61
|
LL | std::arch::x86_64::_mm_blend_ps(loop {}, loop {}, foo::<{ 1 + 2 }>());
| ^^^^^^^^^
|
help: try using a const generic argument instead
|
LL | std::arch::x86_64::_mm_blend_ps::<{ foo::<{ 1 + 2 }>() }>(loop {}, loop {});
| ++++++++++++++++++++++++++ ~~~~~~~~~~~~~~~~
error: invalid argument to a legacy const generic: cannot have const blocks, closures, async blocks or items
--> $DIR/invalid-rustc_legacy_const_generics-issue-123077.rs:17:61
|
LL | std::arch::x86_64::_mm_blend_ps(loop {}, loop {}, foo::<3>());
| ^
|
help: try using a const generic argument instead
|
LL | std::arch::x86_64::_mm_blend_ps::<{ foo::<3>() }>(loop {}, loop {});
| ++++++++++++++++++ ~~~~~~~~~~~~~~~~
error: invalid argument to a legacy const generic: cannot have const blocks, closures, async blocks or items
--> $DIR/invalid-rustc_legacy_const_generics-issue-123077.rs:20:56
|
LL | std::arch::x86_64::_mm_blend_ps(loop {}, loop {}, &const {});
| ^^^^^^^^
|
help: try using a const generic argument instead
|
LL | std::arch::x86_64::_mm_blend_ps::<{ &const {} }>(loop {}, loop {});
| +++++++++++++++++ ~~~~~~~~~~~~~~~~
error: invalid argument to a legacy const generic: cannot have const blocks, closures, async blocks or items
--> $DIR/invalid-rustc_legacy_const_generics-issue-123077.rs:24:9
|
LL | struct F();
| ^^^^^^^^^^^
|
help: try using a const generic argument instead
|
LL ~ std::arch::x86_64::_mm_blend_ps::<{ {
LL + struct F();
LL + 1
LL ~ } }>(loop {}, loop {});
|
error: invalid argument to a legacy const generic: cannot have const blocks, closures, async blocks or items
--> $DIR/invalid-rustc_legacy_const_generics-issue-123077.rs:29:59
|
LL | std::arch::x86_64::_mm_inserti_si64(loop {}, loop {}, || (), 1 + || ());
| ^^^^^
|
help: try using a const generic argument instead
|
LL | std::arch::x86_64::_mm_inserti_si64::<{ || () }, { 1 + (|| ()) }>(loop {}, loop {});
| ++++++++++++++++++++++++++++++ ~~~~~~~~~~~~~~~~
error: aborting due to 7 previous errors