Bug: Double Parentheses in Union Types with positional_names: false
When converting Sorbet signatures to RBS format with positional_names: false, union types in required parameters are wrapped in double parentheses.
Running dev rbs should turn:
sig { params(x: T.any(Symbol, String)).returns(Integer) }def foo(x); end
into:
def foo: (Symbol | String) -> Integer
but it actually does this:
def foo: ((Symbol | String)) -> Integer
Root Cause
The TypePrinter#visit_any method always wraps union types in parentheses (A | B). When print_sig_param prints parameters without positional names, these parentheses are combined with the method signature parameter list parentheses, creating ((A | B)).
Fix?? strip outer parentheses from union types for required parameters only (optional and rest parameters need the inner parens for clarity: ?(A | B) and *(A | B)).
Related file:
rbsprinter.rb line
I believe this is still valid with the parenthesis right?
See on sorbet.run, all these examples are valid syntax:
#: ((Symbol | String)) -> void
def foo(x); end
#: (Symbol | String) -> void
def bar(x); end
#: ((Symbol | String) x) -> void
def baz(x); end
#: (Symbol | String x) -> void
def qux(x); end)
We could try to omit the parenthesis but it becomes tricky when the type is used in return position (sorbet.run):
#: -> (Symbol | String)
def foo; T.unsafe(nil); end
#: -> Symbol | String
# ^ error: Failed to parse RBS signature (expected a token `pEOF`)
def bar(x); T.unsafe(nil); end
I don't see an easy fix unless the RBS parser starts to accept return union without parenthesis.
Maybe you could bring it to https://github.com/ruby/rbs/issues?