private TInstance findCommon(V overload, TInputSet inputSet,
List<? extends TPreptimeValue> inputs, TCastResolver resolver)
{
assert inputSet.targetType() == null : inputSet; // so we have to look at inputs
TClass common = null;
TInstance commonInst = null;
int lastPositionalInput = overload.positionalInputs();
boolean notVararg = ! overload.isVararg();
boolean nullable = false;
for (int i = 0, size = inputs.size(); i < size; ++i) {
if (overload.inputSetAt(i) != inputSet)
continue;
if (notVararg && (i >= lastPositionalInput))
break;
TPreptimeValue inputTpv = inputs.get(i);
nullable |= inputTpv.isNullable();
TInstance inputInstance = inputTpv.type();
if (inputInstance == null) {
// unknown type, like a NULL literal or parameter
continue;
}
TClass inputClass = inputInstance.typeClass();
if (common == null) {
// First input we've seen, so just use it.
common = inputClass;
commonInst = inputInstance;
}
else if (inputClass == common) {
// saw the same TClass as before, so pick it
commonInst = (commonInst == null) ? inputInstance : common.pickInstance(commonInst, inputInstance);
}
else {
// Saw a different TCLass as before, so need to cast one of them. We'll get the new common type,
// at which point we have exactly one of three possibilities:
// 1) newCommon == [old] common, in which case we'll keep the old TInstance
// 2) newCommon == inputClass, in which case we'll use the inputInstance
// 3) newCommon is neither, in which case we'll generate a new TInstance
// We know that we can't have both #1 and #2, because that would imply [old] common == inputClass,
// which has already been handled.
TClass newCommon = resolver.commonTClass(common, inputClass);
if (newCommon == null)
throw new OverloadException(overload + ": couldn't find common types for " + inputSet
+ " with " + inputs);
if (newCommon == inputClass) { // case #2