Skip to content

Commit e243a03

Browse files
committed
Desugar builtin#format_args
1 parent abe8f1e commit e243a03

File tree

19 files changed

+783
-243
lines changed

19 files changed

+783
-243
lines changed

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

Lines changed: 405 additions & 45 deletions
Large diffs are not rendered by default.

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

Lines changed: 17 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
33
use std::fmt::{self, Write};
44

5-
use hir_expand::db::ExpandDatabase;
65
use itertools::Itertools;
76
use syntax::ast::HasName;
87

@@ -52,8 +51,7 @@ pub(super) fn print_body_hir(db: &dyn DefDatabase, body: &Body, owner: DefWithBo
5251
}
5352
};
5453

55-
let mut p =
56-
Printer { db: db.upcast(), body, buf: header, indent_level: 0, needs_indent: false };
54+
let mut p = Printer { db, body, buf: header, indent_level: 0, needs_indent: false };
5755
if let DefWithBodyId::FunctionId(it) = owner {
5856
p.buf.push('(');
5957
body.params.iter().zip(&db.function_data(it).params).for_each(|(&param, ty)| {
@@ -77,8 +75,7 @@ pub(super) fn print_expr_hir(
7775
_owner: DefWithBodyId,
7876
expr: ExprId,
7977
) -> String {
80-
let mut p =
81-
Printer { db: db.upcast(), body, buf: String::new(), indent_level: 0, needs_indent: false };
78+
let mut p = Printer { db, body, buf: String::new(), indent_level: 0, needs_indent: false };
8279
p.print_expr(expr);
8380
p.buf
8481
}
@@ -99,7 +96,7 @@ macro_rules! wln {
9996
}
10097

10198
struct Printer<'a> {
102-
db: &'a dyn ExpandDatabase,
99+
db: &'a dyn DefDatabase,
103100
body: &'a Body,
104101
buf: String,
105102
indent_level: usize,
@@ -156,18 +153,16 @@ impl Printer<'_> {
156153
Expr::Missing => w!(self, "�"),
157154
Expr::Underscore => w!(self, "_"),
158155
Expr::InlineAsm(_) => w!(self, "builtin#asm(_)"),
159-
Expr::FormatArgs(_fmt_args) => {
160-
w!(self, "builtin#format_args(");
161-
// FIXME
162-
w!(self, ")");
163-
}
164156
Expr::OffsetOf(offset_of) => {
165157
w!(self, "builtin#offset_of(");
166158
self.print_type_ref(&offset_of.container);
167159
w!(
168160
self,
169161
", {})",
170-
offset_of.fields.iter().format_with(".", |field, f| f(&field.display(self.db)))
162+
offset_of
163+
.fields
164+
.iter()
165+
.format_with(".", |field, f| f(&field.display(self.db.upcast())))
171166
);
172167
}
173168
Expr::Path(path) => self.print_path(path),
@@ -189,7 +184,7 @@ impl Printer<'_> {
189184
}
190185
Expr::Loop { body, label } => {
191186
if let Some(lbl) = label {
192-
w!(self, "{}: ", self.body[*lbl].name.display(self.db));
187+
w!(self, "{}: ", self.body[*lbl].name.display(self.db.upcast()));
193188
}
194189
w!(self, "loop ");
195190
self.print_expr(*body);
@@ -209,7 +204,7 @@ impl Printer<'_> {
209204
}
210205
Expr::MethodCall { receiver, method_name, args, generic_args } => {
211206
self.print_expr(*receiver);
212-
w!(self, ".{}", method_name.display(self.db));
207+
w!(self, ".{}", method_name.display(self.db.upcast()));
213208
if let Some(args) = generic_args {
214209
w!(self, "::<");
215210
print_generic_args(self.db, args, self).unwrap();
@@ -247,13 +242,13 @@ impl Printer<'_> {
247242
Expr::Continue { label } => {
248243
w!(self, "continue");
249244
if let Some(lbl) = label {
250-
w!(self, " {}", self.body[*lbl].name.display(self.db));
245+
w!(self, " {}", self.body[*lbl].name.display(self.db.upcast()));
251246
}
252247
}
253248
Expr::Break { expr, label } => {
254249
w!(self, "break");
255250
if let Some(lbl) = label {
256-
w!(self, " {}", self.body[*lbl].name.display(self.db));
251+
w!(self, " {}", self.body[*lbl].name.display(self.db.upcast()));
257252
}
258253
if let Some(expr) = expr {
259254
self.whitespace();
@@ -292,7 +287,7 @@ impl Printer<'_> {
292287
w!(self, "{{");
293288
self.indented(|p| {
294289
for field in &**fields {
295-
w!(p, "{}: ", field.name.display(self.db));
290+
w!(p, "{}: ", field.name.display(self.db.upcast()));
296291
p.print_expr(field.expr);
297292
wln!(p, ",");
298293
}
@@ -309,7 +304,7 @@ impl Printer<'_> {
309304
}
310305
Expr::Field { expr, name } => {
311306
self.print_expr(*expr);
312-
w!(self, ".{}", name.display(self.db));
307+
w!(self, ".{}", name.display(self.db.upcast()));
313308
}
314309
Expr::Await { expr } => {
315310
self.print_expr(*expr);
@@ -447,7 +442,8 @@ impl Printer<'_> {
447442
}
448443
Expr::Literal(lit) => self.print_literal(lit),
449444
Expr::Block { id: _, statements, tail, label } => {
450-
let label = label.map(|lbl| format!("{}: ", self.body[lbl].name.display(self.db)));
445+
let label =
446+
label.map(|lbl| format!("{}: ", self.body[lbl].name.display(self.db.upcast())));
451447
self.print_block(label.as_deref(), statements, tail);
452448
}
453449
Expr::Unsafe { id: _, statements, tail } => {
@@ -523,7 +519,7 @@ impl Printer<'_> {
523519
w!(self, " {{");
524520
self.indented(|p| {
525521
for arg in args.iter() {
526-
w!(p, "{}: ", arg.name.display(self.db));
522+
w!(p, "{}: ", arg.name.display(self.db.upcast()));
527523
p.print_pat(arg.pat);
528524
wln!(p, ",");
529525
}
@@ -682,6 +678,6 @@ impl Printer<'_> {
682678
BindingAnnotation::Ref => "ref ",
683679
BindingAnnotation::RefMut => "ref mut ",
684680
};
685-
w!(self, "{}{}", mode, name.display(self.db));
681+
w!(self, "{}{}", mode, name.display(self.db.upcast()));
686682
}
687683
}

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

Lines changed: 86 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
mod block;
22

33
use base_db::{fixture::WithFixture, SourceDatabase};
4-
use expect_test::Expect;
4+
use expect_test::{expect, Expect};
55

66
use crate::{test_db::TestDB, ModuleDefId};
77

88
use super::*;
99

10-
fn lower(ra_fixture: &str) -> Arc<Body> {
10+
fn lower(ra_fixture: &str) -> (TestDB, Arc<Body>, DefWithBodyId) {
1111
let db = TestDB::with_files(ra_fixture);
1212

1313
let krate = db.crate_graph().iter().next().unwrap();
@@ -21,8 +21,10 @@ fn lower(ra_fixture: &str) -> Arc<Body> {
2121
}
2222
}
2323
}
24+
let fn_def = fn_def.unwrap().into();
2425

25-
db.body(fn_def.unwrap().into())
26+
let body = db.body(fn_def);
27+
(db, body, fn_def)
2628
}
2729

2830
fn def_map_at(ra_fixture: &str) -> String {
@@ -138,3 +140,84 @@ mod m {
138140
"#,
139141
);
140142
}
143+
144+
#[test]
145+
fn desugar_builtin_format_args() {
146+
// Regression test for a path resolution bug introduced with inner item handling.
147+
let (db, body, def) = lower(
148+
r#"
149+
//- minicore: fmt
150+
fn main() {
151+
let are = "are";
152+
let count = 10;
153+
builtin#format_args("hello {count:02} {} friends, we {are:?} {0}{last}", "fancy", last = "!");
154+
}
155+
"#,
156+
);
157+
158+
expect![[r#"
159+
fn main() {
160+
let are = "are";
161+
let count = 10;
162+
builtin#lang(Arguments::new_v1_formatted)(
163+
&[
164+
"\"hello ", " ", " friends, we ", " ", "", "\"",
165+
],
166+
&[
167+
builtin#lang(Argument::new_display)(
168+
&count,
169+
), builtin#lang(Argument::new_display)(
170+
&"fancy",
171+
), builtin#lang(Argument::new_debug)(
172+
&are,
173+
), builtin#lang(Argument::new_display)(
174+
&"!",
175+
),
176+
],
177+
&[
178+
builtin#lang(Placeholder::new)(
179+
0usize,
180+
' ',
181+
builtin#lang(Alignment::Unknown),
182+
8u32,
183+
builtin#lang(Count::Implied),
184+
builtin#lang(Count::Is)(
185+
2usize,
186+
),
187+
), builtin#lang(Placeholder::new)(
188+
1usize,
189+
' ',
190+
builtin#lang(Alignment::Unknown),
191+
0u32,
192+
builtin#lang(Count::Implied),
193+
builtin#lang(Count::Implied),
194+
), builtin#lang(Placeholder::new)(
195+
2usize,
196+
' ',
197+
builtin#lang(Alignment::Unknown),
198+
0u32,
199+
builtin#lang(Count::Implied),
200+
builtin#lang(Count::Implied),
201+
), builtin#lang(Placeholder::new)(
202+
1usize,
203+
' ',
204+
builtin#lang(Alignment::Unknown),
205+
0u32,
206+
builtin#lang(Count::Implied),
207+
builtin#lang(Count::Implied),
208+
), builtin#lang(Placeholder::new)(
209+
3usize,
210+
' ',
211+
builtin#lang(Alignment::Unknown),
212+
0u32,
213+
builtin#lang(Count::Implied),
214+
builtin#lang(Count::Implied),
215+
),
216+
],
217+
unsafe {
218+
builtin#lang(UnsafeArg::new)()
219+
},
220+
);
221+
}"#]]
222+
.assert_eq(&body.pretty_print(&db, def))
223+
}

