Reference. Incremental Bidirectional Typing via Order Maintenance
Live programming environments provide various semantic services, including type checking and evaluation, continuously as the user is editing the program. The live paradigm promises to improve the developer experience, but liveness is an implementation challenge, particularly when working with large programs. This paper specifies and efficiently implements a system that is able to incrementally update type information for a live program in response to fine-grained program edits. This information includes type error marks and information about the expected and actual type of every expression. The system is specified type-theoretically as a small-step dynamics that propagates updates through the marked and annotated program. Most updates flow according to a base bidirectional type system. Additional pointers are maintained to connect bound variables to their binding locations, with type updates traversing these pointers directly. Order maintenance data structures are employed to efficiently maintain these pointers and to prioritize the order of update propagation. We prove this system is equivalent to naive reanalysis in the Agda theorem prover, along with other important metatheoretic properties. We then provide an efficient OCaml implementation, detailing a number of impactful optimizations. We evaluate this implementation’s performance with a large stress-test and find that it is able to achieve multiple orders of magnitude speed-up compared to from-scratch reanalysis.
Cite
Cites 48 works (3 here)
With notes (3)
Total Type Error Localization and Recovery with Holes zhao-2024-total
Type systems typically only define the conditions under which an expression is well-typed, leaving ill-typed expressions formally meaningless. This approach is insufficient as the basis for language servers driving modern programming environments, which are expected to recover from simultaneously localized errors and continue to provide a variety of downstream semantic services. This paper addresses this problem, contributing the first comprehensive formal account of total type error localization and recovery: the marked lambda calculus. In particular, we define a gradual type system for expressions with marked errors, which operate as non-empty holes, together with a total procedure for marking arbitrary unmarked expressions. We mechanize the metatheory of the marked lambda calculus in Agda and implement it, scaled up, as the new basis for Hazel, a full-scale live functional programming environment with, uniquely, no meaningless editor states. The marked lambda calculus is bidirectionally typed, so localization decisions are systematically predictable based on a local flow of typing information. Constraint-based type inference can bring more distant information to bear in discovering inconsistencies but this notoriously complicates error localization. We approach this problem by deploying constraint solving as a type-hole-filling layer atop this gradual bidirectionally typed core. Errors arising from inconsistent unification constraints are localized exclusively to type and expression holes, i.e., the system identifies unfillable holes using a system of traced provenances, rather than localized in an ad hoc manner to particular expressions. The user can then interactively shift these errors to particular downstream expressions by selecting from suggested partially consistent type hole fillings, which returns control back to the bidirectional system. We implement this type hole inference system in Hazel.
Bidirectional Typing dunfield-2021-bidirectional
Bidirectional typing combines two modes of typing: type checking, which checks that a program satisfies a known type, and type synthesis, which determines a type from the program. Using checking enables bidirectional typing to support features for which inference is undecidable; using synthesis enables bidirectional typing to avoid the large annotation burden of explicitly typed languages. In addition, bidirectional typing improves error locality. We highlight the design principles that underlie bidirectional type systems, survey the development of bidirectional typing from the prehistoric period before Pierce and Turner’s local type inference to the present day, and provide guidance for future investigations.
Hazelnut: a bidirectionally typed structure editor calculus omar-2017-hazelnut
External (45)
- Artifact for Incremental Bidirectional Typing via Order Maintenance (2025)
- Reusing Caches and Invariants for Efficient and Sound Incremental Static Analysis (2025)
- Spineless Traversal for Layout Invalidation (2025)
- Incremental Computation: What Is the Essence? (Invited Contribution) (2024)
- Pantograph: A Fluid and Typed Structure Editor (2024)
- Toward a Live, Rich, Composable, and Collaborative Planetary Compute Engine (2024)
- A Case for Planetary Computing (2023)
- IR Mapping: Intermediate Representation (IR) based Mapping to facilitate Incremental Static Analysis (2022)
- Towards Elastic Incrementalization for Datalog (2021)
- A systematic approach to deriving incremental type checkers (2020)
- Incremental Abstract Interpretation (2020)
- Using Standard Typing Algorithms Incrementally (2019)
- Build systems à la carte (2018)
- Toward Semantic Foundations for Program Editors (2017)
- Incremental Analysis for Probabilistic Programs (2017)
- Incrementalizing Abstract Interpretation (2017)
- IncA: a DSL for the definition of incremental program analyses (2016)
- A co-contextual formulation of type rules and its application to incremental type checking (2015)
- Incremental computation with names (2015)
- Compositional Symbolic Execution with Memoized Replay (2015)
- Refined Criteria for Gradual Typing (2015)
- Adapton: composable, demand-driven incremental computation (2014)
- Efficient Incremental Static Analysis Using Path Abstraction (2014)
- Directed Incremental Symbolic Execution (2014)
- Scalable and incremental software bug detection (2013)
- A Language Independent Task Engine for Incremental Name and Type Analysis (2013)
- Memoise: A tool for memoized symbolic execution (2013)
- Memoized symbolic execution (2012)
- Type Preservation as a Confluence Problem (2011)
- The Scratch Programming Language and Environment (2010)
- How browsers work (2010)
- A Rewriting Semantics for Type Inference (2007)
- Gradual Typing for Functional Languages (2006)
- Self-adjusting computation (PhD thesis, Carnegie Mellon University) (2005)
- Adaptive functional programming (2002)
- Two Simplified Algorithms for Maintaining Order in a List (2002)
- Local type inference (2000)
- Meaningful change detection in structured data (1997)
- A categorized bibliography on incremental computation (1993)
- Incremental polymorphism (1991)
- Incremental computation via function caching (1989)
- Incremental polymorphic type checking in B (1983)
- Maintaining order in a linked list (1982)
- Incremental evaluation for attribute grammars with application to syntax-directed editors (1981)
- The Cornell program synthesizer: a syntax-directed programming environment (1981)