Skip to content

Conversation

@marsninja
Copy link
Collaborator

Summary

  • Adds a failing test (test_type_narrowing) and fixture (checker_type_narrowing.jac) that will pass once CFG-based type narrowing is implemented in the type checker
  • Covers 6 narrowing scenarios: isinstance in if-branch, isinstance with else (negative narrowing), is not None, is None + early return, join-point type restoration, and chained elif narrowing
  • Uses explicit typed assignments (e.g. d: Dog = animal) to verify narrowed types, since union member access is currently lenient

Details

The fixture currently produces 11 type errors because the type checker does not use the CFG for flow-sensitive analysis. After narrowing is implemented, 10 of those errors should disappear — only the join-point assignment (fail: Dog = animal after an if/else where animal is Dog | Cat) should remain.

Test plan

  • New test fails as expected (11 errors instead of 1)
  • All 62 existing type checker tests still pass
  • Test will pass once CFG-based type narrowing is implemented in the type evaluator

Add failing test and fixture for flow-sensitive type narrowing that
will pass once CFG integration is implemented in the type checker.

Covers isinstance narrowing, None narrowing, negative narrowing in
else branches, join-point type restoration, and chained elif narrowing.
Add stack-based type narrowing to the type checker that narrows union
types inside conditional branches (isinstance, is None, is not None).
Types widen back at join points after if/else blocks.

- Add narrowing_stack, get_narrowed_type, extract_narrowing_predicates,
  and exclude_type_from_union to TypeEvaluator
- Modify type expression cache to bypass for Name nodes under narrowing
- Add enter/exit handlers for IfStmt, ElseIf, ElseStmt in TypeCheckPass
- Support early-return narrowing (if x is None { return; } -> x is non-None)
- Support elif chain narrowing with cumulative type exclusion
Replace the stack-based narrowing approach with a demand-driven backward
CFG walk that uses bb_in/bb_out edges already built by CFGBuildPass.
This provides a robust foundation for production-grade flow-sensitive
type checking.

Key changes:
- Add NarrowingPredicate to represent narrowing operations declaratively
- Implement _compute_narrowed_at for recursive backward CFG traversal
- Implement _classify_edge to infer true/false from unlabeled CFG edges
- Implement _find_predicate_for to pattern-match isinstance/is None guards
- Implement _apply_narrowing for positive and negative type exclusion
- Remove 6 enter/exit handlers for if_stmt, else_if, else_stmt from
  TypeCheckPass (narrowing is now fully in the evaluator)
- Remove narrowing_stack and early_return_narrowing_depth

The CFG approach handles elif chains, early returns, and join-point
widening naturally through graph structure rather than stack manipulation.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant