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.21k stars 1.57k forks source link

Analyzer const cast fails for `Never?`. #54820

Open lrhn opened 8 months ago

lrhn commented 8 months ago

Example:

  const v = null as Never?;

The analyzer reports a compile-time error for this:

line 3 • Evaluation of this constant expression throws an exception.

Doesn't say which exception, and it shouldn't since null is a valid value of any nullable type. (Doesn't check type for nullability?)

bwilkerson commented 8 months ago

I'm guessing that Never? means that it will either return null or never return. There are likely other places in the analyzer / linter where Never? isn't being handled correctly. For example, the code

Never? f() => null;

results in the lint Unnecessary use of the type 'Null'. Try using 'void' instead.. This seems like a poor message, at the very least.

@scheglov @pq

pq commented 8 months ago

I'm inclined to agree that at least prefer_void_to_null is overreporting.

Issue filed: https://github.com/dart-lang/linter/issues/4867

eernstg commented 8 months ago

We've got this one as well: https://github.com/dart-lang/linter/issues/4758.

pq commented 8 months ago

Yes, thanks @eernstg!

lrhn commented 8 months ago

I'm guessing that Never? means that it will either return null or never return.

Or throw, just like Null. The type Never? is NORM-equivalent to Null, which means that it should behave exactly the same in most contexts (likely all contexts for this type, a few other types have a few exceptions where the pre-normalization type matters).

It's definitely true that Never? \<: Null and Null \<: Never?, and their Type objects are equal, and identical if const:

typedef NeverQ = Never?;
void main() { 
  assert(Null == NeverQ);
  const t1 = Null; 
  const t2 = NeverQ;
  assert(identical(t1, t2));
}