在类似情况下,类型推断的行为有所不同

时间:2019-05-24 16:04:33

标签: dart type-inference

运行以下代码(Dart 2.3)会引发异常: type 'List<dynamic>' is not a subtype of type 'List<bool>'

bar() => 0;
foo() => [bar()];

main() {
  var l = [1, 2, 3];
  l = foo();
}

但是,这个稍有改动的示例可以正常运行:

main() {
  bar() => 0;
  var l = [1, 2, 3];
  l = [bar()];
}

这样做:

main() {
  bar() => 0;
  foo() => [bar()];
  var l = [1, 2, 3];
  l = foo();
}

Dart的类型推断算法使这些情况的行为有所不同是什么?似乎函数foobar的类型应该很容易推断,因为它们总是返回相同的值。在我看来,为什么在这些情况下四处移动函数声明会更改类型推断也并不明显。

有人知道这是怎么回事吗?

2 个答案:

答案 0 :(得分:1)

叶·彼得森(Leaf Petersen)在对dart-lang/sdk issue #33137: Type inference of function return value的评论中对此进行了解释:

  

这是设计使然。我们推断非递归 local 的返回类型   函数(在另一个函数范围内声明的函数   或方法),但对于顶级功能和方法,我们无法推断   返回类型(通过覆盖推断除外)。原因是   如下:

     
      
  • 方法和顶层函数通常是程序API的一部分,因此能够快速读取程序API的值很有价值。   一段代码。基于方法主体的返回类型推断手段   理解API的签名需要通读   方法主体。
  •   方法和顶级函数可以任意相互递归,这使得推理问题变得越来越困难   昂贵。   
     

主要由于这些原因,我们不推断顶级函数和方法的返回类型。放弃返回类型只是说dynamic的另一种方式。

如果您设置

analyzer:
  strong-mode:
    implicit-dynamic: false

在您的analysis_options.yaml文件中,那么当顶层函数具有隐式的dartanalyzer返回类型时,dynamic将产生错误:

  error • Missing return type for 'bar' at example.dart:1:1 • strong_mode_implicit_dynamic_return
  error • Missing return type for 'foo' at example.dart:2:1 • strong_mode_implicit_dynamic_return

答案 1 :(得分:0)

看起来嵌套函数与顶级函数的处理方式有所不同。 可能是一个错误。我从Dart 2.3.1的Dartpad获得以下内容。

foo() => 0;
bar() => [foo()];

main() {
  baz() => 0;
  qux() => [baz()];
  print(foo.runtimeType);
  print(bar.runtimeType);
  print(baz.runtimeType);
  print(qux.runtimeType);
}

// () => dynamic
// () => dynamic
// () => int
// () => List<int>

说明here

  

这是预期的行为。   本地函数使用类型推断来推断其返回类型,但顶级/类级别的函数则不能。

     

区别的主要原因是顶级和类功能与类型声明存在于同一级别。如果在我们还不了解类签名的时候还必须分析函数体,则解决类型与函数之间的循环依赖关系就变得更加困难。

     

当顶层推断完成时,我们确实知道类型层次结构,并且顶层函数是无序的,它们可以以任意方式相互引用,局部函数是线性的,并且只能依赖于全局函数或先前函数本地功能。这意味着我们可以在本地分析函数主体以找到返回类型,而无需查看除函数主体本身以外的任何内容以及我们已经分析过的事物。