"Types and Programming Languages" (The most well-known textbook of type systems) • It explains: • Base type system • Subtyping • Recursive types • Generics … in TypeScript I am one of the translators of TAPL (Ja version)
• It sells better than Ruby • First-class functions make it convenient to explain the traditional type systems • I want more contributors for Ruby types • Interested in Steep or Sorbet? Check it out! • Available at the bookstore (the 2nd floor) • Book signing next break. Get one!
about 100+ PRs (Thanks all contributors!) • Supported for Ruby's full syntax • Created TypeProf.wasm (a demo in browser by ruby.wasm) • https://mame.github.io/typeprof.wasm/ • Improved for practical use cases • Fixed a bug of infinite-loop Today's main topics
"Ruby TypeProf" plugin • Put typeprof.conf.json (or jsonc) in the top folder • Reopen VSCode, and see if it works • If it doesn't work well, that's a good chance to contribute • For details, check my slide deck for RubyKaigi 2024 { "typeprof_version": "experimental", "rbs_dir": "sig/", }
project size grows, it will not scale lib/typeprof/core module TypeProf::Core class Service def update(path, text) ... end end end module TypeProf::LSP serv = Core::Service.new ... serv.update("path", "1+1") end (String, String) inferred lib/typeprof
module TypeProf::Core class Service def update(path, text) ... end end end module TypeProf::LSP serv = Core::Service.new ... serv.update("path", "1+1") end lib/typeprof/core lib/typeprof/lsp no inference
update(path, text) ... end end end module TypeProf::LSP serv = Core::Service.new ... serv.update("path", "1+1") end lib/typeprof/core lib/typeprof/lsp module TypeProf::Core class Service def update_file: (String, String) -> void end end sig/pub.rbs typecheck typecheck
• C::Foo • The current context has the priority • M::Foo, P::Foo, Q::Foo • The inheritance has the next priority • B::Foo, A::Foo, ::Foo • The scope has the last priority • (Note: Z::Foo is not searched) class P < Q end class A class B < Z class C < P include M Foo.new(...) end end end What could this Foo refer to?
end # myapp/string.rb module M class String end end class MyApp include M end This String should be ::String… Also indirectly makes MyApp::String accessible
resolutions: • when a new constant is defined • when the inheritance hierarchy is changed # myapp/main.rb class MyApp String.new(...) end # myapp/string.rb class MyApp class String end end MyApp::String is defined! Re-analyze all "String" references Updated: this is MyApp::String Assume that this is ::String
resolutions: • when a new constant is defined • when the inheritance hierarchy is changed # myapp/main.rb class MyApp String.new(...) end # myapp/string.rb class MyApp include M end This changes the inheritance! Re-analyze all references under MyApp Updated: this is MyApp::String Assume that this is ::String
module M module M end end class MyApp include M end 0. There are ::M and ::M::M 1. This M should be ::M 2. This changes the inheritance hierarchy! Re-analyze all references under MyApp 3. Updated: This M should be ::M::M (!) 4. This changes the inheritance hierarchy! Re-analyze all references under MyApp 5. Updated: This M should be ::M Infinite loop!
inconsistent between ruby and rbs-inline module M module M end end class MyApp include M include M end Ruby semantics: ::M::M rbs-inline semantics: ::M inconsistent
argument of include • Ruby's constant resolution • C::Foo • The current context has the priority • M::Foo, P::Foo, Q::Foo • The inheritance has the next priority • B::Foo, A::Foo, ::Foo • The scope has the last priority class P < Q end class A class B class C < P include M include Foo end end end What could this Foo refer to? TypeProf no longer searches for inheritance
module M module M end end class MyApp include M end 0. There are ::M and ::M::M 1. This M should be ::M 2. This changes the inheritance! Re-analyze all references under MyApp 3. Updated: This M should be ::M::M (!) 4. This changes the inheritance! Re-analyze all references under MyApp 5. Updated: This M should be ::M Infinite loop! TypeProf no longer resolves this to ::M::M Fixed!
to use TypeProf or rbs-inline (or Sorbet) • Do not depend on the inheritance on constants module M module X end end class MyApp include M include X end module M module X end end class MyApp include M include ::M::X end Don't do this! Do this