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.27k stars 1.58k forks source link

Analyzer does not consistently consider invocations on `Never` to have type `Never`. #56985

Open stereotype441 opened 3 weeks ago

stereotype441 commented 3 weeks ago

The NNBD spec says:

Calling a method (including an operator) or getter on a receiver of static type Never is treated by static analysis as producing a result of type Never. Tearing off a method from a receiver of static type Never produces a value of type Never. Applying an expression of type Never in the function position of a function call produces a result of type Never.

Assuming "operator" means "user-definable operator" (i.e. not &&, ||, or ??), then as far as I can tell, the CFE implements this faithfully.

The analyzer is inconsistent, though:

stereotype441 commented 3 weeks ago

I'm working on some refactoring that would benefit from fixing this, so I'll work on a fix. Note that the fix will be a non-breaking change, since it will bring the analyzer into alignment with the CFE.

lrhn commented 2 weeks ago

Assuming "operator" means "user-definable operator"

It does here since it refers to "method (including an operator)" so it's about operators which are also instance methods. Probably except == which always has type bool.

(Although it could safely apply to the rest too, if the first operand has type Never, the entire expression could soundly have type Never.)

Every place where a non-Never, non-dynamic invocation would use the member signature of the member on the receiver type to infer the result type, an invocation on Never has result type Never, no bounds for type arguments and no context type or required type for arguments.

"Tearing off a method from a receiver of static type Never produces a value of type Never. "

That's a little misleading. It's an unspecified member access. It's impossible to say whether a member access on Never targets a getter or a method. In fact, it's definitely neither.

Anyway, seems like the analyzer refused a little more of the behavior of dynamic. The only real problem with that is inconsistency, it'll never cause a runtime problem (he says confidently).