Skip to content

Commit a03eb19

Browse files
chloestefantsovaCommit Bot
authored and
Commit Bot
committed
[cfe] Infer missing type arguments on enum elements
This CL also moves the resolution of the _Enum type before it's checked for being a correct supertype. Part of #47453 Change-Id: I80d4197a430b90e4aea785961bfbcbbee588255a Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/228644 Reviewed-by: Johnni Winther <[email protected]> Commit-Queue: Chloe Stefantsova <[email protected]>
1 parent 26d9cb5 commit a03eb19

20 files changed

+442
-30
lines changed

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -199,14 +199,14 @@ class SourceClassBuilder extends ClassBuilderImpl
199199

200200
scope.forEach(buildBuilders);
201201
constructors.forEach(buildBuilders);
202-
if (supertypeBuilder != null) {
203-
supertypeBuilder = _checkSupertype(supertypeBuilder!);
204-
}
205202
if (isEnumMixin) {
206203
assert(supertypeBuilder?.name == "_Enum");
207204
supertypeBuilder?.resolveIn(coreLibrary.scope,
208205
supertypeBuilder?.charOffset ?? charOffset, fileUri, library);
209206
}
207+
if (supertypeBuilder != null) {
208+
supertypeBuilder = _checkSupertype(supertypeBuilder!);
209+
}
210210
Supertype? supertype =
211211
supertypeBuilder?.buildSupertype(library, charOffset, fileUri);
212212
if (supertype != null) {

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

Lines changed: 16 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -6,30 +6,7 @@ library fasta.enum_builder;
66

77
import 'package:_fe_analyzer_shared/src/scanner/token.dart';
88

9-
import 'package:kernel/ast.dart'
10-
show
11-
Arguments,
12-
AsyncMarker,
13-
Class,
14-
Constructor,
15-
ConstructorInvocation,
16-
DartType,
17-
Expression,
18-
Field,
19-
InstanceAccessKind,
20-
InstanceGet,
21-
IntLiteral,
22-
ListLiteral,
23-
Name,
24-
ProcedureKind,
25-
Reference,
26-
ReturnStatement,
27-
StaticGet,
28-
StringConcatenation,
29-
StringLiteral,
30-
SuperInitializer,
31-
ThisExpression,
32-
setParents;
9+
import 'package:kernel/ast.dart';
3310
import 'package:kernel/class_hierarchy.dart';
3411
import 'package:kernel/reference_from_index.dart' show IndexedClass;
3512

@@ -594,24 +571,37 @@ class SourceEnumBuilder extends SourceClassBuilder {
594571
}
595572
}
596573
BodyBuilder? bodyBuilder;
597-
if (enumConstantInfo.argumentsBeginToken != null) {
574+
if (enumConstantInfo.argumentsBeginToken != null ||
575+
typeArgumentBuilders == null && cls.typeParameters.isNotEmpty) {
576+
// We need to create a BodyBuilder in two cases: 1) if the
577+
// arguments token is provided, we'll use the BodyBuilder to
578+
// parse them and perform inference, 2) if the type arguments
579+
// aren't provided, but required, we'll use it to infer them.
598580
bodyBuilder = library.loader
599581
.createBodyBuilderForOutlineExpression(
600582
library, this, this, scope, fileUri);
601583
bodyBuilder.constantContext = ConstantContext.required;
602-
arguments = bodyBuilder
584+
}
585+
586+
if (enumConstantInfo.argumentsBeginToken != null) {
587+
arguments = bodyBuilder!
603588
.parseArguments(enumConstantInfo.argumentsBeginToken!);
604589
bodyBuilder.performBacklogComputations(delayedActionPerformers);
605590

606591
arguments.positional.insertAll(0, enumSyntheticArguments);
607592
} else {
608593
arguments = new ArgumentsImpl(enumSyntheticArguments);
609594
}
595+
610596
if (typeArguments != null && arguments is ArgumentsImpl) {
611597
ArgumentsImpl.setNonInferrableArgumentTypes(
612598
arguments, typeArguments);
599+
} else if (cls.typeParameters.isNotEmpty) {
600+
arguments.types.addAll(new List<DartType>.filled(
601+
cls.typeParameters.length, const UnknownType()));
613602
}
614603
setParents(enumSyntheticArguments, arguments);
604+
615605
Expression initializer = new ConstructorInvocation(
616606
constructorBuilder.constructor, arguments,
617607
isConst: true)

pkg/front_end/test/spell_checking_list_tests.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -491,6 +491,8 @@ gesture
491491
getter1c
492492
getter1d
493493
getter1e
494+
gi
495+
gm
494496
goo
495497
google
496498
graphic

pkg/front_end/testcases/enhanced_enums/inference_in_constructor_parameters.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,8 @@ enum E2<X> {
1616
const E2(X f);
1717
}
1818

19+
enum E3<X extends num, Y extends String, Z extends Function(X, Y)> {
20+
element
21+
}
22+
1923
main() {}

pkg/front_end/testcases/enhanced_enums/inference_in_constructor_parameters.dart.strong.expect

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,15 @@ class E2<X extends core::Object? = dynamic> extends core::_Enum /*isEnum*/ {
2020
method toString() → core::String
2121
return "E2.${this.{core::_Enum::_name}{core::String}}";
2222
}
23+
class E3<X extends core::num, Y extends core::String, Z extends (self::E3::X, self::E3::Y) → dynamic = (Never, Never) → dynamic> extends core::_Enum /*isEnum*/ {
24+
static const field core::List<self::E3<core::num, core::String, (Never, Never) → dynamic>> values = #C9;
25+
static const field self::E3<core::num, core::String, (core::num, core::String) → dynamic> element = #C8;
26+
const constructor •(core::int index, core::String name) → self::E3<self::E3::X, self::E3::Y, self::E3::Z>
27+
: super core::_Enum::•(index, name)
28+
;
29+
method toString() → core::String
30+
return "E3.${this.{core::_Enum::_name}{core::String}}";
31+
}
2332
static method foo<X extends core::Object? = dynamic>(self::foo::X% x) → self::foo::X%
2433
return x;
2534
static method main() → dynamic {}
@@ -31,6 +40,9 @@ constants {
3140
#C4 = <self::E1>[#C3]
3241
#C5 = self::E2<<X extends core::Object? = dynamic>(X%) → X%> {index:#C1, _name:#C2}
3342
#C6 = <self::E2<dynamic>>[#C5]
43+
#C7 = "element"
44+
#C8 = self::E3<core::num, core::String, (core::num, core::String) → dynamic> {index:#C1, _name:#C7}
45+
#C9 = <self::E3<dynamic, dynamic, dynamic>>[#C8]
3446
}
3547

3648

@@ -40,3 +52,4 @@ org-dartlang-testcase:///inference_in_constructor_parameters.dart:
4052
- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
4153
- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
4254
- E2. (from org-dartlang-testcase:///inference_in_constructor_parameters.dart:16:9)
55+
- E3. (from org-dartlang-testcase:///inference_in_constructor_parameters.dart:19:6)

pkg/front_end/testcases/enhanced_enums/inference_in_constructor_parameters.dart.strong.transformed.expect

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,15 @@ class E2<X extends core::Object? = dynamic> extends core::_Enum /*isEnum*/ {
2020
method toString() → core::String
2121
return "E2.${this.{core::_Enum::_name}{core::String}}";
2222
}
23+
class E3<X extends core::num, Y extends core::String, Z extends (self::E3::X, self::E3::Y) → dynamic = (Never, Never) → dynamic> extends core::_Enum /*isEnum*/ {
24+
static const field core::List<self::E3<core::num, core::String, (Never, Never) → dynamic>> values = #C9;
25+
static const field self::E3<core::num, core::String, (core::num, core::String) → dynamic> element = #C8;
26+
const constructor •(core::int index, core::String name) → self::E3<self::E3::X, self::E3::Y, self::E3::Z>
27+
: super core::_Enum::•(index, name)
28+
;
29+
method toString() → core::String
30+
return "E3.${this.{core::_Enum::_name}{core::String}}";
31+
}
2332
static method foo<X extends core::Object? = dynamic>(self::foo::X% x) → self::foo::X%
2433
return x;
2534
static method main() → dynamic {}
@@ -31,6 +40,9 @@ constants {
3140
#C4 = <self::E1>[#C3]
3241
#C5 = self::E2<<X extends core::Object? = dynamic>(X%) → X%> {index:#C1, _name:#C2}
3342
#C6 = <self::E2<dynamic>>[#C5]
43+
#C7 = "element"
44+
#C8 = self::E3<core::num, core::String, (core::num, core::String) → dynamic> {index:#C1, _name:#C7}
45+
#C9 = <self::E3<dynamic, dynamic, dynamic>>[#C8]
3446
}
3547

3648

@@ -40,3 +52,4 @@ org-dartlang-testcase:///inference_in_constructor_parameters.dart:
4052
- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
4153
- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
4254
- E2. (from org-dartlang-testcase:///inference_in_constructor_parameters.dart:16:9)
55+
- E3. (from org-dartlang-testcase:///inference_in_constructor_parameters.dart:19:6)
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
X foo<X>(X x) => x;
22
enum E1 { bar(foo); const E1(int Function(int) f); }
33
enum E2<X> { bar(foo); const E2(X f); }
4+
enum E3<X extends num, Y extends String, Z extends Function(X, Y)> { element }
45
main() {}

pkg/front_end/testcases/enhanced_enums/inference_in_constructor_parameters.dart.weak.expect

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,15 @@ class E2<X extends core::Object? = dynamic> extends core::_Enum /*isEnum*/ {
2020
method toString() → core::String
2121
return "E2.${this.{core::_Enum::_name}{core::String}}";
2222
}
23+
class E3<X extends core::num, Y extends core::String, Z extends (self::E3::X, self::E3::Y) → dynamic = (Never, Never) → dynamic> extends core::_Enum /*isEnum*/ {
24+
static const field core::List<self::E3<core::num, core::String, (Never, Never) → dynamic>> values = #C9;
25+
static const field self::E3<core::num, core::String, (core::num, core::String) → dynamic> element = #C8;
26+
const constructor •(core::int index, core::String name) → self::E3<self::E3::X, self::E3::Y, self::E3::Z>
27+
: super core::_Enum::•(index, name)
28+
;
29+
method toString() → core::String
30+
return "E3.${this.{core::_Enum::_name}{core::String}}";
31+
}
2332
static method foo<X extends core::Object? = dynamic>(self::foo::X% x) → self::foo::X%
2433
return x;
2534
static method main() → dynamic {}
@@ -31,6 +40,9 @@ constants {
3140
#C4 = <self::E1*>[#C3]
3241
#C5 = self::E2<<X extends core::Object? = dynamic>(X*) →* X*> {index:#C1, _name:#C2}
3342
#C6 = <self::E2<dynamic>*>[#C5]
43+
#C7 = "element"
44+
#C8 = self::E3<core::num*, core::String*, (core::num*, core::String*) →* dynamic> {index:#C1, _name:#C7}
45+
#C9 = <self::E3<dynamic, dynamic, dynamic>*>[#C8]
3446
}
3547

3648

@@ -40,3 +52,4 @@ org-dartlang-testcase:///inference_in_constructor_parameters.dart:
4052
- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
4153
- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
4254
- E2. (from org-dartlang-testcase:///inference_in_constructor_parameters.dart:16:9)
55+
- E3. (from org-dartlang-testcase:///inference_in_constructor_parameters.dart:19:6)

pkg/front_end/testcases/enhanced_enums/inference_in_constructor_parameters.dart.weak.modular.expect

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,15 @@ class E2<X extends core::Object? = dynamic> extends core::_Enum /*isEnum*/ {
2020
method toString() → core::String
2121
return "E2.${this.{core::_Enum::_name}{core::String}}";
2222
}
23+
class E3<X extends core::num, Y extends core::String, Z extends (self::E3::X, self::E3::Y) → dynamic = (Never, Never) → dynamic> extends core::_Enum /*isEnum*/ {
24+
static const field core::List<self::E3<core::num, core::String, (Never, Never) → dynamic>> values = #C9;
25+
static const field self::E3<core::num, core::String, (core::num, core::String) → dynamic> element = #C8;
26+
const constructor •(core::int index, core::String name) → self::E3<self::E3::X, self::E3::Y, self::E3::Z>
27+
: super core::_Enum::•(index, name)
28+
;
29+
method toString() → core::String
30+
return "E3.${this.{core::_Enum::_name}{core::String}}";
31+
}
2332
static method foo<X extends core::Object? = dynamic>(self::foo::X% x) → self::foo::X%
2433
return x;
2534
static method main() → dynamic {}
@@ -31,6 +40,9 @@ constants {
3140
#C4 = <self::E1*>[#C3]
3241
#C5 = self::E2<<X extends core::Object? = dynamic>(X*) →* X*> {index:#C1, _name:#C2}
3342
#C6 = <self::E2<dynamic>*>[#C5]
43+
#C7 = "element"
44+
#C8 = self::E3<core::num*, core::String*, (core::num*, core::String*) →* dynamic> {index:#C1, _name:#C7}
45+
#C9 = <self::E3<dynamic, dynamic, dynamic>*>[#C8]
3446
}
3547

3648

@@ -40,3 +52,4 @@ org-dartlang-testcase:///inference_in_constructor_parameters.dart:
4052
- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
4153
- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
4254
- E2. (from org-dartlang-testcase:///inference_in_constructor_parameters.dart:16:9)
55+
- E3. (from org-dartlang-testcase:///inference_in_constructor_parameters.dart:19:6)

pkg/front_end/testcases/enhanced_enums/inference_in_constructor_parameters.dart.weak.outline.expect

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,15 @@ class E2<X extends core::Object? = dynamic> extends core::_Enum /*isEnum*/ {
2020
method toString() → core::String
2121
return "E2.${this.{core::_Enum::_name}{core::String}}";
2222
}
23+
class E3<X extends core::num, Y extends core::String, Z extends (self::E3::X, self::E3::Y) → dynamic = (Never, Never) → dynamic> extends core::_Enum /*isEnum*/ {
24+
static const field core::List<self::E3<core::num, core::String, (Never, Never) → dynamic>> values = const <self::E3<dynamic, dynamic, dynamic>>[self::E3::element];
25+
static const field self::E3<core::num, core::String, (core::num, core::String) → dynamic> element = const self::E3::•<core::num, core::String, (core::num, core::String) → dynamic>(0, "element");
26+
const constructor •(core::int index, core::String name) → self::E3<self::E3::X, self::E3::Y, self::E3::Z>
27+
: super core::_Enum::•(index, name)
28+
;
29+
method toString() → core::String
30+
return "E3.${this.{core::_Enum::_name}{core::String}}";
31+
}
2332
static method foo<X extends core::Object? = dynamic>(self::foo::X% x) → self::foo::X%
2433
;
2534
static method main() → dynamic
@@ -31,4 +40,6 @@ Evaluated: ListLiteral @ org-dartlang-testcase:///inference_in_constructor_param
3140
Evaluated: ConstructorInvocation @ org-dartlang-testcase:///inference_in_constructor_parameters.dart:8:3 -> InstanceConstant(const E1{_Enum.index: 0, _Enum._name: "bar"})
3241
Evaluated: ListLiteral @ org-dartlang-testcase:///inference_in_constructor_parameters.dart:13:6 -> ListConstant(const <E2<dynamic>*>[const E2<X* Function<X>(X*)*>{_Enum.index: 0, _Enum._name: "bar"}])
3342
Evaluated: ConstructorInvocation @ org-dartlang-testcase:///inference_in_constructor_parameters.dart:14:3 -> InstanceConstant(const E2<X* Function<X>(X*)*>{_Enum.index: 0, _Enum._name: "bar"})
34-
Extra constant evaluation: evaluated: 14, effectively constant: 4
43+
Evaluated: ListLiteral @ org-dartlang-testcase:///inference_in_constructor_parameters.dart:19:6 -> ListConstant(const <E3<dynamic, dynamic, dynamic>*>[const E3<num*, String*, dynamic Function(num*, String*)*>{_Enum.index: 0, _Enum._name: "element"}])
44+
Evaluated: ConstructorInvocation @ org-dartlang-testcase:///inference_in_constructor_parameters.dart:20:3 -> InstanceConstant(const E3<num*, String*, dynamic Function(num*, String*)*>{_Enum.index: 0, _Enum._name: "element"})
45+
Extra constant evaluation: evaluated: 21, effectively constant: 6

pkg/front_end/testcases/enhanced_enums/inference_in_constructor_parameters.dart.weak.transformed.expect

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,15 @@ class E2<X extends core::Object? = dynamic> extends core::_Enum /*isEnum*/ {
2020
method toString() → core::String
2121
return "E2.${this.{core::_Enum::_name}{core::String}}";
2222
}
23+
class E3<X extends core::num, Y extends core::String, Z extends (self::E3::X, self::E3::Y) → dynamic = (Never, Never) → dynamic> extends core::_Enum /*isEnum*/ {
24+
static const field core::List<self::E3<core::num, core::String, (Never, Never) → dynamic>> values = #C9;
25+
static const field self::E3<core::num, core::String, (core::num, core::String) → dynamic> element = #C8;
26+
const constructor •(core::int index, core::String name) → self::E3<self::E3::X, self::E3::Y, self::E3::Z>
27+
: super core::_Enum::•(index, name)
28+
;
29+
method toString() → core::String
30+
return "E3.${this.{core::_Enum::_name}{core::String}}";
31+
}
2332
static method foo<X extends core::Object? = dynamic>(self::foo::X% x) → self::foo::X%
2433
return x;
2534
static method main() → dynamic {}
@@ -31,6 +40,9 @@ constants {
3140
#C4 = <self::E1*>[#C3]
3241
#C5 = self::E2<<X extends core::Object? = dynamic>(X*) →* X*> {index:#C1, _name:#C2}
3342
#C6 = <self::E2<dynamic>*>[#C5]
43+
#C7 = "element"
44+
#C8 = self::E3<core::num*, core::String*, (core::num*, core::String*) →* dynamic> {index:#C1, _name:#C7}
45+
#C9 = <self::E3<dynamic, dynamic, dynamic>*>[#C8]
3446
}
3547

3648

@@ -40,3 +52,4 @@ org-dartlang-testcase:///inference_in_constructor_parameters.dart:
4052
- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
4153
- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
4254
- E2. (from org-dartlang-testcase:///inference_in_constructor_parameters.dart:16:9)
55+
- E3. (from org-dartlang-testcase:///inference_in_constructor_parameters.dart:19:6)
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
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+
// The test checks an execution path where _Enum as supertype was checked before
6+
// being resolved.
7+
8+
mixin GM<T> on Enum {}
9+
10+
mixin M on Object {}
11+
12+
abstract class I {}
13+
14+
abstract class GI<T> {}
15+
16+
enum E<S extends num, T extends num>
17+
with GM<T>, M
18+
implements I, GI<S> { element }
19+
20+
main() {}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
library /*isNonNullableByDefault*/;
2+
import self as self;
3+
import "dart:core" as core;
4+
5+
abstract class GM<T extends core::Object? = dynamic> extends core::Enum /*isMixinDeclaration*/ {
6+
}
7+
abstract class M extends core::Object /*isMixinDeclaration*/ {
8+
}
9+
abstract class I extends core::Object {
10+
synthetic constructor •() → self::I
11+
: super core::Object::•()
12+
;
13+
}
14+
abstract class GI<T extends core::Object? = dynamic> extends core::Object {
15+
synthetic constructor •() → self::GI<self::GI::T%>
16+
: super core::Object::•()
17+
;
18+
}
19+
abstract class _E&_Enum&GM<S extends core::num, T extends core::num> = core::_Enum with self::GM<self::_E&_Enum&GM::T> /*isAnonymousMixin,hasConstConstructor*/ {
20+
const synthetic constructor •(core::int index, core::String _name) → self::_E&_Enum&GM<self::_E&_Enum&GM::S, self::_E&_Enum&GM::T>
21+
: super core::_Enum::•(index, _name)
22+
;
23+
}
24+
abstract class _E&_Enum&GM&M<S extends core::num, T extends core::num> = self::_E&_Enum&GM<self::_E&_Enum&GM&M::S, self::_E&_Enum&GM&M::T> with self::M /*isAnonymousMixin,hasConstConstructor*/ {
25+
const synthetic constructor •(core::int index, core::String _name) → self::_E&_Enum&GM&M<self::_E&_Enum&GM&M::S, self::_E&_Enum&GM&M::T>
26+
: super self::_E&_Enum&GM::•(index, _name)
27+
;
28+
}
29+
class E<S extends core::num, T extends core::num> extends self::_E&_Enum&GM&M<self::E::S, self::E::T> implements self::I, self::GI<self::E::S> /*isEnum*/ {
30+
static const field core::List<self::E<core::num, core::num>> values = #C4;
31+
static const field self::E<core::num, core::num> element = #C3;
32+
const constructor •(core::int index, core::String name) → self::E<self::E::S, self::E::T>
33+
: super self::_E&_Enum&GM&M::•(index, name)
34+
;
35+
method toString() → core::String
36+
;
37+
}
38+
static method main() → dynamic {}
39+
40+
constants {
41+
#C1 = 0
42+
#C2 = "element"
43+
#C3 = self::E<core::num, core::num> {index:#C1, _name:#C2}
44+
#C4 = <self::E<dynamic, dynamic>>[#C3]
45+
}
46+
47+
48+
Constructor coverage from constants:
49+
org-dartlang-testcase:///supertype_resolved_before_checking.dart:
50+
- E. (from org-dartlang-testcase:///supertype_resolved_before_checking.dart:16:6)
51+
- _E&_Enum&GM&M. (from org-dartlang-testcase:///supertype_resolved_before_checking.dart:16:6)
52+
- _E&_Enum&GM. (from org-dartlang-testcase:///supertype_resolved_before_checking.dart:16:6)
53+
- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
54+
- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)

0 commit comments

Comments
 (0)