Skip to content

Commit ef8add0

Browse files
srawlinscommit-bot@chromium.org
authored and
commit-bot@chromium.org
committed
Analyzer function refs: report more disallowed instantiations
Only the following short list of elements are allowed to be type- instantiated: top-level function, local function, instance method, constructor, type. Bug: #46233 and Change-Id: I37e2a793b7fb25ef670152490e73b227b7c0cdac #46590 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/207643 Reviewed-by: Brian Wilkerson <brianwilkerson@google.com> Reviewed-by: Konstantin Shcheglov <scheglov@google.com> Commit-Queue: Samuel Rawlins <srawlins@google.com>
1 parent c058aac commit ef8add0

File tree

2 files changed

+115
-19
lines changed

2 files changed

+115
-19
lines changed

pkg/analyzer/lib/src/dart/resolver/function_reference_resolver.dart

Lines changed: 40 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,11 @@ class FunctionReferenceResolver {
225225
// Continue to resolve type.
226226
}
227227

228-
// TODO(srawlins): If PropertyAccessorElement, report error.
228+
if (member is PropertyAccessorElement) {
229+
function.accept(_resolver);
230+
_resolveDisallowedExpression(node, member.returnType);
231+
return;
232+
}
229233

230234
_resolve(node: node, rawType: member.type, name: propertyName.name);
231235
}
@@ -298,9 +302,11 @@ class FunctionReferenceResolver {
298302
return;
299303
}
300304

301-
// TODO(srawlins): Need to report cases where [methodElement] is not
302-
// generic. The 'test_instanceGetter_explicitReceiver' test case needs to
303-
// be updated to handle this.
305+
if (methodElement is PropertyAccessorElement) {
306+
function.accept(_resolver);
307+
_resolveDisallowedExpression(node, methodElement.returnType);
308+
return;
309+
}
304310

305311
function.accept(_resolver);
306312
node.staticType = DynamicTypeImpl.instance;
@@ -388,8 +394,6 @@ class FunctionReferenceResolver {
388394
PrefixedIdentifier prefix,
389395
Element element,
390396
) {
391-
// TODO(srawlins): Handle `loadLibrary`, as in `p.loadLibrary<int>;`.
392-
393397
if (element is MultiplyDefinedElement) {
394398
MultiplyDefinedElement multiply = element;
395399
element = multiply.conflictingElements[0];
@@ -472,17 +476,25 @@ class FunctionReferenceResolver {
472476
// Continue to assign types.
473477
}
474478

479+
if (method is PropertyAccessorElement) {
480+
_resolveDisallowedExpression(node, method.returnType);
481+
return;
482+
}
483+
475484
function.staticElement = method;
476485
function.staticType = method.type;
477486
_resolve(node: node, rawType: method.type, name: function.name);
478487
return;
479488
} else {
480-
// TODO(srawlins): Report CompileTimeErrorCode.UNDEFINED_METHOD.
489+
_resolver.errorReporter.reportErrorForNode(
490+
CompileTimeErrorCode.UNDEFINED_METHOD,
491+
function,
492+
[function.name, enclosingClass],
493+
);
494+
function.staticType = DynamicTypeImpl.instance;
495+
node.staticType = DynamicTypeImpl.instance;
481496
return;
482497
}
483-
484-
// TODO(srawlins): if `(target is PropertyAccessorElement)`, report an
485-
// error.
486498
}
487499

488500
// Classes and type aliases are checked first so as to include a
@@ -504,18 +516,34 @@ class FunctionReferenceResolver {
504516
_resolveTypeAlias(node: node, element: element, typeAlias: function);
505517
return;
506518
}
507-
} else if (element is ExecutableElement) {
519+
} else if (element is MethodElement) {
508520
function.staticElement = element;
509521
function.staticType = element.type;
510522
_resolve(node: node, rawType: element.type, name: element.name);
511523
return;
524+
} else if (element is FunctionElement) {
525+
function.staticElement = element;
526+
function.staticType = element.type;
527+
_resolve(node: node, rawType: element.type, name: element.name);
528+
return;
529+
} else if (element is PropertyAccessorElement) {
530+
function.staticElement = element;
531+
function.staticType = element.returnType;
532+
_resolveDisallowedExpression(node, element.returnType);
533+
return;
534+
} else if (element is ExecutableElement) {
535+
function.staticElement = element;
536+
function.staticType = element.type;
537+
_resolveDisallowedExpression(node, element.type);
538+
return;
512539
} else if (element is VariableElement) {
513540
function.staticElement = element;
514541
function.staticType = element.type;
515542
_resolveDisallowedExpression(node, element.type);
516543
return;
517544
} else {
518-
node.staticType = DynamicTypeImpl.instance;
545+
_resolveDisallowedExpression(node, DynamicTypeImpl.instance);
546+
return;
519547
}
520548
}
521549

