mirror of
https://github.com/dart-lang/sdk
synced 2024-10-06 14:39:38 +00:00
analyzer: Resolve extension methods on nullable Never type
Fixes https://github.com/dart-lang/sdk/issues/55000 Cq-Include-Trybots: luci.dart.try:flutter-analyze-try,analyzer-win-release-try,pkg-win-release-try Change-Id: Ie71d4762bc294028787c28976b2e0a7e604ab2fa Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/372880 Reviewed-by: Konstantin Shcheglov <scheglov@google.com> Commit-Queue: Sam Rawlins <srawlins@google.com>
This commit is contained in:
parent
89d9912790
commit
4d20dea313
|
@ -71,6 +71,10 @@ class MethodInvocationResolver with ScopeHelpers {
|
|||
|
||||
TypeSystemImpl get _typeSystem => _resolver.typeSystem;
|
||||
|
||||
/// Resolves the method invocation, [node].
|
||||
///
|
||||
/// If [node] is rewritten to be a [FunctionExpressionInvocation] in the
|
||||
/// process, then returns that new node. Otherwise, returns `null`.
|
||||
FunctionExpressionInvocation? resolve(
|
||||
MethodInvocationImpl node, List<WhyNotPromotedGetter> whyNotPromotedList,
|
||||
{required DartType contextType}) {
|
||||
|
@ -142,9 +146,9 @@ class MethodInvocationResolver with ScopeHelpers {
|
|||
}
|
||||
|
||||
if (receiverType is NeverTypeImpl) {
|
||||
_resolveReceiverNever(node, receiver, receiverType, whyNotPromotedList,
|
||||
contextType: contextType);
|
||||
return null;
|
||||
return _resolveReceiverNever(
|
||||
node, receiver, receiverType, whyNotPromotedList,
|
||||
contextType: contextType, nameNode: nameNode, name: name);
|
||||
}
|
||||
|
||||
if (receiverType is VoidType) {
|
||||
|
@ -344,6 +348,10 @@ class MethodInvocationResolver with ScopeHelpers {
|
|||
return null;
|
||||
}
|
||||
|
||||
/// Resolves the method invocation, [node], as an extension member.
|
||||
///
|
||||
/// If [node] is rewritten to be a [FunctionExpressionInvocation] in the
|
||||
/// process, then returns that new node. Otherwise, returns `null`.
|
||||
FunctionExpressionInvocation? _resolveExtensionMember(
|
||||
MethodInvocationImpl node,
|
||||
Identifier receiver,
|
||||
|
@ -380,6 +388,11 @@ class MethodInvocationResolver with ScopeHelpers {
|
|||
return null;
|
||||
}
|
||||
|
||||
/// Resolves the method invocation, [node], as called on an extension
|
||||
/// override.
|
||||
///
|
||||
/// If [node] is rewritten to be a [FunctionExpressionInvocation] in the
|
||||
/// process, then returns that new node. Otherwise, returns `null`.
|
||||
FunctionExpressionInvocation? _resolveExtensionOverride(
|
||||
MethodInvocationImpl node,
|
||||
ExtensionOverride override,
|
||||
|
@ -468,9 +481,20 @@ class MethodInvocationResolver with ScopeHelpers {
|
|||
.resolveInvocation(rawType: rawType);
|
||||
}
|
||||
|
||||
void _resolveReceiverNever(MethodInvocationImpl node, Expression receiver,
|
||||
DartType receiverType, List<WhyNotPromotedGetter> whyNotPromotedList,
|
||||
{required DartType contextType}) {
|
||||
/// Resolves the method invocation, [node], as an instance invocation on an
|
||||
/// expression of type `Never` or `Never?`.
|
||||
///
|
||||
/// If [node] is rewritten to be a [FunctionExpressionInvocation] in the
|
||||
/// process, then returns that new node. Otherwise, returns `null`.
|
||||
FunctionExpressionInvocation? _resolveReceiverNever(
|
||||
MethodInvocationImpl node,
|
||||
Expression receiver,
|
||||
DartType receiverType,
|
||||
List<WhyNotPromotedGetter> whyNotPromotedList, {
|
||||
required DartType contextType,
|
||||
required SimpleIdentifierImpl nameNode,
|
||||
required String name,
|
||||
}) {
|
||||
_setExplicitTypeArgumentTypes();
|
||||
|
||||
if (receiverType == NeverTypeImpl.instanceNullable) {
|
||||
|
@ -485,16 +509,19 @@ class MethodInvocationResolver with ScopeHelpers {
|
|||
whyNotPromotedList,
|
||||
contextType: contextType,
|
||||
);
|
||||
return null;
|
||||
} else {
|
||||
_setInvalidTypeResolution(node,
|
||||
whyNotPromotedList: whyNotPromotedList, contextType: contextType);
|
||||
_resolver.nullableDereferenceVerifier.report(
|
||||
CompileTimeErrorCode.UNCHECKED_METHOD_INVOCATION_OF_NULLABLE_VALUE,
|
||||
methodName,
|
||||
receiverType,
|
||||
return _resolveReceiverType(
|
||||
node: node,
|
||||
receiver: receiver,
|
||||
receiverType: receiverType,
|
||||
nameNode: nameNode,
|
||||
name: name,
|
||||
receiverErrorNode: receiver,
|
||||
whyNotPromotedList: whyNotPromotedList,
|
||||
contextType: contextType,
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (receiverType == NeverTypeImpl.instance) {
|
||||
|
@ -514,10 +541,16 @@ class MethodInvocationResolver with ScopeHelpers {
|
|||
node.methodName.setPseudoExpressionStaticType(_dynamicType);
|
||||
node.staticInvokeType = _dynamicType;
|
||||
node.recordStaticType(NeverTypeImpl.instance, resolver: _resolver);
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Resolves the method invocation, [node], as an instance invocation on an
|
||||
/// expression of type `Null`.
|
||||
///
|
||||
/// If [node] is rewritten to be a [FunctionExpressionInvocation] in the
|
||||
/// process, then returns that new node. Otherwise, returns `null`.
|
||||
FunctionExpressionInvocation? _resolveReceiverNull(
|
||||
MethodInvocationImpl node,
|
||||
SimpleIdentifierImpl nameNode,
|
||||
|
@ -620,6 +653,11 @@ class MethodInvocationResolver with ScopeHelpers {
|
|||
);
|
||||
}
|
||||
|
||||
/// Resolves the method invocation, [node], as a top-level function
|
||||
/// invocation, referenced with a prefix.
|
||||
///
|
||||
/// If [node] is rewritten to be a [FunctionExpressionInvocation] in the
|
||||
/// process, then returns that new node. Otherwise, returns `null`.
|
||||
FunctionExpressionInvocation? _resolveReceiverPrefix(
|
||||
MethodInvocationImpl node,
|
||||
PrefixElement prefix,
|
||||
|
@ -679,6 +717,11 @@ class MethodInvocationResolver with ScopeHelpers {
|
|||
return null;
|
||||
}
|
||||
|
||||
/// Resolves the method invocation, [node], as an instance invocation a
|
||||
/// `super` expression.
|
||||
///
|
||||
/// If [node] is rewritten to be a [FunctionExpressionInvocation] in the
|
||||
/// process, then returns that new node. Otherwise, returns `null`.
|
||||
FunctionExpressionInvocation? _resolveReceiverSuper(
|
||||
MethodInvocationImpl node,
|
||||
SuperExpression receiver,
|
||||
|
@ -740,6 +783,10 @@ class MethodInvocationResolver with ScopeHelpers {
|
|||
return null;
|
||||
}
|
||||
|
||||
/// Resolves the type of the receiver of the method invocation, [node].
|
||||
///
|
||||
/// If [node] is rewritten to be a [FunctionExpressionInvocation] in the
|
||||
/// process, then returns that new node. Otherwise, returns `null`.
|
||||
FunctionExpressionInvocation? _resolveReceiverType({
|
||||
required MethodInvocationImpl node,
|
||||
required Expression? receiver,
|
||||
|
@ -830,6 +877,11 @@ class MethodInvocationResolver with ScopeHelpers {
|
|||
return null;
|
||||
}
|
||||
|
||||
/// Resolves the method invocation, [node], as an method invocation with a
|
||||
/// type literal target.
|
||||
///
|
||||
/// If [node] is rewritten to be a [FunctionExpressionInvocation] in the
|
||||
/// process, then returns that new node. Otherwise, returns `null`.
|
||||
FunctionExpressionInvocation? _resolveReceiverTypeLiteral(
|
||||
MethodInvocationImpl node,
|
||||
InterfaceElement receiver,
|
||||
|
@ -882,12 +934,14 @@ class MethodInvocationResolver with ScopeHelpers {
|
|||
return null;
|
||||
}
|
||||
|
||||
/// Rewrites [node] as a [FunctionExpressionInvocation].
|
||||
///
|
||||
/// We have identified that [node] is not a real [MethodInvocation],
|
||||
/// because it does not invoke a method, but instead invokes the result
|
||||
/// of a getter execution, or implicitly invokes the `call` method of
|
||||
/// an [InterfaceType]. So, it should be represented as instead as a
|
||||
/// [FunctionExpressionInvocation].
|
||||
FunctionExpressionInvocation? _rewriteAsFunctionExpressionInvocation(
|
||||
FunctionExpressionInvocation _rewriteAsFunctionExpressionInvocation(
|
||||
MethodInvocationImpl node, DartType getterReturnType,
|
||||
{bool isSuperAccess = false}) {
|
||||
var targetType = _typeSystem.resolveToBound(getterReturnType);
|
||||
|
|
|
@ -267,6 +267,10 @@ class ElementResolver {
|
|||
_resolveAnnotations(node.metadata);
|
||||
}
|
||||
|
||||
/// Resolves the method invocation, [node].
|
||||
///
|
||||
/// If [node] is rewritten to be a [FunctionExpressionInvocation] in the
|
||||
/// process, then returns that new node. Otherwise, returns `null`.
|
||||
FunctionExpressionInvocation? visitMethodInvocation(MethodInvocation node,
|
||||
{List<WhyNotPromotedGetter>? whyNotPromotedList,
|
||||
required DartType contextType}) {
|
||||
|
|
|
@ -216,6 +216,18 @@ extension E on A? {
|
|||
]);
|
||||
}
|
||||
|
||||
test_methodInvocation_nuverNullable_extensionMethod() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
extension<X> on X {
|
||||
X m() => this;
|
||||
}
|
||||
|
||||
Future<void> f(Never? x) async {
|
||||
(await x).m();
|
||||
}
|
||||
''');
|
||||
}
|
||||
|
||||
test_prefixExpression_minus_nonNullable() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
class A {
|
||||
|
|
Loading…
Reference in a new issue