Skip to content

Commit 111f3d2

Browse files
stroxlermeta-codesync[bot]
authored andcommitted
Switch unpacking loops to shared display inference
Summary: Consume the iteration-element observations produced by the shared display helpers, falling back to ordinary iteration when no observation is available. This removes the duplicate `iterate_expr` walker and its fabricated display traces. Ordinary inference owns hints, shape handling, anonymous TypedDict fields, and IDE traces. Unknown-length unpacking and union simplification keep their existing policy; this change adds no cardinality analysis. mypy_primer differential: Pending owner-run manual CI before landing. ___ landed-with-radar-review Differential Revision: D131820038 fbshipit-source-id: 01761c94f2c0559e937a2dd74467f7c12abc681a
1 parent 7382e85 commit 111f3d2

1 file changed

Lines changed: 5 additions & 77 deletions

File tree

‎pyrefly/lib/alt/solve.rs‎

Lines changed: 5 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,7 @@ use ruff_python_ast::ExprAttribute;
3939
use ruff_python_ast::ExprBinOp;
4040
use ruff_python_ast::ExprBoolOp;
4141
use ruff_python_ast::ExprCall;
42-
use ruff_python_ast::ExprList;
4342
use ruff_python_ast::ExprName;
44-
use ruff_python_ast::ExprSet;
4543
use ruff_python_ast::ExprSubscript;
4644
use ruff_python_ast::ExprUnaryOp;
4745
use ruff_python_ast::Identifier;
@@ -5536,80 +5534,6 @@ impl<'ctx, 'answer, Ans: LookupAnswer> AnswersSolver<'ctx, 'answer, Ans> {
55365534
}
55375535
}
55385536

5539-
/// Iterate over displays before mutable-container inference promotes their literal elements.
5540-
fn iterate_expr(&self, e: &Expr, errors: &ErrorCollector) -> Vec<Iterable> {
5541-
let promote_element = |ty: Type| {
5542-
self.distribute_over_union(&ty, |ty| match ty {
5543-
// String and bytes literals carry the length of the value being unpacked.
5544-
Type::Literal(lit) if matches!(lit.value, Lit::Str(_) | Lit::Bytes(_)) => {
5545-
ty.clone()
5546-
}
5547-
_ => ty.clone().promote(self.stdlib),
5548-
})
5549-
};
5550-
match e {
5551-
Expr::List(ExprList { elts, .. }) | Expr::Set(ExprSet { elts, .. })
5552-
if !elts.is_empty() =>
5553-
{
5554-
let types = elts
5555-
.iter()
5556-
.map(|elt| {
5557-
promote_element(match elt {
5558-
Expr::Starred(star) => {
5559-
self.get_produced_type(self.iterate_expr(&star.value, errors))
5560-
}
5561-
_ => self.expr_infer(elt, errors),
5562-
})
5563-
})
5564-
.collect();
5565-
let element = self.unions(types);
5566-
let container = match e {
5567-
Expr::List(_) => self.stdlib.list(element.clone().promote(self.stdlib)),
5568-
Expr::Set(_) => self.stdlib.set(element.clone().promote(self.stdlib)),
5569-
_ => unreachable!("Only list and set displays match this branch"),
5570-
};
5571-
self.record_type_trace(e.range(), &self.heap.mk_class_type(container));
5572-
vec![Iterable::OfType(element)]
5573-
}
5574-
Expr::Dict(dict) if !dict.items.is_empty() => {
5575-
let mut keys = Vec::new();
5576-
let mut values = Vec::new();
5577-
for item in Ast::flatten_dict_items(&dict.items) {
5578-
if let Some(key) = &item.key {
5579-
keys.push(promote_element(self.expr_infer(key, errors)));
5580-
values.push(self.expr_infer(&item.value, errors));
5581-
} else {
5582-
let ty = self.expr_infer(&item.value, errors);
5583-
if let Some((key, value)) = self.unwrap_mapping_for_unpacking(&ty) {
5584-
keys.push(key);
5585-
values.push(value);
5586-
} else {
5587-
keys.push(self.error(
5588-
errors,
5589-
item.value.range(),
5590-
ErrorKind::InvalidArgument,
5591-
format!("Expected a mapping, got {}", self.for_display(ty)),
5592-
));
5593-
}
5594-
}
5595-
}
5596-
let key = self.unions(keys);
5597-
self.record_type_trace(
5598-
e.range(),
5599-
&self.heap.mk_class_type(self.stdlib.dict(
5600-
key.clone().promote(self.stdlib),
5601-
self.unions(values).promote(self.stdlib),
5602-
)),
5603-
);
5604-
vec![Iterable::OfType(key)]
5605-
}
5606-
_ => {
5607-
let (iterable, _) = self.expr_infer_for_iteration(e, errors);
5608-
self.iterate(&iterable, e.range(), errors, None)
5609-
}
5610-
}
5611-
}
5612-
56135537
/// Handle `Binding::IterableValue` - extract value type from an iterable.
56145538
/// The `#[inline(never)]` annotation is intentional to reduce stack frame size.
56155539
#[inline(never)]
@@ -5656,7 +5580,11 @@ impl<'ctx, 'answer, Ans: LookupAnswer> AnswersSolver<'ctx, 'answer, Ans> {
56565580
self.expr_infer_with_hint(e, infer_hint.as_ref().map(HintRef::soft), errors);
56575581
self.async_iterate(&iterable, e.range(), errors)
56585582
} else if is_unpacking {
5659-
self.iterate_expr(e, errors)
5583+
let (iterable, element) = self.expr_infer_for_iteration(e, errors);
5584+
match element {
5585+
Some(element) => vec![Iterable::OfType(element)],
5586+
None => self.iterate(&iterable, e.range(), errors, None),
5587+
}
56605588
} else {
56615589
let infer_hint = ann.and_then(|x| {
56625590
x.ty(self.heap, self.stdlib)

0 commit comments

Comments
 (0)