Skip to content

Commit

Permalink
Remove match-less special case in format_args!() expansion.
Browse files Browse the repository at this point in the history
  • Loading branch information
m-ou-se committed Jan 12, 2023
1 parent 5659310 commit a6d6589
Show file tree
Hide file tree
Showing 4 changed files with 19 additions and 76 deletions.
73 changes: 7 additions & 66 deletions compiler/rustc_ast_lowering/src/format.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
use super::LoweringContext;
use rustc_ast as ast;
use rustc_ast::visit::{self, Visitor};
use rustc_ast::*;
use rustc_data_structures::fx::FxIndexSet;
use rustc_hir as hir;
Expand Down Expand Up @@ -190,37 +188,10 @@ fn expand_format_args<'hir>(
ctx.expr_array_ref(macsp, ctx.arena.alloc_from_iter(elements))
});

let arguments = fmt.arguments.all_args();

// If the args array contains exactly all the original arguments once,
// in order, we can use a simple array instead of a `match` construction.
// However, if there's a yield point in any argument except the first one,
// we don't do this, because an ArgumentV1 cannot be kept across yield points.
let use_simple_array = argmap.len() == arguments.len()
&& 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 fmt.arguments.all_args().is_empty() {
// Generate:
// &[
// ::core::fmt::ArgumentV1::new_display(&arg0),
// ::core::fmt::ArgumentV1::new_lower_hex(&arg1),
// ::core::fmt::ArgumentV1::new_debug(&arg2),
// ]
let elements: Vec<_> = arguments
.iter()
.zip(argmap)
.map(|(arg, (_, ty))| {
let sp = arg.expr.span.with_ctxt(macsp.ctxt());
let arg = ctx.lower_expr(&arg.expr);
let ref_arg = ctx.arena.alloc(ctx.expr(
sp,
hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Not, arg),
));
make_argument(ctx, sp, ref_arg, ty)
})
.collect();
ctx.expr_array_ref(macsp, ctx.arena.alloc_from_iter(elements))
// &[]
ctx.expr_array_ref(macsp, &[])
} else {
// Generate:
// &match (&arg0, &arg1, &arg2) {
Expand All @@ -233,7 +204,7 @@ fn expand_format_args<'hir>(
let args_ident = Ident::new(sym::args, macsp);
let (args_pat, args_hir_id) = ctx.pat_ident(macsp, args_ident);
let args = ctx.arena.alloc_from_iter(argmap.iter().map(|&(arg_index, ty)| {
if let Some(arg) = arguments.get(arg_index) {
if let Some(arg) = fmt.arguments.all_args().get(arg_index) {
let sp = arg.expr.span.with_ctxt(macsp.ctxt());
let args_ident_expr = ctx.expr_ident(macsp, args_ident, args_hir_id);
let arg = ctx.arena.alloc(ctx.expr(
Expand All @@ -248,7 +219,9 @@ fn expand_format_args<'hir>(
ctx.expr(macsp, hir::ExprKind::Err)
}
}));
let elements: Vec<_> = arguments
let elements: Vec<_> = fmt
.arguments
.all_args()
.iter()
.map(|arg| {
let arg_expr = ctx.lower_expr(&arg.expr);
Expand Down Expand Up @@ -320,35 +293,3 @@ fn expand_format_args<'hir>(
hir::ExprKind::Call(new_v1, new_args)
}
}

fn may_contain_yield_point(e: &ast::Expr) -> bool {
struct MayContainYieldPoint(bool);

impl Visitor<'_> for MayContainYieldPoint {
fn visit_expr(&mut self, e: &ast::Expr) {
if let ast::ExprKind::Await(_) | ast::ExprKind::Yield(_) = e.kind {
self.0 = true;
} else {
visit::walk_expr(self, e);
}
}

fn visit_mac_call(&mut self, _: &ast::MacCall) {
self.0 = true;
}

fn visit_attribute(&mut self, _: &ast::Attribute) {
// Conservatively assume this may be a proc macro attribute in
// expression position.
self.0 = true;
}

fn visit_item(&mut self, _: &ast::Item) {
// Do not recurse into nested items.
}
}

let mut visitor = MayContainYieldPoint(false);
visitor.visit_expr(e);
visitor.0
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ LL | let c1 : () = c;
| expected due to this
|
= note: expected unit type `()`
found closure `[mod1::f<T>::{closure#0} closure_substs=(unavailable) substs=[T, _#16t, extern "rust-call" fn(()), _#15t]]`
found closure `[mod1::f<T>::{closure#0} closure_substs=(unavailable) substs=[T, _#19t, extern "rust-call" fn(()), _#18t]]`
help: use parentheses to call this closure
|
LL | let c1 : () = c();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ LL | let c1 : () = c;
| expected due to this
|
= note: expected unit type `()`
found closure `[f<T>::{closure#0} closure_substs=(unavailable) substs=[T, _#16t, extern "rust-call" fn(()), _#15t]]`
found closure `[f<T>::{closure#0} closure_substs=(unavailable) substs=[T, _#19t, extern "rust-call" fn(()), _#18t]]`
help: use parentheses to call this closure
|
LL | let c1 : () = c();
Expand Down
18 changes: 10 additions & 8 deletions tests/ui/issues/issue-69455.stderr
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
error[E0282]: type annotations needed
--> $DIR/issue-69455.rs:29:20
error[E0284]: type annotations needed
--> $DIR/issue-69455.rs:29:41
|
LL | println!("{}", 23u64.test(xs.iter().sum()));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the associated function `new_display`
| ---- ^^^ cannot infer type of the type parameter `S` declared on the associated function `sum`
| |
| type must be known at this point
|
= note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
= note: cannot satisfy `<u64 as Test<_>>::Output == _`
help: consider specifying the generic argument
|
LL | println!("{}", 23u64.test(xs.iter().sum())::<T>);
| +++++
LL | println!("{}", 23u64.test(xs.iter().sum::<S>()));
| +++++

error[E0283]: type annotations needed
--> $DIR/issue-69455.rs:29:41
Expand All @@ -33,5 +35,5 @@ LL | println!("{}", 23u64.test(xs.iter().sum::<S>()));

error: aborting due to 2 previous errors

Some errors have detailed explanations: E0282, E0283.
For more information about an error, try `rustc --explain E0282`.
Some errors have detailed explanations: E0283, E0284.
For more information about an error, try `rustc --explain E0283`.

0 comments on commit a6d6589

Please sign in to comment.