Desugar builtin#format_args

This commit is contained in:
Lukas Wirth 2023-09-06 15:21:41 +02:00
parent abe8f1ece4
commit e243a03da1
19 changed files with 783 additions and 243 deletions

View file

@ -9,10 +9,7 @@ use chalk_ir::{
};
use hir_def::{
data::adt::VariantData,
hir::{
format_args::FormatArgumentKind, Array, BinaryOp, BindingId, CaptureBy, Expr, ExprId, Pat,
PatId, Statement, UnaryOp,
},
hir::{Array, BinaryOp, BindingId, CaptureBy, Expr, ExprId, Pat, PatId, Statement, UnaryOp},
lang_item::LangItem,
resolver::{resolver_for_expr, ResolveValueResult, ValueNs},
DefWithBodyId, FieldId, HasModule, VariantId,
@ -456,14 +453,6 @@ 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);

View file

@ -9,8 +9,7 @@ use chalk_ir::{cast::Cast, fold::Shift, DebruijnIndex, Mutability, TyVariableKin
use hir_def::{
generics::TypeOrConstParamData,
hir::{
format_args::FormatArgumentKind, ArithOp, Array, BinaryOp, ClosureKind, Expr, ExprId,
LabelId, Literal, Statement, UnaryOp,
ArithOp, Array, BinaryOp, ClosureKind, Expr, ExprId, LabelId, Literal, Statement, UnaryOp,
},
lang_item::{LangItem, LangItemTarget},
path::{GenericArg, GenericArgs},
@ -849,25 +848,6 @@ 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);

View file

@ -3,10 +3,7 @@
use chalk_ir::Mutability;
use hir_def::{
hir::{
format_args::FormatArgumentKind, Array, BinaryOp, BindingAnnotation, Expr, ExprId, PatId,
Statement, UnaryOp,
},
hir::{Array, BinaryOp, BindingAnnotation, Expr, ExprId, PatId, Statement, UnaryOp},
lang_item::LangItem,
};
use hir_expand::name;
@ -40,13 +37,6 @@ 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);

View file

@ -178,13 +178,30 @@ impl InferenceContext<'_> {
remaining_index: usize,
id: ExprOrPatId,
) -> Option<(ValueNs, Substitution)> {
assert!(remaining_index < path.segments().len());
// there may be more intermediate segments between the resolved one and
// the end. Only the last segment needs to be resolved to a value; from
// the segments before that, we need to get either a type or a trait ref.
let resolved_segment = path.segments().get(remaining_index - 1).unwrap();
let remaining_segments = path.segments().skip(remaining_index);
let _d;
let (resolved_segment, remaining_segments) = match path {
Path::Normal { .. } => {
assert!(remaining_index < path.segments().len());
(
path.segments().get(remaining_index - 1).unwrap(),
path.segments().skip(remaining_index),
)
}
Path::LangItem(_, seg) => (
PathSegment {
name: {
_d = hir_expand::name::known::Unknown;
&_d
},
args_and_bindings: None,
},
path.segments(),
),
};
let is_before_last = remaining_segments.len() == 1;
match (def, is_before_last) {

View file

@ -376,9 +376,6 @@ 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());

View file

@ -3615,22 +3615,15 @@ fn main() {
#[test]
fn builtin_format_args() {
check_infer(
check(
r#"
#[lang = "format_arguments"]
pub struct Arguments<'a>;
//- minicore: fmt
fn main() {
let are = "are";
builtin#format_args("hello {} friends, we {are} {0}{last}", "fancy", last = "!");
let count = 10;
builtin#format_args("hello {count:02} {} friends, we {are:?} {0}{last}", "fancy", last = "!");
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type: Arguments<'_>
}
"#,
expect![[r#"
65..175 '{ ...!"); }': ()
75..78 'are': &str
81..86 '"are"': &str
92..172 'builti...= "!")': Arguments<'_>
152..159 '"fancy"': &str
168..171 '"!"': &str
"#]],
);
}