private void updateTypeOfArguments(Node n, FunctionType fnType) {
    checkState(NodeUtil.isInvocation(n), n);
    Iterator<Node> parameters = fnType.getParameters().iterator();
    if (n.isTaggedTemplateLit()) {
      // Skip the first parameter because it corresponds to a constructed array of the template lit
      // subs, not an actual AST node, so there's nothing to update.
      if (!parameters.hasNext()) {
        // TypeCheck will warn if there is no first parameter. Just bail out here.
        return;
      }
      parameters.next();
    }
    Iterator<Node> arguments = NodeUtil.getInvocationArgsAsIterable(n).iterator();

    Node iParameter;
    Node iArgument;

    // Note: if there are too many or too few arguments, TypeCheck will warn.
    while (parameters.hasNext() && arguments.hasNext()) {
      iArgument = arguments.next();
      JSType iArgumentType = getJSType(iArgument);

      iParameter = parameters.next();
      JSType iParameterType = getJSType(iParameter);

      inferPropertyTypesToMatchConstraint(iArgumentType, iParameterType);

      // If the parameter to the call is a function expression, propagate the
      // function signature from the call site to the function node.

      // Filter out non-function types (such as null and undefined) as
      // we only care about FUNCTION subtypes here.
      FunctionType restrictedParameter = null;
      if (iParameterType.isUnionType()) {
        UnionType union = iParameterType.toMaybeUnionType();
        for (JSType alternative : union.getAlternates()) {
          if (alternative.isFunctionType()) {
            // There is only one function type per union.
            restrictedParameter = alternative.toMaybeFunctionType();
            break;
          }
        }
      } else {
        restrictedParameter = iParameterType.toMaybeFunctionType();
      }

      if (restrictedParameter != null
          && iArgument.isFunction()
          && iArgumentType.isFunctionType()) {
        FunctionType argFnType = iArgumentType.toMaybeFunctionType();
        JSDocInfo argJsdoc = iArgument.getJSDocInfo();
        // Treat the parameter & return types of the function as 'declared' if the function has
        // JSDoc with type annotations, or a parameter has inline JSDoc.
        // Note that this does not distinguish between cases where all parameters have JSDoc vs
        // only one parameter has JSDoc.
        boolean declared =
            (argJsdoc != null && argJsdoc.containsDeclaration())
                || NodeUtil.functionHasInlineJsdocs(iArgument);
        iArgument.setJSType(matchFunction(restrictedParameter, argFnType, declared));
      }
    }
  }
private void updateTypeOfArguments ( Node n , FunctionType fnType ) { checkState ( NodeUtil . isInvocation ( n ) , n ) ; Iterator < Node > parameters = fnType . getParameters ( ) . iterator ( ) ; if ( n . isTaggedTemplateLit ( ) ) { if ( ! parameters . hasNext ( ) ) { return ; } parameters . next ( ) ; } Iterator < Node > arguments = NodeUtil . getInvocationArgsAsIterable ( n ) . iterator ( ) ; Node iParameter ; Node iArgument ; while ( parameters . hasNext ( ) && arguments . hasNext ( ) ) { iArgument = arguments . next ( ) ; JSType iArgumentType = getJSType ( iArgument ) ; iParameter = parameters . next ( ) ; JSType iParameterType = getJSType ( iParameter ) ; inferPropertyTypesToMatchConstraint ( iArgumentType , iParameterType ) ; FunctionType restrictedParameter = null ; if ( iParameterType . isUnionType ( ) ) { UnionType union = iParameterType . toMaybeUnionType ( ) ; for ( JSType alternative : union . getAlternates ( ) ) { if ( alternative . isFunctionType ( ) ) { restrictedParameter = alternative . toMaybeFunctionType ( ) ; break ; } } } else { restrictedParameter = iParameterType . toMaybeFunctionType ( ) ; } if ( restrictedParameter != null && iArgument . isFunction ( ) && iArgumentType . isFunctionType ( ) ) { FunctionType argFnType = iArgumentType . toMaybeFunctionType ( ) ; JSDocInfo argJsdoc = iArgument . getJSDocInfo ( ) ; boolean declared = ( argJsdoc != null && argJsdoc . containsDeclaration ( ) ) || NodeUtil . functionHasInlineJsdocs ( iArgument ) ; iArgument . setJSType ( matchFunction ( restrictedParameter , argFnType , declared ) ) ; } } }
Performs a limited back-inference on function arguments based on the expected parameter types.

<p>Currently this only does back-inference in two cases: it infers the type of function literal
arguments and adds inferred properties to inferred object-typed arguments.

<p>For example: if someone calls `Promise<string>.prototype.then` with `(result) => ...` then
we infer that the type of the arrow function is `function(string): ?`, and inside the arrow
function body we know that `result` is a string.