Skip to content

Commit c162674

Browse files
chloestefantsovaCommit Bot
authored and
Commit Bot
committed
[cfe] Perform inference on enum elements as on other fields
The type inference on enum elements was performed at the outline expression building phase, which is later than the inference on the rest of the members. It prevents some type checks from being performed correctly, for example, a check for the type of the getter induced by the element and a declared static setter. This CL moves the inference on enum elements to the same phase as for the rest of the class and enum members. Part of #47453 Change-Id: Iefc5606e6db07df8cd2de101c47d115c2ff8454a Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/236000 Reviewed-by: Johnni Winther <[email protected]> Commit-Queue: Chloe Stefantsova <[email protected]>
1 parent 900176f commit c162674

12 files changed

+466
-118
lines changed

pkg/front_end/lib/src/fasta/kernel/implicit_field_type.dart

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
library fasta.implicit_type;
66

77
import 'package:_fe_analyzer_shared/src/scanner/token.dart' show Token;
8+
import 'package:front_end/src/fasta/source/source_enum_builder.dart';
89
import 'package:kernel/ast.dart';
910
import 'package:kernel/src/assumptions.dart';
1011
import 'package:kernel/src/legacy_erasure.dart';
@@ -13,6 +14,7 @@ import 'package:kernel/src/printer.dart';
1314
import '../constant_context.dart';
1415
import '../fasta_codes.dart';
1516
import '../problems.dart' show unsupported;
17+
import '../builder/builder.dart';
1618
import '../source/source_field_builder.dart';
1719
import '../type_inference/type_inferrer.dart';
1820
import '../type_inference/type_schema.dart';
@@ -115,6 +117,7 @@ class _ImplicitFieldTypeRoot extends ImplicitFieldType {
115117
}
116118
isStarted = true;
117119
DartType? inferredType;
120+
Builder? parent = fieldBuilder.parent;
118121
if (_overriddenFields != null) {
119122
for (ImplicitFieldType overridden in _overriddenFields!) {
120123
DartType overriddenType = overridden.inferType();
@@ -128,6 +131,10 @@ class _ImplicitFieldTypeRoot extends ImplicitFieldType {
128131
}
129132
}
130133
return inferredType!;
134+
} else if (parent is SourceEnumBuilder &&
135+
parent.elementBuilders.contains(fieldBuilder)) {
136+
inferredType = parent.buildElement(
137+
parent.library, fieldBuilder, parent.library.loader.coreTypes);
131138
} else if (initializerToken != null) {
132139
InterfaceType? enclosingClassThisType = fieldBuilder.classBuilder == null
133140
? null

pkg/front_end/lib/src/fasta/source/source_enum_builder.dart

Lines changed: 164 additions & 118 deletions
Large diffs are not rendered by default.

pkg/front_end/test/spell_checking_list_common.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2022,6 +2022,7 @@ nullability
20222022
nullable
20232023
num
20242024
number
2025+
numbering
20252026
numbers
20262027
numeric
20272028
object
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
enum E<T> {
6+
element<int>(),
7+
element2<int>();
8+
9+
static void set element(E<int> val) {} // Ok.
10+
static void set element2(E<String> val) {} // Error.
11+
}
12+
13+
main() {}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
library /*isNonNullableByDefault*/;
2+
//
3+
// Problems in library:
4+
//
5+
// pkg/front_end/testcases/enhanced_enums/setter_getter_type_check.dart:7:3: Error: The type 'E<int>' of the getter 'E.element2' is not a subtype of the type 'E<String>' of the setter 'E.element2'.
6+
// - 'E' is from 'pkg/front_end/testcases/enhanced_enums/setter_getter_type_check.dart'.
7+
// element2<int>();
8+
// ^^^^^^^^
9+
// pkg/front_end/testcases/enhanced_enums/setter_getter_type_check.dart:10:19: Context: This is the declaration of the setter 'E.element2'.
10+
// static void set element2(E<String> val) {} // Error.
11+
// ^^^^^^^^
12+
//
13+
import self as self;
14+
import "dart:core" as core;
15+
16+
class E<T extends core::Object? = dynamic> extends core::_Enum /*isEnum*/ {
17+
static const field core::List<self::E<dynamic>> values = #C7;
18+
static const field self::E<core::int> element = #C3;
19+
static const field self::E<core::int> element2 = #C6;
20+
const constructor •(core::int index, core::String name) → self::E<self::E::T%>
21+
: super core::_Enum::•(index, name)
22+
;
23+
method toString() → core::String
24+
return "E.${this.{core::_Enum::_name}{core::String}}";
25+
static set element(self::E<core::int> val) → void {}
26+
static set element2(self::E<core::String> val) → void {}
27+
}
28+
static method main() → dynamic {}
29+
30+
constants {
31+
#C1 = 0
32+
#C2 = "element"
33+
#C3 = self::E<core::int> {index:#C1, _name:#C2}
34+
#C4 = 1
35+
#C5 = "element2"
36+
#C6 = self::E<core::int> {index:#C4, _name:#C5}
37+
#C7 = <self::E<dynamic>>[#C3, #C6]
38+
}
39+
40+
41+
Constructor coverage from constants:
42+
org-dartlang-testcase:///setter_getter_type_check.dart:
43+
- E. (from org-dartlang-testcase:///setter_getter_type_check.dart:5:6)
44+
- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:103:9)
45+
- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
library /*isNonNullableByDefault*/;
2+
//
3+
// Problems in library:
4+
//
5+
// pkg/front_end/testcases/enhanced_enums/setter_getter_type_check.dart:7:3: Error: The type 'E<int>' of the getter 'E.element2' is not a subtype of the type 'E<String>' of the setter 'E.element2'.
6+
// - 'E' is from 'pkg/front_end/testcases/enhanced_enums/setter_getter_type_check.dart'.
7+
// element2<int>();
8+
// ^^^^^^^^
9+
// pkg/front_end/testcases/enhanced_enums/setter_getter_type_check.dart:10:19: Context: This is the declaration of the setter 'E.element2'.
10+
// static void set element2(E<String> val) {} // Error.
11+
// ^^^^^^^^
12+
//
13+
import self as self;
14+
import "dart:core" as core;
15+
16+
class E<T extends core::Object? = dynamic> extends core::_Enum /*isEnum*/ {
17+
static const field core::List<self::E<dynamic>> values = #C7;
18+
static const field self::E<core::int> element = #C3;
19+
static const field self::E<core::int> element2 = #C6;
20+
const constructor •(core::int index, core::String name) → self::E<self::E::T%>
21+
: super core::_Enum::•(index, name)
22+
;
23+
method toString() → core::String
24+
return "E.${this.{core::_Enum::_name}{core::String}}";
25+
static set element(self::E<core::int> val) → void {}
26+
static set element2(self::E<core::String> val) → void {}
27+
}
28+
static method main() → dynamic {}
29+
30+
constants {
31+
#C1 = 0
32+
#C2 = "element"
33+
#C3 = self::E<core::int> {index:#C1, _name:#C2}
34+
#C4 = 1
35+
#C5 = "element2"
36+
#C6 = self::E<core::int> {index:#C4, _name:#C5}
37+
#C7 = <self::E<dynamic>>[#C3, #C6]
38+
}
39+
40+
41+
Constructor coverage from constants:
42+
org-dartlang-testcase:///setter_getter_type_check.dart:
43+
- E. (from org-dartlang-testcase:///setter_getter_type_check.dart:5:6)
44+
- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:103:9)
45+
- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
enum E<T> {
2+
element<int>(),
3+
element2<int>();
4+
5+
static void set element(E<int> val) {}
6+
static void set element2(E<String> val) {}
7+
}
8+
9+
main() {}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
enum E<T> {
2+
element<int>(),
3+
element2<int>();
4+
5+
static void set element(E<int> val) {}
6+
static void set element2(E<String> val) {}
7+
}
8+
9+
main() {}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
library /*isNonNullableByDefault*/;
2+
//
3+
// Problems in library:
4+
//
5+
// pkg/front_end/testcases/enhanced_enums/setter_getter_type_check.dart:7:3: Error: The type 'E<int>' of the getter 'E.element2' is not a subtype of the type 'E<String>' of the setter 'E.element2'.
6+
// - 'E' is from 'pkg/front_end/testcases/enhanced_enums/setter_getter_type_check.dart'.
7+
// element2<int>();
8+
// ^^^^^^^^
9+
// pkg/front_end/testcases/enhanced_enums/setter_getter_type_check.dart:10:19: Context: This is the declaration of the setter 'E.element2'.
10+
// static void set element2(E<String> val) {} // Error.
11+
// ^^^^^^^^
12+
//
13+
import self as self;
14+
import "dart:core" as core;
15+
16+
class E<T extends core::Object? = dynamic> extends core::_Enum /*isEnum*/ {
17+
static const field core::List<self::E<dynamic>> values = #C7;
18+
static const field self::E<core::int> element = #C3;
19+
static const field self::E<core::int> element2 = #C6;
20+
const constructor •(core::int index, core::String name) → self::E<self::E::T%>
21+
: super core::_Enum::•(index, name)
22+
;
23+
method toString() → core::String
24+
return "E.${this.{core::_Enum::_name}{core::String}}";
25+
static set element(self::E<core::int> val) → void {}
26+
static set element2(self::E<core::String> val) → void {}
27+
}
28+
static method main() → dynamic {}
29+
30+
constants {
31+
#C1 = 0
32+
#C2 = "element"
33+
#C3 = self::E<core::int*> {index:#C1, _name:#C2}
34+
#C4 = 1
35+
#C5 = "element2"
36+
#C6 = self::E<core::int*> {index:#C4, _name:#C5}
37+
#C7 = <self::E<dynamic>*>[#C3, #C6]
38+
}
39+
40+
41+
Constructor coverage from constants:
42+
org-dartlang-testcase:///setter_getter_type_check.dart:
43+
- E. (from org-dartlang-testcase:///setter_getter_type_check.dart:5:6)
44+
- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:103:9)
45+
- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
library /*isNonNullableByDefault*/;
2+
//
3+
// Problems in library:
4+
//
5+
// pkg/front_end/testcases/enhanced_enums/setter_getter_type_check.dart:7:3: Error: The type 'E<int>' of the getter 'E.element2' is not a subtype of the type 'E<String>' of the setter 'E.element2'.
6+
// - 'E' is from 'pkg/front_end/testcases/enhanced_enums/setter_getter_type_check.dart'.
7+
// element2<int>();
8+
// ^^^^^^^^
9+
// pkg/front_end/testcases/enhanced_enums/setter_getter_type_check.dart:10:19: Context: This is the declaration of the setter 'E.element2'.
10+
// static void set element2(E<String> val) {} // Error.
11+
// ^^^^^^^^
12+
//
13+
import self as self;
14+
import "dart:core" as core;
15+
16+
class E<T extends core::Object? = dynamic> extends core::_Enum /*isEnum*/ {
17+
static const field core::List<self::E<dynamic>> values = #C7;
18+
static const field self::E<core::int> element = #C3;
19+
static const field self::E<core::int> element2 = #C6;
20+
const constructor •(core::int index, core::String name) → self::E<self::E::T%>
21+
: super core::_Enum::•(index, name)
22+
;
23+
method toString() → core::String
24+
return "E.${this.{core::_Enum::_name}{core::String}}";
25+
static set element(self::E<core::int> val) → void {}
26+
static set element2(self::E<core::String> val) → void {}
27+
}
28+
static method main() → dynamic {}
29+
30+
constants {
31+
#C1 = 0
32+
#C2 = "element"
33+
#C3 = self::E<core::int*> {index:#C1, _name:#C2}
34+
#C4 = 1
35+
#C5 = "element2"
36+
#C6 = self::E<core::int*> {index:#C4, _name:#C5}
37+
#C7 = <self::E<dynamic>*>[#C3, #C6]
38+
}
39+
40+
41+
Constructor coverage from constants:
42+
org-dartlang-testcase:///setter_getter_type_check.dart:
43+
- E. (from org-dartlang-testcase:///setter_getter_type_check.dart:5:6)
44+
- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:103:9)
45+
- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
library /*isNonNullableByDefault*/;
2+
//
3+
// Problems in library:
4+
//
5+
// pkg/front_end/testcases/enhanced_enums/setter_getter_type_check.dart:7:3: Error: The type 'E<int>' of the getter 'E.element2' is not a subtype of the type 'E<String>' of the setter 'E.element2'.
6+
// - 'E' is from 'pkg/front_end/testcases/enhanced_enums/setter_getter_type_check.dart'.
7+
// element2<int>();
8+
// ^^^^^^^^
9+
// pkg/front_end/testcases/enhanced_enums/setter_getter_type_check.dart:10:19: Context: This is the declaration of the setter 'E.element2'.
10+
// static void set element2(E<String> val) {} // Error.
11+
// ^^^^^^^^
12+
//
13+
import self as self;
14+
import "dart:core" as core;
15+
16+
class E<T extends core::Object? = dynamic> extends core::_Enum /*isEnum*/ {
17+
static const field core::List<self::E<dynamic>> values = const <self::E<dynamic>>[self::E::element, self::E::element2];
18+
static const field self::E<core::int> element = const self::E::•<core::int>(0, "element");
19+
static const field self::E<core::int> element2 = const self::E::•<core::int>(1, "element2");
20+
const constructor •(core::int index, core::String name) → self::E<self::E::T%>
21+
: super core::_Enum::•(index, name)
22+
;
23+
method toString() → core::String
24+
return "E.${this.{core::_Enum::_name}{core::String}}";
25+
static set element(self::E<core::int> val) → void
26+
;
27+
static set element2(self::E<core::String> val) → void
28+
;
29+
}
30+
static method main() → dynamic
31+
;
32+
33+
34+
Extra constant evaluation status:
35+
Evaluated: ListLiteral @ org-dartlang-testcase:///setter_getter_type_check.dart:5:6 -> ListConstant(const <E<dynamic>*>[const E<int*>{_Enum.index: 0, _Enum._name: "element"}, const E<int*>{_Enum.index: 1, _Enum._name: "element2"}])
36+
Evaluated: ConstructorInvocation @ org-dartlang-testcase:///setter_getter_type_check.dart:6:3 -> InstanceConstant(const E<int*>{_Enum.index: 0, _Enum._name: "element"})
37+
Evaluated: ConstructorInvocation @ org-dartlang-testcase:///setter_getter_type_check.dart:7:3 -> InstanceConstant(const E<int*>{_Enum.index: 1, _Enum._name: "element2"})
38+
Extra constant evaluation: evaluated: 8, effectively constant: 3
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
library /*isNonNullableByDefault*/;
2+
//
3+
// Problems in library:
4+
//
5+
// pkg/front_end/testcases/enhanced_enums/setter_getter_type_check.dart:7:3: Error: The type 'E<int>' of the getter 'E.element2' is not a subtype of the type 'E<String>' of the setter 'E.element2'.
6+
// - 'E' is from 'pkg/front_end/testcases/enhanced_enums/setter_getter_type_check.dart'.
7+
// element2<int>();
8+
// ^^^^^^^^
9+
// pkg/front_end/testcases/enhanced_enums/setter_getter_type_check.dart:10:19: Context: This is the declaration of the setter 'E.element2'.
10+
// static void set element2(E<String> val) {} // Error.
11+
// ^^^^^^^^
12+
//
13+
import self as self;
14+
import "dart:core" as core;
15+
16+
class E<T extends core::Object? = dynamic> extends core::_Enum /*isEnum*/ {
17+
static const field core::List<self::E<dynamic>> values = #C7;
18+
static const field self::E<core::int> element = #C3;
19+
static const field self::E<core::int> element2 = #C6;
20+
const constructor •(core::int index, core::String name) → self::E<self::E::T%>
21+
: super core::_Enum::•(index, name)
22+
;
23+
method toString() → core::String
24+
return "E.${this.{core::_Enum::_name}{core::String}}";
25+
static set element(self::E<core::int> val) → void {}
26+
static set element2(self::E<core::String> val) → void {}
27+
}
28+
static method main() → dynamic {}
29+
30+
constants {
31+
#C1 = 0
32+
#C2 = "element"
33+
#C3 = self::E<core::int*> {index:#C1, _name:#C2}
34+
#C4 = 1
35+
#C5 = "element2"
36+
#C6 = self::E<core::int*> {index:#C4, _name:#C5}
37+
#C7 = <self::E<dynamic>*>[#C3, #C6]
38+
}
39+
40+
41+
Constructor coverage from constants:
42+
org-dartlang-testcase:///setter_getter_type_check.dart:
43+
- E. (from org-dartlang-testcase:///setter_getter_type_check.dart:5:6)
44+
- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:103:9)
45+
- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)

0 commit comments

Comments
 (0)