Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 7e3310b

Browse files
author
Dart CI
committed
Version 2.17.0-93.0.dev
Merge commit 'f481cbf2fa27ca7d72ababdccc561b4465bd1660' into 'dev'
2 parents 516530f + f481cbf commit 7e3310b

23 files changed

+469
-96
lines changed

pkg/analyzer/lib/error/error.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,7 @@ const List<ErrorCode> errorCodeValues = [
162162
CompileTimeErrorCode.DUPLICATE_PART,
163163
CompileTimeErrorCode.ENUM_CONSTANT_SAME_NAME_AS_ENCLOSING,
164164
CompileTimeErrorCode.ENUM_CONSTANT_WITH_NON_CONST_CONSTRUCTOR,
165+
CompileTimeErrorCode.ENUM_INSTANTIATED_TO_BOUNDS_IS_NOT_WELL_BOUNDED,
165166
CompileTimeErrorCode.ENUM_MIXIN_WITH_INSTANCE_VARIABLE,
166167
CompileTimeErrorCode.ENUM_WITH_ABSTRACT_MEMBER,
167168
CompileTimeErrorCode.EQUAL_ELEMENTS_IN_CONST_SET,
@@ -478,6 +479,7 @@ const List<ErrorCode> errorCodeValues = [
478479
CompileTimeErrorCode.URI_WITH_INTERPOLATION,
479480
CompileTimeErrorCode.USE_OF_NATIVE_EXTENSION,
480481
CompileTimeErrorCode.USE_OF_VOID_RESULT,
482+
CompileTimeErrorCode.VALUES_DECLARATION_IN_ENUM,
481483
CompileTimeErrorCode.VARIABLE_TYPE_MISMATCH,
482484
CompileTimeErrorCode.WRONG_EXPLICIT_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE,
483485
CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR,

pkg/analyzer/lib/src/dart/analysis/index.dart

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -644,7 +644,7 @@ class _IndexContributor extends GeneralizingAstVisitor {
644644
}
645645

646646
@override
647-
visitEnumConstantDeclaration(node) {
647+
void visitEnumConstantDeclaration(EnumConstantDeclaration node) {
648648
var constructorElement = node.constructorElement;
649649
if (constructorElement != null) {
650650
int offset;
@@ -657,8 +657,15 @@ class _IndexContributor extends GeneralizingAstVisitor {
657657
offset = node.name.end;
658658
length = 0;
659659
}
660-
recordRelationOffset(constructorElement, IndexRelationKind.IS_INVOKED_BY,
661-
offset, length, true);
660+
recordRelationOffset(
661+
constructorElement,
662+
node.arguments == null
663+
? IndexRelationKind.IS_INVOKED_BY_ENUM_CONSTANT_WITHOUT_ARGUMENTS
664+
: IndexRelationKind.IS_INVOKED_BY,
665+
offset,
666+
length,
667+
true,
668+
);
662669
}
663670

664671
super.visitEnumConstantDeclaration(node);

pkg/analyzer/lib/src/dart/ast/ast.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3699,6 +3699,8 @@ abstract class ExpressionImpl extends AstNodeImpl
36993699
var parent = child.parent;
37003700
if (parent is ConstantContextForExpressionImpl) {
37013701
return true;
3702+
} else if (parent is EnumConstantArguments) {
3703+
return true;
37023704
} else if (parent is TypedLiteralImpl && parent.constKeyword != null) {
37033705
// Inside an explicitly `const` list or map literal.
37043706
return true;

pkg/analyzer/lib/src/dart/constant/constant_verifier.dart

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,16 @@ class ConstantVerifier extends RecursiveAstVisitor<void> {
119119
}
120120
}
121121

122+
@override
123+
visitEnumConstantDeclaration(node) {
124+
super.visitEnumConstantDeclaration(node);
125+
126+
var argumentList = node.arguments?.argumentList;
127+
if (argumentList != null) {
128+
_validateConstantArguments(argumentList);
129+
}
130+
}
131+
122132
@override
123133
void visitFunctionExpression(FunctionExpression node) {
124134
super.visitFunctionExpression(node);

pkg/analyzer/lib/src/dart/element/type_system.dart

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import 'package:analyzer/src/dart/element/type_demotion.dart';
3030
import 'package:analyzer/src/dart/element/type_provider.dart';
3131
import 'package:analyzer/src/dart/element/type_schema.dart';
3232
import 'package:analyzer/src/dart/element/type_schema_elimination.dart';
33+
import 'package:analyzer/src/dart/element/well_bounded.dart';
3334

3435
/// The [TypeSystem] implementation.
3536
class TypeSystemImpl implements TypeSystem {
@@ -1178,6 +1179,17 @@ class TypeSystemImpl implements TypeSystem {
11781179
return false;
11791180
}
11801181

1182+
/// See `15.2 Super-bounded types` in the language specification.
1183+
TypeBoundedResult isWellBounded(
1184+
DartType type, {
1185+
required bool allowSuperBounded,
1186+
}) {
1187+
return TypeBoundedHelper(this).isWellBounded(
1188+
type,
1189+
allowSuperBounded: allowSuperBounded,
1190+
);
1191+
}
1192+
11811193
/// Returns the least closure of [type] with respect to [typeParameters].
11821194
///
11831195
/// https://github.com/dart-lang/language
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
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+
import 'package:analyzer/dart/element/element.dart';
6+
import 'package:analyzer/dart/element/type.dart';
7+
import 'package:analyzer/src/dart/element/type_algebra.dart';
8+
import 'package:analyzer/src/dart/element/type_system.dart';
9+
10+
class NotWellBoundedTypeResult implements TypeBoundedResult {
11+
final String elementName;
12+
final List<TypeArgumentIssue> issues;
13+
14+
NotWellBoundedTypeResult._({
15+
required this.elementName,
16+
required this.issues,
17+
});
18+
}
19+
20+
class RegularBoundedTypeResult implements WellBoundedTypeResult {
21+
const RegularBoundedTypeResult._();
22+
}
23+
24+
class SuperBoundedTypeResult implements WellBoundedTypeResult {
25+
const SuperBoundedTypeResult._();
26+
}
27+
28+
class TypeArgumentIssue {
29+
/// The index for type argument within the passed type arguments.
30+
final int index;
31+
32+
/// The type parameter with the bound that was violated.
33+
final TypeParameterElement parameter;
34+
35+
/// The substituted bound of the [parameter].
36+
final DartType parameterBound;
37+
38+
/// The type argument that violated the [parameterBound].
39+
final DartType argument;
40+
41+
TypeArgumentIssue(
42+
this.index,
43+
this.parameter,
44+
this.parameterBound,
45+
this.argument,
46+
);
47+
48+
@override
49+
String toString() {
50+
return 'TypeArgumentIssue(index=$index, parameter=$parameter, '
51+
'parameterBound=$parameterBound, argument=$argument)';
52+
}
53+
}
54+
55+
/// Helper for checking whether a type if well-bounded.
56+
///
57+
/// See `15.2 Super-bounded types` in the language specification.
58+
class TypeBoundedHelper {
59+
final TypeSystemImpl typeSystem;
60+
61+
TypeBoundedHelper(this.typeSystem);
62+
63+
TypeBoundedResult isWellBounded(
64+
DartType type, {
65+
required bool allowSuperBounded,
66+
}) {
67+
var result = _isRegularBounded(type);
68+
if (!allowSuperBounded) {
69+
return result;
70+
}
71+
72+
return _isSuperBounded(type);
73+
}
74+
75+
TypeBoundedResult _isRegularBounded(DartType type) {
76+
List<TypeArgumentIssue>? issues;
77+
78+
final String elementName;
79+
final List<TypeParameterElement> typeParameters;
80+
final List<DartType> typeArguments;
81+
final alias = type.alias;
82+
if (alias != null) {
83+
elementName = alias.element.name;
84+
typeParameters = alias.element.typeParameters;
85+
typeArguments = alias.typeArguments;
86+
} else if (type is InterfaceType) {
87+
elementName = type.element.name;
88+
typeParameters = type.element.typeParameters;
89+
typeArguments = type.typeArguments;
90+
} else {
91+
return const RegularBoundedTypeResult._();
92+
}
93+
94+
final substitution = Substitution.fromPairs(typeParameters, typeArguments);
95+
for (var i = 0; i < typeParameters.length; i++) {
96+
var typeParameter = typeParameters[i];
97+
var typeArgument = typeArguments[i];
98+
99+
var bound = typeParameter.bound;
100+
if (bound == null) {
101+
continue;
102+
}
103+
104+
bound = typeSystem.toLegacyType(bound);
105+
bound = substitution.substituteType(bound);
106+
107+
if (!typeSystem.isSubtypeOf(typeArgument, bound)) {
108+
issues ??= <TypeArgumentIssue>[];
109+
issues.add(
110+
TypeArgumentIssue(i, typeParameter, bound, typeArgument),
111+
);
112+
}
113+
}
114+
115+
if (issues == null) {
116+
return const RegularBoundedTypeResult._();
117+
} else {
118+
return NotWellBoundedTypeResult._(
119+
elementName: elementName,
120+
issues: issues,
121+
);
122+
}
123+
}
124+
125+
TypeBoundedResult _isSuperBounded(DartType type) {
126+
final invertedType = typeSystem.replaceTopAndBottom(type);
127+
var result = _isRegularBounded(invertedType);
128+
if (result is RegularBoundedTypeResult) {
129+
return const SuperBoundedTypeResult._();
130+
} else {
131+
return result;
132+
}
133+
}
134+
}
135+
136+
abstract class TypeBoundedResult {}
137+
138+
class WellBoundedTypeResult implements TypeBoundedResult {}

pkg/analyzer/lib/src/error/codes.g.dart

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3671,6 +3671,13 @@ class CompileTimeErrorCode extends AnalyzerErrorCode {
36713671
correctionMessage: "Try invoking a const generative constructor.",
36723672
);
36733673

3674+
static const CompileTimeErrorCode
3675+
ENUM_INSTANTIATED_TO_BOUNDS_IS_NOT_WELL_BOUNDED = CompileTimeErrorCode(
3676+
'ENUM_INSTANTIATED_TO_BOUNDS_IS_NOT_WELL_BOUNDED',
3677+
"The result of instantiating the enum to bounds is not well-bounded.",
3678+
correctionMessage: "Try using different bounds for type parameters.",
3679+
);
3680+
36743681
static const CompileTimeErrorCode ENUM_MIXIN_WITH_INSTANCE_VARIABLE =
36753682
CompileTimeErrorCode(
36763683
'ENUM_MIXIN_WITH_INSTANCE_VARIABLE',
@@ -15583,6 +15590,13 @@ class CompileTimeErrorCode extends AnalyzerErrorCode {
1558315590
hasPublishedDocs: true,
1558415591
);
1558515592

15593+
static const CompileTimeErrorCode VALUES_DECLARATION_IN_ENUM =
15594+
CompileTimeErrorCode(
15595+
'VALUES_DECLARATION_IN_ENUM',
15596+
"A member named 'values' can't be declared in an enum.",
15597+
correctionMessage: "Try using a different name.",
15598+
);
15599+
1558615600
/**
1558715601
* Parameters:
1558815602
* 0: the type of the object being assigned.

pkg/analyzer/lib/src/error/duplicate_definition_verifier.dart

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -53,13 +53,9 @@ class DuplicateDefinitionVerifier {
5353
var staticGetters = <String, Element>{};
5454
var staticSetters = <String, Element>{};
5555

56-
var valuesField = enumElement.valuesField;
57-
if (valuesField != null) {
58-
staticGetters['values'] = valuesField;
59-
}
60-
6156
for (EnumConstantDeclaration constant in node.constants) {
6257
_checkDuplicateIdentifier(staticGetters, constant.name);
58+
_checkValuesDeclarationInEnum(constant.name);
6359
}
6460

6561
for (var member in node.members) {
@@ -89,13 +85,15 @@ class DuplicateDefinitionVerifier {
8985
identifier,
9086
setterScope: member.isStatic ? staticSetters : instanceSetters,
9187
);
88+
_checkValuesDeclarationInEnum(identifier);
9289
}
9390
} else if (member is MethodDeclaration) {
9491
_checkDuplicateIdentifier(
9592
member.isStatic ? staticGetters : instanceGetters,
9693
member.name,
9794
setterScope: member.isStatic ? staticSetters : instanceSetters,
9895
);
96+
_checkValuesDeclarationInEnum(member.name);
9997
}
10098
}
10199

@@ -514,6 +512,15 @@ class DuplicateDefinitionVerifier {
514512
}
515513
}
516514

515+
void _checkValuesDeclarationInEnum(SimpleIdentifier name) {
516+
if (name.name == 'values') {
517+
_errorReporter.reportErrorForNode(
518+
CompileTimeErrorCode.VALUES_DECLARATION_IN_ENUM,
519+
name,
520+
);
521+
}
522+
}
523+
517524
ExecutableElement? _getInheritedMember(
518525
ClassElement element, String baseName) {
519526
var libraryUri = _currentLibrary.source.uri;

pkg/analyzer/lib/src/error/inheritance_override.dart

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -197,9 +197,11 @@ class _ClassVerifier {
197197
var fieldElement = field.declaredElement as FieldElement;
198198
_checkDeclaredMember(field.name, libraryUri, fieldElement.getter);
199199
_checkDeclaredMember(field.name, libraryUri, fieldElement.setter);
200+
if (!member.isStatic && !classElement.isEnum) {
201+
_checkIllegalEnumValuesDeclaration(field.name);
202+
}
200203
if (!member.isStatic) {
201204
_checkIllegalNonAbstractEnumIndex(field.name);
202-
_checkIllegalEnumValuesDeclaration(field.name);
203205
}
204206
}
205207
} else if (member is MethodDeclaration) {
@@ -210,7 +212,7 @@ class _ClassVerifier {
210212

211213
_checkDeclaredMember(member.name, libraryUri, member.declaredElement,
212214
methodParameterNodes: member.parameters?.parameters);
213-
if (!member.isStatic) {
215+
if (!member.isStatic && !classElement.isEnum) {
214216
_checkIllegalEnumValuesDeclaration(member.name);
215217
}
216218
if (!(member.isStatic || member.isAbstract || member.isSetter)) {

pkg/analyzer/lib/src/generated/error_verifier.dart

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
2626
import 'package:analyzer/src/dart/element/type.dart';
2727
import 'package:analyzer/src/dart/element/type_provider.dart';
2828
import 'package:analyzer/src/dart/element/type_system.dart';
29+
import 'package:analyzer/src/dart/element/well_bounded.dart';
2930
import 'package:analyzer/src/dart/resolver/scope.dart';
3031
import 'package:analyzer/src/dart/resolver/variance.dart';
3132
import 'package:analyzer/src/diagnostic/diagnostic_factory.dart';
@@ -582,12 +583,11 @@ class ErrorVerifier extends RecursiveAstVisitor<void>
582583
_checkClassInheritance(node, null, withClause, implementsClause);
583584
}
584585

585-
// TODO(scheglov) implement
586-
// _checkForConflictingClassMembers();
587586
_constructorFieldsVerifier.enterEnum(node);
588587
_checkForFinalNotInitializedInClass(node.members);
589588
_checkForWrongTypeParameterVarianceInSuperinterfaces();
590589
_checkForMainFunction(node.name);
590+
_checkForEnumInstantiatedToBoundsIsNotWellBounded(node, element);
591591

592592
super.visitEnumDeclaration(node);
593593
} finally {
@@ -2463,6 +2463,25 @@ class ErrorVerifier extends RecursiveAstVisitor<void>
24632463
return true;
24642464
}
24652465

2466+
void _checkForEnumInstantiatedToBoundsIsNotWellBounded(
2467+
EnumDeclaration node,
2468+
EnumElementImpl element,
2469+
) {
2470+
var valuesFieldType = element.valuesField?.type;
2471+
if (valuesFieldType is InterfaceType) {
2472+
var isWellBounded = typeSystem.isWellBounded(
2473+
valuesFieldType.typeArguments.single,
2474+
allowSuperBounded: true,
2475+
);
2476+
if (isWellBounded is NotWellBoundedTypeResult) {
2477+
errorReporter.reportErrorForNode(
2478+
CompileTimeErrorCode.ENUM_INSTANTIATED_TO_BOUNDS_IS_NOT_WELL_BOUNDED,
2479+
node.name,
2480+
);
2481+
}
2482+
}
2483+
}
2484+
24662485
/// Check that if the visiting library is not system, then any given library
24672486
/// should not be SDK internal library. The [exportElement] is the
24682487
/// [ExportElement] retrieved from the node, if the element in the node was

0 commit comments

Comments
 (0)