I'd like to have a Ruby class method return an instance on reading from a file. And I'd like that method to either take a string which is the path to the file, or an IO where the caller has opened the file themselves. And I'd like to do this for a few methods in a few classes, so I define a helper module:
module IOUtil extend self def io_with_mode(arg, mode) case arg when String File.open(arg, mode) do |io| yield io end when File yield arg else raise TypeError, arg end endendclass Foo attr_reader :str def initialize(str) @str = str end def self.from_bar(arg) IOUtil.io_with_mode(arg, 'r') do |io| new(io.read) end endend
That all works nicely, if I have a file bar.dat
with some text in it then
bar1 = Foo.from_bar('bar.dat')puts bar1puts bar1.strbar2 = File.open('bar.dat') { |io| Foo.from_bar(io) }puts bar2puts bar2.str
then I get
#<Foo:0x00007f853ae1d1d0>Hello#<Foo:0x00007f853ae1c500>Hello
I want to type-check this so create the signature file which I think is right:
module IOUtil extend IOUtil def io_with_mode: [T] (String | IO, String) { (IO) -> T } -> Tendclass Foo def initialize: (String) -> void def str: () -> String def self.from_bar: (String | IO) -> instanceend
and steep check
gives me a pass, but the warning
[Steep 1.6.0] [typecheck:typecheck@2] [background] [#typecheck_source(path=lib/minimal.rb)] [#type_check_file(lib/minimal.rb@lib)] [synthesize:(1:1)] [synthesize:(18:1)] [synthesize:(19:3)] [synthesize:(25:3)] [::Foo <: instance] `T <: instance` doesn't hold generally, but testing it with `::Foo <: instance && instance <: ::Foo` for compatibility
Is there anything to worry about here? I don't really understand why the warning.
If not, is there a way to quieten the warning?