Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix ICE when passing DefId-creating args to legacy_const_generics. #130443

Merged
merged 1 commit into from
Nov 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3270,6 +3270,7 @@ name = "rustc_ast_lowering"
version = "0.0.0"
dependencies = [
"rustc_ast",
"rustc_ast_pretty",
"rustc_data_structures",
"rustc_errors",
"rustc_fluent_macro",
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_ast_lowering/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ doctest = false
[dependencies]
# tidy-alphabetical-start
rustc_ast = { path = "../rustc_ast" }
rustc_ast_pretty = { path = "../rustc_ast_pretty" }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was this already a transitive dep, or did this change reduce build parallelism?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was a dep through rustc_errors (and it also was a direct dep ~10 days ago: b480f0f)

rustc_data_structures = { path = "../rustc_data_structures" }
rustc_errors = { path = "../rustc_errors" }
rustc_fluent_macro = { path = "../rustc_fluent_macro" }
Expand Down
6 changes: 6 additions & 0 deletions compiler/rustc_ast_lowering/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,12 @@ ast_lowering_invalid_asm_template_modifier_reg_class =
ast_lowering_invalid_asm_template_modifier_sym =
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 =
invalid register `{$reg}`: {$error}
Expand Down
23 changes: 23 additions & 0 deletions compiler/rustc_ast_lowering/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -451,3 +451,26 @@ pub(crate) struct YieldInClosure {
#[suggestion(code = "#[coroutine] ", applicability = "maybe-incorrect", style = "verbose")]
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,
}
70 changes: 67 additions & 3 deletions compiler/rustc_ast_lowering/src/expr.rs
Original file line number Diff line number Diff line change
@@ -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,
Expand All @@ -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(..) => {
veluca93 marked this conversation as resolved.
Show resolved Hide resolved
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)))
Expand Down Expand Up @@ -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();
Expand All @@ -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);
Expand Down
12 changes: 0 additions & 12 deletions tests/crashes/123077-2.rs

This file was deleted.

7 changes: 0 additions & 7 deletions tests/crashes/129150.rs

This file was deleted.

Original file line number Diff line number Diff line change
@@ -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
}
veluca93 marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -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

Loading