Skip to content

Commit 63837f2

Browse files
committed
Infer element types for array literals and NilClass for nil literals
Array literal chains (`[1, 2, 3]`) previously resolved to a bare `Array` with no element type. Infer each child's type and attach it as the Array's generic parameter, falling back to plain `Array` when empty or undefined. `simplify_literals` left the `nil` pseudo-type tag as-is instead of converting it to `NilClass` like other literals are converted to their class names. This also surfaced two previously-pending specs (NilClass/nil conformance, and passing a NilClass value to a `nil` parameter) that now pass.
1 parent e6017cd commit 63837f2

6 files changed

Lines changed: 14 additions & 6 deletions

File tree

lib/solargraph/complex_type/unique_type.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ def to_s
103103
# @return [self]
104104
def simplify_literals
105105
transform do |t|
106+
next t.recreate(new_name: 'NilClass') if t.nil_type?
106107
next t unless t.literal?
107108
t.recreate(new_name: t.non_literal_name)
108109
end
@@ -309,7 +310,7 @@ def to_rbs
309310
'untyped'
310311
elsif name == 'Boolean'
311312
'bool'
312-
elsif name.downcase == 'nil'
313+
elsif name.downcase == 'nil' || name == 'NilClass'
313314
'nil'
314315
elsif name == GENERIC_TAG_NAME
315316
all_params.first&.name

lib/solargraph/source/chain/array.rb

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,16 @@ def word
1919
# @param name_pin [Pin::Base]
2020
# @param locals [::Array<Pin::Parameter, Pin::LocalVariable>]
2121
def resolve api_map, name_pin, locals
22-
type = ComplexType::UniqueType.new('Array', rooted: true)
22+
type = if @children.empty?
23+
ComplexType::UniqueType.new('Array', rooted: true)
24+
else
25+
element_type = ComplexType.new(@children.map { |c| c.infer(api_map, name_pin, locals) })
26+
if element_type.undefined?
27+
ComplexType::UniqueType.new('Array', rooted: true)
28+
else
29+
ComplexType::UniqueType.new('Array', [], [element_type], rooted: true, parameters_type: :list)
30+
end
31+
end
2332
[Pin::ProxyType.anonymous(type, source: :chain)]
2433
end
2534
end

spec/complex_type/conforms_to_spec.rb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,6 @@ class Sub < Sup; end
8181
end
8282

8383
it 'handles singleton types compared against their literals' do
84-
pending 'side of effect of inference changes'
8584
exp = Solargraph::ComplexType::UniqueType.new('nil', rooted: true)
8685
inf = Solargraph::ComplexType::UniqueType.new('NilClass', rooted: true)
8786
match = inf.conforms_to?(api_map, exp, :method_call)

spec/pin/base_variable_spec.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ def bar
4242
pin = api_map.get_instance_variable_pins('Foo').first
4343
type = pin.probe(api_map)
4444
expect(type.tags).to eq('Integer, nil')
45-
expect(type.simple_tags).to eq('Integer, nil')
45+
expect(type.simple_tags).to eq('Integer, NilClass')
4646
expect(type.to_rbs).to eq('(::Integer | nil)')
4747
expect(type.simplify_literals.to_rbs).to eq('(::Integer | nil)')
4848
end

spec/pin/method_spec.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -321,7 +321,7 @@ def bar
321321
type = pin.probe(api_map)
322322
expect(type.rooted_tags).to eq('::Integer, nil')
323323
expect(type.to_rbs).to eq('(::Integer | nil)')
324-
expect(type.simple_tags).to eq('Integer, nil')
324+
expect(type.simple_tags).to eq('Integer, NilClass')
325325
end
326326

327327
it 'infers from chains' do

spec/type_checker/levels/strict_spec.rb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1021,7 +1021,6 @@ def foo(a); end
10211021
end
10221022

10231023
it 'does not complain when passing NilClass to nil parameter' do
1024-
pending 'should be feasible'
10251024
checker = type_checker(%(
10261025
# @param a [nil]
10271026
def foo(a); end

0 commit comments

Comments
 (0)