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.09k stars 1.56k forks source link

[analyzer] Soundness issue with typing of equality expressions #54083

Open eernstg opened 10 months ago

eernstg commented 10 months ago

Consider the following example, based on this comment:

class NeverEqual {
  Never operator ==(Object? o) => throw 0;
}

void main() {
  NeverEqual? neverEqual = NeverEqual() as dynamic, other;
  Object? o = true;

  if (o is! int) neverEqual == other; // Incorrect to assume that this throws.
  print(o.toRadixString(16)); // Unsound.
}

This shows that it is unsound to assume that the type of an <equalityExpression> is Never, even in the case where the corresponding declaration of operator == has return type Never. Equality expressions should always have the type bool.

However, the analyzer (DartPad based on Dart SDK 3.3.0-16.0.dev) does not report any errors on the line marked 'Unsound', which implies that it considers neverEqual == other to be an expression that cannot complete normally.

lrhn commented 10 months ago

It's worth mentioning that this cannot affect constant evaluation, since constant == is only allowed with primitive equality, not anything that calls a user written implementation. So it will only be incorrect typing of code that will never be executed at that type. (So technically it's not "unsound", there is no expression which is evaluated to a type which isn't a subtype of its static type. It's just not correct, it doesn't match the compiler behavior.)

eernstg commented 10 months ago

Well, it's an analyzer issue. If the CFE had had the same static analysis then it would certainly have been a soundness issue: It will attempt to call toRadixString on true.

eernstg commented 8 months ago

@srawlins, I just tried the example, and it looks like it has been resolved already?