dart-lang / sdk

The Dart SDK, including the VM, JS and Wasm compilers, analysis, core libraries, and more.
https://dart.dev
BSD 3-Clause "New" or "Revised" License
10.22k stars 1.57k forks source link

Weird strict inference failure on function return type #56631

Open FMorschel opened 1 month ago

FMorschel commented 1 month ago

I recently found https://github.com/dart-lang/sdk/issues/39277 and the example code it provides is the following:

_createChildren() {
  return [Text("Hello"), Text("Lars"), Text("Testing")];
}

With strict-inference: true the above code triggers an inference_failure_on_function_return_type hint.

But the weird thing is that it also triggers the Add return type assist.

I could not understand the docs on strict-inference for function return types fully, so maybe this is not a bug but it got me thinking on why should it be triggering when it does know how to infer the return type with the assist.

dart-github-bot commented 1 month ago

Summary: The _createChildren function returns a list of Text widgets, but with strict-inference: true, the analyzer fails to infer the return type and suggests adding it explicitly. This behavior is unexpected, as the analyzer can infer the return type and offers an assist to add it.

eernstg commented 1 month ago

Top-level declarations (including function declarations) are considered to enter into a contract with the surrounding code (we might treat private declarations differently, but this isn't done today), and this means that they shouldn't change their typing properties by accident, and they shouldn't change it frequently. Hence, it's recommended that the signature of a top-level function is specified explicitly. Hence the need to add an explicitly declared return type.

In general, top-level declarations can depend on each other in ways that include mutual recursion as well as dependencies on other libraries. The complexity of performing type inference in this situation is substantial, and Dart takes the approach that return types of top-level function declarations are not inferred, even in the cases where it might look like an easy task. Hence the lack of an implicitly inferred return type.

The 'Add return type' assist isn't constrained by the language rules, it's fine if this assist can come up with a useful return type in some situations, and it doesn't have a solution in other situations. Hence the availability of an assist.

So it's all working as intended.

@bwilkerson, do you have further comments on this?

DanTup commented 1 month ago

I too was confused by this, but maybe the issue is just that the message "The return type of '_createChildren' cannot be inferred." could be interpreted in two ways:

  1. it can't be inferred because you enabled this setting that says it must be explicit
  2. this expression is complicated and we can't infer the type

I assumed it meant the second, but if it means the first, maybe rather than saying "it cannot be inferred", it would be better written differently, something like:

I think this would make it clearer that it's not that it can't be inferred, but that it won't due to the strict inference setting.

FMorschel commented 1 month ago

I do agree with the above. In cases where that assist can solve this, there could be another message. Maybe link that as a quick-fix if it is not already (I've recently looked at that assist code and I don't think it is marked as a quick-fix).