4
4
5
5
import 'dart:collection' ;
6
6
7
+ import 'package:analyzer/dart/analysis/features.dart' ;
7
8
import 'package:analyzer/dart/ast/ast.dart' ;
8
9
import 'package:analyzer/dart/ast/token.dart' ;
9
10
import 'package:analyzer/dart/ast/visitor.dart' ;
@@ -141,6 +142,7 @@ class ConstantEvaluationEngine {
141
142
var result = evaluateConstructorCall (
142
143
library,
143
144
constNode,
145
+ element.returnType.typeArguments,
144
146
constNode.arguments! .arguments,
145
147
element,
146
148
constantVisitor,
@@ -272,15 +274,26 @@ class ConstantEvaluationEngine {
272
274
DartObjectImpl ? evaluateConstructorCall (
273
275
LibraryElementImpl library,
274
276
AstNode node,
277
+ List <DartType >? typeArguments,
275
278
List <Expression > arguments,
276
279
ConstructorElement constructor,
277
280
ConstantVisitor constantVisitor,
278
281
ErrorReporter errorReporter, {
279
282
ConstructorInvocation ? invocation,
280
283
}) {
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
+ );
284
297
}
285
298
286
299
/// Generate an error indicating that the given [constant] is not a valid
@@ -430,7 +443,12 @@ class ConstantVisitor extends UnifyingAstVisitor<DartObjectImpl> {
430
443
/// The library that contains the constant expression being evaluated.
431
444
final LibraryElementImpl _library;
432
445
446
+ /// A mapping of variable names to runtime values.
433
447
final Map <String , DartObjectImpl >? _lexicalEnvironment;
448
+
449
+ /// A mapping of type parameter names to runtime values (types).
450
+ final Map <String , DartType >? _lexicalTypeEnvironment;
451
+
434
452
final Substitution ? _substitution;
435
453
436
454
/// Error reporter that we use to report errors accumulated while computing
@@ -453,8 +471,10 @@ class ConstantVisitor extends UnifyingAstVisitor<DartObjectImpl> {
453
471
this ._library,
454
472
this ._errorReporter, {
455
473
Map <String , DartObjectImpl >? lexicalEnvironment,
474
+ Map <String , DartType >? lexicalTypeEnvironment,
456
475
Substitution ? substitution,
457
476
}) : _lexicalEnvironment = lexicalEnvironment,
477
+ _lexicalTypeEnvironment = lexicalTypeEnvironment,
458
478
_substitution = substitution {
459
479
_dartObjectComputer = DartObjectComputer (
460
480
typeSystem,
@@ -705,8 +725,15 @@ class ConstantVisitor extends UnifyingAstVisitor<DartObjectImpl> {
705
725
return null ;
706
726
}
707
727
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
+ );
710
737
}
711
738
712
739
@override
@@ -1253,7 +1280,18 @@ class ConstantVisitor extends UnifyingAstVisitor<DartObjectImpl> {
1253
1280
TypeState (_typeProvider.neverType),
1254
1281
);
1255
1282
} 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
+ }
1257
1295
}
1258
1296
1259
1297
// TODO(https://github.com/dart-lang/sdk/issues/47061): Use a specific
@@ -1926,13 +1964,17 @@ class _InstanceCreationEvaluator {
1926
1964
_constructor.library as LibraryElementImpl ,
1927
1965
_externalErrorReporter,
1928
1966
lexicalEnvironment: _parameterMap,
1967
+ lexicalTypeEnvironment: _typeParameterMap,
1929
1968
substitution: Substitution .fromInterfaceType (definingType),
1930
1969
);
1931
1970
1932
- final AstNode _node;
1971
+ /// The node used for most error reporting.
1972
+ final AstNode _errorNode;
1933
1973
1934
1974
final ConstructorElement _constructor;
1935
1975
1976
+ final List <DartType >? _typeArguments;
1977
+
1936
1978
final ConstructorInvocation _invocation;
1937
1979
1938
1980
final Map <String , NamedExpression > _namedNodes;
@@ -1941,17 +1983,25 @@ class _InstanceCreationEvaluator {
1941
1983
1942
1984
final List <DartObjectImpl > _argumentValues;
1943
1985
1986
+ final Map <String , DartType > _typeParameterMap = HashMap ();
1987
+
1944
1988
final Map <String , DartObjectImpl > _parameterMap = HashMap ();
1945
1989
1946
1990
final Map <String , DartObjectImpl > _fieldMap = HashMap ();
1947
1991
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 ._(
1949
1998
this ._evaluationEngine,
1950
1999
this ._declaredVariables,
1951
2000
this ._errorReporter,
1952
2001
this ._library,
1953
- this ._node,
1954
- this ._constructor, {
2002
+ this ._errorNode,
2003
+ this ._constructor,
2004
+ this ._typeArguments, {
1955
2005
required Map <String , NamedExpression > namedNodes,
1956
2006
required Map <String , DartObjectImpl > namedValues,
1957
2007
required List <DartObjectImpl > argumentValues,
@@ -1979,7 +2029,7 @@ class _InstanceCreationEvaluator {
1979
2029
if (_constructor.name == "fromEnvironment" ) {
1980
2030
if (! _checkFromEnvironmentArguments (arguments, definingType)) {
1981
2031
_errorReporter.reportErrorForNode (
1982
- CompileTimeErrorCode .CONST_EVAL_THROWS_EXCEPTION , _node );
2032
+ CompileTimeErrorCode .CONST_EVAL_THROWS_EXCEPTION , _errorNode );
1983
2033
return null ;
1984
2034
}
1985
2035
String ? variableName =
@@ -2004,7 +2054,7 @@ class _InstanceCreationEvaluator {
2004
2054
argumentCount == 1 ) {
2005
2055
if (! _checkSymbolArguments (arguments, isNullSafe: isNullSafe)) {
2006
2056
_errorReporter.reportErrorForNode (
2007
- CompileTimeErrorCode .CONST_EVAL_THROWS_EXCEPTION , _node );
2057
+ CompileTimeErrorCode .CONST_EVAL_THROWS_EXCEPTION , _errorNode );
2008
2058
return null ;
2009
2059
}
2010
2060
return DartObjectImpl (
@@ -2028,6 +2078,7 @@ class _InstanceCreationEvaluator {
2028
2078
// Start with final fields that are initialized at their declaration site.
2029
2079
_checkFields ();
2030
2080
2081
+ _checkTypeParameters ();
2031
2082
_checkParameters (arguments);
2032
2083
var evaluationResult = _checkInitializers ();
2033
2084
if (evaluationResult.evaluationIsComplete) {
@@ -2038,7 +2089,7 @@ class _InstanceCreationEvaluator {
2038
2089
superArguments: evaluationResult.superArguments);
2039
2090
if (_externalErrorListener.errorReported) {
2040
2091
_errorReporter.reportErrorForNode (
2041
- CompileTimeErrorCode .CONST_EVAL_THROWS_EXCEPTION , _node );
2092
+ CompileTimeErrorCode .CONST_EVAL_THROWS_EXCEPTION , _errorNode );
2042
2093
}
2043
2094
return DartObjectImpl (
2044
2095
typeSystem,
@@ -2049,8 +2100,7 @@ class _InstanceCreationEvaluator {
2049
2100
2050
2101
void _checkFields () {
2051
2102
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) {
2054
2104
if ((field.isFinal || field.isConst) &&
2055
2105
! field.isStatic &&
2056
2106
field is ConstFieldElementImpl ) {
@@ -2067,7 +2117,7 @@ class _InstanceCreationEvaluator {
2067
2117
if (! typeSystem.runtimeTypeMatch (fieldValue, fieldType)) {
2068
2118
_errorReporter.reportErrorForNode (
2069
2119
CompileTimeErrorCode .CONST_CONSTRUCTOR_FIELD_TYPE_MISMATCH ,
2070
- _node ,
2120
+ _errorNode ,
2071
2121
[fieldValue.type, field.name, fieldType]);
2072
2122
}
2073
2123
_fieldMap[field.name] = fieldValue;
@@ -2130,7 +2180,7 @@ class _InstanceCreationEvaluator {
2130
2180
var fieldName = initializer.fieldName.name;
2131
2181
if (_fieldMap.containsKey (fieldName)) {
2132
2182
_errorReporter.reportErrorForNode (
2133
- CompileTimeErrorCode .CONST_EVAL_THROWS_EXCEPTION , _node );
2183
+ CompileTimeErrorCode .CONST_EVAL_THROWS_EXCEPTION , _errorNode );
2134
2184
}
2135
2185
_fieldMap[fieldName] = evaluationResult;
2136
2186
var getter = definingType.getGetter (fieldName);
@@ -2139,13 +2189,13 @@ class _InstanceCreationEvaluator {
2139
2189
if (! typeSystem.runtimeTypeMatch (evaluationResult, field.type)) {
2140
2190
_errorReporter.reportErrorForNode (
2141
2191
CompileTimeErrorCode .CONST_CONSTRUCTOR_FIELD_TYPE_MISMATCH ,
2142
- _node ,
2192
+ _errorNode ,
2143
2193
[evaluationResult.type, fieldName, field.type]);
2144
2194
}
2145
2195
}
2146
2196
} else {
2147
2197
_errorReporter.reportErrorForNode (
2148
- CompileTimeErrorCode .CONST_EVAL_THROWS_EXCEPTION , _node );
2198
+ CompileTimeErrorCode .CONST_EVAL_THROWS_EXCEPTION , _errorNode );
2149
2199
}
2150
2200
} else if (initializer is SuperConstructorInvocation ) {
2151
2201
var name = initializer.constructorName;
@@ -2162,15 +2212,16 @@ class _InstanceCreationEvaluator {
2162
2212
constructor = ConstructorMember .from (constructor, definingType);
2163
2213
var result = _evaluationEngine.evaluateConstructorCall (
2164
2214
_library,
2165
- _node,
2215
+ _errorNode,
2216
+ _typeArguments,
2166
2217
initializer.argumentList.arguments,
2167
2218
constructor,
2168
2219
_initializerVisitor,
2169
2220
_externalErrorReporter,
2170
2221
invocation: _invocation);
2171
2222
if (_externalErrorListener.errorReported) {
2172
2223
_errorReporter.reportErrorForNode (
2173
- CompileTimeErrorCode .CONST_EVAL_THROWS_EXCEPTION , _node );
2224
+ CompileTimeErrorCode .CONST_EVAL_THROWS_EXCEPTION , _errorNode );
2174
2225
}
2175
2226
return _InitializersEvaluationResult (result,
2176
2227
evaluationIsComplete: true );
@@ -2182,7 +2233,7 @@ class _InstanceCreationEvaluator {
2182
2233
! evaluationResult.isBool ||
2183
2234
evaluationResult.toBoolValue () == false ) {
2184
2235
_errorReporter.reportErrorForNode (
2185
- CompileTimeErrorCode .CONST_EVAL_THROWS_EXCEPTION , _node );
2236
+ CompileTimeErrorCode .CONST_EVAL_THROWS_EXCEPTION , _errorNode );
2186
2237
return _InitializersEvaluationResult (null ,
2187
2238
evaluationIsComplete: true );
2188
2239
}
@@ -2213,7 +2264,7 @@ class _InstanceCreationEvaluator {
2213
2264
// No argument node that we can direct error messages to, because we
2214
2265
// are handling an optional parameter that wasn't specified. So just
2215
2266
// direct error messages to the constructor call.
2216
- errorTarget ?? = _node ;
2267
+ errorTarget ?? = _errorNode ;
2217
2268
if (argumentValue == null && baseParameter is ParameterElementImpl ) {
2218
2269
// The parameter is an optional positional parameter for which no value
2219
2270
// was provided, so use the default value.
@@ -2252,7 +2303,7 @@ class _InstanceCreationEvaluator {
2252
2303
var fieldName = field.name;
2253
2304
if (_fieldMap.containsKey (fieldName)) {
2254
2305
_errorReporter.reportErrorForNode (
2255
- CompileTimeErrorCode .CONST_EVAL_THROWS_EXCEPTION , _node );
2306
+ CompileTimeErrorCode .CONST_EVAL_THROWS_EXCEPTION , _errorNode );
2256
2307
}
2257
2308
_fieldMap[fieldName] = argumentValue;
2258
2309
}
@@ -2288,8 +2339,9 @@ class _InstanceCreationEvaluator {
2288
2339
if (superConstructor.isConst) {
2289
2340
var evaluationResult = _evaluationEngine.evaluateConstructorCall (
2290
2341
_library,
2291
- _node,
2292
- superArguments ?? astFactory.nodeList (_node),
2342
+ _errorNode,
2343
+ superclass.typeArguments,
2344
+ superArguments ?? astFactory.nodeList (_errorNode),
2293
2345
superConstructor,
2294
2346
_initializerVisitor,
2295
2347
_externalErrorReporter,
@@ -2328,6 +2380,20 @@ class _InstanceCreationEvaluator {
2328
2380
return _isValidPublicSymbol (name);
2329
2381
}
2330
2382
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
+
2331
2397
/// Evaluates [node] as an instance creation expression using [constructor] .
2332
2398
static DartObjectImpl ? evaluate (
2333
2399
ConstantEvaluationEngine evaluationEngine,
@@ -2336,6 +2402,7 @@ class _InstanceCreationEvaluator {
2336
2402
LibraryElementImpl library,
2337
2403
AstNode node,
2338
2404
ConstructorElement constructor,
2405
+ List <DartType >? typeArguments,
2339
2406
List <Expression > arguments,
2340
2407
ConstantVisitor constantVisitor, {
2341
2408
required bool isNullSafe,
@@ -2386,13 +2453,14 @@ class _InstanceCreationEvaluator {
2386
2453
2387
2454
constructor = _followConstantRedirectionChain (constructor);
2388
2455
2389
- var evaluator = _InstanceCreationEvaluator .generative (
2456
+ var evaluator = _InstanceCreationEvaluator ._ (
2390
2457
evaluationEngine,
2391
2458
declaredVariables,
2392
2459
errorReporter,
2393
2460
library,
2394
2461
node,
2395
2462
constructor,
2463
+ typeArguments,
2396
2464
namedNodes: namedNodes,
2397
2465
namedValues: namedValues,
2398
2466
argumentValues: argumentValues,
0 commit comments