Skip to content

Commit 46e8d20

Browse files
committed
Auto merge of #130443 - veluca93:legacy-const-generics-fix, r=BoxyUwU
Fix ICE when passing DefId-creating args to legacy_const_generics. r? BoxyUwU Fixes #123077 Fixes #129150
2 parents d3a4b1f + b462c68 commit 46e8d20

9 files changed

+211
-22
lines changed

Cargo.lock

+1
Original file line numberDiff line numberDiff line change
@@ -3270,6 +3270,7 @@ name = "rustc_ast_lowering"
32703270
version = "0.0.0"
32713271
dependencies = [
32723272
"rustc_ast",
3273+
"rustc_ast_pretty",
32733274
"rustc_data_structures",
32743275
"rustc_errors",
32753276
"rustc_fluent_macro",

compiler/rustc_ast_lowering/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ doctest = false
99
[dependencies]
1010
# tidy-alphabetical-start
1111
rustc_ast = { path = "../rustc_ast" }
12+
rustc_ast_pretty = { path = "../rustc_ast_pretty" }
1213
rustc_data_structures = { path = "../rustc_data_structures" }
1314
rustc_errors = { path = "../rustc_errors" }
1415
rustc_fluent_macro = { path = "../rustc_fluent_macro" }

compiler/rustc_ast_lowering/messages.ftl

+6
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,12 @@ ast_lowering_invalid_asm_template_modifier_reg_class =
103103
ast_lowering_invalid_asm_template_modifier_sym =
104104
asm template modifiers are not allowed for `sym` arguments
105105
106+
ast_lowering_invalid_legacy_const_generic_arg =
107+
invalid argument to a legacy const generic: cannot have const blocks, closures, async blocks or items
108+
109+
ast_lowering_invalid_legacy_const_generic_arg_suggestion =
110+
try using a const generic argument instead
111+
106112
ast_lowering_invalid_register =
107113
invalid register `{$reg}`: {$error}
108114

compiler/rustc_ast_lowering/src/errors.rs

+23
Original file line numberDiff line numberDiff line change
@@ -451,3 +451,26 @@ pub(crate) struct YieldInClosure {
451451
#[suggestion(code = "#[coroutine] ", applicability = "maybe-incorrect", style = "verbose")]
452452
pub suggestion: Option<Span>,
453453
}
454+
455+
#[derive(Diagnostic)]
456+
#[diag(ast_lowering_invalid_legacy_const_generic_arg)]
457+
pub(crate) struct InvalidLegacyConstGenericArg {
458+
#[primary_span]
459+
pub span: Span,
460+
#[subdiagnostic]
461+
pub suggestion: UseConstGenericArg,
462+
}
463+
464+
#[derive(Subdiagnostic)]
465+
#[multipart_suggestion(
466+
ast_lowering_invalid_legacy_const_generic_arg_suggestion,
467+
applicability = "maybe-incorrect"
468+
)]
469+
pub(crate) struct UseConstGenericArg {
470+
#[suggestion_part(code = "::<{const_args}>")]
471+
pub end_of_fn: Span,
472+
pub const_args: String,
473+
pub other_args: String,
474+
#[suggestion_part(code = "{other_args}")]
475+
pub call_args: Span,
476+
}

compiler/rustc_ast_lowering/src/expr.rs

+67-3
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,22 @@
11
use std::assert_matches::assert_matches;
2+
use std::ops::ControlFlow;
23

34
use rustc_ast::ptr::P as AstP;
45
use rustc_ast::*;
6+
use rustc_ast_pretty::pprust::expr_to_string;
57
use rustc_data_structures::stack::ensure_sufficient_stack;
68
use rustc_data_structures::sync::Lrc;
79
use rustc_hir as hir;
810
use rustc_hir::HirId;
911
use rustc_hir::def::{DefKind, Res};
1012
use rustc_middle::span_bug;
13+
use rustc_middle::ty::TyCtxt;
1114
use rustc_session::errors::report_lit_error;
1215
use rustc_span::source_map::{Spanned, respan};
1316
use rustc_span::symbol::{Ident, Symbol, kw, sym};
1417
use rustc_span::{DUMMY_SP, DesugaringKind, Span};
1518
use thin_vec::{ThinVec, thin_vec};
19+
use visit::{Visitor, walk_expr};
1620

1721
use super::errors::{
1822
AsyncCoroutinesNotSupported, AwaitOnlyInAsyncFnAndBlocks, BaseExpressionDoubleDot,
@@ -23,9 +27,32 @@ use super::errors::{
2327
use super::{
2428
GenericArgsMode, ImplTraitContext, LoweringContext, ParamMode, ResolverAstLoweringExt,
2529
};
26-
use crate::errors::YieldInClosure;
30+
use crate::errors::{InvalidLegacyConstGenericArg, UseConstGenericArg, YieldInClosure};
2731
use crate::{AllowReturnTypeNotation, FnDeclKind, ImplTraitPosition, fluent_generated};
2832

33+
struct WillCreateDefIdsVisitor {}
34+
35+
impl<'v> rustc_ast::visit::Visitor<'v> for WillCreateDefIdsVisitor {
36+
type Result = ControlFlow<Span>;
37+
38+
fn visit_anon_const(&mut self, c: &'v AnonConst) -> Self::Result {
39+
ControlFlow::Break(c.value.span)
40+
}
41+
42+
fn visit_item(&mut self, item: &'v Item) -> Self::Result {
43+
ControlFlow::Break(item.span)
44+
}
45+
46+
fn visit_expr(&mut self, ex: &'v Expr) -> Self::Result {
47+
match ex.kind {
48+
ExprKind::Gen(..) | ExprKind::ConstBlock(..) | ExprKind::Closure(..) => {
49+
ControlFlow::Break(ex.span)
50+
}
51+
_ => walk_expr(self, ex),
52+
}
53+
}
54+
}
55+
2956
impl<'hir> LoweringContext<'_, 'hir> {
3057
fn lower_exprs(&mut self, exprs: &[AstP<Expr>]) -> &'hir [hir::Expr<'hir>] {
3158
self.arena.alloc_from_iter(exprs.iter().map(|x| self.lower_expr_mut(x)))
@@ -396,10 +423,34 @@ impl<'hir> LoweringContext<'_, 'hir> {
396423
unreachable!();
397424
};
398425

426+
let mut error = None;
427+
let mut invalid_expr_error = |tcx: TyCtxt<'_>, span| {
428+
// Avoid emitting the error multiple times.
429+
if error.is_none() {
430+
let mut const_args = vec![];
431+
let mut other_args = vec![];
432+
for (idx, arg) in args.iter().enumerate() {
433+
if legacy_args_idx.contains(&idx) {
434+
const_args.push(format!("{{ {} }}", expr_to_string(arg)));
435+
} else {
436+
other_args.push(expr_to_string(arg));
437+
}
438+
}
439+
let suggestion = UseConstGenericArg {
440+
end_of_fn: f.span.shrink_to_hi(),
441+
const_args: const_args.join(", "),
442+
other_args: other_args.join(", "),
443+
call_args: args[0].span.to(args.last().unwrap().span),
444+
};
445+
error = Some(tcx.dcx().emit_err(InvalidLegacyConstGenericArg { span, suggestion }));
446+
}
447+
error.unwrap()
448+
};
449+
399450
// Split the arguments into const generics and normal arguments
400451
let mut real_args = vec![];
401452
let mut generic_args = ThinVec::new();
402-
for (idx, arg) in args.into_iter().enumerate() {
453+
for (idx, arg) in args.iter().cloned().enumerate() {
403454
if legacy_args_idx.contains(&idx) {
404455
let parent_def_id = self.current_def_id_parent;
405456
let node_id = self.next_node_id();
@@ -410,7 +461,20 @@ impl<'hir> LoweringContext<'_, 'hir> {
410461
self.create_def(parent_def_id, node_id, kw::Empty, DefKind::AnonConst, f.span);
411462
}
412463

413-
let anon_const = AnonConst { id: node_id, value: arg };
464+
let mut visitor = WillCreateDefIdsVisitor {};
465+
let const_value = if let ControlFlow::Break(span) = visitor.visit_expr(&arg) {
466+
AstP(Expr {
467+
id: self.next_node_id(),
468+
kind: ExprKind::Err(invalid_expr_error(self.tcx, span)),
469+
span: f.span,
470+
attrs: [].into(),
471+
tokens: None,
472+
})
473+
} else {
474+
arg
475+
};
476+
477+
let anon_const = AnonConst { id: node_id, value: const_value };
414478
generic_args.push(AngleBracketedArg::Arg(GenericArg::Const(anon_const)));
415479
} else {
416480
real_args.push(arg);

tests/crashes/123077-2.rs

-12
This file was deleted.

tests/crashes/129150.rs

-7
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
//@ only-x86_64
2+
3+
const fn foo<const U: i32>() -> i32 {
4+
U
5+
}
6+
7+
fn main() {
8+
std::arch::x86_64::_mm_blend_ps(loop {}, loop {}, || ());
9+
//~^ invalid argument to a legacy const generic
10+
11+
std::arch::x86_64::_mm_blend_ps(loop {}, loop {}, 5 + || ());
12+
//~^ invalid argument to a legacy const generic
13+
14+
std::arch::x86_64::_mm_blend_ps(loop {}, loop {}, foo::<{ 1 + 2 }>());
15+
//~^ invalid argument to a legacy const generic
16+
17+
std::arch::x86_64::_mm_blend_ps(loop {}, loop {}, foo::<3>());
18+
//~^ invalid argument to a legacy const generic
19+
20+
std::arch::x86_64::_mm_blend_ps(loop {}, loop {}, &const {});
21+
//~^ invalid argument to a legacy const generic
22+
23+
std::arch::x86_64::_mm_blend_ps(loop {}, loop {}, {
24+
struct F();
25+
//~^ invalid argument to a legacy const generic
26+
1
27+
});
28+
29+
std::arch::x86_64::_mm_inserti_si64(loop {}, loop {}, || (), 1 + || ());
30+
//~^ invalid argument to a legacy const generic
31+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
error: invalid argument to a legacy const generic: cannot have const blocks, closures, async blocks or items
2+
--> $DIR/invalid-rustc_legacy_const_generics-issue-123077.rs:8:55
3+
|
4+
LL | std::arch::x86_64::_mm_blend_ps(loop {}, loop {}, || ());
5+
| ^^^^^
6+
|
7+
help: try using a const generic argument instead
8+
|
9+
LL | std::arch::x86_64::_mm_blend_ps::<{ || () }>(loop {}, loop {});
10+
| +++++++++++++ ~~~~~~~~~~~~~~~~
11+
12+
error: invalid argument to a legacy const generic: cannot have const blocks, closures, async blocks or items
13+
--> $DIR/invalid-rustc_legacy_const_generics-issue-123077.rs:11:59
14+
|
15+
LL | std::arch::x86_64::_mm_blend_ps(loop {}, loop {}, 5 + || ());
16+
| ^^^^^
17+
|
18+
help: try using a const generic argument instead
19+
|
20+
LL | std::arch::x86_64::_mm_blend_ps::<{ 5 + (|| ()) }>(loop {}, loop {});
21+
| +++++++++++++++++++ ~~~~~~~~~~~~~~~~
22+
23+
error: invalid argument to a legacy const generic: cannot have const blocks, closures, async blocks or items
24+
--> $DIR/invalid-rustc_legacy_const_generics-issue-123077.rs:14:61
25+
|
26+
LL | std::arch::x86_64::_mm_blend_ps(loop {}, loop {}, foo::<{ 1 + 2 }>());
27+
| ^^^^^^^^^
28+
|
29+
help: try using a const generic argument instead
30+
|
31+
LL | std::arch::x86_64::_mm_blend_ps::<{ foo::<{ 1 + 2 }>() }>(loop {}, loop {});
32+
| ++++++++++++++++++++++++++ ~~~~~~~~~~~~~~~~
33+
34+
error: invalid argument to a legacy const generic: cannot have const blocks, closures, async blocks or items
35+
--> $DIR/invalid-rustc_legacy_const_generics-issue-123077.rs:17:61
36+
|
37+
LL | std::arch::x86_64::_mm_blend_ps(loop {}, loop {}, foo::<3>());
38+
| ^
39+
|
40+
help: try using a const generic argument instead
41+
|
42+
LL | std::arch::x86_64::_mm_blend_ps::<{ foo::<3>() }>(loop {}, loop {});
43+
| ++++++++++++++++++ ~~~~~~~~~~~~~~~~
44+
45+
error: invalid argument to a legacy const generic: cannot have const blocks, closures, async blocks or items
46+
--> $DIR/invalid-rustc_legacy_const_generics-issue-123077.rs:20:56
47+
|
48+
LL | std::arch::x86_64::_mm_blend_ps(loop {}, loop {}, &const {});
49+
| ^^^^^^^^
50+
|
51+
help: try using a const generic argument instead
52+
|
53+
LL | std::arch::x86_64::_mm_blend_ps::<{ &const {} }>(loop {}, loop {});
54+
| +++++++++++++++++ ~~~~~~~~~~~~~~~~
55+
56+
error: invalid argument to a legacy const generic: cannot have const blocks, closures, async blocks or items
57+
--> $DIR/invalid-rustc_legacy_const_generics-issue-123077.rs:24:9
58+
|
59+
LL | struct F();
60+
| ^^^^^^^^^^^
61+
|
62+
help: try using a const generic argument instead
63+
|
64+
LL ~ std::arch::x86_64::_mm_blend_ps::<{ {
65+
LL + struct F();
66+
LL + 1
67+
LL ~ } }>(loop {}, loop {});
68+
|
69+
70+
error: invalid argument to a legacy const generic: cannot have const blocks, closures, async blocks or items
71+
--> $DIR/invalid-rustc_legacy_const_generics-issue-123077.rs:29:59
72+
|
73+
LL | std::arch::x86_64::_mm_inserti_si64(loop {}, loop {}, || (), 1 + || ());
74+
| ^^^^^
75+
|
76+
help: try using a const generic argument instead
77+
|
78+
LL | std::arch::x86_64::_mm_inserti_si64::<{ || () }, { 1 + (|| ()) }>(loop {}, loop {});
79+
| ++++++++++++++++++++++++++++++ ~~~~~~~~~~~~~~~~
80+
81+
error: aborting due to 7 previous errors
82+

0 commit comments

Comments
 (0)