/** * Given a partial solution to our type argument inference, replace any uses of type parameters * that have been solved with their arguments. * * <p>That is: Let S be a partial solution to our inference (i.e. we have inferred type arguments * for some types) Let S be a map {@code (T0 -> A0, T1 -> A1, ..., TN -> AN)} where Ti is a type * parameter and Ai is its solved argument. For all uses of Ti in this constraint, replace them * with Ai. * * <p>For the mapping {@code (T0 -> A0)}, the following constraint: {@code ArrayList<T0> << * List<T1>} * * <p>Becomes: {@code ArrayList<A0> << List<T1>} * * <p>A constraint: {@code T0 << T1} * * <p>Becomes: {@code A0 << T1} * * @param substitutions a mapping of target type parameter to the type argument to * @return a new constraint that contains no use of the keys in substitutions */ public AFConstraint substitute(final Map<TypeVariable, AnnotatedTypeMirror> substitutions) { final AnnotatedTypeMirror newArgument = TypeArgInferenceUtil.substitute(substitutions, argument); final AnnotatedTypeMirror newFormalParameter = TypeArgInferenceUtil.substitute(substitutions, formalParameter); return construct(newArgument, newFormalParameter); }
/** * @param targets the type parameters whose arguments we are trying to solve for * @return true if this constraint can't be broken up into other constraints or further simplified * In general, if either argument or formal parameter is a use of the type parameters we are * inferring over then the constraint cannot be reduced further */ public boolean isIrreducible(final Set<TypeVariable> targets) { return TypeArgInferenceUtil.isATarget(argument, targets) || TypeArgInferenceUtil.isATarget(formalParameter, targets); }