Open ybiquitous opened 1 year ago
Currently, I'm not very open to adding new features to support refinements...
The most straightforward way to support it seems like adding refinement
annotation to RBS class/module definitions.
module M
refinement class String
def foo: () -> void
end
end
And type checkers will update the definition of refinement
classes/modules when using
calls or equivalent is detected.
module Foo
using M
String.new.foo # Will type check
end
Thanks for the response. Indeed, we would like to avoid an addition to the RBS syntax if possible.
Is there a way to avoid Ruby::NoMethod
for top-level using
now without changing the current RBS?
Using interface and intersection type may be one of the possible workarounds, but not sure if it solves your problem...
# @type var string: String & _StringRefinement
string = _ = ""
In the case of adding a new method by refinements, the current RBS seems to work even if not using the @type var
workaround. For example:
a.rbs
:
module M
end
class String
def foo: () -> void
end
a.rb
:
module M
refine String do
def foo
"foo"
end
end
end
using M
puts "".foo
Run ruby a.rb
:
$ bundle exec ruby a.rb
foo
Run steep check
:
$ bundle exec steep check
a.rb:9:0: [error] Type `::Object` does not have method `using`
│ Diagnostic ID: Ruby::NoMethod
│
└ using M
~~~~~
Detected 1 problem from 1 file
Even in this case, using
fails to type-check.
However, when changing an existing method signature, the refinement fails to type-check. Probably RBS may need a new feature to address refinements, as you commented on https://github.com/ruby/rbs/issues/1117#issuecomment-1271269302.
For example:
a.rbs
:
module M
end
class String
def size: (String name) -> Integer
end
a.rb
:
module M
refine String do
def size(name)
puts "size name: #{name}"
self.length
end
end
end
using M
puts "".size("foo")
Run ruby a.rb
:
$ bundle exec ruby a.rb
size name: foo
0
Run steep check
:
$ bundle exec steep check
vendor/bundle/ruby/3.1.0/gems/rbs-2.7.0/core/string.rbs:2497:2: [error] Non-overloading method definition of `size` in `::String` cannot be duplicated
│ Diagnostic ID: RBS::DuplicatedMethodDefinition
│
└ alias size length
~~~~~~~~~~~~~~~~~
a.rb:5:11: [error] Type `(::Object & ::M)` does not have method `length`
│ Diagnostic ID: Ruby::NoMethod
│
└ self.length
~~~~~~
a.rb:10:0: [error] Type `::Object` does not have method `using`
│ Diagnostic ID: Ruby::NoMethod
│
└ using M
~~~~~
a.rb:12:5: [error] UnexpectedError: /Users/koba/tmp/foo/vendor/bundle/ruby/3.1.0/gems/rbs-2.7.0/core/string.rbs:2497:2...2497:19: ::String#size has duplicated definitions in a.rbs:5:2...5:36
│ Diagnostic ID: Ruby::UnexpectedError
│
└ puts "".size("foo")
~~~~~~~~~~~~~~
Detected 4 problems from 2 files
@ybiquitous Ah! I'm sorry. I was misunderstanding your question.
Seems like we need a support for main object!
Seems like we need a support for main object!
I see. That makes sense. 👍🏼
@soutaro I'd like to add RBS for the main
object, but I'm unsure how to do it. Is it correct to add using
to Object
like this...?
class Object
def using: (Module module) -> self
end
@ybiquitous It would be a workaround, if you can accept that the #using
is available anywhere in your code...
Another one is using # @type self
annotation:
self.then do
# @type self: Object & _Main
using FooBar
end
Looks like it works, but 😫...
I don't think it can be done without the support of type checkers. For example,
_Main
interface in RBS, which has #using
method, andself
be Object & _Main
in Steep
- Add
_Main
interface in RBS, which has#using
method, and- Let the type of toplevel
self
beObject & _Main
in Steep
Sounds good! 👍🏼
Hello. The
using
method at the top level seems not typed. Is there a way to resolve it?Reprodoction
The following is a reproduction using Steep. First, prepare a few files.
a.rb
:Steepfile
:Gemfile
:Then, install the gems and run
steep
on your terminal:You should see the following output:
Environment
2.6.02.7.01.1.01.2.0Note
The
Module#using
method signature has been existing already:https://github.com/ruby/rbs/blob/95667d76c725566fa455bbcca0c10cc1e539475a/core/module.rbs#L1519