Class InvocationTypeInference

java.lang.Object
org.checkerframework.framework.util.typeinference8.InvocationTypeInference

public class InvocationTypeInference extends Object
Performs invocation type inference as described in JLS Section 18.5.2. Main entry point is infer(ExpressionTree, AnnotatedExecutableType)

Invocation type inference is the process by which method type arguments are inferred for a given method invocation. An overview of the process is given below.

1. Inference creates an inference variable for each method type argument for a given method invocation. Each inference variable may have zero or more upper, lower, and equal bounds. The bounds of an inference variable are initially the bounds on the type argument. More bounds may be infered in later steps.

Bounds are between an inference variable and an abstract type. AbstractTypes are type-like structures that might include inference variables. Abstract types might also be an inference variable or a type without any inference variables, which is also know as a proper type.

An inference variable is represented by a Variable object which holds bounds for the inference variable, in an VariableBounds object. Additional inference variables may be created in later steps if any subexpression of the method invocation requires type inference.

2. Next, inference creates constraints between the arguments to the method invocation and its formal parameters. Also, for non-void methods, a constraint between the declared return type and the "target type" of the method invocation is created. "Target types" are defined in JLS Chapter 5. For example, the target type of a method invocation assigned to a variable is the type of the variable.

Constraints are represented by TypeConstraint objects and are between abstract types (see AbstractType) and either expressions (see Expression) or other abstract types. A constraint might also be an abstract type that might be thrown by the method invocation (see CheckedExceptionConstraint). Groups of constraints are stored in ConstraintSets.

3. Next, these constraints are "reduced" producing bounds on the inference variables. Reduction depends on the kind of constraint and is defined in JLS section 18.2. In this code base, constraints are reduced via ConstraintSet.reduce(Java8InferenceContext).

4. The inference variables' bounds are then "incorporated" which produces more bounds and/or constraints that must then be "reduced" or "incorporated". Incorporation and reduction continue until no new bounds or constraints are produced. Bounds are incorporated via BoundSet.incorporateToFixedPoint(BoundSet). Incorporation in defined in JLS section 18.3.

5. Finally, a type for each inference variable is computed by "resolving" the bounds. Variables are resolved via Resolution.resolve(Collection, BoundSet, Java8InferenceContext). Resolution is defined in the JLS section 18.4.

An object of this class stores information about some particular invocation that requires inference.

  • Field Details

    • checker

      protected final SourceChecker checker
      Checker used to issue errors/warnings.
    • context

      protected final Java8InferenceContext context
      Stores information about the current inference problem being solved.
    • inferenceExpression

      protected final Tree inferenceExpression
      Tree for which type arguments are being inferred.
  • Constructor Details

    • InvocationTypeInference

      public InvocationTypeInference(AnnotatedTypeFactory factory, TreePath pathToExpression)
      Creates an inference problem.
      Parameters:
      factory - the annotated type factory to use
      pathToExpression - path to the expression for which inference is preformed
  • Method Details

    • getInferenceExpression

      public Tree getInferenceExpression()
      Returns the tree for which inference is being inferred.
      Returns:
      the tree for which inference is being inferred
    • infer

      Perform invocation type inference on invocation. See JLS 18.5.2.
      Parameters:
      invocation - invocation which needs inference
      methodType - type of the method invocation
      Returns:
      the result of inference
      Throws:
      FalseBoundException - if inference fails because of the java types
    • infer

      public InferenceResult infer(MemberReferenceTree invocation) throws FalseBoundException
      Perform invocation type inference on invocation. See JLS 18.5.2.
      Parameters:
      invocation - member reference tree
      Returns:
      the result of inference
      Throws:
      FalseBoundException - if inference fails because of the java types
    • createB2

      public BoundSet createB2(InvocationType methodType, List<? extends ExpressionTree> args, Theta map)
      Creates the bound set used to determine whether a method is applicable. This method is called B2 in JLS Section 18.5.1.

      It does this by:

      1. Creating the inference variables and initializing their bounds based on the type parameter declaration.
      2. Adding any bounds implied by the throws clause of methodType.
      3. Constructing constraints between formal parameters and arguments that are "pertinent to applicability" (See JLS Section 15.12.2.2). Generally, all arguments are applicable except: inexact method reference, implicitly typed lambdas, or explicitly typed lambda whose return expression(s) are not pertinent.
      4. Reducing and incorporating those constraints which finally produces B2.
      Parameters:
      methodType - the type of the method or constructor invoked
      args - argument expression tress
      map - map of type variables to (inference) variables
      Returns:
      bound set used to determine whether a method is applicable
    • createB2MethodRef

      public BoundSet createB2MethodRef(InvocationType methodType, List<AbstractType> args, Theta map)
      Same as createB2(InvocationType, List, Theta), but for method references. A list of types is used instead of a list of arguments. These types are the types of the formal parameters of function type of target type of the method reference.
      Parameters:
      methodType - the type of the method or constructor invoked
      args - types to use as arguments
      map - map of type variables to (inference) variables
      Returns:
      bound set used to determine whether a method is applicable
    • createB3

      public BoundSet createB3(BoundSet b2, ExpressionTree invocation, InvocationType methodType, AbstractType target, Theta map)
      Creates constraints against the target type of invocation and then reduces and incorporates those constraints with b2. (See JLS 18.5.2.1.)
      Parameters:
      b2 - BoundSet created by createB2(InvocationType, List, Theta)
      invocation - a method or constructor invocation
      methodType - the type of the method or constructor invoked by expression
      target - target type of the invocation
      map - map of type variables to (inference) variables
      Returns:
      bound set created by constraints against the target type of the invocation
    • createC

      public ConstraintSet createC(InvocationType methodType, List<? extends ExpressionTree> args, Theta map)
      Creates the constraints between the formal parameters and arguments that are not pertinent to applicability. (See JLS 18.5.2.2.)
      Parameters:
      methodType - type of method invoked
      args - argument expression trees
      map - map from type variable to inference variable
      Returns:
      the constraints between the formal parameters and arguments that are not pertinent to applicability