final List<Type> capturedArgs = types.capture(argtypes);
List<Type> actuals = capturedArgs;
List<Type> actualsNoCapture = argtypes;
// instantiate all polymorphic argument types and
// set up lower bounds constraints for undetvars
Type varargsFormal = useVarargs ? formals.last() : null;
if (varargsFormal == null &&
actuals.size() != formals.size()) {
throw unambiguousNoInstanceException
.setMessage("infer.arg.length.mismatch");
}
while (actuals.nonEmpty() && formals.head != varargsFormal) {
Type formal = formals.head;
Type actual = actuals.head.baseType();
Type actualNoCapture = actualsNoCapture.head.baseType();
if (actual.tag == FORALL)
actual = instantiateArg((ForAll)actual, formal, tvars, warn);
Type undetFormal = types.subst(formal, tvars, undetvars);
boolean works = allowBoxing
? types.isConvertible(actual, undetFormal, warn)
: types.isSubtypeUnchecked(actual, undetFormal, warn);
if (!works) {
throw unambiguousNoInstanceException
.setMessage("infer.no.conforming.assignment.exists",
tvars, actualNoCapture, formal);
}
formals = formals.tail;
actuals = actuals.tail;
actualsNoCapture = actualsNoCapture.tail;
}
if (formals.head != varargsFormal) // not enough args
throw unambiguousNoInstanceException.setMessage("infer.arg.length.mismatch");
// for varargs arguments as well
if (useVarargs) {
Type elemType = types.elemtype(varargsFormal);
Type elemUndet = types.subst(elemType, tvars, undetvars);
while (actuals.nonEmpty()) {
Type actual = actuals.head.baseType();
Type actualNoCapture = actualsNoCapture.head.baseType();
if (actual.tag == FORALL)
actual = instantiateArg((ForAll)actual, elemType, tvars, warn);
boolean works = types.isConvertible(actual, elemUndet, warn);
if (!works) {
throw unambiguousNoInstanceException