Skip to content

Commit

Permalink
Resolve MethodInvocation(s) with Never and Never? receivers.
Browse files Browse the repository at this point in the history
Change-Id: I7314efe7ccc352da7a407c3a657a30cc0956580b
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/130180
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
  • Loading branch information
scheglov authored and commit-bot@chromium.org committed Jan 4, 2020
1 parent d735f1f commit 76e3faa
Show file tree
Hide file tree
Showing 3 changed files with 219 additions and 124 deletions.
68 changes: 53 additions & 15 deletions pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart
Original file line number Diff line number Diff line change
Expand Up @@ -171,8 +171,8 @@ class MethodInvocationResolver {
return;
}

if (receiverType == NeverTypeImpl.instance) {
_reportUseOfNeverType(node, receiver);
if (receiverType is NeverTypeImpl) {
_resolveReceiverNever(node, receiver, receiverType);
return;
}
}
Expand Down Expand Up @@ -290,14 +290,6 @@ class MethodInvocationResolver {
);
}

void _reportUseOfNeverType(MethodInvocation node, AstNode errorNode) {
_setDynamicResolution(node);
_resolver.errorReporter.reportErrorForNode(
StaticWarningCode.INVALID_USE_OF_NEVER_VALUE,
errorNode,
);
}

void _reportUseOfVoidType(MethodInvocation node, AstNode errorNode) {
_setDynamicResolution(node);
_resolver.errorReporter.reportErrorForNode(
Expand All @@ -306,12 +298,19 @@ class MethodInvocationResolver {
);
}

void _resolveArguments_finishInference(MethodInvocation node) {
/// [InvocationExpression.staticInvokeType] has been set for the [node].
/// Use it to set context for arguments, and resolve them.
void _resolveArguments(MethodInvocation node) {
_inferenceHelper.inferArgumentTypesForInvocation(node);
node.argumentList.accept(_resolver);
}

void _resolveArguments_finishInference(MethodInvocation node) {
_resolveArguments(node);

_inferenceHelper.inferGenericInvocationExpression(node);

// TODO(scheglov) Call this only when member lookup failed?
var inferred = _inferenceHelper.inferMethodInvocationObject(node);

if (!inferred) {
Expand Down Expand Up @@ -589,6 +588,49 @@ class MethodInvocationResolver {
}
}

void _resolveReceiverNever(
MethodInvocation node,
Expression receiver,
DartType receiverType,
) {
_setExplicitTypeArgumentTypes();

if (receiverType == NeverTypeImpl.instanceNullable) {
var methodName = node.methodName;
var objectElement = _resolver.typeProvider.objectElement;
var objectMember = objectElement.getMethod(methodName.name);
if (objectMember != null) {
objectMember = _resolver.toLegacyElement(objectMember);
methodName.staticElement = objectMember;
_setResolution(
node,
_elementTypeProvider.getExecutableType(objectMember),
);
} else {
_setDynamicResolution(node);
_resolver.errorReporter.reportErrorForNode(
StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE,
receiver,
);
}
return;
}

if (receiverType == NeverTypeImpl.instance) {
node.methodName.staticType = _dynamicType;
node.staticInvokeType = _dynamicType;
node.staticType = NeverTypeImpl.instance;

_resolveArguments(node);

_resolver.errorReporter.reportErrorForNode(
StaticWarningCode.INVALID_USE_OF_NEVER_VALUE,
receiver,
);
return;
}
}

void _resolveReceiverNull(
MethodInvocation node, SimpleIdentifier nameNode, String name) {
var element = nameScope.lookup(nameNode, _definingLibrary);
Expand Down Expand Up @@ -958,10 +1000,6 @@ class MethodInvocationResolver {
return _reportUseOfVoidType(node, node.methodName);
}

if (type == NeverTypeImpl.instance) {
return _reportUseOfNeverType(node, node.methodName);
}

_reportInvocationOfNonFunction(node);
}

Expand Down
4 changes: 4 additions & 0 deletions pkg/analyzer/test/src/dart/element/nullable_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,8 @@ class IsNonNullableTest extends _NullableBase {

test_never() {
isNonNullable(neverNone);
isNotNonNullable(neverQuestion);
isNonNullable(neverStar);
}

test_null() {
Expand Down Expand Up @@ -238,6 +240,8 @@ class IsNullableTest extends _NullableBase {

test_never() {
isNotNullable(neverNone);
isNullable(neverQuestion);
isNotNullable(neverStar);
}

test_null() {
Expand Down
Loading

0 comments on commit 76e3faa

Please sign in to comment.