in Arriba/Arriba/Structures/Value.cs [394:448]
public Type BestType(Type bestSoFar)
{
// If there's an existing best and this value converts to it, keep it
object unused;
if (bestSoFar != null && TryConvert(bestSoFar, out unused)) return bestSoFar;
Type thisBest = this.BestType();
// If this is object, stick with bestSoFar
if (thisBest.Equals(typeof(object))) return bestSoFar;
// If bestSoFar is null, use this type
if (bestSoFar == null) return thisBest;
// If the same, return the same
if (thisBest.Equals(bestSoFar)) return bestSoFar;
// If either is string, it must be string
if (thisBest.Equals(typeof(string)) || bestSoFar.Equals(typeof(string))) return typeof(string);
// Allow converting to 'broader' types (int -> long, float -> double, int -> float)
if(bestSoFar.Equals(typeof(long)))
{
if (thisBest.Equals(typeof(int))) return typeof(long);
if (thisBest.Equals(typeof(float))) return typeof(float);
if (thisBest.Equals(typeof(double))) return typeof(double);
}
else if(bestSoFar.Equals(typeof(int)))
{
if (thisBest.Equals(typeof(long))) return typeof(long);
if (thisBest.Equals(typeof(float))) return typeof(float);
if (thisBest.Equals(typeof(double))) return typeof(double);
if (thisBest.Equals(typeof(TimeSpan))) return typeof(TimeSpan);
}
else if (bestSoFar.Equals(typeof(float)))
{
if (thisBest.Equals(typeof(int))) return typeof(float);
if (thisBest.Equals(typeof(long))) return typeof(float);
if (thisBest.Equals(typeof(double))) return typeof(double);
}
else if(bestSoFar.Equals(typeof(double)))
{
if (thisBest.Equals(typeof(int))) return typeof(double);
if (thisBest.Equals(typeof(long))) return typeof(double);
if (thisBest.Equals(typeof(float))) return typeof(double);
}
else if(bestSoFar.Equals(typeof(TimeSpan)))
{
if (thisBest.Equals(typeof(int))) return typeof(TimeSpan);
}
// Otherwise, must fall back to string
return typeof(string);
}