8000 Type promotion failed in named records · Issue #55473 · dart-lang/sdk · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Type promotion failed in named records #55473

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
yiiim opened this issue Apr 15, 2024 · 7 comments
Open

Type promotion failed in named records #55473

yiiim opened this issue Apr 15, 2024 · 7 comments
Labels
area-dart-model For issues related to conformance to the language spec in the parser, compilers or the CLI analyzer. cfe-dysfunctionalities Issues for the CFE not behaving as intended model-flow Implementation of flow analysis in analyzer/cfe type-bug Incorrect behavior (everything from a crash to more subtle misbehavior)

Comments

@yiiim
Copy link
yiiim commented Apr 15, 2024

Run the following code in DartPad:

void main() {
  int? a;
  Future(
    () {
      ({String b, String c}) test = (
        b: "${a!.isEven}",
        c: "${a.isEven}",
      );
      print(test);
    },
  );
  a = 0;
}
compileDDC
main.dart:7:17: Error: Property 'isEven' cannot be accessed on 'int?' because it is potentially null.
Try accessing using ?. instead.
        c: "${a.isEven}",
                ^^^^^^
@lrhn lrhn added type-bug Incorrect behavior (everything from a crash to more subtle misbehavior) area-fe-analyzer-shared and removed type-bug Incorrect behavior (everything from a crash to more subtle misbehavior) labels Apr 15, 2024
@lrhn
Copy link
Member
lrhn commented Apr 15, 2024

This looks like it's working as currently intended. (Edit, narrator voice: It did not.)

Code inside a closure cannot promote a variable if there are assignments to it outside of the closure (maybe only later).
That is the case here.

The fact that the only assignment is to a non-null isn't taken into account. The value may change at a time that is not known to not happen between the a! and the a.isEven, and that's enough to disable promotion.

@yiiim
Copy link
Author
yiiim commented Apr 15, 2024

So is this an error that belongs to the IDE plug-in? I did not get any error prompts in the vscode Dart plug-in v3.86.0.

@yiiim
Copy link
Author
yiiim commented Apr 15, 2024

If it's an unnamed record type, this code can work properly.

void main() {
  int? a;
  Future(
    () {
      (String, String) test = (
        "${a!.isEven}",
        "${a.isEven}",
      );
      print(test);
    },
  );
  a = 0;
}

@lrhn
Copy link
Member
lrhn commented Apr 15, 2024

Good point. It seems like DDC is promoting the variable in one case, so it should in the other too.

@lrhn lrhn added the type-bug Incorrect behavior (everything from a crash to more subtle misbehavior) label Apr 15, 2024
@johnniwinther
Copy link
Member

cc @stereotype441

@johnniwinther johnniwinther added the cfe-dysfunctionalities Issues for the CFE not behaving as intended label Apr 17, 2024
@tp
Copy link
Contributor
tp commented Apr 23, 2024

In our codebase we had a similar case (and given that it's a closure parameter (which could even be final)) I felt this is a stronger example of the issue:

void main() {
  f((x) => [x!.a, x.b]); // OK
  f((x) => (x!.a, x.b)); // OK
  f((x) => (a: x!.a, b: x.b)); // ERR
}

void f(void Function(X?) c) {
  c(X());
}

class X {
  final a = 1;
  final b = 2;
}

passes dart analyze (which wants one to not add a ! to x.b), but fails compilation with

compileDDC
main.dart:3:33: Error: Property 'b' cannot be accessed on 'X?' because it is potentially null.
 - 'X' is from 'package:dartpad_sample/main.dart' ('/tmp/dartpadTJDUDK/lib/main.dart').
Try accessing using ?. instead.
  f((final x) => (a: x!.a, b: x.b));
                                ^

@lrhn
Copy link
Member
lrhn commented Apr 23, 2024

Seems to be related to information flow between expressions in a record expression that contains named fields.
(As in: it's not there. The promotions of a prior field are not used as starting state for the next field expression, but only if the record expression itself contains named fields.)

void main() {
  ({int x, int y})? a = (x: 42, y: 37) as dynamic;
  var yes = DateTime.now().millisecondsSinceEpoch > 0;
  // Named fields, requires promotion to flow between field expressions.
  // All fail.
  if (yes) {
    print((a!.x, n2: a.y)); // ERR
  }
  if (yes) {
    print((n1: a!.x, a.y)); // ERR
  }
  if (yes) {
    print((n1: a!.x, n2: a.y)); // ERR
  }
  if (yes) {
    print((a!.x, a.y, n3: 0)); // ERR
  }
  // Promotion flow out of record. Works.
  if (yes) {
    print((a!.x, n2: 0));
    print(a.y);
  }
  if (yes) {
    print((n1: a!.x, n2: 0));
    print(a.y);
  }
  // Promotion flow inside field expression. Works.
  if (yes) {
    print((a!.x + a.y, n2: 0));
  }
  if (yes) {
    print((n1: a!.x + a.y, n2: 0));
  }
  // No mamed fields in same record as promotion. Works.
  if (yes) {
    print((a!.x, (n2: a.y)));
    print(a.y);
  }
  if (yes) {
    print((a!.x, a.y));
  }
  // Not records, all work.
  if (yes) {
    print([a!.x, a.y]);
  }
  if (yes) {
    foo(a!.x, a.y);
  }
  if (yes) {
    bar(x: a!.x, y: a.y);
  }
}

void foo([int x = 0, int y = 0]) {
  print("$x,$y");
}

void bar({int x = 0, int y = 0}) {
  print("$x,$y");
}

@johnniwinther johnniwinther added area-dart-model For issues related to conformance to the language spec in the parser, compilers or the CLI analyzer. model-flow Implementation of flow analysis in analyzer/cfe and removed legacy-area-fe-analyzer-shared labels Apr 1, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-dart-model For issues related to conformance to the language spec in the parser, compilers or the CLI analyzer. cfe-dysfunctionalities Issues for the CFE not behaving as intended model-flow Implementation of flow analysis in analyzer/cfe type-bug Incorrect behavior (everything from a crash to more subtle misbehavior)
Projects
None yet
Development

No branches or pull requests

4 participants
0