Skip to content

Commit

Permalink
Set context type for extension override receiver.
Browse files Browse the repository at this point in the history
Change-Id: I9c32f67af8e934ac78c580c97174547278618bfe
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/112320
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
  • Loading branch information
scheglov authored and commit-bot@chromium.org committed Aug 9, 2019
1 parent dc2c942 commit b0d079a
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 15 deletions.
65 changes: 50 additions & 15 deletions pkg/analyzer/lib/src/dart/resolver/extension_member_resolver.dart
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ class ExtensionMemberResolver {
return ExtensionResolutionResult.ambiguous;
}

/// Perform upward inference for the override.
void resolveOverride(ExtensionOverride node) {
var nodeImpl = node as ExtensionOverrideImpl;
var element = node.staticElement;
Expand Down Expand Up @@ -114,6 +115,44 @@ class ExtensionMemberResolver {
}
}

/// Set the type context for the receiver of the override.
///
/// The context of the invocation that is made through the override does
/// not affect the type inference of the override and the receiver.
void setOverrideReceiverContextType(ExtensionOverride node) {
var element = node.staticElement;
var typeParameters = element.typeParameters;

var arguments = node.argumentList.arguments;
if (arguments.length != 1) {
return;
}

List<DartType> typeArgumentTypes;
var typeArguments = node.typeArguments;
if (typeArguments != null) {
var arguments = typeArguments.arguments;
if (arguments.length == typeParameters.length) {
typeArgumentTypes = arguments.map((a) => a.type).toList();
} else {
typeArgumentTypes = _listOfDynamic(typeParameters);
}
} else {
typeArgumentTypes = List.filled(
typeParameters.length,
UnknownInferredType.instance,
);
}

var extendedForDownward = Substitution.fromPairs(
typeParameters,
typeArgumentTypes,
).substituteType(element.extendedType);

var receiver = arguments[0];
InferenceContext.setType(receiver, extendedForDownward);
}

/// Return the most specific extension or `null` if no single one can be
/// identified.
InstantiatedExtension _chooseMostSpecific(
Expand Down Expand Up @@ -295,21 +334,17 @@ class ExtensionMemberResolver {
return _listOfDynamic(typeParameters);
}
} else {
if (receiverType != null) {
var inferrer = GenericInferrer(
_typeProvider,
_typeSystem,
typeParameters,
);
inferrer.constrainArgument(
receiverType,
extension.extendedType,
'extendedType',
);
return inferrer.infer(typeParameters);
} else {
return _listOfDynamic(typeParameters);
}
var inferrer = GenericInferrer(
_typeProvider,
_typeSystem,
typeParameters,
);
inferrer.constrainArgument(
receiverType,
extension.extendedType,
'extendedType',
);
return inferrer.infer(typeParameters);
}
}

Expand Down
13 changes: 13 additions & 0 deletions pkg/analyzer/lib/src/generated/resolver.dart
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
import 'package:analyzer/src/dart/element/member.dart' show ConstructorMember;
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/dart/resolver/exit_detector.dart';
import 'package:analyzer/src/dart/resolver/extension_member_resolver.dart';
import 'package:analyzer/src/dart/resolver/flow_analysis_visitor.dart';
import 'package:analyzer/src/dart/resolver/scope.dart';
import 'package:analyzer/src/diagnostic/diagnostic_factory.dart';
Expand Down Expand Up @@ -3824,6 +3825,18 @@ class ResolverVisitor extends ScopedVisitor {
}
}

@override
void visitExtensionOverride(ExtensionOverride node) {
node.extensionName.accept(this);
node.typeArguments?.accept(this);

ExtensionMemberResolver(this).setOverrideReceiverContextType(node);
node.argumentList.accept(this);

node.accept(elementResolver);
node.accept(typeAnalyzer);
}

@override
void visitForElementInScope(ForElement node) {
ForLoopParts forLoopParts = node.forLoopParts;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,48 @@ void f(A<int> a) {
);
}

test_override_downward_hasTypeArguments() async {
await assertNoErrorsInCode('''
extension E<T> on Set<T> {
void foo() {}
}
main() {
E<int>({}).foo();
}
''');
var literal = findNode.setOrMapLiteral('{}).');
assertType(literal, 'Set<int>');
}

test_override_downward_hasTypeArguments_wrongNumber() async {
await assertNoErrorsInCode('''
extension E<T> on Set<T> {
void foo() {}
}
main() {
E<int, bool>({}).foo();
}
''');
var literal = findNode.setOrMapLiteral('{}).');
assertType(literal, 'Set<dynamic>');
}

test_override_downward_noTypeArguments() async {
await assertNoErrorsInCode('''
extension E<T> on Set<T> {
void foo() {}
}
main() {
E({}).foo();
}
''');
var literal = findNode.setOrMapLiteral('{}).');
assertType(literal, 'Set<dynamic>');
}

test_override_hasTypeArguments_getter() async {
await assertNoErrorsInCode('''
class A<T> {}
Expand Down

0 comments on commit b0d079a

Please sign in to comment.