Skip to content

CFE: Incorrect enum constants in co19/LanguageFeatures/Enhanced-Enum/enum_name_A01_t01 #48099

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

Closed
alexmarkov opened this issue Jan 7, 2022 · 2 comments
Assignees
Labels
legacy-area-front-end Legacy: Use area-dart-model instead.

Comments

@alexmarkov
Copy link
Contributor

This is a part of #47453.

When compiling tests/co19/src/LanguageFeatures/Enhanced-Enum/enum_name_A01_t01.dart with sound null safety the following compile-time errors are issued:

tests/co19/src/LanguageFeatures/Enhanced-Enum/enum_name_A01_t01.dart:30:6: Error: Constant evaluation error:
enum E<T extends num> {
     ^
tests/co19/src/LanguageFeatures/Enhanced-Enum/enum_name_A01_t01.dart:30:6: Context: Expected constant 'null' to be of type 'E<dynamic>', but was of type 'Null'.
 - 'E' is from 'tests/co19/src/LanguageFeatures/Enhanced-Enum/enum_name_A01_t01.dart'.
enum E<T extends num> {
     ^
tests/co19/src/LanguageFeatures/Enhanced-Enum/enum_name_A01_t01.dart:30:6: Context: While analyzing:
enum E<T extends num> {
     ^

However, when compiling and running with --no-sound-null-safety, this test compiles without errors and fails at run time.

Kernel generated by the front-end doesn't look right:

  class E<T extends core::num> extends core::_Enum /*isEnum*/  {
    static const field core::List<enu::E<dynamic>> values = #C5;
    static const field enu::E<dynamic> e1 = #C1;
    static const field enu::E<dynamic> e2 = #C1;
    static const field enu::E<core::int> e3 = #C4;
    const constructor named(core::int index, core::String name, core::int x) → enu::E<enu::E::T>
      : super core::_Enum::•(index, name)
      ;
    method toString() → core::String
      return "E.${this.{core::_Enum::_name}{core::String}}";
  }
  static method main() → dynamic {
    Exp::Expect::equals("e1", core::EnumName|get#name(#C1));
    Exp::Expect::equals("e2", core::EnumName|get#name(#C1));
    Exp::Expect::equals("e3", core::EnumName|get#name(#C4));
  }

  #C1 = null
  #C2 = 0
  #C3 = "e3"
  #C4 = enu::E<core::int*> {index:#C2, _name:#C3}
  #C5 = <enu::E<dynamic>*>[#C1, #C1, #C4]

Both e1 and e2 enum elements are declared as null constants (#C1). This causes the test to fail with RuntimeError in dartk-weak-asserts-* configurations.

/cc @chloestefantsova @johnniwinther

@alexmarkov alexmarkov added the legacy-area-front-end Legacy: Use area-dart-model instead. label Jan 7, 2022
@chloestefantsova
Copy link
Contributor

I think it's a case of a test that needs correction and the lack of a compile-time error message from the CFE. If I'm reading the spec correctly, the default constructor for the enum is not generated if it has a generative constructor or an unnamed factory:

Default constructor: If no generative constructors were declared, and no unnamed factory constructor was added, a default generative constructor is added:

const Name();
(This differs from the default constructor of a normal class declaration by being constant.)

So what I think happens is that the declaration of E.name prevents the CFE from generating the default constructor, making the declarations of the elements e1 and e2 erroneous. The CFE doesn't report in that case yet and silently uses null as the value for both of the elements.

@alexmarkov
Copy link
Contributor Author

Filed dart-lang/co19#1269.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
legacy-area-front-end Legacy: Use area-dart-model instead.
Projects
None yet
Development

No branches or pull requests

2 participants