Skip to content

Commit c688bc8

Browse files
chloestefantsovaCommit Queue
authored and
Commit Queue
committed
[cfe] Implement relaxed rule on representation/implemented types
Closes #53867 Part of #49731 Change-Id: I1a286a8f507e92f85a79acb18d124d3322e1daa5 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/332961 Commit-Queue: Chloe Stefantsova <[email protected]> Reviewed-by: Johnni Winther <[email protected]>
1 parent 9ed368c commit c688bc8

18 files changed

+611
-32
lines changed

pkg/front_end/lib/src/fasta/fasta_codes_cfe_generated.dart

+2-2
Original file line numberDiff line numberDiff line change
@@ -2799,7 +2799,7 @@ const Template<
27992799
DartType _type3, bool isNonNullableByDefault)>(
28002800
"InvalidExtensionTypeSuperExtensionType",
28012801
problemMessageTemplate:
2802-
r"""The representation type '#type' of extension type '#name' must be a subtype of the representation type '#type2' of the implemented extension type '#type3'.""",
2802+
r"""The representation type '#type' of extension type '#name' must be either a subtype of the representation type '#type2' of the implemented extension type '#type3' or a subtype of '#type3' itself.""",
28032803
correctionMessageTemplate:
28042804
r"""Try changing the representation type to a subtype of '#type2'.""",
28052805
withArguments: _withArgumentsInvalidExtensionTypeSuperExtensionType);
@@ -2832,7 +2832,7 @@ Message _withArgumentsInvalidExtensionTypeSuperExtensionType(
28322832
String type3 = type3Parts.join();
28332833
return new Message(codeInvalidExtensionTypeSuperExtensionType,
28342834
problemMessage:
2835-
"""The representation type '${type}' of extension type '${name}' must be a subtype of the representation type '${type2}' of the implemented extension type '${type3}'.""" +
2835+
"""The representation type '${type}' of extension type '${name}' must be either a subtype of the representation type '${type2}' of the implemented extension type '${type3}' or a subtype of '${type3}' itself.""" +
28362836
labeler.originMessages,
28372837
correctionMessage: """Try changing the representation type to a subtype of '${type2}'.""",
28382838
arguments: {

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

+21-17
Original file line numberDiff line numberDiff line change
@@ -458,23 +458,27 @@ class SourceExtensionTypeDeclarationBuilder
458458
typeBuilder.fileUri);
459459
}
460460
} else if (interface is ExtensionType) {
461-
DartType instantiatedRepresentationType =
462-
Substitution.fromExtensionType(interface).substituteType(interface
463-
.extensionTypeDeclaration.declaredRepresentationType);
464-
if (!hierarchyBuilder.types.isSubtypeOf(
465-
declaredRepresentationType,
466-
instantiatedRepresentationType,
467-
SubtypeCheckMode.withNullabilities)) {
468-
libraryBuilder.addProblem(
469-
templateInvalidExtensionTypeSuperExtensionType.withArguments(
470-
declaredRepresentationType,
471-
name,
472-
instantiatedRepresentationType,
473-
interface,
474-
true),
475-
typeBuilder.charOffset!,
476-
noLength,
477-
typeBuilder.fileUri);
461+
if (!hierarchyBuilder.types.isSubtypeOf(declaredRepresentationType,
462+
interface, SubtypeCheckMode.withNullabilities)) {
463+
DartType instantiatedImplementedRepresentationType =
464+
Substitution.fromExtensionType(interface).substituteType(
465+
interface
466+
.extensionTypeDeclaration.declaredRepresentationType);
467+
if (!hierarchyBuilder.types.isSubtypeOf(
468+
declaredRepresentationType,
469+
instantiatedImplementedRepresentationType,
470+
SubtypeCheckMode.withNullabilities)) {
471+
libraryBuilder.addProblem(
472+
templateInvalidExtensionTypeSuperExtensionType.withArguments(
473+
declaredRepresentationType,
474+
name,
475+
instantiatedImplementedRepresentationType,
476+
interface,
477+
true),
478+
typeBuilder.charOffset!,
479+
noLength,
480+
typeBuilder.fileUri);
481+
}
478482
}
479483
}
480484
}

