Skip to content

Commit 5046889

Browse files
committed
Don't allocate the format_args template string as an expression
1 parent 3fa0bf0 commit 5046889

File tree

4 files changed

+31
-46
lines changed

4 files changed

+31
-46
lines changed

crates/hir-def/src/body/lower.rs

+25-25
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ use crate::{
3232
hir::{
3333
dummy_expr_id,
3434
format_args::{
35-
self, FormatAlignment, FormatArgsPiece, FormatArgument, FormatArgumentKind,
35+
self, FormatAlignment, FormatArgs, FormatArgsPiece, FormatArgument, FormatArgumentKind,
3636
FormatArgumentsCollector, FormatCount, FormatDebugHex, FormatOptions,
3737
FormatPlaceholder, FormatSign, FormatTrait,
3838
},
@@ -1568,6 +1568,24 @@ impl ExprCollector<'_> {
15681568
// endregion: labels
15691569

15701570
// region: format
1571+
fn expand_macros_to_string(&mut self, expr: ast::Expr) -> Option<(ast::String, bool)> {
1572+
let m = match expr {
1573+
ast::Expr::MacroExpr(m) => m,
1574+
ast::Expr::Literal(l) => {
1575+
return match l.kind() {
1576+
ast::LiteralKind::String(s) => Some((s, true)),
1577+
_ => None,
1578+
}
1579+
}
1580+
_ => return None,
1581+
};
1582+
let e = m.macro_call()?;
1583+
let macro_ptr = AstPtr::new(&e);
1584+
let (exp, _) = self.collect_macro_call(e, macro_ptr, true, |this, expansion| {
1585+
expansion.and_then(|it| this.expand_macros_to_string(it))
1586+
})?;
1587+
Some((exp, false))
1588+
}
15711589

15721590
fn collect_format_args(
15731591
&mut self,
@@ -1586,31 +1604,13 @@ impl ExprCollector<'_> {
15861604
});
15871605
let template = f.template();
15881606
let fmt_snippet = template.as_ref().map(ToString::to_string);
1589-
1590-
// FIXME: We shouldn't allocate this one, just resolve and expand the macros to fetch the
1591-
// string literal!
1592-
let expr = self.collect_expr_opt(template);
1593-
1594-
let fmt = 'b: {
1595-
if let Expr::Literal(Literal::String(_)) = self.body[expr] {
1596-
let source = self.source_map.expr_map_back[expr].clone();
1597-
let is_direct_literal = source.file_id == self.expander.current_file_id;
1598-
if let ast::Expr::Literal(l) =
1599-
source.value.to_node(&self.db.parse_or_expand(source.file_id))
1600-
{
1601-
if let ast::LiteralKind::String(s) = l.kind() {
1602-
break 'b format_args::parse(
1603-
expr,
1604-
&s,
1605-
fmt_snippet,
1606-
args,
1607-
is_direct_literal,
1608-
|name| self.alloc_expr_desugared(Expr::Path(Path::from(name))),
1609-
);
1610-
}
1611-
}
1607+
let fmt = match template.and_then(|it| self.expand_macros_to_string(it)) {
1608+
Some((s, is_direct_literal)) => {
1609+
format_args::parse(&s, fmt_snippet, args, is_direct_literal, |name| {
1610+
self.alloc_expr_desugared(Expr::Path(Path::from(name)))
1611+
})
16121612
}
1613-
return self.missing_expr();
1613+
None => FormatArgs { template: Default::default(), arguments: args.finish() },
16141614
};
16151615

16161616
// Create a list of all _unique_ (argument, format trait) combinations.

crates/hir-def/src/body/tests.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ fn main() {
161161
let count = 10;
162162
builtin#lang(Arguments::new_v1_formatted)(
163163
&[
164-
"\"hello ", " ", " friends, we ", " ", "", "\"",
164+
"\"hello ", " ", " friends, we ", " ", "", "\"",
165165
],
166166
&[
167167
builtin#lang(Argument::new_display)(
@@ -172,7 +172,7 @@ fn main() {
172172
&are,
173173
), builtin#lang(Argument::new_display)(
174174
&"!",
175-
),
175+
),
176176
],
177177
&[
178178
builtin#lang(Placeholder::new)(
@@ -212,7 +212,7 @@ fn main() {
212212
0u32,
213213
builtin#lang(Count::Implied),
214214
builtin#lang(Count::Implied),
215-
),
215+
),
216216
],
217217
unsafe {
218218
builtin#lang(UnsafeArg::new)()

crates/hir-def/src/hir/format_args.rs

+3-12
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
//! Parses `format_args` input.
12
use std::mem;
23

34
use hir_expand::name::Name;
@@ -12,7 +13,6 @@ mod parse;
1213

1314
#[derive(Debug, Clone, PartialEq, Eq)]
1415
pub struct FormatArgs {
15-
pub template_expr: ExprId,
1616
pub template: Box<[FormatArgsPiece]>,
1717
pub arguments: FormatArguments,
1818
}
@@ -166,7 +166,6 @@ enum PositionUsedAs {
166166
use PositionUsedAs::*;
167167

168168
pub(crate) fn parse(
169-
expr: ExprId,
170169
s: &ast::String,
171170
fmt_snippet: Option<String>,
172171
mut args: FormatArgumentsCollector,
@@ -195,11 +194,7 @@ pub(crate) fn parse(
195194
let is_source_literal = parser.is_source_literal;
196195
if !parser.errors.is_empty() {
197196
// FIXME: Diagnose
198-
return FormatArgs {
199-
template_expr: expr,
200-
template: Default::default(),
201-
arguments: args.finish(),
202-
};
197+
return FormatArgs { template: Default::default(), arguments: args.finish() };
203198
}
204199

205200
let to_span = |inner_span: parse::InnerSpan| {
@@ -419,11 +414,7 @@ pub(crate) fn parse(
419414
// FIXME: Diagnose
420415
}
421416

422-
FormatArgs {
423-
template_expr: expr,
424-
template: template.into_boxed_slice(),
425-
arguments: args.finish(),
426-
}
417+
FormatArgs { template: template.into_boxed_slice(), arguments: args.finish() }
427418
}
428419

429420
#[derive(Debug, Clone, PartialEq, Eq)]

crates/ide-assists/src/handlers/extract_expressions_from_format_string.rs

-6
Original file line numberDiff line numberDiff line change
@@ -34,23 +34,17 @@ pub(crate) fn extract_expressions_from_format_string(
3434
let fmt_string = ctx.find_token_at_offset::<ast::String>()?;
3535
let tt = fmt_string.syntax().parent().and_then(ast::TokenTree::cast)?;
3636

37-
dbg!();
3837
let expanded_t = ast::String::cast(
3938
ctx.sema.descend_into_macros_with_kind_preference(fmt_string.syntax().clone(), 0.into()),
4039
)?;
41-
dbg!();
4240
if !is_format_string(&expanded_t) {
43-
dbg!();
4441
return None;
4542
}
4643

47-
dbg!();
4844
let (new_fmt, extracted_args) = parse_format_exprs(fmt_string.text()).ok()?;
49-
dbg!();
5045
if extracted_args.is_empty() {
5146
return None;
5247
}
53-
dbg!();
5448

5549
acc.add(
5650
AssistId(

0 commit comments

Comments
 (0)