18 research outputs found

    Untangling Typechecking of Intersections and Unions

    Full text link
    Intersection and union types denote conjunctions and disjunctions of properties. Using bidirectional typechecking, intersection types are relatively straightforward, but union types present challenges. For union types, we can case-analyze a subterm of union type when it appears in evaluation position (replacing the subterm with a variable, and checking that term twice under appropriate assumptions). This technique preserves soundness in a call-by-value semantics. Sadly, there are so many choices of subterms that a direct implementation is not practical. But carefully transforming programs into let-normal form drastically reduces the number of choices. The key results are soundness and completeness: a typing derivation (in the system with too many subterm choices) exists for a program if and only if a derivation exists for the let-normalized program.Comment: In Proceedings ITRS 2010, arXiv:1101.410

    Bounded Refinement Types

    Full text link
    We present a notion of bounded quantification for refinement types and show how it expands the expressiveness of refinement typing by using it to develop typed combinators for: (1) relational algebra and safe database access, (2) Floyd-Hoare logic within a state transformer monad equipped with combinators for branching and looping, and (3) using the above to implement a refined IO monad that tracks capabilities and resource usage. This leap in expressiveness comes via a translation to "ghost" functions, which lets us retain the automated and decidable SMT based checking and inference that makes refinement typing effective in practice.Comment: 14 pages, International Conference on Functional Programming, ICFP 201

    Safe Stream-Based Programming with Refinement Types

    Full text link
    In stream-based programming, data sources are abstracted as a stream of values that can be manipulated via callback functions. Stream-based programming is exploding in popularity, as it provides a powerful and expressive paradigm for handling asynchronous data sources in interactive software. However, high-level stream abstractions can also make it difficult for developers to reason about control- and data-flow relationships in their programs. This is particularly impactful when asynchronous stream-based code interacts with thread-limited features such as UI frameworks that restrict UI access to a single thread, since the threading behavior of streaming constructs is often non-intuitive and insufficiently documented. In this paper, we present a type-based approach that can statically prove the thread-safety of UI accesses in stream-based software. Our key insight is that the fluent APIs of stream-processing frameworks enable the tracking of threads via type-refinement, making it possible to reason automatically about what thread a piece of code runs on -- a difficult problem in general. We implement the system as an annotation-based Java typechecker for Android programs built upon the popular ReactiveX framework and evaluate its efficacy by annotating and analyzing 8 open-source apps, where we find 33 instances of unsafe UI access while incurring an annotation burden of only one annotation per 186 source lines of code. We also report on our experience applying the typechecker to two much larger apps from the Uber Technologies Inc. codebase, where it currently runs on every code change and blocks changes that introduce potential threading bugs

    Sound and complete bidirectional typechecking for higher-rank polymorphism with existentials and indexed types

    Get PDF
    Bidirectional typechecking, in which terms either synthesize a type or are checked against a known type, has become popular for its applicability to a variety of type systems, its error reporting, and its ease of implementation. Following principles from proof theory, bidirectional typing can be applied to many type constructs. The principles underlying a bidirectional approach to indexed types (generalized algebraic datatypes) are less clear. Building on proof-theoretic treatments of equality, we give a declarative specification of typing based on focalization. This approach permits declarative rules for coverage of pattern matching, as well as support for first-class existential types using a focalized subtyping judgment. We use refinement types to avoid explicitly passing equality proofs in our term syntax, making our calculus similar to languages such as Haskell and OCaml. We also extend the declarative specification with an explicit rules for deducing when a type is principal, permitting us to give a complete declarative specification for a rich type system with significant type inference. We also give a set of algorithmic typing rules, and prove that it is sound and complete with respect to the declarative system. The proof requires a number of technical innovations, including proving soundness and completeness in a mutually recursive fashion.EPSRC grant EP/N02706X/

    Focusing on Refinement Typing

    Full text link
    We present a logically principled foundation for systematizing, in a way that works with any computational effect and evaluation order, SMT constraint generation seen in refinement type systems for functional programming languages. By carefully combining a focalized variant of call-by-push-value, bidirectional typing, and our novel technique of value-determined indexes, our system generates solvable SMT constraints without existential (unification) variables. We design a polarized subtyping relation allowing us to prove our logically focused typing algorithm is sound, complete, and decidable. We prove type soundness of our declarative system with respect to an elementary domain-theoretic denotational semantics. Type soundness implies, relatively simply, the total correctness and logical consistency of our system. The relative ease with which we obtain both algorithmic and semantic results ultimately stems from the proof-theoretic technique of focalization.Comment: 61 pages + appendix with proofs, Just Accepted version of paper (with new title) at ACM Transactions on Programming Languages and System

    Adding dependent types to class-based mutable objects

    Get PDF
    Tese de doutoramento, Informática (Ciência da Computação), Universidade de Lisboa, Faculdade de Ciências, 2018In this thesis, we present an imperative object-oriented language featuring a dependent type system designed to support class-based programming and inheritance. The system brings classes and dependent types into play so as to enable types (classes) to be refined by value parameters (indices) drawn from some constraint domain. This combination allows statically checking interesting properties of imperative programs that are impossible to check in conventional static type systems for objects. From a pragmatic point of view, this work opens the possibility to combine the scalability and modularity of object orientation with the safety provided by dependent types in the form of index refinements. These may be used to provide additional guarantees about the fields of objects, and to prevent, for example, a method call that could leave an object in a state that would violate the class invariant. One key feature is that the programmer is not required to prove equations between indices issued by types, but instead the typechecker depends on external constraint solving. From a theoretic perspective, our fundamental contribution is to formulate a system that unifies the three very different features: dependent types, mutable objects and class-based inheritance with subtyping. Our approach includes universal and existential types, as well as union types. Subtyping is induced by inheritance and quantifier instantiation. Moreover, dependent types require the system to track type varying objects, a feature missing from standard type systems in which the type is constant throughout the object’s lifetime. To ensure that an object is used correctly, aliasing is handled via a linear type discipline that enforces unique references to type varying objects. The system is decidable, provided indices are drawn from some decidable theory, and proved sound via subject reduction and progress. We also formulate a typechecking algorithm that gives a precise account of quantifier instantiation in a bidirectional style, combining type synthesis with checking. We prove that our algorithm is sound and complete. By way of example, we implement insertion and deletion for binary search trees in an imperative style, and come up with types that ensure the binary search tree invariant. To attest the relevance of the language proposed, we provide a fully functional prototype where this and other examples can be typechecked, compiled and run. The prototype can be found at http://rss.di.fc.ul.pt/tools/dol/

    Type Targeted Testing

    Full text link
    We present a new technique called type targeted testing, which translates precise refinement types into comprehensive test-suites. The key insight behind our approach is that through the lens of SMT solvers, refinement types can also be viewed as a high-level, declarative, test generation technique, wherein types are converted to SMT queries whose models can be decoded into concrete program inputs. Our approach enables the systematic and exhaustive testing of implementations from high-level declarative specifications, and furthermore, provides a gradual path from testing to full verification. We have implemented our approach as a Haskell testing tool called TARGET, and present an evaluation that shows how TARGET can be used to test a wide variety of properties and how it compares against state-of-the-art testing approaches
    corecore