@@ -250,6 +250,9 @@ class TypeInferrerImpl implements TypeInferrer {
250
250
251
251
CoreTypes get coreTypes => engine.coreTypes;
252
252
253
+ bool get isInferenceUpdate1Enabled =>
254
+ libraryBuilder.isInferenceUpdate1Enabled;
255
+
253
256
bool get isNonNullableByDefault => libraryBuilder.isNonNullableByDefault;
254
257
255
258
NnbdMode get nnbdMode => libraryBuilder.loader.nnbdMode;
@@ -2395,10 +2398,41 @@ class TypeInferrerImpl implements TypeInferrer {
2395
2398
hoistingEndIndex = 0 ;
2396
2399
}
2397
2400
2401
+ ExpressionInferenceResult inferArgument (
2402
+ DartType formalType, Expression argumentExpression,
2403
+ {required bool isNamed}) {
2404
+ DartType inferredFormalType = substitution != null
2405
+ ? substitution.substituteType (formalType)
2406
+ : formalType;
2407
+ if (! isNamed) {
2408
+ if (isSpecialCasedBinaryOperator) {
2409
+ inferredFormalType =
2410
+ typeSchemaEnvironment.getContextTypeOfSpecialCasedBinaryOperator (
2411
+ typeContext, receiverType! , inferredFormalType,
2412
+ isNonNullableByDefault: isNonNullableByDefault);
2413
+ } else if (isSpecialCasedTernaryOperator) {
2414
+ inferredFormalType =
2415
+ typeSchemaEnvironment.getContextTypeOfSpecialCasedTernaryOperator (
2416
+ typeContext, receiverType! , inferredFormalType,
2417
+ isNonNullableByDefault: isNonNullableByDefault);
2418
+ }
2419
+ }
2420
+ return inferExpression (
2421
+ argumentExpression,
2422
+ isNonNullableByDefault
2423
+ ? inferredFormalType
2424
+ : legacyErasure (inferredFormalType),
2425
+ inferenceNeeded ||
2426
+ isSpecialCasedBinaryOperator ||
2427
+ isSpecialCasedTernaryOperator ||
2428
+ typeChecksNeeded);
2429
+ }
2430
+
2398
2431
List <EqualityInfo <VariableDeclaration , DartType >?>? identicalInfo =
2399
2432
isIdentical && arguments.positional.length == 2 ? [] : null ;
2400
2433
int positionalIndex = 0 ;
2401
2434
int namedIndex = 0 ;
2435
+ List <_DeferredParamInfo >? deferredFunctionLiterals;
2402
2436
for (int evaluationOrderIndex = 0 ;
2403
2437
evaluationOrderIndex < argumentsEvaluationOrder.length;
2404
2438
evaluationOrderIndex++ ) {
@@ -2421,60 +2455,77 @@ class TypeInferrerImpl implements TypeInferrer {
2421
2455
formalType = getNamedParameterType (calleeType, namedArgument.name);
2422
2456
argumentExpression = namedArgument.value;
2423
2457
}
2424
- DartType inferredFormalType = substitution != null
2425
- ? substitution.substituteType (formalType)
2426
- : formalType;
2427
- if (isExpression) {
2428
- if (isImplicitExtensionMember && index == 0 ) {
2429
- assert (
2430
- receiverType != null ,
2431
- "No receiver type provided for implicit extension member "
2432
- "invocation." );
2433
- continue ;
2434
- }
2435
- if (isSpecialCasedBinaryOperator) {
2436
- inferredFormalType =
2437
- typeSchemaEnvironment.getContextTypeOfSpecialCasedBinaryOperator (
2438
- typeContext, receiverType! , inferredFormalType,
2439
- isNonNullableByDefault: isNonNullableByDefault);
2440
- } else if (isSpecialCasedTernaryOperator) {
2441
- inferredFormalType =
2442
- typeSchemaEnvironment.getContextTypeOfSpecialCasedTernaryOperator (
2443
- typeContext, receiverType! , inferredFormalType,
2444
- isNonNullableByDefault: isNonNullableByDefault);
2445
- }
2446
- }
2447
- ExpressionInferenceResult result = inferExpression (
2448
- argumentExpression,
2449
- isNonNullableByDefault
2450
- ? inferredFormalType
2451
- : legacyErasure (inferredFormalType),
2452
- inferenceNeeded ||
2453
- isSpecialCasedBinaryOperator ||
2454
- isSpecialCasedTernaryOperator ||
2455
- typeChecksNeeded);
2456
- DartType inferredType = identical (result.inferredType, noInferredType) ||
2457
- isNonNullableByDefault
2458
- ? result.inferredType
2459
- : legacyErasure (result.inferredType);
2460
- if (localHoistedExpressions != null &&
2461
- evaluationOrderIndex >= hoistingEndIndex) {
2462
- hoistedExpressions = null ;
2458
+ if (isExpression && isImplicitExtensionMember && index == 0 ) {
2459
+ assert (
2460
+ receiverType != null ,
2461
+ "No receiver type provided for implicit extension member "
2462
+ "invocation." );
2463
+ continue ;
2463
2464
}
2464
- Expression expression =
2465
- _hoist (result.expression, inferredType, hoistedExpressions);
2466
- identicalInfo
2467
- ? .add (flowAnalysis.equalityOperand_end (expression, inferredType));
2468
- if (isExpression) {
2469
- arguments.positional[index] = expression..parent = arguments;
2465
+ if (isInferenceUpdate1Enabled &&
2466
+ argumentExpression is FunctionExpression ) {
2467
+ (deferredFunctionLiterals ?? = []).add (new _DeferredParamInfo (
2468
+ formalType: formalType,
2469
+ argumentExpression: argumentExpression,
2470
+ isNamed: ! isExpression,
2471
+ evaluationOrderIndex: evaluationOrderIndex,
2472
+ index: index));
2473
+ // We don't have `identical` info yet, so fill it in with `null` for
2474
+ // now. Later, when we visit the function literal, we'll replace it.
2475
+ identicalInfo? .add (null );
2476
+ if (useFormalAndActualTypes) {
2477
+ formalTypes! .add (formalType);
2478
+ // We don't have an inferred type yet, so fill it in with UnknownType
2479
+ // for now. Later, when we infer a type, we'll replace it.
2480
+ actualTypes! .add (const UnknownType ());
2481
+ }
2470
2482
} else {
2471
- NamedExpression namedArgument = arguments.named[index];
2472
- namedArgument.value = expression..parent = namedArgument;
2483
+ ExpressionInferenceResult result = inferArgument (
2484
+ formalType, argumentExpression,
2485
+ isNamed: ! isExpression);
2486
+ DartType inferredType = _computeInferredType (result);
2487
+ if (localHoistedExpressions != null &&
2488
+ evaluationOrderIndex >= hoistingEndIndex) {
2489
+ hoistedExpressions = null ;
2490
+ }
2491
+ Expression expression =
2492
+ _hoist (result.expression, inferredType, hoistedExpressions);
2493
+ identicalInfo
2494
+ ? .add (flowAnalysis.equalityOperand_end (expression, inferredType));
2495
+ if (isExpression) {
2496
+ arguments.positional[index] = expression..parent = arguments;
2497
+ } else {
2498
+ NamedExpression namedArgument = arguments.named[index];
2499
+ namedArgument.value = expression..parent = namedArgument;
2500
+ }
2501
+ gatherer? .tryConstrainLower (formalType, inferredType);
2502
+ if (useFormalAndActualTypes) {
2503
+ formalTypes! .add (formalType);
2504
+ actualTypes! .add (inferredType);
2505
+ }
2473
2506
}
2474
- gatherer? .tryConstrainLower (formalType, inferredType);
2475
- if (useFormalAndActualTypes) {
2476
- formalTypes! .add (formalType);
2477
- actualTypes! .add (inferredType);
2507
+ }
2508
+ if (deferredFunctionLiterals != null ) {
2509
+ for (_DeferredParamInfo deferredArgument in deferredFunctionLiterals) {
2510
+ ExpressionInferenceResult result = inferArgument (
2511
+ deferredArgument.formalType, deferredArgument.argumentExpression,
2512
+ isNamed: deferredArgument.isNamed);
2513
+ DartType inferredType = _computeInferredType (result);
2514
+ Expression expression = result.expression;
2515
+ identicalInfo? [deferredArgument.evaluationOrderIndex] =
2516
+ flowAnalysis.equalityOperand_end (expression, inferredType);
2517
+ if (deferredArgument.isNamed) {
2518
+ NamedExpression namedArgument =
2519
+ arguments.named[deferredArgument.index];
2520
+ namedArgument.value = expression..parent = namedArgument;
2521
+ } else {
2522
+ arguments.positional[deferredArgument.index] = expression
2523
+ ..parent = arguments;
2524
+ }
2525
+ gatherer? .tryConstrainLower (deferredArgument.formalType, inferredType);
2526
+ if (useFormalAndActualTypes) {
2527
+ actualTypes! [deferredArgument.evaluationOrderIndex] = inferredType;
2528
+ }
2478
2529
}
2479
2530
}
2480
2531
if (identicalInfo != null ) {
@@ -4718,6 +4769,11 @@ class TypeInferrerImpl implements TypeInferrer {
4718
4769
Expression createEqualsNull (int fileOffset, Expression left) {
4719
4770
return new EqualsNull (left)..fileOffset = fileOffset;
4720
4771
}
4772
+
4773
+ DartType _computeInferredType (ExpressionInferenceResult result) =>
4774
+ identical (result.inferredType, noInferredType) || isNonNullableByDefault
4775
+ ? result.inferredType
4776
+ : legacyErasure (result.inferredType);
4721
4777
}
4722
4778
4723
4779
class TypeInferrerImplBenchmarked implements TypeInferrer {
@@ -5877,3 +5933,33 @@ class ImplicitInstantiation {
5877
5933
ImplicitInstantiation (
5878
5934
this .typeArguments, this .functionType, this .instantiatedType);
5879
5935
}
5936
+
5937
+ /// Information about an invocation argument that needs to be resolved later due
5938
+ /// to the fact that it's a function literal and the `inference-update-1`
5939
+ /// feature is enabled.
5940
+ class _DeferredParamInfo {
5941
+ /// The (unsubstituted) type of the formal parameter corresponding to this
5942
+ /// argument.
5943
+ final DartType formalType;
5944
+
5945
+ /// The function literal expression.
5946
+ final FunctionExpression argumentExpression;
5947
+
5948
+ /// Indicates whether this is a named argument.
5949
+ final bool isNamed;
5950
+
5951
+ /// The index into the full argument list (considering both named and unnamed
5952
+ /// arguments) of the function literal expression.
5953
+ final int evaluationOrderIndex;
5954
+
5955
+ /// The index into either [Arguments.named] or [Arguments.positional] of the
5956
+ /// function literal expression (depending upon the value of [isNamed] ).
5957
+ final int index;
5958
+
5959
+ _DeferredParamInfo (
5960
+ {required this .formalType,
5961
+ required this .argumentExpression,
5962
+ required this .isNamed,
5963
+ required this .evaluationOrderIndex,
5964
+ required this .index});
5965
+ }
0 commit comments