Skip to content

Analyzer constant evaluation special-cases identical(int, double). #60647

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
lrhn opened this issue Apr 30, 2025 · 0 comments
Open

Analyzer constant evaluation special-cases identical(int, double). #60647

lrhn opened this issue Apr 30, 2025 · 0 comments
Labels
analyzer-constants area-dart-model For issues related to conformance to the language spec in the parser, compilers or the CLI analyzer. model-const-eval Implementation of constant evaluation in analyzer/cfe

Comments

@lrhn
Copy link
Member

lrhn commented Apr 30, 2025

The analyzer constant evaluation has a special case for identical(c1, c2) when one is a double and the other an int, in particular:

    // Workaround for Flutter `const kIsWeb = identical(0, 0.0)`.
    if (type.isDartCoreInt && rightOperand.type.isDartCoreDouble ||
        type.isDartCoreDouble && rightOperand.type.isDartCoreInt) {
      return DartObjectImpl(
        typeSystem,
        typeSystem.typeProvider.boolType,
        BoolState.UNKNOWN_VALUE,
      );
    }
    // ...

I think it should stop doing that.

The behavior is that if one value is an int and the other a double, the analyzer decides that it doesn't know if they are identical or not. (Even if they weren't even equal.)

That can have downstream consequences, where code that tries to have separate branches for JS-numbers and native numbers will have both branches analyzed, even if one of them will always fail.

As a degenerate example:

const int minNativeInt = (1 << 63); // Zero on web.
const int minJSInt = -(double.maxFinite / 2 ~/ 1 + 1) * 2; // Zero on native.

const bool jsNumbers = identical(1, 1.0);
class C {
  final int x;
  const C(int v)
    : assert(jsNumbers ? minJSInt != 0 : minNativeInt != 0), // Should succeed. Or throw here.
      x = jsNumbers ? (v ~/ minJSInt) : (v ~/ minNativeInt); // Should never fail with a division by zero.
}

void main() {
  print("Native: $minNativeInt");
  print("Web   : $minJSInt");
  const C(0); // Runs on all platforms, analyzer fails to analyze.
}

The real issue occurred in testing, where I needed a bigger delta than 1 for some tests when running with JS precision,
so I had var offset = jsNumbers ? 1024 : 1;. That ends up being an "unknown integer constant" in the analyzer, not either actual value I wanted.
Then I tested constant evaluation of const Duration(hours: max, microseconds: offset), and it did not trigger an assert that checked for overflow (because an "unkown bool" value of an assert does not report an error), but it did fail in a later branch guarded by the same condition as the assert, because it hit something that was intended to throw during non-constant evaluation, and be guarded by the assert in constant evaluation.

Which means I got spurious errors in an error test when run with the analyzer.

I think the analyzer should not special case here. It runs constant evaluation with either JS or native semantics, and it's not like it doesn't know which. (It's native.)

Trying to not admit that just pushes people to do other tests, like:

const jsNumbers = 0x20_0000_0000_0000 == (0x20_0000_0000_0000 + 1); // 2^54 (+ 1)

which compares only integers, still distinguishes when those integers are actually doubles, and doesn't pretend that it doesn't know in the analyzer.

(That's what I switched to in my test, and is putting into package:expect/variations.dart instead of identical(1, 1.0).)

@lrhn lrhn added analyzer-constants area-dart-model For issues related to conformance to the language spec in the parser, compilers or the CLI analyzer. model-const-eval Implementation of constant evaluation in analyzer/cfe labels Apr 30, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
analyzer-constants area-dart-model For issues related to conformance to the language spec in the parser, compilers or the CLI analyzer. model-const-eval Implementation of constant evaluation in analyzer/cfe
Projects
None yet
Development

No branches or pull requests

1 participant