Skip to content

Commit be68f15

Browse files
johnniwintherCommit Queue
authored andcommitted
[cfe] Perform extension invocation inference on the original arguments
This changes how extension invocation is performed. Previously the inference was done on the lowered encoding, requiring the inference to bypass the synthesized extension type parameters and the extension receiver. The new approach uses the arguments directly for the source, avoiding a lot of complexity in the inference and aligning with the principle of only performing lowering _after_ inference. Change-Id: I70973ee647b074589e1905c2993a846c15a70ce4 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/447581 Commit-Queue: Johnni Winther <[email protected]> Reviewed-by: Chloe Stefantsova <[email protected]>
1 parent 9a0992f commit be68f15

30 files changed

+847
-708
lines changed

pkg/front_end/lib/src/kernel/body_builder.dart

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6323,20 +6323,12 @@ class BodyBuilder extends StackListenerImpl
63236323

63246324
@override
63256325
LocatedMessage? checkArgumentsForType(
6326-
FunctionType function, Arguments arguments, int offset,
6327-
{bool isExtensionMemberInvocation = false}) {
6326+
FunctionType function, Arguments arguments, int offset) {
63286327
int requiredPositionalParameterCountToReport =
63296328
function.requiredParameterCount;
63306329
int positionalParameterCountToReport = function.positionalParameters.length;
63316330
int positionalArgumentCountToReport =
63326331
forest.argumentsPositional(arguments).length;
6333-
if (isExtensionMemberInvocation) {
6334-
// Extension member invocations have additional synthetic parameter for
6335-
// `this`.
6336-
--requiredPositionalParameterCountToReport;
6337-
--positionalParameterCountToReport;
6338-
--positionalArgumentCountToReport;
6339-
}
63406332
if (forest.argumentsPositional(arguments).length <
63416333
function.requiredParameterCount) {
63426334
return cfe.codeTooFewArguments

pkg/front_end/lib/src/kernel/internal_ast.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ import '../type_inference/type_schema.dart' show UnknownType;
3737
typedef SharedMatchContext = shared.MatchContext<TreeNode, Expression, Pattern,
3838
SharedTypeView, VariableDeclaration>;
3939

40+
// Coverage-ignore(suite): Not run.
4041
int getExtensionTypeParameterCount(Arguments arguments) {
4142
if (arguments is ArgumentsImpl) {
4243
return arguments._extensionTypeParameterCount;
@@ -46,6 +47,7 @@ int getExtensionTypeParameterCount(Arguments arguments) {
4647
}
4748
}
4849

50+
// Coverage-ignore(suite): Not run.
4951
List<DartType>? getExplicitExtensionTypeArguments(Arguments arguments) {
5052
if (arguments is ArgumentsImpl) {
5153
if (arguments._explicitExtensionTypeArgumentCount == 0) {
@@ -141,6 +143,7 @@ List<DartType>? getExplicitTypeArguments(Arguments arguments) {
141143
} else if (arguments._extensionTypeParameterCount == 0) {
142144
return arguments.types;
143145
} else {
146+
// Coverage-ignore-block(suite): Not run.
144147
return arguments.types
145148
.skip(arguments._extensionTypeParameterCount)
146149
.toList();
@@ -475,6 +478,7 @@ class ArgumentsImpl extends Arguments {
475478
static List<DartType> _normalizeTypeArguments(
476479
int length, List<DartType> arguments) {
477480
if (arguments.isEmpty && length > 0) {
481+
// Coverage-ignore-block(suite): Not run.
478482
return new List<DartType>.filled(length, const UnknownType());
479483
}
480484
return arguments;

pkg/front_end/lib/src/type_inference/inference_helper.dart

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,7 @@ abstract class InferenceHelper {
1616
Expression? expression});
1717

1818
LocatedMessage? checkArgumentsForType(
19-
FunctionType function, Arguments arguments, int offset,
20-
{bool isExtensionMemberInvocation = false});
19+
FunctionType function, Arguments arguments, int offset);
2120

2221
void addProblem(Message message, int charOffset, int length,
2322
{List<LocatedMessage>? context, bool wasHandled = false});

pkg/front_end/lib/src/type_inference/inference_results.dart

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,12 @@ abstract class InvocationInferenceResult {
109109
///
110110
/// A successful result leaves [expression] intact, and an error detected
111111
/// during inference would wrap the expression into an [InvalidExpression].
112-
Expression applyResult(Expression expression);
112+
///
113+
/// If the [expression] is an invocation of an extension instance method or
114+
/// an extension type instance method, then [extensionReceiverType] must be
115+
/// provided to support hoisting the receiver, if necessary.
116+
Expression applyResult(Expression expression,
117+
{DartType? extensionReceiverType});
113118

114119
/// Returns `true` if the arguments of the call where not applicable to the
115120
/// target.
@@ -141,7 +146,8 @@ class SuccessfulInferenceResult implements InvocationInferenceResult {
141146
{required this.hoistedArguments, this.inferredReceiverType});
142147

143148
@override
144-
Expression applyResult(Expression expression) {
149+
Expression applyResult(Expression expression,
150+
{DartType? extensionReceiverType}) {
145151
List<VariableDeclaration>? hoistedArguments = this.hoistedArguments;
146152
if (hoistedArguments == null || hoistedArguments.isEmpty) {
147153
return expression;
@@ -189,6 +195,19 @@ class SuccessfulInferenceResult implements InvocationInferenceResult {
189195
return InvocationInferenceResult._insertHoistedExpressions(
190196
expression, hoistedArguments);
191197
} else if (expression is StaticInvocation) {
198+
if (extensionReceiverType != null) {
199+
Expression receiver = expression.arguments.positional.first;
200+
if (!isPureExpression(receiver)) {
201+
VariableDeclaration receiverVariable =
202+
createVariable(receiver, extensionReceiverType);
203+
expression.arguments.positional.first =
204+
createVariableGet(receiverVariable)..parent = expression;
205+
return createLet(
206+
receiverVariable,
207+
InvocationInferenceResult._insertHoistedExpressions(
208+
expression, hoistedArguments));
209+
}
210+
}
192211
return InvocationInferenceResult._insertHoistedExpressions(
193212
expression, hoistedArguments);
194213
} else if (expression is SuperMethodInvocation) {
@@ -233,7 +252,8 @@ class WrapInProblemInferenceResult implements InvocationInferenceResult {
233252
{required this.isInapplicable, required this.hoistedArguments});
234253

235254
@override
236-
Expression applyResult(Expression expression) {
255+
Expression applyResult(Expression expression,
256+
{DartType? extensionReceiverType}) {
237257
expression = helper.wrapInProblem(expression, message, fileOffset, length);
238258
List<VariableDeclaration>? hoistedArguments = this.hoistedArguments;
239259
if (hoistedArguments == null || hoistedArguments.isEmpty) {

pkg/front_end/lib/src/type_inference/inference_visitor.dart

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1538,27 +1538,24 @@ class InferenceVisitorImpl extends InferenceVisitorBase
15381538
receiver = ensureAssignable(extensionOnType, receiverType, receiver);
15391539
receiverType = extensionOnType;
15401540

1541-
ArgumentsImpl extensionInvocationArguments =
1542-
createExtensionInvocationArgument(target, receiver, node.arguments);
1543-
15441541
InvocationTargetType invocationTargetType = target.getFunctionType(this);
1545-
TypeArgumentsInfo typeArgumentsInfo =
1546-
getTypeArgumentsInfo(extensionInvocationArguments);
15471542
InvocationInferenceResult result = inferInvocation(this, typeContext,
1548-
node.fileOffset, invocationTargetType, extensionInvocationArguments,
1549-
staticTarget: node.method,
1550-
receiverType: receiverType,
1551-
isExtensionMemberInvocation: true);
1543+
node.fileOffset, invocationTargetType, node.arguments,
1544+
staticTarget: node.method, receiverType: receiverType);
15521545

1546+
ArgumentsImpl extensionInvocationArguments =
1547+
createExtensionInvocationArgument(target, receiver, node.arguments);
15531548
StaticInvocation replacement = createStaticInvocation(
15541549
node.method, extensionInvocationArguments,
15551550
fileOffset: node.fileOffset);
15561551

1552+
TypeArgumentsInfo typeArgumentsInfo =
1553+
getTypeArgumentsInfo(extensionInvocationArguments);
15571554
libraryBuilder.checkBoundsInStaticInvocation(replacement, node.name,
15581555
typeSchemaEnvironment, helper.uri, typeArgumentsInfo);
15591556

1560-
return new ExpressionInferenceResult(
1561-
result.inferredType, result.applyResult(replacement));
1557+
return new ExpressionInferenceResult(result.inferredType,
1558+
result.applyResult(replacement, extensionReceiverType: receiverType));
15621559
}
15631560

15641561
ExpressionInferenceResult visitExtensionIfNullSet(

0 commit comments

Comments
 (0)