changed way to compute common supertype for number types

(using only supertypes, not exact value)
This commit is contained in:
Svetlana Isakova
2013-07-22 16:22:32 +04:00
parent fccfa0051e
commit fa1740a26e
3 changed files with 69 additions and 37 deletions
@@ -84,8 +84,7 @@ public class ConstraintsUtil {
addToValuesIfDifferent(superTypeOfNumberLowerBounds, values);
if (superTypeOfLowerBounds != null && superTypeOfNumberLowerBounds != null) {
JetType superTypeOfAllLowerBounds =
commonSupertype(Lists.newArrayList(superTypeOfLowerBounds, superTypeOfNumberLowerBounds));
JetType superTypeOfAllLowerBounds = commonSupertype(Lists.newArrayList(superTypeOfLowerBounds, superTypeOfNumberLowerBounds));
if (trySuggestion(superTypeOfAllLowerBounds, typeConstraints)) {
return Collections.singleton(superTypeOfAllLowerBounds);
}
@@ -116,22 +115,7 @@ public class ConstraintsUtil {
@Nullable
private static JetType commonSupertypeForNumberTypes(@NotNull Collection<JetType> numberLowerBounds) {
if (numberLowerBounds.isEmpty()) return null;
Set<Long> numbers = Sets.newHashSet();
for (JetType numberLowerBound : numberLowerBounds) {
assert numberLowerBound.getConstructor() instanceof NumberValueTypeConstructor;
numbers.add(((NumberValueTypeConstructor) numberLowerBound.getConstructor()).getValue());
}
assert !numbers.isEmpty();
return getDefaultNumberType(numbers);
}
private static JetType getDefaultNumberType(Collection<Long> values) {
for (Long value : values) {
if (value < Integer.MIN_VALUE || value > Integer.MAX_VALUE) {
return KotlinBuiltIns.getInstance().getLongType();
}
}
return KotlinBuiltIns.getInstance().getIntType();
return TypeUtils.commonSupertypeForNumberTypes(numberLowerBounds);
}
private static boolean trySuggestion(
@@ -29,16 +29,11 @@ import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.JetTypeInfo;
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
import org.jetbrains.jet.lang.types.TypeUtils;
import org.jetbrains.jet.lang.types.expressions.OperatorConventions;
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
import static org.jetbrains.jet.lang.diagnostics.Errors.ERROR_COMPILE_TIME_VALUE;
import static org.jetbrains.jet.lang.types.TypeUtils.noExpectedType;
import static org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils.getDefaultType;
import static org.jetbrains.jet.lang.types.expressions.OperatorConventions.*;
import static org.jetbrains.jet.lang.types.expressions.OperatorConventions.BYTE;
import static org.jetbrains.jet.lang.types.expressions.OperatorConventions.INT;
public class ConstantUtils {
@@ -80,24 +75,12 @@ public class ConstantUtils {
@NotNull JetExpression expression,
@NotNull ResolutionContext<?> context
) {
CompileTimeConstantResolver compileTimeConstantResolver = new CompileTimeConstantResolver();
CompileTimeConstant<?> value = compileTimeConstantResolver.getIntegerValue(numberValueTypeConstructor.getValue(), expectedType);
JetTypeInfo recordedTypeInfo = BindingContextUtils.getRecordedTypeInfo(expression, context.trace.getBindingContext());
assert recordedTypeInfo != null : "Expression " + expression + " should have been analyzed";
JetScope resolutionScope = context.trace.get(BindingContext.RESOLUTION_SCOPE, expression);
assert resolutionScope != null : "Expression " + expression + " should have been analyzed";
JetType type;
if (value instanceof ErrorValue) {
ErrorValue errorValue = (ErrorValue) value;
type = getDefaultType(expression.getNode().getElementType());
if (!noExpectedType(context.expectedType) && JetTypeChecker.INSTANCE.isSubtypeOf(type, context.expectedType)) {
context.trace.report(ERROR_COMPILE_TIME_VALUE.on(expression, errorValue.getMessage()));
}
}
else {
type = value.getType(KotlinBuiltIns.getInstance());
}
JetType type = TypeUtils.getPrimitiveNumberType(numberValueTypeConstructor, expectedType);
BindingContextUtils.recordExpressionType(expression, context.trace, resolutionScope,
JetTypeInfo.create(type, recordedTypeInfo.getDataFlowInfo()));
return type;
@@ -30,6 +30,7 @@ import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintResolutionListen
import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystemSolution;
import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystemWithPriorities;
import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintType;
import org.jetbrains.jet.lang.resolve.constants.NumberValueTypeConstructor;
import org.jetbrains.jet.lang.resolve.scopes.ChainedScope;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
@@ -551,4 +552,68 @@ public class TypeUtils {
return builder.toString();
}
@NotNull
public static JetType commonSupertypeForNumberTypes(@NotNull Collection<JetType> numberLowerBounds) {
assert !numberLowerBounds.isEmpty();
Set<JetType> intersectionOfSupertypes = getIntersectionOfSupertypes(numberLowerBounds);
JetType primitiveNumberType = getDefaultPrimitiveNumberType(intersectionOfSupertypes);
if (primitiveNumberType != null) {
return primitiveNumberType;
}
return CommonSupertypes.commonSupertype(numberLowerBounds);
}
@NotNull
private static Set<JetType> getIntersectionOfSupertypes(@NotNull Collection<JetType> types) {
Set<JetType> upperBounds = Sets.newHashSet();
for (JetType type : types) {
Set<JetType> supertypes = Sets.newHashSet(type.getConstructor().getSupertypes());
if (upperBounds.isEmpty()) {
upperBounds.addAll(supertypes);
}
else {
upperBounds = Sets.intersection(upperBounds, supertypes);
}
}
return upperBounds;
}
@Nullable
public static JetType getDefaultPrimitiveNumberType(@NotNull NumberValueTypeConstructor numberValueTypeConstructor) {
return getDefaultPrimitiveNumberType(numberValueTypeConstructor.getSupertypes());
}
@Nullable
private static JetType getDefaultPrimitiveNumberType(@NotNull Collection<JetType> supertypes) {
JetType doubleType = KotlinBuiltIns.getInstance().getDoubleType();
if (supertypes.contains(doubleType)) {
return doubleType;
}
JetType intType = KotlinBuiltIns.getInstance().getIntType();
if (supertypes.contains(intType)) {
return intType;
}
JetType longType = KotlinBuiltIns.getInstance().getLongType();
if (supertypes.contains(longType)) {
return longType;
}
return null;
}
@Nullable
public static JetType getPrimitiveNumberType(
@NotNull NumberValueTypeConstructor numberValueTypeConstructor,
@NotNull JetType expectedType
) {
if (noExpectedType(expectedType) || ErrorUtils.isErrorType(expectedType)) {
return getDefaultPrimitiveNumberType(numberValueTypeConstructor);
}
for (JetType primitiveNumberType : numberValueTypeConstructor.getSupertypes()) {
if (JetTypeChecker.INSTANCE.isSubtypeOf(primitiveNumberType, expectedType)) {
return primitiveNumberType;
}
}
return getDefaultPrimitiveNumberType(numberValueTypeConstructor);
}
}