Skip to content

Commit

Permalink
Rollup merge of #110770 - m-ou-se:fmt-temp-lifetime, r=oli-obk
Browse files Browse the repository at this point in the history
Limit lifetime of format_args!() with inlined args.

Fixes #110769
  • Loading branch information
matthiaskrgr authored May 9, 2023
2 parents 88fbfaf + d5843dd commit e4c8250
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 1 deletion.
25 changes: 24 additions & 1 deletion compiler/rustc_ast_lowering/src/format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -446,7 +446,30 @@ fn expand_format_args<'hir>(
&& argmap.iter().enumerate().all(|(i, (&(j, _), _))| i == j)
&& arguments.iter().skip(1).all(|arg| !may_contain_yield_point(&arg.expr));

let args = if use_simple_array {
let args = if arguments.is_empty() {
// Generate:
// &<core::fmt::Argument>::none()
//
// Note:
// `none()` just returns `[]`. We use `none()` rather than `[]` to limit the lifetime.
//
// This makes sure that this still fails to compile, even when the argument is inlined:
//
// ```
// let f = format_args!("{}", "a");
// println!("{f}"); // error E0716
// ```
//
// Cases where keeping the object around is allowed, such as `format_args!("a")`,
// are handled above by the `allow_const` case.
let none_fn = ctx.arena.alloc(ctx.expr_lang_item_type_relative(
macsp,
hir::LangItem::FormatArgument,
sym::none,
));
let none = ctx.expr_call(macsp, none_fn, &[]);
ctx.expr(macsp, hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Not, none))
} else if use_simple_array {
// Generate:
// &[
// <core::fmt::Argument>::new_display(&arg0),
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1033,6 +1033,7 @@ symbols! {
non_exhaustive_omitted_patterns_lint,
non_lifetime_binders,
non_modrs_mods,
none,
nontemporal_store,
noop_method_borrow,
noop_method_clone,
Expand Down
15 changes: 15 additions & 0 deletions library/core/src/fmt/rt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,21 @@ impl<'a> Argument<'a> {
None
}
}

/// Used by `format_args` when all arguments are gone after inlining,
/// when using `&[]` would incorrectly allow for a bigger lifetime.
///
/// This fails without format argument inlining, and that shouldn't be different
/// when the argument is inlined:
///
/// ```compile_fail,E0716
/// let f = format_args!("{}", "a");
/// println!("{f}");
/// ```
#[inline(always)]
pub fn none() -> [Self; 0] {
[]
}
}

/// This struct represents the unsafety of constructing an `Arguments`.
Expand Down

0 comments on commit e4c8250

Please sign in to comment.