Class TypeArgInferenceUtil

java.lang.Object
org.checkerframework.framework.util.typeinference.TypeArgInferenceUtil

public class TypeArgInferenceUtil extends Object
Miscellaneous utilities to help in type argument inference.
  • Constructor Details

    • TypeArgInferenceUtil

      public TypeArgInferenceUtil()
  • Method Details

    • getArgumentTypes

      public static List<AnnotatedTypeMirror> getArgumentTypes(ExpressionTree methodInvocation, AnnotatedTypeFactory typeFactory)
      Returns a list of boxed annotated types corresponding to the arguments in methodInvocation.
      Parameters:
      methodInvocation - MethodInvocationTree or NewClassTree
      typeFactory - type factory
      Returns:
      a list of boxed annotated types corresponding to the arguments in methodInvocation.
    • isATarget

      public static boolean isATarget(AnnotatedTypeMirror type, Set<TypeVariable> targetTypeVars)
      Given a set of type variables for which we are inferring a type, returns true if type is a use of a type variable in the list of targetTypeVars.
    • methodTypeToTargets

      public static Set<TypeVariable> methodTypeToTargets(AnnotatedTypeMirror.AnnotatedExecutableType methodType)
      Given an AnnotatedExecutableType return a set of type variables that represents the generic type parameters of that method.
    • assignedTo

      public static @Nullable AnnotatedTypeMirror assignedTo(AnnotatedTypeFactory atypeFactory, TreePath path)
      Returns the annotated type that the leaf of path is assigned to, if it is within an assignment context. Returns the annotated type that the method invocation at the leaf is assigned to. If the result is a primitive, return the boxed version.
      Parameters:
      atypeFactory - the type factory, for looking up types
      path - the path whole leaf to look up a type for
      Returns:
      the type of path's leaf
    • assignedToVariable

      public static AnnotatedTypeMirror assignedToVariable(AnnotatedTypeFactory atypeFactory, VariableTree assignmentContext)
      If the variable's type is a type variable, return getAnnotatedTypeLhsNoTypeVarDefault(tree). Rationale:

      For example:

      
       <S> S bar () {...}
      
       <T> T foo(T p) {
           T local = bar();
           return local;
         }
       
      During type argument inference of bar, the assignment context is local. If the local variable default is used, then the type of assignment context type is @Nullable T and the type argument inferred for bar() is @Nullable T. And an incompatible types in return error is issued.

      If instead, the local variable default is not applied, then the assignment context type is T (with lower bound @NonNull Void and upper bound @Nullable Object) and the type argument inferred for bar() is T. During dataflow, the type of local is refined to T and the return is legal.

      If the assignment context type was a declared type, for example:

      
       <S> S bar () {...}
       Object foo() {
           Object local = bar();
           return local;
       }
       
      The local variable default must be used or else the assignment context type is missing an annotation. So, an incompatible types in return error is issued in the above code. We could improve type argument inference in this case and by using the lower bound of S instead of the local variable default.
      Parameters:
      atypeFactory - the type factory
      assignmentContext - VariableTree
      Returns:
      AnnotatedTypeMirror of Assignment context
    • containsTypeParameter

      public static boolean containsTypeParameter(AnnotatedTypeMirror type, Collection<TypeVariable> typeVariables)
      Returns true if type contains a use of a type variable in typeVariables.
      Parameters:
      type - type to search
      typeVariables - collection of type variables
      Returns:
      true if type contains a use of a type variable in typeVariables
    • createHierarchyMap

      public static AnnotationMirrorMap<AnnotationMirror> createHierarchyMap(AnnotationMirrorSet annos, QualifierHierarchy qualHierarchy)
      Take a set of annotations and separate them into a mapping of hierarchy top => annotations in hierarchy.
    • checkForUninferredTypes

      public static void checkForUninferredTypes(AnnotatedTypeMirror type)
      Throws an exception if the type is an uninferred type argument.

      The error will be caught in DefaultTypeArgumentInference#infer and inference will be aborted, but type-checking will continue.

    • substitute

      public static AnnotatedTypeMirror substitute(TypeVariable typeVariable, AnnotatedTypeMirror substitution, AnnotatedTypeMirror toModify)
      Replace all uses of typeVariable with substitution in a copy of toModify using the normal substitution rules. Return the copy
      See Also:
    • substitute

      public static AnnotatedTypeMirror substitute(Map<TypeVariable,AnnotatedTypeMirror> substitutions, AnnotatedTypeMirror toModify)
      Create a copy of toModify. In the copy, for each pair typeVariable => annotated type replace uses of typeVariable with the corresponding annotated type using normal substitution rules (@see TypeVariableSubstitutor). Return the copy.
    • leastUpperBound

      public static AnnotatedTypeMirror leastUpperBound(AnnotatedTypeFactory typeFactory, Iterable<AnnotatedTypeMirror> types)
      Successively calls least upper bound on the elements of types. Unlike leastUpperBound, this method will box primitives if necessary
    • correctResults

      protected static Map<TypeVariable,AnnotatedTypeMirror> correctResults(Map<TypeVariable,AnnotatedTypeMirror> result, ExpressionTree invocation, ExecutableType methodType, AnnotatedTypeFactory factory)
      If the type arguments computed by DefaultTypeArgumentInference don't match the return type mirror of invocation, then replace those type arguments with an uninferred wildcard.