Skip to content

Commit 0529834

Browse files
srawlinscommit-bot@chromium.org
authored and
commit-bot@chromium.org
committed
Allow type variables in constant evaluation, if ctor-tearoffs are enabled.
This requires passing the runtime type arguments into the InstanceCreationEvaluator, so that it can store them in a lexical scope map. Bug: #47302 Change-Id: I6b9d660f20b981d26810f29858784c034cc8abfd Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/215960 Commit-Queue: Samuel Rawlins <srawlins@google.com> Reviewed-by: Brian Wilkerson <brianwilkerson@google.com> Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
1 parent 396e58e commit 0529834

File tree

3 files changed

+228
-27
lines changed

3 files changed

+228
-27
lines changed

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@ class ConstantVerifier extends RecursiveAstVisitor<void> {
171171
_evaluationEngine.evaluateConstructorCall(
172172
_currentLibrary,
173173
node,
174+
constructor.returnType.typeArguments,
174175
node.argumentList.arguments,
175176
constructor,
176177
constantVisitor,

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

Lines changed: 95 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import 'dart:collection';
66

7+
import 'package:analyzer/dart/analysis/features.dart';
78
import 'package:analyzer/dart/ast/ast.dart';
89
import 'package:analyzer/dart/ast/token.dart';
910
import 'package:analyzer/dart/ast/visitor.dart';
@@ -141,6 +142,7 @@ class ConstantEvaluationEngine {
141142
var result = evaluateConstructorCall(
142143
library,
143144
constNode,
145+
element.returnType.typeArguments,
144146
constNode.arguments!.arguments,
145147
element,
146148
constantVisitor,
@@ -272,15 +274,26 @@ class ConstantEvaluationEngine {
272274
DartObjectImpl? evaluateConstructorCall(
273275
LibraryElementImpl library,
274276
AstNode node,
277+
List<DartType>? typeArguments,
275278
List<Expression> arguments,
276279
ConstructorElement constructor,
277280
ConstantVisitor constantVisitor,
278281
ErrorReporter errorReporter, {
279282
ConstructorInvocation? invocation,
280283
}) {
281-
return _InstanceCreationEvaluator.evaluate(this, _declaredVariables,
282-
errorReporter, library, node, constructor, arguments, constantVisitor,
283-
isNullSafe: _isNonNullableByDefault, invocation: invocation);
284+
return _InstanceCreationEvaluator.evaluate(
285+
this,
286+
_declaredVariables,
287+
errorReporter,
288+
library,
289+
node,
290+
constructor,
291+
typeArguments,
292+
arguments,
293+
constantVisitor,
294+
isNullSafe: _isNonNullableByDefault,
295+
invocation: invocation,
296+
);
284297
}
285298

286299
/// Generate an error indicating that the given [constant] is not a valid
@@ -430,7 +443,12 @@ class ConstantVisitor extends UnifyingAstVisitor<DartObjectImpl> {
430443
/// The library that contains the constant expression being evaluated.
431444
final LibraryElementImpl _library;
432445

446+
/// A mapping of variable names to runtime values.
433447
final Map<String, DartObjectImpl>? _lexicalEnvironment;
448+
449+
/// A mapping of type parameter names to runtime values (types).
450+
final Map<String, DartType>? _lexicalTypeEnvironment;
451+
434452
final Substitution? _substitution;
435453

436454
/// Error reporter that we use to report errors accumulated while computing
@@ -453,8 +471,10 @@ class ConstantVisitor extends UnifyingAstVisitor<DartObjectImpl> {
453471
this._library,
454472
this._errorReporter, {
455473
Map<String, DartObjectImpl>? lexicalEnvironment,
474+
Map<String, DartType>? lexicalTypeEnvironment,
456475
Substitution? substitution,
457476
}) : _lexicalEnvironment = lexicalEnvironment,
477+
_lexicalTypeEnvironment = lexicalTypeEnvironment,
458478
_substitution = substitution {
459479
_dartObjectComputer = DartObjectComputer(
460480
typeSystem,
@@ -705,8 +725,15 @@ class ConstantVisitor extends UnifyingAstVisitor<DartObjectImpl> {
705725
return null;
706726
}
707727

708-
return evaluationEngine.evaluateConstructorCall(_library, node,
709-
node.argumentList.arguments, constructor, this, _errorReporter);
728+
return evaluationEngine.evaluateConstructorCall(
729+
_library,
730+
node,
731+
constructor.returnType.typeArguments,
732+
node.argumentList.arguments,
733+
constructor,
734+
this,
735+
_errorReporter,
736+
);
710737
}
711738

712739
@override
@@ -1253,7 +1280,18 @@ class ConstantVisitor extends UnifyingAstVisitor<DartObjectImpl> {
12531280
TypeState(_typeProvider.neverType),
12541281
);
12551282
} else if (variableElement is TypeParameterElement) {
1256-
// Constants may not refer to type parameters.
1283+
// Constants may refer to type parameters only if the constructor-tearoffs
1284+
// feature is enabled.
1285+
if (_library.featureSet.isEnabled(Feature.constructor_tearoffs)) {
1286+
var typeArgument = _lexicalTypeEnvironment?[identifier.name];
1287+
if (typeArgument != null) {
1288+
return DartObjectImpl(
1289+
typeSystem,
1290+
_typeProvider.typeType,
1291+
TypeState(typeArgument),
1292+
);
1293+
}
1294+
}
12571295
}
12581296

12591297
// TODO(https://github.com/dart-lang/sdk/issues/47061): Use a specific
@@ -1926,13 +1964,17 @@ class _InstanceCreationEvaluator {
19261964
_constructor.library as LibraryElementImpl,
19271965
_externalErrorReporter,
19281966
lexicalEnvironment: _parameterMap,
1967+
lexicalTypeEnvironment: _typeParameterMap,
19291968
substitution: Substitution.fromInterfaceType(definingType),
19301969
);
19311970

1932-
final AstNode _node;
1971+
/// The node used for most error reporting.
1972+
final AstNode _errorNode;
19331973

19341974
final ConstructorElement _constructor;
19351975

1976+
final List<DartType>? _typeArguments;
1977+
19361978
final ConstructorInvocation _invocation;
19371979

19381980
final Map<String, NamedExpression> _namedNodes;
@@ -1941,17 +1983,25 @@ class _InstanceCreationEvaluator {
19411983

19421984
final List<DartObjectImpl> _argumentValues;
19431985

1986+
final Map<String, DartType> _typeParameterMap = HashMap();
1987+
19441988
final Map<String, DartObjectImpl> _parameterMap = HashMap();
19451989

19461990
final Map<String, DartObjectImpl> _fieldMap = HashMap();
19471991

1948-
_InstanceCreationEvaluator.generative(
1992+
/// Constructor for [_InstanceCreationEvaluator].
1993+
///
1994+
/// This constructor is private, as the entry point for using a
1995+
/// [_InstanceCreationEvaluator] is the static method,
1996+
/// [_InstanceCreationEvaluator.evaluate].
1997+
_InstanceCreationEvaluator._(
19491998
this._evaluationEngine,
19501999
this._declaredVariables,
19512000
this._errorReporter,
19522001
this._library,
1953-
this._node,
1954-
this._constructor, {
2002+
this._errorNode,
2003+
this._constructor,
2004+
this._typeArguments, {
19552005
required Map<String, NamedExpression> namedNodes,
19562006
required Map<String, DartObjectImpl> namedValues,
19572007
required List<DartObjectImpl> argumentValues,
@@ -1979,7 +2029,7 @@ class _InstanceCreationEvaluator {
19792029
if (_constructor.name == "fromEnvironment") {
19802030
if (!_checkFromEnvironmentArguments(arguments, definingType)) {
19812031
_errorReporter.reportErrorForNode(
1982-
CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, _node);
2032+
CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, _errorNode);
19832033
return null;
19842034
}
19852035
String? variableName =
@@ -2004,7 +2054,7 @@ class _InstanceCreationEvaluator {
20042054
argumentCount == 1) {
20052055
if (!_checkSymbolArguments(arguments, isNullSafe: isNullSafe)) {
20062056
_errorReporter.reportErrorForNode(
2007-
CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, _node);
2057+
CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, _errorNode);
20082058
return null;
20092059
}
20102060
return DartObjectImpl(
@@ -2028,6 +2078,7 @@ class _InstanceCreationEvaluator {
20282078
// Start with final fields that are initialized at their declaration site.
20292079
_checkFields();
20302080

2081+
_checkTypeParameters();
20312082
_checkParameters(arguments);
20322083
var evaluationResult = _checkInitializers();
20332084
if (evaluationResult.evaluationIsComplete) {
@@ -2038,7 +2089,7 @@ class _InstanceCreationEvaluator {
20382089
superArguments: evaluationResult.superArguments);
20392090
if (_externalErrorListener.errorReported) {
20402091
_errorReporter.reportErrorForNode(
2041-
CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, _node);
2092+
CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, _errorNode);
20422093
}
20432094
return DartObjectImpl(
20442095
typeSystem,
@@ -2049,8 +2100,7 @@ class _InstanceCreationEvaluator {
20492100

20502101
void _checkFields() {
20512102
var fields = _constructor.enclosingElement.fields;
2052-
for (var i = 0; i < fields.length; i++) {
2053-
var field = fields[i];
2103+
for (var field in fields) {
20542104
if ((field.isFinal || field.isConst) &&
20552105
!field.isStatic &&
20562106
field is ConstFieldElementImpl) {
@@ -2067,7 +2117,7 @@ class _InstanceCreationEvaluator {
20672117
if (!typeSystem.runtimeTypeMatch(fieldValue, fieldType)) {
20682118
_errorReporter.reportErrorForNode(
20692119
CompileTimeErrorCode.CONST_CONSTRUCTOR_FIELD_TYPE_MISMATCH,
2070-
_node,
2120+
_errorNode,
20712121
[fieldValue.type, field.name, fieldType]);
20722122
}
20732123
_fieldMap[field.name] = fieldValue;
@@ -2130,7 +2180,7 @@ class _InstanceCreationEvaluator {
21302180
var fieldName = initializer.fieldName.name;
21312181
if (_fieldMap.containsKey(fieldName)) {
21322182
_errorReporter.reportErrorForNode(
2133-
CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, _node);
2183+
CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, _errorNode);
21342184
}
21352185
_fieldMap[fieldName] = evaluationResult;
21362186
var getter = definingType.getGetter(fieldName);
@@ -2139,13 +2189,13 @@ class _InstanceCreationEvaluator {
21392189
if (!typeSystem.runtimeTypeMatch(evaluationResult, field.type)) {
21402190
_errorReporter.reportErrorForNode(
21412191
CompileTimeErrorCode.CONST_CONSTRUCTOR_FIELD_TYPE_MISMATCH,
2142-
_node,
2192+
_errorNode,
21432193
[evaluationResult.type, fieldName, field.type]);
21442194
}
21452195
}
21462196
} else {
21472197
_errorReporter.reportErrorForNode(
2148-
CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, _node);
2198+
CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, _errorNode);
21492199
}
21502200
} else if (initializer is SuperConstructorInvocation) {
21512201
var name = initializer.constructorName;
@@ -2162,15 +2212,16 @@ class _InstanceCreationEvaluator {
21622212
constructor = ConstructorMember.from(constructor, definingType);
21632213
var result = _evaluationEngine.evaluateConstructorCall(
21642214
_library,
2165-
_node,
2215+
_errorNode,
2216+
_typeArguments,
21662217
initializer.argumentList.arguments,
21672218
constructor,
21682219
_initializerVisitor,
21692220
_externalErrorReporter,
21702221
invocation: _invocation);
21712222
if (_externalErrorListener.errorReported) {
21722223
_errorReporter.reportErrorForNode(
2173-
CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, _node);
2224+
CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, _errorNode);
21742225
}
21752226
return _InitializersEvaluationResult(result,
21762227
evaluationIsComplete: true);
@@ -2182,7 +2233,7 @@ class _InstanceCreationEvaluator {
21822233
!evaluationResult.isBool ||
21832234
evaluationResult.toBoolValue() == false) {
21842235
_errorReporter.reportErrorForNode(
2185-
CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, _node);
2236+
CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, _errorNode);
21862237
return _InitializersEvaluationResult(null,
21872238
evaluationIsComplete: true);
21882239
}
@@ -2213,7 +2264,7 @@ class _InstanceCreationEvaluator {
22132264
// No argument node that we can direct error messages to, because we
22142265
// are handling an optional parameter that wasn't specified. So just
22152266
// direct error messages to the constructor call.
2216-
errorTarget ??= _node;
2267+
errorTarget ??= _errorNode;
22172268
if (argumentValue == null && baseParameter is ParameterElementImpl) {
22182269
// The parameter is an optional positional parameter for which no value
22192270
// was provided, so use the default value.
@@ -2252,7 +2303,7 @@ class _InstanceCreationEvaluator {
22522303
var fieldName = field.name;
22532304
if (_fieldMap.containsKey(fieldName)) {
22542305
_errorReporter.reportErrorForNode(
2255-
CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, _node);
2306+
CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, _errorNode);
22562307
}
22572308
_fieldMap[fieldName] = argumentValue;
22582309
}
@@ -2288,8 +2339,9 @@ class _InstanceCreationEvaluator {
22882339
if (superConstructor.isConst) {
22892340
var evaluationResult = _evaluationEngine.evaluateConstructorCall(
22902341
_library,
2291-
_node,
2292-
superArguments ?? astFactory.nodeList(_node),
2342+
_errorNode,
2343+
superclass.typeArguments,
2344+
superArguments ?? astFactory.nodeList(_errorNode),
22932345
superConstructor,
22942346
_initializerVisitor,
22952347
_externalErrorReporter,
@@ -2328,6 +2380,20 @@ class _InstanceCreationEvaluator {
23282380
return _isValidPublicSymbol(name);
23292381
}
23302382

2383+
void _checkTypeParameters() {
2384+
var typeParameters = _constructor.enclosingElement.typeParameters;
2385+
var typeArguments = _typeArguments;
2386+
if (typeParameters.isNotEmpty &&
2387+
typeArguments != null &&
2388+
typeParameters.length == typeArguments.length) {
2389+
for (int i = 0; i < typeParameters.length; i++) {
2390+
var typeParameter = typeParameters[i];
2391+
var typeArgument = typeArguments[i];
2392+
_typeParameterMap[typeParameter.name] = typeArgument;
2393+
}
2394+
}
2395+
}
2396+
23312397
/// Evaluates [node] as an instance creation expression using [constructor].
23322398
static DartObjectImpl? evaluate(
23332399
ConstantEvaluationEngine evaluationEngine,
@@ -2336,6 +2402,7 @@ class _InstanceCreationEvaluator {
23362402
LibraryElementImpl library,
23372403
AstNode node,
23382404
ConstructorElement constructor,
2405+
List<DartType>? typeArguments,
23392406
List<Expression> arguments,
23402407
ConstantVisitor constantVisitor, {
23412408
required bool isNullSafe,
@@ -2386,13 +2453,14 @@ class _InstanceCreationEvaluator {
23862453

23872454
constructor = _followConstantRedirectionChain(constructor);
23882455

2389-
var evaluator = _InstanceCreationEvaluator.generative(
2456+
var evaluator = _InstanceCreationEvaluator._(
23902457
evaluationEngine,
23912458
declaredVariables,
23922459
errorReporter,
23932460
library,
23942461
node,
23952462
constructor,
2463+
typeArguments,
23962464
namedNodes: namedNodes,
23972465
namedValues: namedValues,
23982466
argumentValues: argumentValues,

0 commit comments

Comments
 (0)