-
Notifications
You must be signed in to change notification settings - Fork 13.8k
Emit simpler code from format_args #91359
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
Changes from all commits
abf1d94
1b5ff95
730249d
490569c
7ee21e3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -11,6 +11,7 @@ use rustc_expand::base::{self, *}; | |||||||||||
use rustc_parse_format as parse; | ||||||||||||
use rustc_span::symbol::{sym, Ident, Symbol}; | ||||||||||||
use rustc_span::{MultiSpan, Span}; | ||||||||||||
use smallvec::SmallVec; | ||||||||||||
|
||||||||||||
use std::borrow::Cow; | ||||||||||||
use std::collections::hash_map::Entry; | ||||||||||||
|
@@ -744,78 +745,95 @@ impl<'a, 'b> Context<'a, 'b> { | |||||||||||
/// Actually builds the expression which the format_args! block will be | ||||||||||||
/// expanded to. | ||||||||||||
fn into_expr(self) -> P<ast::Expr> { | ||||||||||||
let mut args = Vec::with_capacity( | ||||||||||||
let mut original_args = self.args; | ||||||||||||
let mut fmt_args = Vec::with_capacity( | ||||||||||||
self.arg_unique_types.iter().map(|v| v.len()).sum::<usize>() + self.count_args.len(), | ||||||||||||
); | ||||||||||||
let mut heads = Vec::with_capacity(self.args.len()); | ||||||||||||
|
||||||||||||
// First, build up the static array which will become our precompiled | ||||||||||||
// format "string" | ||||||||||||
let pieces = self.ecx.expr_vec_slice(self.fmtsp, self.str_pieces); | ||||||||||||
|
||||||||||||
// Before consuming the expressions, we have to remember spans for | ||||||||||||
// count arguments as they are now generated separate from other | ||||||||||||
// arguments, hence have no access to the `P<ast::Expr>`'s. | ||||||||||||
let spans_pos: Vec<_> = self.args.iter().map(|e| e.span).collect(); | ||||||||||||
|
||||||||||||
// Right now there is a bug such that for the expression: | ||||||||||||
// foo(bar(&1)) | ||||||||||||
// the lifetime of `1` doesn't outlast the call to `bar`, so it's not | ||||||||||||
// valid for the call to `foo`. To work around this all arguments to the | ||||||||||||
// format! string are shoved into locals. Furthermore, we shove the address | ||||||||||||
// of each variable because we don't want to move out of the arguments | ||||||||||||
// passed to this function. | ||||||||||||
for (i, e) in self.args.into_iter().enumerate() { | ||||||||||||
for arg_ty in self.arg_unique_types[i].iter() { | ||||||||||||
args.push(Context::format_arg(self.ecx, self.macsp, e.span, arg_ty, i)); | ||||||||||||
} | ||||||||||||
// use the arg span for `&arg` so that borrowck errors | ||||||||||||
// point to the specific expression passed to the macro | ||||||||||||
// (the span is otherwise unavailable in MIR) | ||||||||||||
heads.push(self.ecx.expr_addr_of(e.span.with_ctxt(self.macsp.ctxt()), e)); | ||||||||||||
} | ||||||||||||
for index in self.count_args { | ||||||||||||
let span = spans_pos[index]; | ||||||||||||
args.push(Context::format_arg(self.ecx, self.macsp, span, &Count, index)); | ||||||||||||
// We need to construct a &[ArgumentV1] to pass into the fmt::Arguments | ||||||||||||
// constructor. In general the expressions in this slice might be | ||||||||||||
// permuted from their order in original_args (such as in the case of | ||||||||||||
// "{1} {0}"), or may have multiple entries referring to the same | ||||||||||||
// element of original_args ("{0} {0}"). | ||||||||||||
// | ||||||||||||
// The following vector has one item per element of our output slice, | ||||||||||||
// identifying the index of which element of original_args it's passing, | ||||||||||||
// and that argument's type. | ||||||||||||
let mut fmt_arg_index_and_ty = SmallVec::<[(usize, &ArgumentType); 8]>::new(); | ||||||||||||
|
fn format_arg( | |
ecx: &ExtCtxt<'_>, | |
macsp: Span, | |
mut sp: Span, | |
ty: &ArgumentType, |
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a reason to prefix args with an underscore? It seems like it should always be used, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure but I'll stick with keeping the name as is (this is the same name currently used on master).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had the underscore because its unused in the 0 value args case. But I think this is no longer true with this PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lol at leftover comments from the original implementation of std::fmt (the
ifmt!
macro at the time) >8 years ago in ffb670f, which has been obsolete/inaccurate since a year before rust 1.0 (early 2014 — #11585).