pkg/front_end/messages.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -7309,7 +7309,7 @@ InvalidExtensionTypeSuperInterface:
73097309
extension type E(num n) implements int {}
73107310
73117311
InvalidExtensionTypeSuperExtensionType:
7312-
problemMessage: "The representation type '#type' of extension type '#name' must be a subtype of the representation type '#type2' of the implemented extension type '#type3'."
7312+
problemMessage: "The representation type '#type' of extension type '#name' must be either a subtype of the representation type '#type2' of the implemented extension type '#type3' or a subtype of '#type3' itself."
73137313
correctionMessage: "Try changing the representation type to a subtype of '#type2'."
73147314
experiments: inline-class
73157315
script: |

pkg/front_end/testcases/extension_types/issue53170.dart.strong.expect

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@ library;
77
// extension type S1(num id) implements String /* Error */ {}
88
// ^
99
//
10-
// pkg/front_end/testcases/extension_types/issue53170.dart:11:41: Error: The representation type 'String' of extension type 'V2' must be a subtype of the representation type 'num' of the implemented extension type 'V1'.
10+
// pkg/front_end/testcases/extension_types/issue53170.dart:11:41: Error: The representation type 'String' of extension type 'V2' must be either a subtype of the representation type 'num' of the implemented extension type 'V1' or a subtype of 'V1' itself.
1111
// Try changing the representation type to a subtype of 'num'.
1212
// extension type V2(String id) implements V1 /* Error */ {}
1313
// ^
1414
//
15-
// pkg/front_end/testcases/extension_types/issue53170.dart:17:41: Error: The representation type 'String' of extension type 'W2' must be a subtype of the representation type 'num' of the implemented extension type 'W1<num>'.
15+
// pkg/front_end/testcases/extension_types/issue53170.dart:17:41: Error: The representation type 'String' of extension type 'W2' must be either a subtype of the representation type 'num' of the implemented extension type 'W1<num>' or a subtype of 'W1<num>' itself.
1616
// Try changing the representation type to a subtype of 'num'.
1717
// extension type W2(String id) implements W1<num> /* Error */ {}
1818
// ^

pkg/front_end/testcases/extension_types/issue53170.dart.strong.transformed.expect

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@ library;
77
// extension type S1(num id) implements String /* Error */ {}
88
// ^
99
//
10-
// pkg/front_end/testcases/extension_types/issue53170.dart:11:41: Error: The representation type 'String' of extension type 'V2' must be a subtype of the representation type 'num' of the implemented extension type 'V1'.
10+
// pkg/front_end/testcases/extension_types/issue53170.dart:11:41: Error: The representation type 'String' of extension type 'V2' must be either a subtype of the representation type 'num' of the implemented extension type 'V1' or a subtype of 'V1' itself.
1111
// Try changing the representation type to a subtype of 'num'.
1212
// extension type V2(String id) implements V1 /* Error */ {}
1313
// ^
1414
//
15-
// pkg/front_end/testcases/extension_types/issue53170.dart:17:41: Error: The representation type 'String' of extension type 'W2' must be a subtype of the representation type 'num' of the implemented extension type 'W1<num>'.
15+
// pkg/front_end/testcases/extension_types/issue53170.dart:17:41: Error: The representation type 'String' of extension type 'W2' must be either a subtype of the representation type 'num' of the implemented extension type 'W1<num>' or a subtype of 'W1<num>' itself.
1616
// Try changing the representation type to a subtype of 'num'.
1717
// extension type W2(String id) implements W1<num> /* Error */ {}
1818
// ^

