Recent Posts
Archives

Posts Tagged ‘TypeSystem’

PostHeaderIcon [KotlinConf2024] Revamping Kotlin’s Type System: A Vision

At KotlinConf2024, Ross Tate, a programming language researcher, exposed critical flaws in Kotlin’s type system, including undecidability and unsoundness, which can crash compilers or misclassify types. Collaborating with the Kotlin team, he proposed pragmatic restrictions to ensure reliability and introduced extensions like categorized union types for error handling. Ross shared a long-term strategy to make type checking sound, decidable, and extensible, inviting developers to shape Kotlin’s future through feedback, balancing theory with practical needs.

Uncovering Type System Flaws

Kotlin’s type system, while powerful, is flawed. Ross revealed its undecidability, where subtyping questions can encode Turing machines, causing unpredictable compiler behavior. This stems from Java’s similar issues, as proven by Ru Gregori’s research. Unsoundness is equally concerning—Ross demonstrated a program tricking the compiler into treating an Int as a String using type projections and nulls. These flaws, also present in Java and Scala, undermine reliability, making robust type checking a priority for Kotlin’s evolution.

The Dangers of Unsound Programs

Unsoundness risks memory corruption. Ross presented a fast integer-to-string converter that, without proper checks, could introduce vulnerabilities. Initially, Kotlin’s compiler rejected it, as Int isn’t a subtype of String. However, adding a magic configuration with existential type projections bypassed this safeguard, fooling the compiler. Adapted from Java and Scala examples, this highlights a shared problem. Ross stressed that revamping Kotlin involves eliminating such unintentional backdoors, ensuring only explicit casts compromise safety, preserving developer trust.

Type Inference Challenges

Type inference, vital for Kotlin’s usability, struggles with decomposition. Ross showed a tree class for sorting adjectives, which type-checks when whole but fails when split into smaller parts. The compiler couldn’t infer the branch type B, violating the principle that breaking programs into smaller units shouldn’t break type checking. Co-variance adjustments revealed a principal type (Nothing), but Java’s undecidable subtyping influenced Kotlin’s conservative design. Ross aims to fix this, ensuring inference supports modular, predictable codebases.

Pragmatic Restrictions for Decidability

To address undecidability, Ross proposed separating interfaces into “shapes” (type constraints, like Comparable) and “materials” (data types, like function interfaces). Analyzing 135 million lines of Java code, he found all interfaces fit one category, making subtyping decidable in practice. By embedding this pattern into Kotlin, type checking becomes reliable and efficient, running in polynomial time. This separation also improves usability, as hovering over a variable avoids irrelevant types like Comparable<*>, aligning with developer expectations.

Categorized Union Types for Errors

Ross previewed categorized union types, restricted to prevent exponential type-checking costs. Types are grouped into categories (e.g., Null, Any, Error), allowing unions only across categories, like T | NoSuchValue. This enables distinguishing custom errors from null, as shown in a lastOrError function. Operators like !. (propagate error), !: (replace error), and !! (throw exception) mirror nullable syntax, simplifying libraries. Q&A clarified errors remain manipulable values, enhancing flexibility without compromising efficiency.

Enhancing Error Handling

The proposed error system differentiates errors (values) from exceptions (control flow). Error classes include a throw method for conversion to exceptions, while Throwable subclasses form distinct categories, enabling multi-catch via union types. A try-catch variant infers the union of thrown types, supporting exhaustive checks with Java’s typed exceptions. This design, inspired by Rust’s result pattern, balances explicit error handling with backward compatibility, addressing interoperability concerns raised in Q&A about Java’s ecosystem.

Shaping Kotlin’s Future

Ross emphasized that these changes are experimental, requiring prototypes, trials, and community input. Challenges like name resolution and method overloading need strategies, and features must cohere. He invited feedback via issue KT-68296, especially on error naming (e.g., “Error” vs. “Sentinel”) to avoid Java confusion. The talk underscored Kotlin’s shift toward optimizing its own experience, even at the cost of some Java interop precision, ensuring a reliable, extensible type system for future developers.

Links:

PostHeaderIcon [PHPForumParis2021] Exceptions: The Weak Spot in PHP’s Type System – Baptiste Langlade

Baptiste Langlade, a PHP developer at EFI Automotive, captivated the Forum PHP 2021 audience with a deep dive into the limitations of exceptions in PHP’s type system. With a decade of experience in PHP and open-source contributions, Baptiste explored how exceptions disrupt type safety and proposed functional programming-inspired solutions. His talk combined technical rigor with practical insights, urging developers to rethink error handling. This post covers four themes: the problem with exceptions, functional programming alternatives, automating error handling, and challenges with interfaces.

The Problem with Exceptions

Baptiste Langlade began by highlighting the inherent flaws in PHP’s exception system, describing it as a “hole in the type system’s racket.” Exceptions, he argued, bypass type checks, leading to unexpected runtime errors that static analysis struggles to catch. Drawing on his work at EFI Automotive, Baptiste illustrated how unchecked exceptions in complex systems, like document management, can lead to fragile code, emphasizing the need for more robust error-handling mechanisms.

Functional Programming Alternatives

Drawing inspiration from functional programming, Baptiste proposed alternatives like the Either monad to handle errors explicitly without exceptions. He demonstrated how returning values that encapsulate success or failure states can improve type safety and predictability. By sharing examples from his open-source packages, Baptiste showed how these patterns integrate with PHP, offering developers a way to write cleaner, more reliable code that aligns with modern type-safe practices.

Automating Error Handling

Baptiste emphasized the importance of automating error detection to address the limitations of manual exception testing. He noted that developers often miss edge cases when writing unit tests, leading to uncaught exceptions. Tools like static analyzers can help by enforcing explicit error handling, but Baptiste cautioned that PHP currently lacks native support for declaring thrown exceptions in method signatures, unlike languages like Java. His insights urged developers to adopt rigorous testing practices to mitigate these risks.

Challenges with Interfaces

Concluding his talk, Baptiste addressed the challenges of using exceptions with PHP interfaces. He explained that interfaces cannot enforce specific exception types, limiting their utility in ensuring type safety. By exploring workarounds, such as explicit documentation and custom error types, Baptiste provided practical solutions for developers. His talk encouraged the PHP community to push for language improvements, drawing on his experiences to advocate for a more robust type system.

Links: