Timee Product Team Blog

タイミー開発者ブログ

Steep エラーリファレンスを作りました(2024/09/30 時点)

タイミーでバックエンドのテックリードをしている新谷(@euglena1215)です。

タイミーでは RBS の活用を推進する取り組みを少しずつ進めています。意図はこちら

メンバーと雑談していたときに「steep check でコケたときにその名前で調べても全然ヒットしないので型周りのキャッチアップが難しい」という話を聞きました。
いくつかのエラー名でググってみたところ、 Ruby::ArgumentTypeMismatchRuby::NoMethod など有名なエラーはヒットしますがほとんどのエラーはヒットせず、ヒットするのは Steep リポジトリの該当実装のみでした。
これでは確かにキャッチアップは難しいだろうと感じたので、Steep のエラーリファレンスを作ってみました。ググってヒットするのが目的なのでテックブログとして公開してインデックスされることを期待します。

 

各エラーの説明は以下のフォーマットで行います。

エラー名

説明: 簡単なエラーの説明

例:

エラーが検出される Ruby コード
steep check を実行して得られるエラーメッセージ

severity:
Steep のエラープリセットに対して、該当エラーの severity がどのように設定されているかの表

 


Ruby::ArgumentTypeMismatch

説明: メソッドの型が一致しない場合に発生します。

違反例:

'1' + 1
test.rb:1:6: [error] Cannot pass a value of type `::Integer` as an argument of type `::string`
│   ::Integer <: ::string
│     ::Integer <: (::String | ::_ToStr)
│       ::Integer <: ::String
│         ::Numeric <: ::String
│           ::Object <: ::String
│             ::BasicObject <: ::String
│
│ Diagnostic ID: Ruby::ArgumentTypeMismatch
│
└ '1' + 1
        ~

severity:

all_error default strict lenient silent
error error error information nil

Ruby::BlockBodyTypeMismatch

説明: ブロックの body の返り値の型が期待される型と一致しない場合に発生します。

違反例:

lambda {|x| x + 1 } #: ^(Integer) -> String
test.rb:1:7: [error] Cannot allow block body have type `::Integer` because declared as type `::String`
│   ::Integer <: ::String
│     ::Numeric <: ::String
│       ::Object <: ::String
│         ::BasicObject <: ::String
│
│ Diagnostic ID: Ruby::BlockBodyTypeMismatch
│
└ lambda {|x| x + 1 } #: ^(Integer) -> String
         ~~~~~~~~~~~~

severity:

all_error default strict lenient silent
error warning error information nil

Ruby::BlockTypeMismatch

説明: ブロックの型が期待される型と一致しない場合に発生します。

違反例:

multi = ->(x, y) { x * y } #: ^(Integer, Integer) -> Integer
[1, 2, 3].map(&multi)
test.rb:2:14: [error] Cannot pass a value of type `^(::Integer, ::Integer) -> ::Integer` as a block-pass-argument of type `^(::Integer) -> U(1)`
│   ^(::Integer, ::Integer) -> ::Integer <: ^(::Integer) -> U(1)
│     (Params are incompatible)
│
│ Diagnostic ID: Ruby::BlockTypeMismatch
│
└ [1, 2, 3].map(&multi)
                ~~~~~~

severity:

all_error default strict lenient silent
error warning error information nil

Ruby::BreakTypeMismatch

説明: break の型が期待される型と一致しない場合に発生します。

違反例:

123.tap { break "" }
test.rb:1:10: [error] Cannot break with a value of type `::String` because type `::Integer` is assumed
│   ::String <: ::Integer
│     ::Object <: ::Integer
│       ::BasicObject <: ::Integer
│
│ Diagnostic ID: Ruby::BreakTypeMismatch
│
└ 123.tap { break "" }
            ~~~~~~~~

severity:

all_error default strict lenient silent
error hint error hint nil

Ruby::DifferentMethodParameterKind

説明: メソッドのパラメータの種類が一致しない場合に発生します。省略可能な引数の prefix に ? をつけ忘れることで発生することが多いです。

違反例:

# @type method bar: (name: String) -> void
def bar(name: "foo")
end
test.rb:2:8: [error] The method parameter has different kind from the declaration `(name: ::String) -> void`
│ Diagnostic ID: Ruby::DifferentMethodParameterKind
│
└ def bar(name: "foo")
          ~~~~~~~~~~~

severity:

all_error default strict lenient silent
error hint error nil nil

Ruby::FallbackAny

説明: 型が不明な場合に untyped が使用されることを示します。一度 [] で値を初期化したのちに再代入するような実装で発生することが多いです。

違反例:

a = []
a << 1
test.rb:1:4: [error] Cannot detect the type of the expression
│ Diagnostic ID: Ruby::FallbackAny
│
└ a = []
      ~~

severity:

all_error default strict lenient silent
error hint warning nil nil

Ruby::FalseAssertion

説明: Steep の型アサーションが誤っている場合に発生します。

違反例:

array = [] #: Array[Integer]
hash = array #: Hash[Symbol, String]
test.rb:2:7: [error] Assertion cannot hold: no relationship between inferred type (`::Array[::Integer]`) and asserted type (`::Hash[::Symbol, ::String]`)
│ Diagnostic ID: Ruby::FalseAssertion
│
└ hash = array #: Hash[Symbol, String]
         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

severity:

all_error default strict lenient silent
error hint error nil nil

Ruby::ImplicitBreakValueMismatch

説明: 引数無し break の値( nil )がメソッドの返り値の期待される型と一致しない場合に発生します。

違反例:

class Foo
  # @rbs () { (String) -> Integer } -> String
  def foo
    ''
  end
end

Foo.new.foo do |x|
  break
end
test.rb:9:2: [error] Breaking without a value may result an error because a value of type `::String` is expected
│   nil <: ::String
│
│ Diagnostic ID: Ruby::ImplicitBreakValueMismatch
│
└   break
    ~~~~~

severity:

all_error default strict lenient silent
error hint information nil nil

Ruby::IncompatibleAnnotation

説明: 型注釈が不適切または一致しない場合に発生します。

違反例:

a = [1,2,3]

if _ = 1
  # @type var a: String
  a + ""
end
test.rb:5:2: [error] Type annotation about `a` is incompatible since ::String <: ::Array[::Integer] doesn't hold
│   ::String <: ::Array[::Integer]
│     ::Object <: ::Array[::Integer]
│       ::BasicObject <: ::Array[::Integer]
│
│ Diagnostic ID: Ruby::IncompatibleAnnotation
│
└   a + ""
    ~~~~~~

severity:

all_error default strict lenient silent
error hint error nil nil

Ruby::IncompatibleArgumentForwarding

説明: 引数に ... を使ってメソッドの引数を forward する際に、引数の型が一致しない場合に発生します。

違反例:

class Foo
  # @rbs (*Integer) -> void
  def foo(*args)
  end

  # @rbs (*String) -> void
  def bar(...)
    foo(...)
  end
end
test.rb:8:8: [error] Cannot forward arguments to `foo`:
│   (*::Integer) <: (*::String)
│     ::String <: ::Integer
│       ::Object <: ::Integer
│
│ Diagnostic ID: Ruby::IncompatibleArgumentForwarding
│
└     foo(...)
          ~~~

severity:

all_error default strict lenient silent
error warning error information nil

Ruby::IncompatibleAssignment

説明: 代入の際の型が不適切または一致しない場合に発生します。

違反例:

# @type var x: Integer
x = "string"
test.rb:2:0: [error] Cannot assign a value of type `::String` to a variable of type `::Integer`
│   ::String <: ::Integer
│     ::Object <: ::Integer
│       ::BasicObject <: ::Integer
│
│ Diagnostic ID: Ruby::IncompatibleAssignment
│
└ x = "string"
  ~~~~~~~~~~~~

severity:

all_error default strict lenient silent
error hint error hint nil

Ruby::InsufficientKeywordArguments

説明: キーワード引数が不足している場合に発生します。

違反例:

class Foo
  def foo(a:, b:)
  end
end
Foo.new.foo(a: 1)
test.rb:5:8: [error] More keyword arguments are required: b
│ Diagnostic ID: Ruby::InsufficientKeywordArguments
│
└ Foo.new.foo(a: 1)
          ~~~~~~~~~

severity:

all_error default strict lenient silent
error error error information nil

Ruby::InsufficientPositionalArguments

説明: 位置引数が不足している場合に発生します。

違反例:

class Foo
  def foo(a, b)
  end
end
Foo.new.foo(1)
test.rb:5:8: [error] More keyword arguments are required: b
│ Diagnostic ID: Ruby::InsufficientKeywordArguments
│
└ Foo.new.foo(a: 1)
          ~~~~~~~~~

severity:

all_error default strict lenient silent
error error error information nil

Ruby::InsufficientTypeArgument

説明: 型引数に対する型注釈が不足している場合に発生します。

違反例:

class Foo
  # @rbs [T, S] (T, S) -> [T, S]
  def foo(x, y)
    [x, y]
  end
end

Foo.new.foo(1, 2) #$ Integer
test.rb:8:0: [error] Requires 2 types, but 1 given: `[T, S] (T, S) -> [T, S]`
│ Diagnostic ID: Ruby::InsufficientTypeArgument
│
└ Foo.new.foo(1, 2) #$ Integer
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~

severity:

all_error default strict lenient silent
error hint error nil nil

Ruby::InvalidIgnoreComment

説明: steep:ignore:start コメントはあるが steep:ignore:end コメントがないなど、無効なコメントが存在する場合に発生します。

違反例:

# steep:ignore:start
test.rb:1:0: [error] Invalid ignore comment
│ Diagnostic ID: Ruby::InvalidIgnoreComment
│
└ # steep:ignore:start
  ~~~~~~~~~~~~~~~~~~~~

severity:

all_error default strict lenient silent
error warning warning warning nil

Ruby::MethodArityMismatch

説明: キーワード引数なのに順序引数としてメソッドの引数の型を記述しているなど、メソッドの引数の型が一致しない場合に発生します。

違反例:

class Foo
  # @rbs (Integer x) -> Integer
  def foo(x:)
    x
  end
end
test.rb:3:9: [error] Method parameters are incompatible with declaration `(::Integer) -> ::Integer`
│ Diagnostic ID: Ruby::MethodArityMismatch
│
└   def foo(x:)
           ~~~~

severity:

all_error default strict lenient silent
error error error information nil

Ruby::MethodBodyTypeMismatch

説明: メソッドの返り値が期待される型と一致しない場合に発生します。

違反例:

class Foo
  # @rbs () -> String
  def foo
    1
  end
end
test.rb:3:6: [error] Cannot allow method body have type `::Integer` because declared as type `::String`
│   ::Integer <: ::String
│     ::Numeric <: ::String
│       ::Object <: ::String
│         ::BasicObject <: ::String
│
│ Diagnostic ID: Ruby::MethodBodyTypeMismatch
│
└   def foo
        ~~~

severity:

all_error default strict lenient silent
error error error warning nil

Ruby::MethodDefinitionMissing

説明: メソッドの型定義が存在するがメソッドの実装が欠落している場合に発生します。

違反例:

class Foo
  # @rbs!
  #   def bar: () -> void
end
test.rb:1:6: [error] Cannot find implementation of method `::Foo#bar`
│ Diagnostic ID: Ruby::MethodDefinitionMissing
│
└ class Foo
        ~~~

severity:

all_error default strict lenient silent
error nil hint nil nil

Ruby::MethodParameterMismatch

説明: メソッドのパラメータの型が一致しない場合に発生します。

違反例:

class Foo
  # @rbs (Integer x) -> Integer
  def foo(x:)
    x
  end
end
test.rb:3:10: [error] The method parameter is incompatible with the declaration `(::Integer) -> ::Integer`
│ Diagnostic ID: Ruby::MethodParameterMismatch
│
└   def foo(x:)
            ~~

severity:

all_error default strict lenient silent
error error error warning nil

Ruby::MethodReturnTypeAnnotationMismatch

説明: メソッドの戻り値の型注釈が期待される型と一致しない場合に発生します。

違反例:

class Foo
  # @rbs () -> String
  def foo
    # @type return: Integer
    123
  end
end
test.rb:3:2: [error] Annotation `@type return` specifies type `::Integer` where declared as type `::String`
│   ::Integer <: ::String
│     ::Numeric <: ::String
│       ::Object <: ::String
│         ::BasicObject <: ::String
│
│ Diagnostic ID: Ruby::MethodReturnTypeAnnotationMismatch
│
└   def foo
    ~~~~~~~

severity:

all_error default strict lenient silent
error hint error nil nil

Ruby::MultipleAssignmentConversionError

説明: 複数代入の変換に失敗した場合に発生します。

違反例:

class WithToAry
  # @rbs () -> Integer
  def to_ary
    1
  end
end

a, b = WithToAry.new()
test.rb:8:8: [error] Cannot convert `::WithToAry` to Array or tuple (`#to_ary` returns `::Integer`)
│ Diagnostic ID: Ruby::MultipleAssignmentConversionError
│
└ (a, b = WithToAry.new())
          ~~~~~~~~~~~~~~~

severity:

all_error default strict lenient silent
error hint error nil nil

Ruby::NoMethod

説明: 型定義が存在しないメソッドが呼び出された場合に発生します。

違反例:

"".non_existent_method
test.rb:1:3: [error] Type `::String` does not have method `non_existent_method`
│ Diagnostic ID: Ruby::NoMethod
│
└ "".non_existent_method
     ~~~~~~~~~~~~~~~~~~~

severity:

all_error default strict lenient silent
error error error information nil

Ruby::ProcHintIgnored

説明: Proc に関する型注釈が無視された場合に発生します。

違反例:

# @type var proc: (^(::Integer) -> ::String) | (^(::String, ::String) -> ::Integer)
proc = -> (x) { x.to_s }
test.rb:2:7: [error] The type hint given to the block is ignored: `(^(::Integer) -> ::String | ^(::String, ::String) -> ::Integer)`
│ Diagnostic ID: Ruby::ProcHintIgnored
│
└ proc = -> (x) { x.to_s }
         ~~~~~~~~~~~~~~~~~

severity:

all_error default strict lenient silent
error hint information nil nil

Ruby::ProcTypeExpected

説明: Proc 型が期待される場合に発生します。

違反例:

-> (&block) do
  # @type var block: Integer
end
test.rb:1:4: [error] Proc type is expected but `::Integer` is specified
│ Diagnostic ID: Ruby::ProcTypeExpected
│
└ -> (&block) do
      ~~~~~~

severity:

all_error default strict lenient silent
error hint error nil nil

Ruby::RBSError

説明: 型アサーションや型適用に書かれたRBS型がエラーを生じる場合に発生します。

違反例:

a = 1 #: Int
test.rb:1:9: [error] Cannot find type `::Int`
│ Diagnostic ID: Ruby::RBSError
│
└ a = 1 #: Int
           ~~~

severity:

all_error default strict lenient silent
error information error information nil

Ruby::RequiredBlockMissing

説明: メソッド呼び出し時に必要な block が欠落している場合に発生します。

違反例:

class Foo
  # @rbs () { () -> void } -> void
  def foo
    yield
  end
end
Foo.new.foo
test.rb:7:8: [error] The method cannot be called without a block
│ Diagnostic ID: Ruby::RequiredBlockMissing
│
└ Foo.new.foo
          ~~~

severity:

all_error default strict lenient silent
error error error hint nil

Ruby::ReturnTypeMismatch

説明: return の型とメソッドの戻り値の型が一致しない場合に発生します。

違反例:

