From fa1740a26e70bbe00a33abde28af52d4c400b682 Mon Sep 17 00:00:00 2001 From: Svetlana Isakova Date: Mon, 22 Jul 2013 16:22:32 +0400 Subject: [PATCH] changed way to compute common supertype for number types (using only supertypes, not exact value) --- .../calls/inference/ConstraintsUtil.java | 20 +----- .../lang/resolve/constants/ConstantUtils.java | 21 +----- .../jetbrains/jet/lang/types/TypeUtils.java | 65 +++++++++++++++++++ 3 files changed, 69 insertions(+), 37 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintsUtil.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintsUtil.java index a8314231f6c..6768cfc1b07 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintsUtil.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintsUtil.java @@ -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 numberLowerBounds) { if (numberLowerBounds.isEmpty()) return null; - Set 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 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( diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/constants/ConstantUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/constants/ConstantUtils.java index 0488c32a5ad..86485355c15 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/constants/ConstantUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/constants/ConstantUtils.java @@ -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; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/TypeUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/TypeUtils.java index a87f22e1388..a11402b0d4f 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/TypeUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/TypeUtils.java @@ -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 numberLowerBounds) { + assert !numberLowerBounds.isEmpty(); + Set intersectionOfSupertypes = getIntersectionOfSupertypes(numberLowerBounds); + JetType primitiveNumberType = getDefaultPrimitiveNumberType(intersectionOfSupertypes); + if (primitiveNumberType != null) { + return primitiveNumberType; + } + return CommonSupertypes.commonSupertype(numberLowerBounds); + } + + @NotNull + private static Set getIntersectionOfSupertypes(@NotNull Collection types) { + Set upperBounds = Sets.newHashSet(); + for (JetType type : types) { + Set 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 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); + } }