为什么Crystal无法解析1+1的赋值类型?

Why can't Crystal resolve the type of the assignment of 1 + 1?

为什么Crystal不能t/won解析this的类型? (我看到文档没有提到编译器可以推断实例方法调用,但它背后的基本原理是什么,尤其是当只涉及 stdlib 函数时?编译时间?)

class Something
  def blah
    @result = 1 + 1
  end
end


Something.new().blah

编译器错误:

Showing last frame. Use --error-trace for full trace.

error in line 3
Error: can't infer the type of instance variable '@result' of SomeObject

The type of a instance variable, if not declared explicitly with
`@result : Type`, is inferred from assignments to it across
the whole program.

The assignments must look like this:

  1. `@result = 1` (or other literals), inferred to the literal's type
  2. `@result = Type.new`, type is inferred to be Type
  3. `@result = Type.method`, where `method` has a return type
     annotation, type is inferred from it
  4. `@result = arg`, with 'arg' being a method argument with a
     type restriction 'Type', type is inferred to be Type
  5. `@result = arg`, with 'arg' being a method argument with a
     default value, type is inferred using rules 1, 2 and 3 from it
  6. `@result = uninitialized Type`, type is inferred to be Type
  7. `@result = LibSome.func`, and `LibSome` is a `lib`, type
     is inferred from that fun.
  8. `LibSome.func(out @result)`, and `LibSome` is a `lib`, type
     is inferred from that fun argument.

Other assignments have no effect on its type.

can't infer the type of instance variable '@result' of SomeObject

如果我没记错的话,Crystal 过去在推导类型时更积极。虽然它在某些示例中很优雅,但在更大的项目中会产生更多问题。编译时间成为一个问题(增量编译很难或不可能),当一切传播时,代码中的错误(例如,由于打字错误)可能更难追踪。

最后,保持干扰规则更简单并回退到表达式的显式类型被认为更实用。这是 2015 年的 discussion about the change。我没有参与语言设计,但通过线程阅读,我认为线程中的参数适用于你的问题(为什么 1 + 1 需要明确输入).请注意,1 + 1 是一个简单的情况,但是一旦允许,表达式可以变得任意复杂。通常,编译器必须遍历整个程序代码才能进行分析。