00:00:12.290
So let's start. I took about yet another type analyzer.
00:00:19.619
This is the second time for me to talk at RubyConf.
00:00:29.449
Oops, okay, thank you. But my previous talk was about object-oriented programming.
00:00:38.249
So this is the first time for me to talk about static types.
00:00:44.370
Okay, so I'm a bit nervous, but I'll do my best.
00:00:50.210
I'm Yusuke Endoh. I became a contributor to Ruby in 2008.
00:00:57.510
I have contributed to Ruby, and one of the most famous features I implemented is keyword arguments.
00:01:03.629
I implemented keyword arguments in Ruby 2.0.
00:01:09.960
I've created a de facto standard benchmark program for Ruby 3 called 'doped carrot,' which has driven many early implementers.
00:01:16.380
I was involved in the design management and have been actively part of it until today.
00:01:25.320
Additionally, I work in Quality Assurance for Ruby, including testing.
00:01:32.070
As for my job, I'm developing Ruby with Cookpad.
00:01:38.250
You may know Cookpad as a robust template to create and share cooking content.
00:01:46.470
Let me briefly introduce our company: Cookpad is dedicated to making everyday cooking fun.
00:01:54.210
Our main service is a collaborative cooking platform where users can submit their original recipes.
00:02:00.240
You can enjoy this space that is used by approximately 90 million monthly unique users globally across 30 languages.
00:02:09.209
We currently have users in 73 countries, with the service continually expanding.
00:02:15.990
Our aim is to be number one in cooking services across 100 countries.
00:02:22.470
Cookpad is powered by Ruby, and to maintain this service, we need many excellent Ruby engineers.
00:02:30.630
Currently, I'm located in Japan, but our headquarters are in the United Kingdom.
00:02:38.640
So, if you're interested in joining our team, feel free to contact me.
00:02:47.990
Okay, today I'll talk about three main topics: Ruby 3's plans, type signatures, and type analyze tools.
00:02:55.500
As mentioned in the previous two talks in this room, we discussed static type checkers for Ruby and its evolution.
00:03:05.000
The goal is to create a comprehensive type checker framework that allows developers to choose the appropriate type analysis tool for their needs.
00:03:13.360
This is a key feature of integrating multiple checkers and defining a Ruby signature.
00:03:22.720
This standard format will help write type information for Ruby code that all type checkers can share.
00:03:30.030
As for our standard libraries and gems, I would like to talk about my project called Type Profiler.
00:03:37.440
Type Profiler is a type analyzer that accepts unannotated Ruby code and attempts to provide type inferences.
00:03:45.780
It helps you to develop and suggest a signature prototype.
00:03:53.250
Now, let me explain the goals of the profiler.
00:03:58.680
Its aim is to find possible values in an abstract running environment, improving the development experience.
00:04:12.660
The results mostly focus on providing insights for human consumption, so a few false positives might be acceptable.
00:04:19.290
For example, consider a method that is defined to accept one integer argument.
00:04:28.090
If it's mistakenly defined to accept a string instead, the goal would be to catch such errors before runtime.
00:04:39.890
The most traditional way to ensure type safety is to write explicit type annotations.
00:04:49.710
You would need to specify what types a method accepts and returns.
00:04:56.280
However, writing these annotations may not be desirable for everyone.
00:05:03.680
So, how many of you would prefer to write type annotations for your Ruby code? Please raise your hand.
00:05:13.500
Okay, thank you. And now, for those who do not want to write such annotations, please raise your hand.
00:05:20.360
Honestly, I had prepared two slides, expecting you would be inclined toward writing type annotations.
00:05:31.870
Annotations are useful not only for type checkers but also as communication tools to clarify API usage.
00:05:39.350
This is especially significant in large-scale projects.
00:05:46.550
In Ruby 3, you can write types manually because it provides an official way to do so.
00:05:53.240
If you include type annotations, you gain the benefits of a strong type-checking system.
00:06:00.620
However, as Matt mentioned in his keynote, he still finds type annotations unappealing.
00:06:08.650
This is why I am working on Type Profiler, which allows you to avoid writing annotations by hand.
00:06:19.920
With this tool, you can check your code almost without limitations.
00:06:26.430
Unfortunately, developing Type Profiler is quite challenging.
00:06:33.060
I admit that it is still very preliminary.
00:06:40.380
Currently, the development of Type Profiler is facing difficulties.
00:06:49.990
To achieve our goals, we plan to provide three main features.
00:06:56.990
First, Ruby signature language will serve as the standard type signature format.
00:07:04.600
Second, we will implement a typing feature to generate signature prototypes.
00:07:12.570
Finally, there will be a type checker to verify the consistency between code and signatures.
00:07:20.620
Using the Ruby signature language, you can write type signatures for your Ruby code.
00:07:28.290
With the second item, you can automatically generate signature prototypes for your Ruby code.
00:07:35.230
Finally, through the third item, you can type-check your code.
00:07:42.360
So, in this talk, I will focus on explaining items one and two.
00:07:49.570
Now, let’s get to Ruby signatures. I asked Sotaro, the author of the signature language, to explain.
00:07:57.540
I will pass the mic to him. Oh, thank you.
00:08:04.590
I'm Sotaro, and I lead the design and implementation of RBS in the Ruby team.
00:08:10.310
I also developed my static type checker called Steep.
00:08:17.710
This year, we don't have such a thing as Steep, but I'm working for the Ruby core.
00:08:23.500
Now, let’s talk about RBS.
00:08:29.570
RBS is a standard language designed to describe the types of Ruby programs, including modules and class definitions.
00:08:36.990
The most important aspect of RBS is that it is a different language from Ruby.
00:08:43.430
It has a distinct syntax and semantic structures.
00:08:50.190
The key purpose is to maintain clean separation between type annotations.
00:08:58.400
Here’s an example of an RBS definition.
00:09:03.860
Within the RBS file, you can define a class named 'Increment' with a method to receive an integer and return an integer.
00:09:10.670
The syntax will look similar to Ruby—but it’s entirely different.
00:09:17.990
The type-related information is isolated in a separate file, unlike being mixed with the Ruby code.
00:09:26.220
RBS supports generics, overloading, optional types, and type blocks.
00:09:34.020
It also supports mixins, including modules and extensions.
00:09:41.780
RBS introduces the concept of interfaces.
00:09:49.570
The difference between modules and interfaces is that interfaces are not tied to specific Ruby classes.
00:09:56.220
Instead, they support a form of duck typing, implying that any type meeting certain method requirements could be used.
00:10:03.920
RBS serves two primary functions: type checking and documentation.
00:10:10.800
If you wish to type-check your application or library with static type checkers including Steep or Sorbet, RBS will describe the type information.
00:10:19.100
Additionally, RBS provides clearer documentation of classes and methods, making it easier to understand.
00:10:26.850
To create RBS files, you can either write them manually or use tools that generate them from existing Ruby code.
00:10:36.420
For instance, we provide tools to generate templates from Ruby code.
00:10:43.500
You can also generate RBS files using Type Profiler, the subject of this session.
00:10:50.300
Now I'm working on a tool to validate RBS definitions against Ruby programs dynamically.
00:10:56.520
This tool uses runtime API checks for type correctness.
00:11:01.420
This approach allows developers to write RBS without attempting exhaustive Ruby code compatibility.
00:11:07.540
Now, let's return to Type Profiler and explore its key concepts and demos.
00:11:17.740
The primary idea of this analysis is to utilize type inference in Ruby.
00:11:23.410
However, it comes with known limitations.
00:11:28.910
Type Profiler applies abstract interpretation to the code, generating potential type signatures from untyped Ruby.
00:11:43.610
For instance, it can analyze logic like the 'increment' method from earlier.
00:11:52.020
In case it works perfectly, the type inference would yield correct results.
00:11:57.590
Nonetheless, if type inference incorrectly interprets input, further investigation is required.
00:12:05.160
The primary focus is ensuring clarity and correctness, thus reducing the need for constant manual typing.
00:12:12.960
To illustrate, I ran two simple test cases to show how Type Profiler can operate.
00:12:21.750
The first test is a basic Ruby program of around 300 lines.
00:12:29.520
Applying Type Profiler to this code outputs the inferred signatures.
00:12:36.360
For example, a method to represent a 3D vector might indicate types such as integers.
00:12:43.730
The analysis may detect parameter types and return types associated with specific methods.
00:12:49.610
However, incorrect assumptions during inference may lead to inaccurate results.
00:12:55.570
Before applying analysis results, the user should check for any discrepancies.
00:13:02.400
Another important feature is the ability to catch bad type pairs.
00:13:11.570
Types would indicate errors like attempting to add an integer and a string.
00:13:19.380
Overall, Type Profiler aims to provide better understanding while navigating Ruby's type structure.
00:13:28.760
Nevertheless, some limitations remain, especially with unknown types or constructs.
00:13:35.450
Before explaining how Type Profiler analyzes Ruby code, let’s explore its capabilities.
00:13:44.520
Next, I will conduct a brief analysis of a complex program.
00:13:52.680
Analyzing the test will provide insight into Ruby's code structure.
00:13:59.840
The first program, Obscura, serves as the benchmark for Ruby 3 and is quite complex.
00:14:07.800
The second is a toy example showcasing fundamental Ruby features.
00:14:14.090
As we review these cases, we can see how Type Profiler effectively handles different coding aspects.
00:14:21.540
For example, the analysis of mathematical operations offers unique challenges.
00:14:30.700
By analyzing type signatures for methods, we learn about method definitions.
00:14:37.900
Such analysis showcases potential performance improvements through method specialization.
00:14:47.400
After this analysis, we identify opportunities to optimize the internals of Ruby.
00:14:54.590
However, many of these features still require additional context from existing Ruby constructs.
00:15:02.020
Despite generating useful insights, Type Profiler may misinterpret unknown classes and types.
00:15:09.820
Thus, it’s essential to regularly update the knowledge base behind Type Profiler.
00:15:15.300
Moving beyond basic examples, Type Profiler needs engagement with real-world applications.
00:15:22.650
This is imperative to validate types against complex Ruby architectures.
00:15:29.420
In conclusion, I appreciate your attention and interest in exploring static typing in Ruby.
00:15:36.590
If any questions persist, please feel free to reach out.
00:15:42.780
Thank you, and I hope to see you at the next RubyConf!