update number value type properly
This commit is contained in:
@@ -22,6 +22,7 @@ import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.intellij.openapi.progress.ProgressIndicatorProvider;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
@@ -40,15 +41,18 @@ import org.jetbrains.jet.lang.resolve.calls.results.ResolutionStatus;
|
||||
import org.jetbrains.jet.lang.resolve.calls.tasks.ResolutionTask;
|
||||
import org.jetbrains.jet.lang.resolve.calls.tasks.TaskPrioritizer;
|
||||
import org.jetbrains.jet.lang.resolve.calls.util.ExpressionAsFunctionDescriptor;
|
||||
import org.jetbrains.jet.lang.resolve.constants.*;
|
||||
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
|
||||
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstantResolver;
|
||||
import org.jetbrains.jet.lang.resolve.constants.ErrorValue;
|
||||
import org.jetbrains.jet.lang.resolve.constants.NumberValueTypeConstructor;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
|
||||
import org.jetbrains.jet.lang.types.*;
|
||||
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
|
||||
import org.jetbrains.jet.lang.types.expressions.DataFlowUtils;
|
||||
import org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils;
|
||||
import org.jetbrains.jet.lang.types.expressions.OperatorConventions;
|
||||
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.ArrayList;
|
||||
@@ -373,7 +377,7 @@ public class CandidateResolver {
|
||||
DataFlowUtils.checkType(result, expression, contextForArgument);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Nullable
|
||||
private JetExpression getDeferredComputationKeyExpression(@NotNull JetExpression expression) {
|
||||
JetVisitor<JetExpression, Void> selectorExpressionFinder = new JetVisitor<JetExpression, Void>() {
|
||||
@Override
|
||||
@@ -386,6 +390,30 @@ public class CandidateResolver {
|
||||
public JetExpression visitExpression(JetExpression expression, Void data) {
|
||||
return expression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetExpression visitParenthesizedExpression(JetParenthesizedExpression expression, Void data) {
|
||||
return expression.getExpression();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetExpression visitPrefixExpression(JetPrefixExpression expression, Void data) {
|
||||
JetExpression baseExpression = JetPsiUtil.getBaseExpressionIfLabeledExpression(expression);
|
||||
return baseExpression != null ? baseExpression : expression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetExpression visitBinaryExpression(JetBinaryExpression expression, Void data) {
|
||||
IElementType operationType = expression.getOperationReference().getReferencedNameElementType();
|
||||
//noinspection SuspiciousMethodCalls
|
||||
if (OperatorConventions.COMPARISON_OPERATIONS.contains(operationType)) {
|
||||
//Result type of comparison doesn't depend on expected type:
|
||||
//it's 'Boolean', but 'compareTo' should return 'Int'.
|
||||
//So we shouldn't check result type of such a call('Int') at completion phase.
|
||||
return null;
|
||||
}
|
||||
return super.visitBinaryExpression(expression, data);
|
||||
}
|
||||
};
|
||||
return expression.accept(selectorExpressionFinder, null);
|
||||
}
|
||||
@@ -412,13 +440,34 @@ public class CandidateResolver {
|
||||
if (type != null && !type.getConstructor().isDenotable()) {
|
||||
if (type.getConstructor() instanceof NumberValueTypeConstructor) {
|
||||
NumberValueTypeConstructor constructor = (NumberValueTypeConstructor) type.getConstructor();
|
||||
type = TypeUtils.getPrimitiveNumberType(constructor, context.expectedType);
|
||||
BindingContextUtils.updateRecordedType(type, expression, context.trace, false);
|
||||
JetType primitiveType = TypeUtils.getPrimitiveNumberType(constructor, context.expectedType);
|
||||
updateNumberType(primitiveType, expression, context);
|
||||
return primitiveType;
|
||||
}
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
private <D extends CallableDescriptor> void updateNumberType(
|
||||
@NotNull JetType numberType,
|
||||
@Nullable JetExpression expression,
|
||||
@NotNull CallCandidateResolutionContext<D> context
|
||||
) {
|
||||
if (expression == null) return;
|
||||
BindingContextUtils.updateRecordedType(numberType, expression, context.trace, false);
|
||||
|
||||
if (!(expression instanceof JetConstantExpression)) {
|
||||
updateNumberType(numberType, JetPsiUtil.deparenthesizeWithNoTypeResolution(expression, false), context);
|
||||
return;
|
||||
}
|
||||
CompileTimeConstant<?> constant =
|
||||
new CompileTimeConstantResolver().getCompileTimeConstant((JetConstantExpression) expression, numberType);
|
||||
|
||||
if (!(constant instanceof ErrorValue)) {
|
||||
context.trace.record(BindingContext.COMPILE_TIME_VALUE, expression, constant);
|
||||
}
|
||||
}
|
||||
|
||||
private <D extends CallableDescriptor> void checkResultArgumentType(
|
||||
@Nullable JetType type,
|
||||
@NotNull ValueArgument argument,
|
||||
@@ -478,8 +527,8 @@ public class CandidateResolver {
|
||||
traceToResolveFunctionLiteral, statementExpression, mismatch);
|
||||
CallCandidateResolutionContext<D> newContext =
|
||||
context.replaceBindingTrace(errorInterceptingTrace).replaceExpectedType(expectedType);
|
||||
JetType type = argumentTypeResolver.getFunctionLiteralTypeInfo((JetFunctionLiteralExpression) argumentExpression, newContext,
|
||||
RESOLVE_FUNCTION_ARGUMENTS).getType();
|
||||
JetType type = argumentTypeResolver.getFunctionLiteralTypeInfo(
|
||||
(JetFunctionLiteralExpression) argumentExpression, newContext, RESOLVE_FUNCTION_ARGUMENTS).getType();
|
||||
if (!mismatch[0]) {
|
||||
constraintSystem.addSubtypeConstraint(
|
||||
type, effectiveExpectedType, ConstraintPosition.getValueParameterPosition(valueParameterDescriptor.getIndex()));
|
||||
|
||||
+4
-1
@@ -34,7 +34,10 @@ public class DoubleValueTypeConstructor extends NumberValueTypeConstructor {
|
||||
private final List<JetType> supertypes;
|
||||
|
||||
private DoubleValueTypeConstructor() {
|
||||
supertypes = Lists.newArrayList(KotlinBuiltIns.getInstance().getFloatType(), KotlinBuiltIns.getInstance().getDoubleType());
|
||||
// order of types matters
|
||||
// 'getPrimitiveNumberType' returns first of supertypes that is a subtype of expected type
|
||||
// for expected type 'Any' result type 'Double' should be returned
|
||||
supertypes = Lists.newArrayList(KotlinBuiltIns.getInstance().getDoubleType(), KotlinBuiltIns.getInstance().getFloatType());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
+4
-1
@@ -31,9 +31,12 @@ public class IntegerValueTypeConstructor extends NumberValueTypeConstructor {
|
||||
}
|
||||
|
||||
private IntegerValueTypeConstructor(long value) {
|
||||
// order of types matters
|
||||
// 'getPrimitiveNumberType' returns first of supertypes that is a subtype of expected type
|
||||
// for expected type 'Any' result type 'Int' should be returned
|
||||
checkBoundsAndAddSuperType(value, (long) Integer.MIN_VALUE, (long) Integer.MAX_VALUE, KotlinBuiltIns.getInstance().getIntType());
|
||||
checkBoundsAndAddSuperType(value, (long) Byte.MIN_VALUE, (long) Byte.MAX_VALUE, KotlinBuiltIns.getInstance().getByteType());
|
||||
checkBoundsAndAddSuperType(value, (long) Short.MIN_VALUE, (long) Short.MAX_VALUE, KotlinBuiltIns.getInstance().getShortType());
|
||||
checkBoundsAndAddSuperType(value, (long) Integer.MIN_VALUE, (long) Integer.MAX_VALUE, KotlinBuiltIns.getInstance().getIntType());
|
||||
supertypes.add(KotlinBuiltIns.getInstance().getLongType());
|
||||
}
|
||||
|
||||
|
||||
@@ -580,9 +580,12 @@ public class TypeUtils {
|
||||
return upperBounds;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@NotNull
|
||||
public static JetType getDefaultPrimitiveNumberType(@NotNull NumberValueTypeConstructor numberValueTypeConstructor) {
|
||||
return getDefaultPrimitiveNumberType(numberValueTypeConstructor.getSupertypes());
|
||||
JetType type = getDefaultPrimitiveNumberType(numberValueTypeConstructor.getSupertypes());
|
||||
assert type != null : "Strange number value type constructor: " + numberValueTypeConstructor + ". " +
|
||||
"Super types doesn't contain double, int or long: " + numberValueTypeConstructor.getSupertypes();
|
||||
return type;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -602,7 +605,7 @@ public class TypeUtils {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@NotNull
|
||||
public static JetType getPrimitiveNumberType(
|
||||
@NotNull NumberValueTypeConstructor numberValueTypeConstructor,
|
||||
@NotNull JetType expectedType
|
||||
|
||||
+4
-1
@@ -139,6 +139,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
|
||||
CompileTimeConstant<?> value = compileTimeConstantResolver.getCompileTimeConstant(expression, context.expectedType);
|
||||
if (value instanceof ErrorValue) {
|
||||
// 'checkType' for 'UNKNOWN_EXPECTED_TYPE' will take place in 'completeInferenceForArgument'
|
||||
if (context.expectedType != UNKNOWN_EXPECTED_TYPE) {
|
||||
context.trace.report(ERROR_COMPILE_TIME_VALUE.on(expression, ((ErrorValue) value).getMessage()));
|
||||
}
|
||||
@@ -911,7 +912,9 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
result = visitAssignmentOperation(expression, contextWithExpectedType);
|
||||
}
|
||||
else if (OperatorConventions.COMPARISON_OPERATIONS.contains(operationType)) {
|
||||
JetTypeInfo typeInfo = getTypeInfoForBinaryCall(context.scope, OperatorConventions.COMPARE_TO, context, expression);
|
||||
//we don't complete 'compareTo' call, because we change its result type from 'Int' to 'Boolean'
|
||||
JetTypeInfo typeInfo = getTypeInfoForBinaryCall(
|
||||
context.scope, OperatorConventions.COMPARE_TO, context.replaceResolveMode(ResolveMode.TOP_LEVEL_CALL), expression);
|
||||
dataFlowInfo = typeInfo.getDataFlowInfo();
|
||||
JetType compareToReturnType = typeInfo.getType();
|
||||
if (compareToReturnType != null && !ErrorUtils.isErrorType(compareToReturnType)) {
|
||||
|
||||
Reference in New Issue
Block a user