# @type method foo: () -> Integer
def foo
  return "string"
end
test.rb:3:2: [error] The method cannot return a value of type `::String` because declared as type `::Integer`
│   ::String <: ::Integer
│     ::Object <: ::Integer
│       ::BasicObject <: ::Integer
│
│ Diagnostic ID: Ruby::ReturnTypeMismatch
│
└   return "string"
    ~~~~~~~~~~~~~~~

severity:

all_error default strict lenient silent
error error error warning nil

Ruby::SetterBodyTypeMismatch

説明: セッターメソッドの戻り値の型が期待される型と一致しない場合に発生します。

違反例:

class Foo
  # @rbs (String) -> String
  def foo=(value)
    123
  end
end
test.rb:3:6: [error] Setter method `foo=` cannot have type `::Integer` because declared as type `::String`
│   ::Integer <: ::String
│     ::Numeric <: ::String
│       ::Object <: ::String
│         ::BasicObject <: ::String
│
│ Diagnostic ID: Ruby::SetterBodyTypeMismatch
│
└   def foo=(value)
        ~~~~

severity:

all_error default strict lenient silent
error information error nil nil

Ruby::SetterReturnTypeMismatch

説明: セッターメソッドの return の型が期待される型と一致しない場合に発生します。

違反例:

class Foo
  # @rbs (String) -> String
  def foo=(value)
    return 123
  end
end
test.rb:4:4: [error] The setter method `foo=` cannot return a value of type `::Integer` because declared as type `::String`
│   ::Integer <: ::String
│     ::Numeric <: ::String
│       ::Object <: ::String
│         ::BasicObject <: ::String
│
│ Diagnostic ID: Ruby::SetterReturnTypeMismatch
│
└     return 123
      ~~~~~~~~~~

severity:

all_error default strict lenient silent
error information error nil nil

Ruby::SyntaxError

説明: Ruby の構文エラーが発生した場合に発生します。

違反例:

if x == 1
  puts "Hello"
test.rb:2:14: [error] SyntaxError: unexpected token $end
│ Diagnostic ID: Ruby::SyntaxError
│
└   puts "Hello"

severity:

all_error default strict lenient silent
error hint hint hint nil

Ruby::TypeArgumentMismatchError

説明: 型引数が期待される型と一致しない場合に発生します。

違反例:

class Foo
  # @rbs [T < Numeric] (T) -> T
  def foo(x)
    x
  end
end
Foo.new.foo("") #$ String
test.rb:7:19: [error] Cannot pass a type `::String` as a type parameter `T < ::Numeric`
│   ::String <: ::Numeric
│     ::Object <: ::Numeric
│       ::BasicObject <: ::Numeric
│
│ Diagnostic ID: Ruby::TypeArgumentMismatchError
│
└ Foo.new.foo("") #$ String
                     ~~~~~~

severity:

all_error default strict lenient silent
error hint error nil nil

Ruby::UnexpectedBlockGiven

説明: ブロックが予期されない場面で渡された場合に発生します。

違反例:

[1].at(1) { 123 }
test.rb:1:10: [error] The method cannot be called with a block
│ Diagnostic ID: Ruby::UnexpectedBlockGiven
│
└ [1].at(1) { 123 }
            ~~~~~~~

severity:

all_error default strict lenient silent
error warning error hint nil

Ruby::UnexpectedDynamicMethod

説明: 動的に定義されたメソッドが存在しない場合に発生します。

違反例:

class Foo
  # @dynamic foo

  def bar
  end
end
test.rb:1:6: [error] @dynamic annotation contains unknown method name `foo`
│ Diagnostic ID: Ruby::UnexpectedDynamicMethod
│
└ class Foo
        ~~~

severity:

all_error default strict lenient silent
error hint information nil nil

Ruby::UnexpectedError

説明: 予期しない一般的なエラーが発生した場合に発生します。

違反例:

class Foo
  # @rbs () -> String123
  def foo
  end
end
test.rb:1:0: [error] UnexpectedError: sig/generated/test.rbs:5:17...5:26: Could not find String123(RBS::NoTypeFoundError)
│ ...
│   (36 more backtrace)
│
│ Diagnostic ID: Ruby::UnexpectedError
│
└ class Foo
  ~~~~~~~~~

severity:

all_error default strict lenient silent
error hint information hint nil

Ruby::UnexpectedJump

説明: 予期しないジャンプが発生した場合に発生します。

違反例:

break
test.rb:1:0: [error] Cannot jump from here
│ Diagnostic ID: Ruby::UnexpectedJump
│
└ break
  ~~~~~

severity:

all_error default strict lenient silent
error hint error nil nil

Ruby::UnexpectedJumpValue

説明: ジャンプの値を渡しても値が無視される場合に発生します。

違反例:

while true
  next 3
end
test.rb:2:2: [error] The value given to next will be ignored
│ Diagnostic ID: Ruby::UnexpectedJumpValue
│
└   next 3
    ~~~~~~

severity:

all_error default strict lenient silent
error hint error nil nil

Ruby::UnexpectedKeywordArgument

説明: 予期しないキーワード引数が渡された場合に発生します。

違反例:

class Foo
  # @rbs (x: Integer) -> void
  def foo(x:)
  end
end

Foo.new.foo(x: 1, y: 2)
test.rb:7:18: [error] Unexpected keyword argument
│ Diagnostic ID: Ruby::UnexpectedKeywordArgument
│
└ Foo.new.foo(x: 1, y: 2)
                    ~

severity:

all_error default strict lenient silent
error error error information nil

Ruby::UnexpectedPositionalArgument

説明: 予期しない位置引数が渡された場合に発生します。

違反例:

class Foo
  # @rbs (Integer) -> void
  def foo(x)
  end
end

Foo.new.foo(1, 2)
test.rb:7:15: [error] Unexpected positional argument
│ Diagnostic ID: Ruby::UnexpectedPositionalArgument
│
└ Foo.new.foo(1, 2)
                 ~

severity:

all_error default strict lenient silent
error error error information nil

Ruby::UnexpectedSuper

説明: super を呼び出した際に親クラスに同名のメソッドが定義されていないなど、予期しない場面で super が使用された場合に発生します。

違反例:

class Foo
  def foo
    super
  end
end
test.rb:3:4: [error] No superclass method `foo` defined
│ Diagnostic ID: Ruby::UnexpectedSuper
│
└     super
      ~~~~~

severity:

all_error default strict lenient silent
error information error nil nil

Ruby::UnexpectedTypeArgument

説明: 予期しない型引数が渡された場合に発生します。

違反例:

class Foo
  # @rbs [T] (T) -> T
  def foo(x)
    x
  end
end

Foo.new.foo(1) #$ Integer, Integer
test.rb:8:27: [error] Unexpected type arg is given to method type `[T] (T) -> T`
│ Diagnostic ID: Ruby::UnexpectedTypeArgument
│
└ Foo.new.foo(1) #$ Integer, Integer
                             ~~~~~~~

severity:

all_error default strict lenient silent
error hint error nil nil

Ruby::UnexpectedYield

説明: yield が予期しない場面で使用された場合に発生します。

違反例:

class Foo
  # @rbs () -> void
  def foo
    yield
  end
end
test.rb:4:4: [error] No block given for `yield`
│ Diagnostic ID: Ruby::UnexpectedYield
│
└     yield
      ~~~~~

severity:

all_error default strict lenient silent
error warning error information nil

Ruby::UnknownConstant

説明: 未知の定数が参照された場合に発生します。

違反例:

FOO
test.rb:1:0: [error] Cannot find the declaration of constant: `FOO`
│ Diagnostic ID: Ruby::UnknownConstant
│
└ FOO
  ~~~

severity:

all_error default strict lenient silent
error warning error hint nil

Ruby::UnknownGlobalVariable

説明: 未知のグローバル変数が参照された場合に発生します。

違反例:

$foo
test.rb:1:0: [error] Cannot find the declaration of global variable: `$foo`
│ Diagnostic ID: Ruby::UnknownGlobalVariable
│
└ $foo
  ~~~~

severity:

all_error default strict lenient silent
error warning error hint nil

Ruby::UnknownInstanceVariable

説明: 未知のインスタンス変数が参照された場合に発生します。

違反例:

class Foo
  def foo
    @foo = 'foo'
  end
end
test.rb:3:4: [error] Cannot find the declaration of instance variable: `@foo`
│ Diagnostic ID: Ruby::UnknownInstanceVariable
│
└     @foo = 'foo'
      ~~~~

severity:

all_error default strict lenient silent
error information error hint nil

Ruby::UnreachableBranch

説明: if ,unless による到達不可能な分岐が存在する場合に発生します。

違反例:

if false
  1
end
test.rb:1:0: [error] The branch is unreachable
│ Diagnostic ID: Ruby::UnreachableBranch
│
└ if false
  ~~

severity:

all_error default strict lenient silent
error hint information hint nil

Ruby::UnreachableValueBranch

説明: case when による到達不可能な分岐が存在し、分岐の型が bot でなかった場合に発生します。

違反例:

x = 1
case x
when Integer
  "one"
when String
  "two"
end
test.rb:5:0: [error] The branch may evaluate to a value of `::String` but unreachable
│ Diagnostic ID: Ruby::UnreachableValueBranch
│
└ when String
  ~~~~

severity:

all_error default strict lenient silent
error hint warning hint nil

Ruby::UnresolvedOverloading

説明: オーバーロードが行われているメソッドに対して型が解決できない場合に発生します。

違反例:

3 + "foo"
test.rb:1:0: [error] Cannot find compatible overloading of method `+` of type `::Integer`
│ Method types:
│   def +: (::Integer) -> ::Integer
│        | (::Float) -> ::Float
│        | (::Rational) -> ::Rational
│        | (::Complex) -> ::Complex
│
│ Diagnostic ID: Ruby::UnresolvedOverloading
│
└ 3 + "foo"
  ~~~~~~~~~

severity:

all_error default strict lenient silent
error error error information nil

Ruby::UnsatisfiableConstraint

説明: RBSと型注釈の辻褄が合わないなど、どうやっても型制約が満たされない場合に発生します。

違反例:

class Foo
  # @rbs [A, B] (A) { (A) -> void } -> B
  def foo(x)
  end
end

test = Foo.new

test.foo(1) do |x|
  # @type var x: String
end
test.rb:9:0: [error] Unsatisfiable constraint `::Integer <: A(1) <: ::String` is generated through (A(1)) { (A(1)) -> void } -> B(2)
│   ::Integer <: ::String
│     ::Numeric <: ::String
│       ::Object <: ::String
│         ::BasicObject <: ::String
│
│ Diagnostic ID: Ruby::UnsatisfiableConstraint
│
└ test.foo(1) do |x|
  ~~~~~~~~~~~~~~~~~~

severity:

all_error default strict lenient silent
error hint error hint nil

Ruby::UnsupportedSyntax

説明: Steep としてサポートされていない構文が使用された場合に発生します。

違反例:

(_ = []).[]=(*(_ = nil))
test.rb:1:13: [error] Unsupported splat node occurrence
│ Diagnostic ID: Ruby::UnsupportedSyntax
│
└ (_ = []).[]=(*(_ = nil))
               ~~~~~~~~~~

severity:

all_error default strict lenient silent
error hint information hint nil

 


狙ったエラーを引き起こすというのは今年の RubyKaigi であった Ruby "enbugging" Quiz に近い感覚でした。難しい。

基本的には Steep リポジトリにあるテストケースを見ながら埋めていったんですが、中にはテストケースがないものもあったので soutaro さんに直接質問をしながら進めていきました。

また、副産物として Steep で使われなくなったが定義として残っているルールを発見し、削除する patch を作れたのも個人的には良かったです。

github.com