mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-30 22:01:37 +00:00
Implement builtin#format_args, using rustc's format_args parser
This commit is contained in:
parent
3431d586e5
commit
abe8f1ece4
19 changed files with 1740 additions and 14 deletions
|
@ -9,7 +9,10 @@ use chalk_ir::{
|
|||
};
|
||||
use hir_def::{
|
||||
data::adt::VariantData,
|
||||
hir::{Array, BinaryOp, BindingId, CaptureBy, Expr, ExprId, Pat, PatId, Statement, UnaryOp},
|
||||
hir::{
|
||||
format_args::FormatArgumentKind, Array, BinaryOp, BindingId, CaptureBy, Expr, ExprId, Pat,
|
||||
PatId, Statement, UnaryOp,
|
||||
},
|
||||
lang_item::LangItem,
|
||||
resolver::{resolver_for_expr, ResolveValueResult, ValueNs},
|
||||
DefWithBodyId, FieldId, HasModule, VariantId,
|
||||
|
@ -453,6 +456,14 @@ impl InferenceContext<'_> {
|
|||
fn walk_expr_without_adjust(&mut self, tgt_expr: ExprId) {
|
||||
match &self.body[tgt_expr] {
|
||||
Expr::OffsetOf(_) => (),
|
||||
Expr::FormatArgs(fa) => {
|
||||
self.walk_expr_without_adjust(fa.template_expr);
|
||||
fa.arguments
|
||||
.arguments
|
||||
.iter()
|
||||
.filter(|it| !matches!(it.kind, FormatArgumentKind::Captured(_)))
|
||||
.for_each(|it| self.walk_expr_without_adjust(it.expr));
|
||||
}
|
||||
Expr::InlineAsm(e) => self.walk_expr_without_adjust(e.e),
|
||||
Expr::If { condition, then_branch, else_branch } => {
|
||||
self.consume_expr(*condition);
|
||||
|
|
|
@ -9,7 +9,8 @@ use chalk_ir::{cast::Cast, fold::Shift, DebruijnIndex, Mutability, TyVariableKin
|
|||
use hir_def::{
|
||||
generics::TypeOrConstParamData,
|
||||
hir::{
|
||||
ArithOp, Array, BinaryOp, ClosureKind, Expr, ExprId, LabelId, Literal, Statement, UnaryOp,
|
||||
format_args::FormatArgumentKind, ArithOp, Array, BinaryOp, ClosureKind, Expr, ExprId,
|
||||
LabelId, Literal, Statement, UnaryOp,
|
||||
},
|
||||
lang_item::{LangItem, LangItemTarget},
|
||||
path::{GenericArg, GenericArgs},
|
||||
|
@ -848,6 +849,25 @@ impl InferenceContext<'_> {
|
|||
self.infer_expr_no_expect(it.e);
|
||||
self.result.standard_types.unit.clone()
|
||||
}
|
||||
Expr::FormatArgs(fa) => {
|
||||
fa.arguments
|
||||
.arguments
|
||||
.iter()
|
||||
.filter(|it| !matches!(it.kind, FormatArgumentKind::Captured(_)))
|
||||
.for_each(|it| _ = self.infer_expr_no_expect(it.expr));
|
||||
|
||||
match self
|
||||
.resolve_lang_item(LangItem::FormatArguments)
|
||||
.and_then(|it| it.as_struct())
|
||||
{
|
||||
Some(s) => {
|
||||
// NOTE: This struct has a lifetime parameter, but we don't currently emit
|
||||
// those to chalk
|
||||
TyKind::Adt(AdtId(s.into()), Substitution::empty(Interner)).intern(Interner)
|
||||
}
|
||||
None => self.err_ty(),
|
||||
}
|
||||
}
|
||||
};
|
||||
// use a new type variable if we got unknown here
|
||||
let ty = self.insert_type_vars_shallow(ty);
|
||||
|
|
|
@ -3,7 +3,10 @@
|
|||
|
||||
use chalk_ir::Mutability;
|
||||
use hir_def::{
|
||||
hir::{Array, BinaryOp, BindingAnnotation, Expr, ExprId, PatId, Statement, UnaryOp},
|
||||
hir::{
|
||||
format_args::FormatArgumentKind, Array, BinaryOp, BindingAnnotation, Expr, ExprId, PatId,
|
||||
Statement, UnaryOp,
|
||||
},
|
||||
lang_item::LangItem,
|
||||
};
|
||||
use hir_expand::name;
|
||||
|
@ -37,6 +40,13 @@ impl InferenceContext<'_> {
|
|||
Expr::Missing => (),
|
||||
Expr::InlineAsm(e) => self.infer_mut_expr_without_adjust(e.e, Mutability::Not),
|
||||
Expr::OffsetOf(_) => (),
|
||||
Expr::FormatArgs(fa) => {
|
||||
fa.arguments
|
||||
.arguments
|
||||
.iter()
|
||||
.filter(|it| !matches!(it.kind, FormatArgumentKind::Captured(_)))
|
||||
.for_each(|arg| self.infer_mut_expr_without_adjust(arg.expr, Mutability::Not));
|
||||
}
|
||||
&Expr::If { condition, then_branch, else_branch } => {
|
||||
self.infer_mut_expr(condition, Mutability::Not);
|
||||
self.infer_mut_expr(then_branch, Mutability::Not);
|
||||
|
|
|
@ -376,6 +376,9 @@ impl<'ctx> MirLowerCtx<'ctx> {
|
|||
Expr::InlineAsm(_) => {
|
||||
not_supported!("builtin#asm")
|
||||
}
|
||||
Expr::FormatArgs(_) => {
|
||||
not_supported!("builtin#format_args")
|
||||
}
|
||||
Expr::Missing => {
|
||||
if let DefWithBodyId::FunctionId(f) = self.owner {
|
||||
let assoc = f.lookup(self.db.upcast());
|
||||
|
|
|
@ -3612,3 +3612,25 @@ fn main() {
|
|||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn builtin_format_args() {
|
||||
check_infer(
|
||||
r#"
|
||||
#[lang = "format_arguments"]
|
||||
pub struct Arguments<'a>;
|
||||
fn main() {
|
||||
let are = "are";
|
||||
builtin#format_args("hello {} friends, we {are} {0}{last}", "fancy", last = "!");
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
65..175 '{ ...!"); }': ()
|
||||
75..78 'are': &str
|
||||
81..86 '"are"': &str
|
||||
92..172 'builti...= "!")': Arguments<'_>
|
||||
152..159 '"fancy"': &str
|
||||
168..171 '"!"': &str
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue