Class DefaultTypeArgumentInference

  • All Implemented Interfaces:
    TypeArgumentInference

    public class DefaultTypeArgumentInference
    extends java.lang.Object
    implements TypeArgumentInference
    An implementation of TypeArgumentInference that mostly follows the process outlined in JLS7 See the JLS 7: JLS §5.12.2.7

    Note, there are some deviations JLS 7 for the following cases:

    • Places where the JLS is vague. For these cases, first the OpenJDK implementation was consulted and then we favored the behavior we desire rather than the implied behavior of the JLS or JDK implementation.
    • The fact that any given type variable type may or may not have annotations for multiple hierarchies means that constraints are more complicated than their Java equivalents. Every constraint must identify the hierarchies to which they apply. This makes solving the constraint sets more complicated.
    • If an argument to a method is null, then the JLS says that it does not constrain the type argument. However, null may constrain the qualifiers on the type argument, so it is included in the constraints but is not used as the underlying type of the type argument.
    TODO: The following limitations need to be fixed, as at the time of this writing we do not have the time to handle them:
    • The GlbUtil does not correctly handled wildcards/typevars when the glb result should be a wildcard or typevar
    • Interdependent Method Invocations -- Currently we do not correctly handle the case where two methods need to have their arguments inferred and one is the argument to the other. E.g.
      
       <T> T get()
       <S> void set(S s)
       set(get())
       
      Presumably, we want to detect these situations and combine the set of constraints with T <: S.
    • Constructor Detail

      • DefaultTypeArgumentInference

        public DefaultTypeArgumentInference​(AnnotatedTypeFactory typeFactory)
    • Method Detail

      • inferTypeArgs

        public java.util.Map<javax.lang.model.type.TypeVariable,​AnnotatedTypeMirror> inferTypeArgs​(AnnotatedTypeFactory typeFactory,
                                                                                                         com.sun.source.tree.ExpressionTree expressionTree,
                                                                                                         javax.lang.model.element.ExecutableElement methodElem,
                                                                                                         AnnotatedTypeMirror.AnnotatedExecutableType methodType)
        Description copied from interface: TypeArgumentInference
        Infer the type arguments for the method or constructor invocation given by invocation.
        Specified by:
        inferTypeArgs in interface TypeArgumentInference
        Parameters:
        typeFactory - the type factory used to create methodType
        expressionTree - a tree representing the method or constructor invocation for which we are inferring type arguments
        methodElem - the element for the declaration of the method being invoked
        methodType - the declaration type of method elem
        Returns:
        a mapping between the Java type parameter and the annotated type that was inferred for it. Note: We use the Java TypeVariable type because this uniquely identifies a declaration where as two uses of an AnnotatedTypeVariable may be uses of the same declaration but are not .equals to each other.
      • createArgumentAFConstraints

        protected java.util.Set<AFConstraint> createArgumentAFConstraints​(AnnotatedTypeFactory typeFactory,
                                                                          java.util.List<AnnotatedTypeMirror> argTypes,
                                                                          AnnotatedTypeMirror.AnnotatedExecutableType methodType,
                                                                          java.util.Set<javax.lang.model.type.TypeVariable> targets,
                                                                          boolean useNullArguments)
        Step 1: Create a constraint Ai << Fi for each Argument(Ai) to formal parameter(Fi). Remove any constraint that does not involve a type parameter to be inferred. Reduce the remaining constraints so that Fi = Tj where Tj is a type parameter with an argument to be inferred. Return the resulting constraint set.
        Parameters:
        typeFactory - the type factory
        argTypes - list of annotated types corresponding to the arguments to the method
        methodType - annotated type of the method
        targets - type variables to be inferred
        useNullArguments - whether or not null method arguments should be considered
        Returns:
        a set of argument constraints
      • createInitialAssignmentConstraints

        protected java.util.Set<FIsA> createInitialAssignmentConstraints​(AnnotatedTypeMirror assignedTo,
                                                                         AnnotatedTypeMirror boxedReturnType,
                                                                         AnnotatedTypeFactory typeFactory,
                                                                         java.util.Set<javax.lang.model.type.TypeVariable> targets)
        Create a set of constraints between return type and any type to which it is assigned. Reduce these set of constraints and remove any that is not an equality (FIsA) constraint.
      • createAssignmentConstraints

        public ConstraintMap createAssignmentConstraints​(AnnotatedTypeMirror assignedTo,
                                                         AnnotatedTypeMirror boxedReturnType,
                                                         AnnotatedTypeMirror.AnnotatedExecutableType methodType,
                                                         java.util.Set<AFConstraint> afArgumentConstraints,
                                                         java.util.Map<javax.lang.model.type.TypeVariable,​AnnotatedTypeMirror> inferredArgs,
                                                         java.util.Set<javax.lang.model.type.TypeVariable> targets,
                                                         AnnotatedTypeFactory typeFactory)
        The first half of Step 6.

        This method creates constraints:

        • between the bounds of types that are already inferred and their inferred arguments
        • between the assignment context and the return type of the method (with the previously inferred arguments substituted into these constraints)
      • reduceAfConstraints

        protected void reduceAfConstraints​(AnnotatedTypeFactory typeFactory,
                                           java.util.Set<AFConstraint> outgoing,
                                           java.util.Queue<AFConstraint> toProcess,
                                           java.util.Set<javax.lang.model.type.TypeVariable> targets)
        Given a set of AFConstraints, remove all constraints that are not relevant to inference and return a set of AFConstraints in which the F is a use of one of the type parameters to infer.
      • afToTuConstraints

        protected java.util.Set<TUConstraint> afToTuConstraints​(java.util.Set<? extends AFConstraint> afConstraints,
                                                                java.util.Set<javax.lang.model.type.TypeVariable> targets)
        Convert AFConstraints to TUConstraints.
      • addConstraintsBetweenTargets

        public void addConstraintsBetweenTargets​(java.util.Set<TUConstraint> constraints,
                                                 java.util.Set<javax.lang.model.type.TypeVariable> targets,
                                                 boolean asSubtype,
                                                 AnnotatedTypeFactory typeFactory)
        Declarations of the form: <A, B extends A> implies a TUConstraint of B <: A. Add these to the constraint list.