Skip to content

Commit abe8f1e

Browse files
committed
Implement builtin#format_args, using rustc's format_args parser
1 parent 3431d58 commit abe8f1e

File tree

19 files changed

+1740
-14
lines changed

19 files changed

+1740
-14
lines changed

Cargo.lock

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/hir-def/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ triomphe.workspace = true
3333

3434
rustc_abi = { version = "0.0.20221221", package = "hkalbasi-rustc-ap-rustc_abi", default-features = false }
3535
rustc_index = { version = "0.0.20221221", package = "hkalbasi-rustc-ap-rustc_index", default-features = false }
36+
rustc_lexer = { version = "0.1.0", package = "ra-ap-rustc_lexer" }
3637

3738
# local deps
3839
stdx.workspace = true

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

+53-6
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,13 @@ use crate::{
2929
db::DefDatabase,
3030
expander::Expander,
3131
hir::{
32-
dummy_expr_id, Array, Binding, BindingAnnotation, BindingId, BindingProblems, CaptureBy,
33-
ClosureKind, Expr, ExprId, InlineAsm, Label, LabelId, Literal, LiteralOrConst, MatchArm,
34-
Movability, OffsetOf, Pat, PatId, RecordFieldPat, RecordLitField, Statement,
32+
dummy_expr_id,
33+
format_args::{
34+
self, FormatArgs, FormatArgument, FormatArgumentKind, FormatArgumentsCollector,
35+
},
36+
Array, Binding, BindingAnnotation, BindingId, BindingProblems, CaptureBy, ClosureKind,
37+
Expr, ExprId, InlineAsm, Label, LabelId, Literal, LiteralOrConst, MatchArm, Movability,
38+
OffsetOf, Pat, PatId, RecordFieldPat, RecordLitField, Statement,
3539
},
3640
item_scope::BuiltinShadowMode,
3741
lang_item::LangItem,
@@ -649,15 +653,58 @@ impl ExprCollector<'_> {
649653
}
650654
ast::Expr::UnderscoreExpr(_) => self.alloc_expr(Expr::Underscore, syntax_ptr),
651655
ast::Expr::AsmExpr(e) => {
652-
let expr = Expr::InlineAsm(InlineAsm { e: self.collect_expr_opt(e.expr()) });
653-
self.alloc_expr(expr, syntax_ptr)
656+
let e = self.collect_expr_opt(e.expr());
657+
self.alloc_expr(Expr::InlineAsm(InlineAsm { e }), syntax_ptr)
654658
}
655659
ast::Expr::OffsetOfExpr(e) => {
656660
let container = Interned::new(TypeRef::from_ast_opt(&self.ctx(), e.ty()));
657661
let fields = e.fields().map(|it| it.as_name()).collect();
658662
self.alloc_expr(Expr::OffsetOf(OffsetOf { container, fields }), syntax_ptr)
659663
}
660-
ast::Expr::FormatArgsExpr(_) => self.missing_expr(),
664+
ast::Expr::FormatArgsExpr(f) => {
665+
let mut args = FormatArgumentsCollector::new();
666+
f.args().for_each(|arg| {
667+
args.add(FormatArgument {
668+
kind: match arg.name() {
669+
Some(name) => FormatArgumentKind::Named(name.as_name()),
670+
None => FormatArgumentKind::Normal,
671+
},
672+
expr: self.collect_expr_opt(arg.expr()),
673+
});
674+
});
675+
let template = f.template();
676+
let fmt_snippet = template.as_ref().map(ToString::to_string);
677+
let expr = self.collect_expr_opt(f.template());
678+
if let Expr::Literal(Literal::String(_)) = self.body[expr] {
679+
let source = self.source_map.expr_map_back[expr].clone();
680+
let is_direct_literal = source.file_id == self.expander.current_file_id;
681+
if let ast::Expr::Literal(l) =
682+
source.value.to_node(&self.db.parse_or_expand(source.file_id))
683+
{
684+
if let ast::LiteralKind::String(s) = l.kind() {
685+
return Some(self.alloc_expr(
686+
Expr::FormatArgs(format_args::parse(
687+
expr,
688+
&s,
689+
fmt_snippet,
690+
args,
691+
is_direct_literal,
692+
)),
693+
syntax_ptr,
694+
));
695+
}
696+
}
697+
}
698+
699+
self.alloc_expr(
700+
Expr::FormatArgs(FormatArgs {
701+
template_expr: expr,
702+
template: Default::default(),
703+
arguments: args.finish(),
704+
}),
705+
syntax_ptr,
706+
)
707+
}
661708
})
662709
}
663710

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

+5
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,11 @@ impl Printer<'_> {
156156
Expr::Missing => w!(self, "�"),
157157
Expr::Underscore => w!(self, "_"),
158158
Expr::InlineAsm(_) => w!(self, "builtin#asm(_)"),
159+
Expr::FormatArgs(_fmt_args) => {
160+
w!(self, "builtin#format_args(");
161+
// FIXME
162+
w!(self, ")");
163+
}
159164
Expr::OffsetOf(offset_of) => {
160165
w!(self, "builtin#offset_of(");
161166
self.print_type_ref(&offset_of.container);

crates/hir-def/src/hir.rs

+12-2
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
//! See also a neighboring `body` module.
1414
1515
pub mod type_ref;
16+
pub mod format_args;
1617

1718
use std::fmt;
1819

@@ -24,6 +25,7 @@ use syntax::ast;
2425

2526
use crate::{
2627
builtin_type::{BuiltinFloat, BuiltinInt, BuiltinUint},
28+
hir::format_args::{FormatArgs, FormatArgumentKind},
2729
path::{GenericArgs, Path},
2830
type_ref::{Mutability, Rawness, TypeRef},
2931
BlockId, ConstBlockId,
@@ -117,7 +119,6 @@ impl From<ast::LiteralKind> for Literal {
117119
fn from(ast_lit_kind: ast::LiteralKind) -> Self {
118120
use ast::LiteralKind;
119121
match ast_lit_kind {
120-
// FIXME: these should have actual values filled in, but unsure on perf impact
121122
LiteralKind::IntNumber(lit) => {
122123
if let builtin @ Some(_) = lit.suffix().and_then(BuiltinFloat::from_suffix) {
123124
Literal::Float(
@@ -283,6 +284,7 @@ pub enum Expr {
283284
Underscore,
284285
OffsetOf(OffsetOf),
285286
InlineAsm(InlineAsm),
287+
FormatArgs(FormatArgs),
286288
}
287289

288290
#[derive(Debug, Clone, PartialEq, Eq)]
@@ -355,7 +357,15 @@ impl Expr {
355357
match self {
356358
Expr::Missing => {}
357359
Expr::Path(_) | Expr::OffsetOf(_) => {}
358-
Expr::InlineAsm(e) => f(e.e),
360+
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+
}
359369
Expr::If { condition, then_branch, else_branch } => {
360370
f(*condition);
361371
f(*then_branch);

0 commit comments

Comments
 (0)