pkg/front_end/testcases/extension_types/issue53170.dart.weak.expect

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@ library;
77
// extension type S1(num id) implements String /* Error */ {}
88
// ^
99
//
10-
// pkg/front_end/testcases/extension_types/issue53170.dart:11:41: Error: The representation type 'String' of extension type 'V2' must be a subtype of the representation type 'num' of the implemented extension type 'V1'.
10+
// pkg/front_end/testcases/extension_types/issue53170.dart:11:41: Error: The representation type 'String' of extension type 'V2' must be either a subtype of the representation type 'num' of the implemented extension type 'V1' or a subtype of 'V1' itself.
1111
// Try changing the representation type to a subtype of 'num'.
1212
// extension type V2(String id) implements V1 /* Error */ {}
1313
// ^
1414
//
15-
// pkg/front_end/testcases/extension_types/issue53170.dart:17:41: Error: The representation type 'String' of extension type 'W2' must be a subtype of the representation type 'num' of the implemented extension type 'W1<num>'.
15+
// pkg/front_end/testcases/extension_types/issue53170.dart:17:41: Error: The representation type 'String' of extension type 'W2' must be either a subtype of the representation type 'num' of the implemented extension type 'W1<num>' or a subtype of 'W1<num>' itself.
1616
// Try changing the representation type to a subtype of 'num'.
1717
// extension type W2(String id) implements W1<num> /* Error */ {}
1818
// ^

pkg/front_end/testcases/extension_types/issue53170.dart.weak.modular.expect

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@ library;
77
// extension type S1(num id) implements String /* Error */ {}
88
// ^
99
//
10-
// pkg/front_end/testcases/extension_types/issue53170.dart:11:41: Error: The representation type 'String' of extension type 'V2' must be a subtype of the representation type 'num' of the implemented extension type 'V1'.
10+
// pkg/front_end/testcases/extension_types/issue53170.dart:11:41: Error: The representation type 'String' of extension type 'V2' must be either a subtype of the representation type 'num' of the implemented extension type 'V1' or a subtype of 'V1' itself.
1111
// Try changing the representation type to a subtype of 'num'.
1212
// extension type V2(String id) implements V1 /* Error */ {}
1313
// ^
1414
//
15-
// pkg/front_end/testcases/extension_types/issue53170.dart:17:41: Error: The representation type 'String' of extension type 'W2' must be a subtype of the representation type 'num' of the implemented extension type 'W1<num>'.
15+
// pkg/front_end/testcases/extension_types/issue53170.dart:17:41: Error: The representation type 'String' of extension type 'W2' must be either a subtype of the representation type 'num' of the implemented extension type 'W1<num>' or a subtype of 'W1<num>' itself.
1616
// Try changing the representation type to a subtype of 'num'.
1717
// extension type W2(String id) implements W1<num> /* Error */ {}
1818
// ^

pkg/front_end/testcases/extension_types/issue53170.dart.weak.outline.expect

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@ library;
77
// extension type S1(num id) implements String /* Error */ {}
88
// ^
99
//
10-
// pkg/front_end/testcases/extension_types/issue53170.dart:11:41: Error: The representation type 'String' of extension type 'V2' must be a subtype of the representation type 'num' of the implemented extension type 'V1'.
10+
// pkg/front_end/testcases/extension_types/issue53170.dart:11:41: Error: The representation type 'String' of extension type 'V2' must be either a subtype of the representation type 'num' of the implemented extension type 'V1' or a subtype of 'V1' itself.
1111
// Try changing the representation type to a subtype of 'num'.
1212
// extension type V2(String id) implements V1 /* Error */ {}
1313
// ^
1414
//
15-
// pkg/front_end/testcases/extension_types/issue53170.dart:17:41: Error: The representation type 'String' of extension type 'W2' must be a subtype of the representation type 'num' of the implemented extension type 'W1<num>'.
15+
// pkg/front_end/testcases/extension_types/issue53170.dart:17:41: Error: The representation type 'String' of extension type 'W2' must be either a subtype of the representation type 'num' of the implemented extension type 'W1<num>' or a subtype of 'W1<num>' itself.
1616
// Try changing the representation type to a subtype of 'num'.
1717
// extension type W2(String id) implements W1<num> /* Error */ {}
1818
// ^

