From 9f7e7f0bb1f9c5d003065f1eccbb29fe2d75f98f Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Sun, 23 Apr 2023 16:05:40 -0400 Subject: [PATCH] Emit less MIR for format_args! with just a str literal --- compiler/rustc_ast_lowering/src/format.rs | 29 ++++++++++++++++++++--- compiler/rustc_ast_lowering/src/item.rs | 1 + compiler/rustc_ast_lowering/src/lib.rs | 1 + compiler/rustc_span/src/hygiene.rs | 2 ++ compiler/rustc_span/src/symbol.rs | 2 ++ library/core/src/fmt/mod.rs | 3 ++- tests/ui/borrowck/issue-64453.rs | 1 - tests/ui/borrowck/issue-64453.stderr | 13 ++-------- 8 files changed, 36 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/format.rs b/compiler/rustc_ast_lowering/src/format.rs index ccf481cb9b39d..5669bb156fc58 100644 --- a/compiler/rustc_ast_lowering/src/format.rs +++ b/compiler/rustc_ast_lowering/src/format.rs @@ -5,6 +5,7 @@ use rustc_ast::*; use rustc_data_structures::fx::FxIndexMap; use rustc_hir as hir; use rustc_span::{ + hygiene::DesugaringKind, sym, symbol::{kw, Ident}, Span, Symbol, @@ -425,14 +426,36 @@ fn expand_format_args<'hir>( if allow_const && arguments.is_empty() && argmap.is_empty() { // Generate: - // ::new_const(lit_pieces) - let new = ctx.arena.alloc(ctx.expr_lang_item_type_relative( + // const { ::new_const(lit_pieces) } + let span = ctx.mark_span_with_reason( + DesugaringKind::FormatArgs, macsp, + ctx.allow_format_args.clone(), + ); + let new = ctx.arena.alloc(ctx.expr_lang_item_type_relative( + span, hir::LangItem::FormatArguments, sym::new_const, )); let new_args = ctx.arena.alloc_from_iter([lit_pieces]); - return hir::ExprKind::Call(new, new_args); + let call = hir::ExprKind::Call(new, new_args); + + let node_id = ctx.next_node_id(); + let call_expr = hir::Expr { hir_id: ctx.lower_node_id(node_id), kind: call, span }; + + let parent_def_id = ctx.current_hir_id_owner; + let node_id = ctx.next_node_id(); + let def_id = ctx.create_def( + parent_def_id.def_id, + node_id, + hir::definitions::DefPathData::AnonConst, + span, + ); + return hir::ExprKind::ConstBlock(hir::AnonConst { + def_id, + hir_id: ctx.lower_node_id(node_id), + body: ctx.lower_body(|_this| (&[], call_expr)), + }); } // If the args array contains exactly all the original arguments once, diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 08e7a4dfe5d5d..d3095c2b60e3c 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -84,6 +84,7 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> { allow_try_trait: Some([sym::try_trait_v2, sym::yeet_desugar_details][..].into()), allow_gen_future: Some([sym::gen_future, sym::closure_track_caller][..].into()), allow_into_future: Some([sym::into_future][..].into()), + allow_format_args: Some([sym::const_fmt_arguments_new, sym::fmt_internals][..].into()), generics_def_id_map: Default::default(), }; lctx.with_hir_id_owner(owner, |lctx| f(lctx)); diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index c969d70960810..81ed1a61aff38 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -137,6 +137,7 @@ struct LoweringContext<'a, 'hir> { allow_try_trait: Option>, allow_gen_future: Option>, allow_into_future: Option>, + allow_format_args: Option>, /// Mapping from generics `def_id`s to TAIT generics `def_id`s. /// For each captured lifetime (e.g., 'a), we create a new lifetime parameter that is a generic diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs index f8741d85934a2..b54bf6df7b4ed 100644 --- a/compiler/rustc_span/src/hygiene.rs +++ b/compiler/rustc_span/src/hygiene.rs @@ -1152,6 +1152,7 @@ pub enum DesugaringKind { ForLoop, WhileLoop, Replace, + FormatArgs, } impl DesugaringKind { @@ -1168,6 +1169,7 @@ impl DesugaringKind { DesugaringKind::ForLoop => "`for` loop", DesugaringKind::WhileLoop => "`while` loop", DesugaringKind::Replace => "drop and replace", + DesugaringKind::FormatArgs => "`format_args!` expansion", } } } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 9891915d076dd..8f75a5ffc7cdf 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -511,6 +511,7 @@ symbols! { const_eval_select, const_evaluatable_checked, const_extern_fn, + const_fmt_arguments_new, const_fn, const_fn_floating_point_arithmetic, const_fn_fn_ptr_basics, @@ -718,6 +719,7 @@ symbols! { fmaf32, fmaf64, fmt, + fmt_internals, fmul_fast, fn_align, fn_must_use, diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index a901ae726698a..69aaf7d47066c 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -393,7 +393,8 @@ impl<'a> Arguments<'a> { #[rustc_const_unstable(feature = "const_fmt_arguments_new", issue = "none")] pub const fn new_const(pieces: &'a [&'static str]) -> Self { if pieces.len() > 1 { - panic!("invalid args"); + // panic! expands to a call to this function, so we do this to avoid recursion. + crate::panicking::panic("invalid args"); } Arguments { pieces, fmt: None, args: &[] } } diff --git a/tests/ui/borrowck/issue-64453.rs b/tests/ui/borrowck/issue-64453.rs index 33d55be5812e7..5f1f35d6ca9bb 100644 --- a/tests/ui/borrowck/issue-64453.rs +++ b/tests/ui/borrowck/issue-64453.rs @@ -3,7 +3,6 @@ struct Value; static settings_dir: String = format!(""); //~^ ERROR cannot call non-const fn -//~| ERROR is not yet stable as a const fn from_string(_: String) -> Value { Value diff --git a/tests/ui/borrowck/issue-64453.stderr b/tests/ui/borrowck/issue-64453.stderr index f032ea779dd48..fadde357c9e51 100644 --- a/tests/ui/borrowck/issue-64453.stderr +++ b/tests/ui/borrowck/issue-64453.stderr @@ -1,12 +1,3 @@ -error: `Arguments::<'a>::new_const` is not yet stable as a const fn - --> $DIR/issue-64453.rs:4:31 - | -LL | static settings_dir: String = format!(""); - | ^^^^^^^^^^^ - | - = help: add `#![feature(const_fmt_arguments_new)]` to the crate attributes to enable - = note: this error originates in the macro `$crate::__export::format_args` which comes from the expansion of the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info) - error[E0015]: cannot call non-const fn `format` in statics --> $DIR/issue-64453.rs:4:31 | @@ -18,12 +9,12 @@ LL | static settings_dir: String = format!(""); = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0507]: cannot move out of static item `settings_dir` - --> $DIR/issue-64453.rs:14:37 + --> $DIR/issue-64453.rs:13:37 | LL | let settings_data = from_string(settings_dir); | ^^^^^^^^^^^^ move occurs because `settings_dir` has type `String`, which does not implement the `Copy` trait -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors Some errors have detailed explanations: E0015, E0507. For more information about an error, try `rustc --explain E0015`.