Rollup merge of #110770 - m-ou-se:fmt-temp-lifetime, r=oli-obk

Limit lifetime of format_args!() with inlined args.

Fixes #110769
This commit is contained in:
Matthias Krüger 2023-05-09 20:49:31 +02:00 committed by GitHub
commit e4c82501c2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 40 additions and 1 deletions

View File

@ -446,7 +446,30 @@ fn expand_format_args<'hir>(
&& argmap.iter().enumerate().all(|(i, (&(j, _), _))| i == j) && argmap.iter().enumerate().all(|(i, (&(j, _), _))| i == j)
&& arguments.iter().skip(1).all(|arg| !may_contain_yield_point(&arg.expr)); && 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: // Generate:
// &[ // &[
// <core::fmt::Argument>::new_display(&arg0), // <core::fmt::Argument>::new_display(&arg0),

View File

@ -1033,6 +1033,7 @@
non_exhaustive_omitted_patterns_lint, non_exhaustive_omitted_patterns_lint,
non_lifetime_binders, non_lifetime_binders,
non_modrs_mods, non_modrs_mods,
none,
nontemporal_store, nontemporal_store,
noop_method_borrow, noop_method_borrow,
noop_method_clone, noop_method_clone,

View File

@ -152,6 +152,21 @@ pub(super) fn as_usize(&self) -> Option<usize> {
None 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`. /// This struct represents the unsafety of constructing an `Arguments`.