Sdk: [Analyzer] Type of function literal can't be inferred because the literal has a block as its body

Created on 2 Jul 2019  Â·  4Comments  Â·  Source: dart-lang/sdk

Dart version and OS

  • Dart SDK Version: 2.4.0 (Wed Jun 19 11:53:45 2019 +0200) on "windows_x64"
  • Also reproducible with DartPad.

I saw the following Analyzer problem on the Gitter channel and I thought it was something which should be reported:

// Type of t1 are Analyzed to be: Iterable<Null>
var t1 = [1].map((value) {
  // info: The type of the function literal can't be inferred because the literal has a block as its body
  return value.toString();
});

// works
// Type of t2 are Analyzed to be: Iterable<String>
var t2 = [1].map((value) => value.toString());

main() {
  // Type of t3 are Analyzed to be: Iterable<String>
  var t3 = [1].map((value) {
    // works
    return value.toString();
  });

  // works
  // Type of t4 are Analyzed to be: Iterable<String>
  var t4 = [1].map((value) => value.toString()); // works

  print(t1.toList()); // works
  print(t2.toList()); // works
  print(t3.toList()); // works
  print(t4.toList()); // works
}

I don't think it makes sense that the type system works different in this situation just because we are on a global context (t1) instead of a context of a method (t3).

Also, the code are running just fine both on VM and Dartpad so it seems to be the Analyzer which have some kind of a problem here.

area-analyzer closed-duplicate type-bug

Most helpful comment

Yes, this is a known issue (#34503).

All 4 comments

An analysis result of Iterable<Null> seems highly curious. I'd have expected Iterable<dynamic> since an Iterable<Null> will almost certainly fail at run-time when the body fails to return null.

The CFE type of t1 is Iterable<String>, so it's obviously possible to do the type analysis here, and it's Iterable<Null> for the analyzer, as stated. (The type is visible in the error message if you write t1 = <String>[];).

@julemand101 wrote:

I don't think it makes sense that the type system works different

In general, there is a significant difference between global type inference and local type inference: Local declarations are strictly ordered (names declared earlier in the text, not later, can be used: var x = 42; var y = x + 1; is ok, but not var y = x + 1; var x = 42;). In contrast, top-level declarations can refer to each other, independently of their textual order.

This means that the complexity of global type inference is higher, and that's probably the reason why the situation is flagged as "too hard", when map needs a type argument, and the function literal needs a signature, and its return type must be computed based on potentially multiple return statements that may themselves give rise to type inference.

Finally, I agree that inferring the type Iterable<Null> for t1 looks like a bug in the analyzer (and it would allow dependent code to have errors: Iterable<int> it = t1; would be OK).

@stereotype441, does this look like a known issue in the analyzer? I don't see anything similar with this search.

Yes, this is a known issue (#34503).

Closing as duplicate of #34503.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ranquild picture ranquild  Â·  3Comments

bergwerf picture bergwerf  Â·  3Comments

Hixie picture Hixie  Â·  3Comments

DartBot picture DartBot  Â·  3Comments

sgrekhov picture sgrekhov  Â·  3Comments