Live Typing for Ruby
Bridging Dynamic and Static Types
Inspired by Hernán Wilkinson’s work on Live Typing in Smalltalk[1], I developed a system that brings type information to Ruby programs by observing their runtime behavior.
Here’s a description of Live Typing, from Hernán’s paper:
Live Typing automatically annotates variable types based on the objects assigned to them, and method return types based on the returned objects. IDEs can exploit this information to greatly improve the development tools and the programming experience, bringing some of the benefits of Static Typing tools to Dynamically Typed Languages.
How It Works
The system consists of two main components:
The runtime type information collector
This component observes program execution and records the actual types of variables and method returns as the code runs. It is implemented in Ruby, and is run in the same virtual machine as the program code. The type information is serialized and stored in
json
format.The structure of the saved type data is the following:
Unlike the Smalltalk implementation, which required modifications to the VM, Ruby’s built-in
TracePoint
API[2] allowed for type collection without low-level modifications.The static type processor
This processes the collected information and presents it embedded on the program source code, through the IDE interface. It is implemented as a RubyMine plugin written in Java.
Usage examples
In this example, we show type annotations for instance variables, methods (parameters + return), including methods defined on metaclasses:
Here, we show type annotations for methods in an inheritance hierarchy, how the annotations chain when sending messages, and what happens if we try a message for which we don’t have any type information.
Final Thoughts
This project demonstrates how we can enhance development tools for dynamically typed languages without sacrificing their flexibility. By observing actual runtime behavior, we get type information that reflects how the code is really used, rather than relying on static analysis alone.
The approach could be extended to collect other kinds of runtime information that might be valuable during development, suggesting new possibilities for bridging the gap between development time and runtime in dynamic languages.
You can find more information about this on the paper “VM support for live typing: automatic type annotation for dynamically typed languages” by Hernán Wilkinson, available here. ↩︎
An object-oriented API provided by the Ruby language to trace different events while the program is running, such as method calls and returns. You can find more information about it in the Ruby documentation. ↩︎