pkg/analyzer/test/src/dart/resolution/function_reference_test.dart

Lines changed: 75 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,26 @@ bar() {
4141
assertType(reference, 'dynamic');
4242
}
4343

44+
test_extensionGetter_extensionOverride() async {
45+
await assertErrorsInCode('''
46+
class A {}
47+
48+
extension E on A {
49+
int get foo => 0;
50+
}
51+
52+
bar(A a) {
53+
E(a).foo<int>;
54+
}
55+
''', [
56+
error(
57+
CompileTimeErrorCode.DISALLOWED_TYPE_INSTANTIATION_EXPRESSION, 67, 8),
58+
]);
59+
60+
var reference = findNode.functionReference('foo<int>;');
61+
assertType(reference, 'dynamic');
62+
}
63+
4464
test_extensionMethod() async {
4565
await assertNoErrorsInCode('''
4666
class A {}
@@ -175,21 +195,41 @@ extension E on A {
175195
reference, findElement.method('foo'), 'void Function(int)');
176196
}
177197

198+
test_instanceGetter() async {
199+
await assertErrorsInCode('''
200+
abstract class A {
201+
late void Function<T>(T) foo;
202+
203+
bar() {
204+
foo<int>;
205+
}
206+
}
207+
208+
''', [
209+
error(
210+
CompileTimeErrorCode.DISALLOWED_TYPE_INSTANTIATION_EXPRESSION, 66, 3),
211+
]);
212+
213+
var reference = findNode.functionReference('foo<int>;');
214+
assertType(reference, 'void Function(int)');
215+
}
216+
178217
test_instanceGetter_explicitReceiver() async {
179-
// This test is here to assert that the resolver does not throw, but in the
180-
// future, an error should be reported here as well.
181-
await assertNoErrorsInCode('''
218+
await assertErrorsInCode('''
182219
class A {
183-
int foo = 0;
220+
late void Function<T>(T) foo;
184221
}
185222
186223
bar(A a) {
187224
a.foo<int>;
188225
}
189-
''');
226+
''', [
227+
error(
228+
CompileTimeErrorCode.DISALLOWED_TYPE_INSTANTIATION_EXPRESSION, 58, 5),
229+
]);
190230

191231
var reference = findNode.functionReference('foo<int>;');
192-
assertType(reference, 'dynamic');
232+
assertType(reference, 'void Function(int)');
193233
}
194234

195235
test_instanceMethod() async {
@@ -430,6 +470,21 @@ class B extends A {
430470
reference, findElement.method('foo'), 'void Function(int)');
431471
}
432472

473+
test_instanceMethod_unknown() async {
474+
await assertErrorsInCode('''
475+
class A {
476+
bar() {
477+
foo<int>;
478+
}
479+
}
480+
''', [
481+
error(CompileTimeErrorCode.UNDEFINED_METHOD, 24, 3),
482+
]);
483+
484+
var reference = findNode.functionReference('foo<int>;');
485+
assertType(reference, 'dynamic');
486+
}
487+
433488
test_localFunction() async {
434489
await assertNoErrorsInCode('''
435490
void bar() {
@@ -722,7 +777,20 @@ void bar() {
722777
);
723778
}
724779

725-
test_topLevelVariable_prefix_unknown() async {
780+
test_topLevelFunction_prefix_unknownPrefix() async {
781+
await assertErrorsInCode('''
782+
bar() {
783+
prefix.foo<int>;
784+
}
785+
''', [
786+
error(CompileTimeErrorCode.UNDEFINED_IDENTIFIER, 10, 6),
787+
]);
788+
789+
var reference = findNode.functionReference('foo<int>;');
790+
assertType(reference, 'dynamic');
791+
}
792+
793+
test_topLevelVariable_prefix_unknownIdentifier() async {
726794
newFile('$testPackageLibPath/a.dart', content: '');
727795
await assertErrorsInCode('''
728796
import 'a.dart' as prefix;

0 commit comments

Comments
 (0)