22// for details. All rights reserved. Use of this source code is governed by a
33// BSD-style license that can be found in the LICENSE.md file.
44
5+ import 'package:_fe_analyzer_shared/src/deferred_function_literal_heuristic.dart' ;
56import 'package:_fe_analyzer_shared/src/flow_analysis/flow_analysis.dart' ;
67import 'package:_fe_analyzer_shared/src/testing/id.dart' ;
78import 'package:_fe_analyzer_shared/src/util/link.dart' ;
@@ -82,6 +83,59 @@ bool isOverloadableArithmeticOperator(String name) {
8283 identical (name, '%' );
8384}
8485
86+ /// Given a [FunctionExpression] , computes a set whose elements consist of (a)
87+ /// an integer corresponding to the zero-based index of each positional
88+ /// parameter of the function expression that has an explicit type annotation,
89+ /// and (b) a string corresponding to the name of each named parameter of the
90+ /// function expression that has an explicit type annotation.
91+ Set <Object > _computeExplicitlyTypedParameterSet (
92+ FunctionExpression functionExpression) {
93+ Set <Object > result = {};
94+ int unnamedParameterIndex = 0 ;
95+ for (VariableDeclaration positionalParameter
96+ in functionExpression.function.positionalParameters) {
97+ int key = unnamedParameterIndex++ ;
98+ if (! (positionalParameter as VariableDeclarationImpl ).isImplicitlyTyped) {
99+ result.add (key);
100+ }
101+ }
102+ for (VariableDeclaration namedParameter
103+ in functionExpression.function.namedParameters) {
104+ String key = namedParameter.name! ;
105+ if (! (namedParameter as VariableDeclarationImpl ).isImplicitlyTyped) {
106+ result.add (key);
107+ }
108+ }
109+ return result;
110+ }
111+
112+ /// Given an function type, computes a map based on the parameters whose keys
113+ /// are either the parameter name (for named parameters) or the zero-based
114+ /// integer index (for unnamed parameters), and whose values are the parameter
115+ /// types.
116+ Map <Object , DartType > _computeParameterMap (FunctionType functionType) => {
117+ for (int i = 0 ; i < functionType.positionalParameters.length; i++ )
118+ i: functionType.positionalParameters[i],
119+ for (NamedType namedType in functionType.namedParameters)
120+ namedType.name: namedType.type
121+ };
122+
123+ /// Computes a list of [_ParamInfo] objects corresponding to the invocation
124+ /// parameters that were *not* deferred.
125+ List <_ParamInfo > _computeUndeferredParamInfo (List <DartType > formalTypes,
126+ List <_DeferredParamInfo > deferredFunctionLiterals) {
127+ // TODO(paulberry): test that the right thing happens when evaluation order differs from classic (positional/named) order.
128+ Set <int > evaluationOrderIndicesAlreadyCovered = {
129+ for (_DeferredParamInfo functionLiteral in deferredFunctionLiterals)
130+ functionLiteral.evaluationOrderIndex
131+ };
132+ return [
133+ for (int i = 0 ; i < formalTypes.length; i++ )
134+ if (! evaluationOrderIndicesAlreadyCovered.contains (i))
135+ new _ParamInfo (formalTypes[i])
136+ ];
137+ }
138+
85139/// Enum denoting the kinds of contravariance check that might need to be
86140/// inserted for a method call.
87141enum MethodContravarianceCheckKind {
@@ -2290,7 +2344,8 @@ class TypeInferrerImpl implements TypeInferrer {
22902344 explicitTypeArguments == null &&
22912345 calleeTypeParameters.isNotEmpty;
22922346 bool typeChecksNeeded = ! isTopLevel;
2293- bool useFormalAndActualTypes = typeChecksNeeded ||
2347+ bool useFormalAndActualTypes = inferenceNeeded ||
2348+ typeChecksNeeded ||
22942349 isSpecialCasedBinaryOperator ||
22952350 isSpecialCasedTernaryOperator;
22962351
@@ -2331,7 +2386,7 @@ class TypeInferrerImpl implements TypeInferrer {
23312386 calleeTypeParameters,
23322387 typeContext,
23332388 libraryBuilder.library);
2334- typeSchemaEnvironment.downwardsInfer (gatherer, calleeTypeParameters,
2389+ typeSchemaEnvironment.partialInfer (gatherer, calleeTypeParameters,
23352390 inferredTypes, libraryBuilder.library);
23362391 substitution =
23372392 Substitution .fromPairs (calleeTypeParameters, inferredTypes);
@@ -2471,6 +2526,7 @@ class TypeInferrerImpl implements TypeInferrer {
24712526 (deferredFunctionLiterals ?? = []).add (new _DeferredParamInfo (
24722527 formalType: formalType,
24732528 argumentExpression: argumentExpression,
2529+ unparenthesizedExpression: unparenthesizedExpression,
24742530 isNamed: ! isExpression,
24752531 evaluationOrderIndex: evaluationOrderIndex,
24762532 index: index));
@@ -2510,26 +2566,44 @@ class TypeInferrerImpl implements TypeInferrer {
25102566 }
25112567 }
25122568 if (deferredFunctionLiterals != null ) {
2513- for (_DeferredParamInfo deferredArgument in deferredFunctionLiterals) {
2514- ExpressionInferenceResult result = inferArgument (
2515- deferredArgument.formalType, deferredArgument.argumentExpression,
2516- isNamed: deferredArgument.isNamed);
2517- DartType inferredType = _computeInferredType (result);
2518- Expression expression = result.expression;
2519- identicalInfo? [deferredArgument.evaluationOrderIndex] =
2520- flowAnalysis.equalityOperand_end (expression, inferredType);
2521- if (deferredArgument.isNamed) {
2522- NamedExpression namedArgument =
2523- arguments.named[deferredArgument.index];
2524- namedArgument.value = expression..parent = namedArgument;
2525- } else {
2526- arguments.positional[deferredArgument.index] = expression
2527- ..parent = arguments;
2569+ bool isFirstStage = true ;
2570+ for (List <_DeferredParamInfo > stage in new _FunctionLiteralDependencies (
2571+ deferredFunctionLiterals,
2572+ calleeType.typeParameters.toSet (),
2573+ inferenceNeeded
2574+ ? _computeUndeferredParamInfo (
2575+ formalTypes! , deferredFunctionLiterals)
2576+ : const [])
2577+ .planReconciliationStages ()) {
2578+ if (gatherer != null && ! isFirstStage) {
2579+ typeSchemaEnvironment.partialInfer (gatherer, calleeTypeParameters,
2580+ inferredTypes! , libraryBuilder.library);
2581+ substitution =
2582+ Substitution .fromPairs (calleeTypeParameters, inferredTypes);
25282583 }
2529- gatherer? .tryConstrainLower (deferredArgument.formalType, inferredType);
2530- if (useFormalAndActualTypes) {
2531- actualTypes! [deferredArgument.evaluationOrderIndex] = inferredType;
2584+ for (_DeferredParamInfo deferredArgument in stage) {
2585+ ExpressionInferenceResult result = inferArgument (
2586+ deferredArgument.formalType, deferredArgument.argumentExpression,
2587+ isNamed: deferredArgument.isNamed);
2588+ DartType inferredType = _computeInferredType (result);
2589+ Expression expression = result.expression;
2590+ identicalInfo? [deferredArgument.evaluationOrderIndex] =
2591+ flowAnalysis.equalityOperand_end (expression, inferredType);
2592+ if (deferredArgument.isNamed) {
2593+ NamedExpression namedArgument =
2594+ arguments.named[deferredArgument.index];
2595+ namedArgument.value = expression..parent = namedArgument;
2596+ } else {
2597+ arguments.positional[deferredArgument.index] = expression
2598+ ..parent = arguments;
2599+ }
2600+ gatherer? .tryConstrainLower (
2601+ deferredArgument.formalType, inferredType);
2602+ if (useFormalAndActualTypes) {
2603+ actualTypes! [deferredArgument.evaluationOrderIndex] = inferredType;
2604+ }
25322605 }
2606+ isFirstStage = false ;
25332607 }
25342608 }
25352609 if (identicalInfo != null ) {
@@ -5967,15 +6041,14 @@ class ImplicitInstantiation {
59676041/// Information about an invocation argument that needs to be resolved later due
59686042/// to the fact that it's a function literal and the `inference-update-1`
59696043/// feature is enabled.
5970- class _DeferredParamInfo {
5971- /// The (unsubstituted) type of the formal parameter corresponding to this
5972- /// argument.
5973- final DartType formalType;
5974-
6044+ class _DeferredParamInfo extends _ParamInfo {
59756045 /// The argument expression (possibly wrapped in an arbitrary number of
59766046 /// ParenthesizedExpressions).
59776047 final Expression argumentExpression;
59786048
6049+ /// The unparenthesized argument expression.
6050+ final FunctionExpression unparenthesizedExpression;
6051+
59796052 /// Indicates whether this is a named argument.
59806053 final bool isNamed;
59816054
@@ -5988,9 +6061,63 @@ class _DeferredParamInfo {
59886061 final int index;
59896062
59906063 _DeferredParamInfo (
5991- {required this . formalType,
6064+ {required DartType formalType,
59926065 required this .argumentExpression,
6066+ required this .unparenthesizedExpression,
59936067 required this .isNamed,
59946068 required this .evaluationOrderIndex,
5995- required this .index});
6069+ required this .index})
6070+ : super (formalType);
6071+ }
6072+
6073+ /// Extension of the shared [FunctionLiteralDependencies] logic used by the
6074+ /// front end.
6075+ class _FunctionLiteralDependencies extends FunctionLiteralDependencies <
6076+ TypeParameter , _ParamInfo , _DeferredParamInfo > {
6077+ _FunctionLiteralDependencies (
6078+ Iterable <_DeferredParamInfo > deferredParamInfo,
6079+ Iterable <TypeParameter > typeVariables,
6080+ List <_ParamInfo > undeferredParamInfo)
6081+ : super (deferredParamInfo, typeVariables, undeferredParamInfo);
6082+
6083+ @override
6084+ Iterable <TypeParameter > typeVarsFreeInParamParams (
6085+ _DeferredParamInfo paramInfo) {
6086+ DartType type = paramInfo.formalType;
6087+ if (type is FunctionType ) {
6088+ Map <Object , DartType > parameterMap = _computeParameterMap (type);
6089+ Set <Object > explicitlyTypedParameters =
6090+ _computeExplicitlyTypedParameterSet (
6091+ paramInfo.unparenthesizedExpression);
6092+ Set <TypeParameter > result = {};
6093+ for (MapEntry <Object , DartType > entry in parameterMap.entries) {
6094+ if (explicitlyTypedParameters.contains (entry.key)) continue ;
6095+ result.addAll (allFreeTypeVariables (entry.value));
6096+ }
6097+ return result;
6098+ } else {
6099+ return const [];
6100+ }
6101+ }
6102+
6103+ @override
6104+ Iterable <TypeParameter > typeVarsFreeInParamReturns (_ParamInfo paramInfo) {
6105+ DartType type = paramInfo.formalType;
6106+ if (type is FunctionType ) {
6107+ return allFreeTypeVariables (type.returnType);
6108+ } else {
6109+ return allFreeTypeVariables (type);
6110+ }
6111+ }
6112+ }
6113+
6114+ /// Information about an invocation argument that may or may not have already
6115+ /// been resolved, as part of the deferred resolution mechanism for the
6116+ /// `inference-update-1` feature.
6117+ class _ParamInfo {
6118+ /// The (unsubstituted) type of the formal parameter corresponding to this
6119+ /// argument.
6120+ final DartType formalType;
6121+
6122+ _ParamInfo (this .formalType);
59966123}
0 commit comments