Говоря Крутому, что значения гарантированно не равны нулю

#ruby #steep

Вопрос:

Я хотел начать использовать Steep для одного из своих проектов, но я продолжаю получать ошибки, которые я не знаю, как исправить. Это один пример, извлеченный из моего кода, с которым я борюсь. Я удалил всю сложность, за исключением соответствующих битов:

Установка

 # lib/a/b.rb module A  class B  C = [[''], ['2', '2''], [''', '3', '’']].freeze  D = (['0']   C.map(amp;:first)).freeze   def initialize(v)  @v = v  end   def lt;=gt;(other)  @v lt;=gt; other.v  end  end end  

Мои подписи выглядят так:

 # sig/a/b.rbs module A  class B  C: ::Array[::Array[::String]]  D: ::Array[::String]   @v: ::Integer   def initialize: (::Integer v) -gt; untyped   attr_reader v: ::Integer   def lt;=gt;: (self other) -gt; ::Integer  end end   

Крутой файл:

 target :lib do  signature 'sig'   check 'lib' end   

Крутой сейчас говорит:

 lib/a/b.rb:4:4: IncompatibleAssignment: lhs_type=::Array[::String], rhs_type=::Array[(::String | nil)] (D = (['0']   C.map(amp;:first)).freeze)  ::Array[(::String | nil)] lt;: ::Array[::String]  (::String | nil) lt;: ::String  nil lt;: ::String ==gt; nil lt;: ::String does not hold lib/a/b.rb:10:4: MethodBodyTypeMismatch: method=lt;=gt;, expected=::Integer, actual=(::Integer | nil) (def lt;=gt;(other))  (::Integer | nil) lt;: ::Integer  nil lt;: ::Integer ==gt; nil lt;: ::Integer does not hold  

Проблема

Я думаю, что понимаю вашу жалобу. В общем Array#first случае возвращает либо значение из этого массива, либо nil . Однако мой массив был определен только одной строкой выше, и поэтому я знаю, что это не nil в данном конкретном случае.

Same thing for lt;=gt; . It could return nil in some cases, but given that I typed the argument other as self , I know other.value is an Integer and a lt;=gt; b where a and b are integers returns an integer. I.e. I know that it’s not nil here.

But how do I tell steep that? Can I cast this to non- nil somehow?