Skip to content

Commit 2369d59

Browse files
srawlinscommit-bot@chromium.org
authored andcommitted
Support constructor references, function references, and type literals as potentially constant
Fixes #47153 Change-Id: Ia86464e1b460a30540c3314e2d6fbf477a9285b6 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/215685 Commit-Queue: Samuel Rawlins <[email protected]> Reviewed-by: Konstantin Shcheglov <[email protected]> Reviewed-by: Brian Wilkerson <[email protected]>
1 parent 72de2cb commit 2369d59

File tree

2 files changed

+88
-3
lines changed

2 files changed

+88
-3
lines changed

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

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ class _Collector {
9494
}
9595

9696
if (node is TypedLiteral) {
97-
return _typeLiteral(node);
97+
return _typedLiteral(node);
9898
}
9999

100100
if (node is ParenthesizedExpression) {
@@ -187,6 +187,22 @@ class _Collector {
187187
return;
188188
}
189189

190+
if (node is ConstructorReference) {
191+
_typeArgumentList(node.constructorName.type2.typeArguments);
192+
return;
193+
}
194+
195+
if (node is FunctionReference) {
196+
_typeArgumentList(node.typeArguments);
197+
collect(node.function);
198+
return;
199+
}
200+
201+
if (node is TypeLiteral) {
202+
_typeArgumentList(node.type.typeArguments);
203+
return;
204+
}
205+
190206
nodes.add(node);
191207
}
192208

@@ -261,6 +277,7 @@ class _Collector {
261277
return;
262278
}
263279
}
280+
// TODO(srawlins): collect type arguments.
264281
nodes.add(node);
265282
}
266283

@@ -292,7 +309,18 @@ class _Collector {
292309
nodes.add(node);
293310
}
294311

295-
void _typeLiteral(TypedLiteral node) {
312+
void _typeArgumentList(TypeArgumentList? typeArgumentList) {
313+
var typeArguments = typeArgumentList?.arguments;
314+
if (typeArguments != null) {
315+
for (var typeArgument in typeArguments) {
316+
if (!isPotentiallyConstantTypeExpression(typeArgument)) {
317+
nodes.add(typeArgument);
318+
}
319+
}
320+
}
321+
}
322+
323+
void _typedLiteral(TypedLiteral node) {
296324
if (!node.isConst) {
297325
nodes.add(node);
298326
return;
@@ -302,6 +330,8 @@ class _Collector {
302330
var typeArguments = node.typeArguments?.arguments;
303331
if (typeArguments != null && typeArguments.length == 1) {
304332
var elementType = typeArguments[0];
333+
// TODO(srawlins): Change to "potentially" constant type expression as
334+
// per https://github.com/dart-lang/sdk/issues/47302?
305335
if (!isConstantTypeExpression(elementType)) {
306336
nodes.add(elementType);
307337
}
@@ -317,6 +347,8 @@ class _Collector {
317347
var typeArguments = node.typeArguments?.arguments;
318348
if (typeArguments != null && typeArguments.length == 1) {
319349
var elementType = typeArguments[0];
350+
// TODO(srawlins): Change to "potentially" constant type expression as
351+
// per https://github.com/dart-lang/sdk/issues/47302?
320352
if (!isConstantTypeExpression(elementType)) {
321353
nodes.add(elementType);
322354
}
@@ -350,7 +382,7 @@ class _ConstantTypeChecker {
350382

351383
_ConstantTypeChecker({required this.potentially});
352384

353-
/// Return `true` if the [node] is a constant type expression.
385+
/// Return `true` if the [node] is a (potentially) constant type expression.
354386
bool check(TypeAnnotation? node) {
355387
if (potentially) {
356388
if (node is NamedType) {

pkg/analyzer/test/src/dart/constant/potentially_constant_test.dart

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -458,6 +458,50 @@ var x = a ? b : c;
458458
]);
459459
}
460460

461+
test_constructorReference_explicitTypeArguments() async {
462+
await _assertConst('''
463+
class A {
464+
final B Function() x;
465+
const A(): x = B<int>.new;
466+
}
467+
468+
class B<T> {}
469+
''', () => findNode.constructorReference('B<int>.new'));
470+
}
471+
472+
test_constructorReference_noTypeArguments() async {
473+
await _assertConst('''
474+
class A {
475+
final B Function() x;
476+
const A(): x = B.new;
477+
}
478+
479+
class B {}
480+
''', () => findNode.constructorReference('B.new'));
481+
}
482+
483+
test_functionReference_explicitTypeArguments() async {
484+
await _assertConst('''
485+
class A {
486+
final int Function(int) x;
487+
const A(): x = id<int>;
488+
}
489+
490+
X id<X>(X x) => x;
491+
''', () => findNode.functionReference('id<int>'));
492+
}
493+
494+
test_functionReference_noTypeArguments() async {
495+
await _assertConst('''
496+
class A {
497+
final int Function(int) x;
498+
const A(): x = id;
499+
}
500+
501+
X id<X>(X x) => x;
502+
''', () => findNode.simple('id;'));
503+
}
504+
461505
test_ifElement_then() async {
462506
await _assertConst(r'''
463507
const a = 0;
@@ -1177,6 +1221,15 @@ var x = 'a';
11771221
''', () => _xInitializer());
11781222
}
11791223

1224+
test_typeLiteral() async {
1225+
await _assertConst('''
1226+
class A {
1227+
Type x;
1228+
const A(): x = List<int>;
1229+
}
1230+
''', () => findNode.typeLiteral('List<int>'));
1231+
}
1232+
11801233
_assertConst(String code, AstNode Function() getNode) async {
11811234
await resolveTestCode(code);
11821235
var node = getNode();

0 commit comments

Comments
 (0)