pkg/front_end/testcases/extension_types/issue53170.dart.weak.transformed.expect

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@ library;
77
// extension type S1(num id) implements String /* Error */ {}
88
// ^
99
//
10-
// pkg/front_end/testcases/extension_types/issue53170.dart:11:41: Error: The representation type 'String' of extension type 'V2' must be a subtype of the representation type 'num' of the implemented extension type 'V1'.
10+
// pkg/front_end/testcases/extension_types/issue53170.dart:11:41: Error: The representation type 'String' of extension type 'V2' must be either a subtype of the representation type 'num' of the implemented extension type 'V1' or a subtype of 'V1' itself.
1111
// Try changing the representation type to a subtype of 'num'.
1212
// extension type V2(String id) implements V1 /* Error */ {}
1313
// ^
1414
//
15-
// pkg/front_end/testcases/extension_types/issue53170.dart:17:41: Error: The representation type 'String' of extension type 'W2' must be a subtype of the representation type 'num' of the implemented extension type 'W1<num>'.
15+
// pkg/front_end/testcases/extension_types/issue53170.dart:17:41: Error: The representation type 'String' of extension type 'W2' must be either a subtype of the representation type 'num' of the implemented extension type 'W1<num>' or a subtype of 'W1<num>' itself.
1616
// Try changing the representation type to a subtype of 'num'.
1717
// extension type W2(String id) implements W1<num> /* Error */ {}
1818
// ^
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// Copyright (c) 2023, 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+
extension type E1(num it) {}
6+
extension type E2(E1 it) implements E1 {} // Ok.
7+
extension type E3(int it) implements E1 {} // Ok.
8+
extension type E4(E3 it) implements E1 {} // Ok.
9+
extension type E5(E3 it) implements E2 {} // Ok.
10+
extension type E6(E2 it) implements E3 {} // Error.
11+
extension type E7(String it) implements E1 {} // Error.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
library;
2+
//
3+
// Problems in library:
4+
//
5+
// pkg/front_end/testcases/extension_types/issue53867.dart:10:37: Error: The representation type 'E2' of extension type 'E6' must be either a subtype of the representation type 'int' of the implemented extension type 'E3' or a subtype of 'E3' itself.
6+
// Try changing the representation type to a subtype of 'int'.
7+
// extension type E6(E2 it) implements E3 {} // Error.
8+
// ^
9+
//
10+
// pkg/front_end/testcases/extension_types/issue53867.dart:11:41: Error: The representation type 'String' of extension type 'E7' must be either a subtype of the representation type 'num' of the implemented extension type 'E1' or a subtype of 'E1' itself.
11+
// Try changing the representation type to a subtype of 'num'.
12+
// extension type E7(String it) implements E1 {} // Error.
13+
// ^
14+
//
15+
import self as self;
16+
import "dart:core" as core;
17+
18+
extension type E1(core::num it) {
19+
abstract inline-class-member representation-field get it() → core::num;
20+
constructor • = self::E1|constructor#;
21+
constructor tearoff • = self::E1|constructor#_#new#tearOff;
22+
}
23+
extension type E2(self::E1 /* = core::num */ it) implements self::E1 /* = core::num */ {
24+
abstract inline-class-member representation-field get it() → self::E1 /* = core::num */;
25+
constructor • = self::E2|constructor#;
26+
constructor tearoff • = self::E2|constructor#_#new#tearOff;
27+
}
28+
extension type E3(core::int it) implements self::E1 /* = core::num */ {
29+
abstract inline-class-member representation-field get it() → core::int;
30+
constructor • = self::E3|constructor#;
31+
constructor tearoff • = self::E3|constructor#_#new#tearOff;
32+
}
33+
extension type E4(self::E3 /* = core::int */ it) implements self::E1 /* = core::num */ {
34+
abstract inline-class-member representation-field get it() → self::E3 /* = core::int */;
35+
constructor • = self::E4|constructor#;
36+
constructor tearoff • = self::E4|constructor#_#new#tearOff;
37+
}
38+
extension type E5(self::E3 /* = core::int */ it) implements self::E2 /* = core::num */ {
39+
abstract inline-class-member representation-field get it() → self::E3 /* = core::int */;
40+
constructor • = self::E5|constructor#;
41+
constructor tearoff • = self::E5|constructor#_#new#tearOff;
42+
}
43+
extension type E6(self::E2 /* = core::num */ it) implements self::E3 /* = core::int */ {
44+
abstract inline-class-member representation-field get it() → self::E2 /* = core::num */;
45+
constructor • = self::E6|constructor#;
46+
constructor tearoff • = self::E6|constructor#_#new#tearOff;
47+
}
48+
extension type E7(core::String it) implements self::E1 /* = core::num */ {
49+
abstract inline-class-member representation-field get it() → core::String;
50+
constructor • = self::E7|constructor#;
51+
constructor tearoff • = self::E7|constructor#_#new#tearOff;
52+
}
53+
static inline-class-member method E1|constructor#(core::num it) → self::E1 /* = core::num */ {
54+
lowered final self::E1 /* = core::num */ #this = it;
55+
return #this;
56+
}
57+
static inline-class-member method E1|constructor#_#new#tearOff(core::num it) → self::E1 /* = core::num */
58+
return self::E1|constructor#(it);
59+
static inline-class-member method E2|constructor#(self::E1 /* = core::num */ it) → self::E2 /* = core::num */ {
60+
lowered final self::E2 /* = core::num */ #this = it;
61+
return #this;
62+
}
63+
static inline-class-member method E2|constructor#_#new#tearOff(self::E1 /* = core::num */ it) → self::E2 /* = core::num */
64+
return self::E2|constructor#(it);
65+
static inline-class-member method E3|constructor#(core::int it) → self::E3 /* = core::int */ {
66+
lowered final self::E3 /* = core::int */ #this = it;
67+
return #this;
68+
}
69+
static inline-class-member method E3|constructor#_#new#tearOff(core::int it) → self::E3 /* = core::int */
70+
return self::E3|constructor#(it);
71+
static inline-class-member method E4|constructor#(self::E3 /* = core::int */ it) → self::E4 /* = core::int */ {
72+
lowered final self::E4 /* = core::int */ #this = it;
73+
return #this;
74+
}
75+
static inline-class-member method E4|constructor#_#new#tearOff(self::E3 /* = core::int */ it) → self::E4 /* = core::int */
76+
return self::E4|constructor#(it);
77+
static inline-class-member method E5|constructor#(self::E3 /* = core::int */ it) → self::E5 /* = core::int */ {
78+
lowered final self::E5 /* = core::int */ #this = it;
79+
return #this;
80+
}
81+
static inline-class-member method E5|constructor#_#new#tearOff(self::E3 /* = core::int */ it) → self::E5 /* = core::int */
82+
return self::E5|constructor#(it);
83+
static inline-class-member method E6|constructor#(self::E2 /* = core::num */ it) → self::E6 /* = core::num */ {
84+
lowered final self::E6 /* = core::num */ #this = it;
85+
return #this;
86+
}
87+
static inline-class-member method E6|constructor#_#new#tearOff(self::E2 /* = core::num */ it) → self::E6 /* = core::num */
88+
return self::E6|constructor#(it);
89+
static inline-class-member method E7|constructor#(core::String it) → self::E7 /* = core::String */ {
90+
lowered final self::E7 /* = core::String */ #this = it;
91+
return #this;
92+
}
93+
static inline-class-member method E7|constructor#_#new#tearOff(core::String it) → self::E7 /* = core::String */
94+
return self::E7|constructor#(it);

0 commit comments

Comments
 (0)