crates/hir-def/src/hir.rs

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ use syntax::ast;
2525

2626
use crate::{
2727
builtin_type::{BuiltinFloat, BuiltinInt, BuiltinUint},
28-
hir::format_args::{FormatArgs, FormatArgumentKind},
2928
path::{GenericArgs, Path},
3029
type_ref::{Mutability, Rawness, TypeRef},
3130
BlockId, ConstBlockId,
@@ -284,7 +283,6 @@ pub enum Expr {
284283
Underscore,
285284
OffsetOf(OffsetOf),
286285
InlineAsm(InlineAsm),
287-
FormatArgs(FormatArgs),
288286
}
289287

290288
#[derive(Debug, Clone, PartialEq, Eq)]
@@ -358,14 +356,6 @@ impl Expr {
358356
Expr::Missing => {}
359357
Expr::Path(_) | Expr::OffsetOf(_) => {}
360358
Expr::InlineAsm(it) => f(it.e),
361-
Expr::FormatArgs(it) => {
362-
f(it.template_expr);
363-
it.arguments
364-
.arguments
365-
.iter()
366-
.filter(|it| !matches!(it.kind, FormatArgumentKind::Captured(_)))
367-
.for_each(|it| f(it.expr));
368-
}
369359
Expr::If { condition, then_branch, else_branch } => {
370360
f(*condition);
371361
f(*then_branch);

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

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use syntax::{
66
AstToken, SmolStr, TextRange,
77
};
88

9-
use crate::hir::{dummy_expr_id, ExprId};
9+
use crate::hir::ExprId;
1010

1111
mod parse;
1212

@@ -31,7 +31,7 @@ pub enum FormatArgsPiece {
3131
Placeholder(FormatPlaceholder),
3232
}
3333

34-
#[derive(Clone, Debug, PartialEq, Eq)]
34+
#[derive(Copy, Debug, Clone, PartialEq, Eq)]
3535
pub struct FormatPlaceholder {
3636
/// Index into [`FormatArgs::arguments`].
3737
pub argument: FormatArgPosition,
@@ -43,7 +43,7 @@ pub struct FormatPlaceholder {
4343
pub format_options: FormatOptions,
4444
}
4545

46-
#[derive(Debug, Clone, PartialEq, Eq)]
46+
#[derive(Copy, Debug, Clone, PartialEq, Eq)]
4747
pub struct FormatArgPosition {
4848
/// Which argument this position refers to (Ok),
4949
/// or would've referred to if it existed (Err).
@@ -64,7 +64,7 @@ pub enum FormatArgPositionKind {
6464
Named,
6565
}
6666

67-
#[derive(Debug, Clone, PartialEq, Eq)]
67+
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
6868
pub enum FormatTrait {
6969
/// `{}`
7070
Display,
@@ -86,7 +86,7 @@ pub enum FormatTrait {
8686
UpperHex,
8787
}
8888

89-
#[derive(Clone, Default, Debug, PartialEq, Eq)]
89+
#[derive(Copy, Clone, Default, Debug, PartialEq, Eq)]
9090
pub struct FormatOptions {
9191
/// The width. E.g. `{:5}` or `{:width$}`.
9292
pub width: Option<FormatCount>,
@@ -131,7 +131,7 @@ pub enum FormatAlignment {
131131
Center,
132132
}
133133

134-
#[derive(Clone, Debug, PartialEq, Eq)]
134+
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
135135
pub enum FormatCount {
136136
/// `{:5}` or `{:.5}`
137137
Literal(usize),
@@ -171,6 +171,7 @@ pub(crate) fn parse(
171171
fmt_snippet: Option<String>,
172172
mut args: FormatArgumentsCollector,
173173
is_direct_literal: bool,
174+
mut synth: impl FnMut(Name) -> ExprId,
174175
) -> FormatArgs {
175176
let text = s.text();
176177
let str_style = match s.quote_offsets() {
@@ -252,10 +253,10 @@ pub(crate) fn parse(
252253
// FIXME: Diagnose
253254
}
254255
Ok(args.add(FormatArgument {
255-
kind: FormatArgumentKind::Captured(name),
256+
kind: FormatArgumentKind::Captured(name.clone()),
256257
// FIXME: This is problematic, we might want to synthesize a dummy
257258
// expression proper and/or desugar these.
258-
expr: dummy_expr_id(),
259+
expr: synth(name),
259260
}))
260261
}
261262
}

crates/hir-def/src/item_tree.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ impl ItemTree {
177177
}
178178

179179
pub fn pretty_print(&self, db: &dyn DefDatabase) -> String {
180-
pretty::print_item_tree(db.upcast(), self)
180+
pretty::print_item_tree(db, self)
181181
}
182182

183183
fn data(&self) -> &ItemTreeData {

0 commit comments

Comments
 (0)