Prohibit identity equals on inline class types

This commit is contained in:
Mikhail Zarechenskiy
2018-06-07 15:11:04 +03:00
parent 9891f562cc
commit b2d9015723
10 changed files with 91 additions and 5 deletions
@@ -744,6 +744,7 @@ public interface Errors {
DiagnosticFactory2<KtBinaryExpression, KotlinType, KotlinType> DEPRECATED_IDENTITY_EQUALS = DiagnosticFactory2.create(WARNING);
DiagnosticFactory2<KtBinaryExpression, KotlinType, KotlinType> IMPLICIT_BOXING_IN_IDENTITY_EQUALS = DiagnosticFactory2.create(WARNING);
DiagnosticFactory2<KtBinaryExpression, KotlinType, KotlinType> FORBIDDEN_IDENTITY_EQUALS = DiagnosticFactory2.create(ERROR);
DiagnosticFactory2<PsiElement, FunctionDescriptor, String> DEPRECATED_BINARY_MOD = DiagnosticFactory2.create(WARNING);
DiagnosticFactory2<PsiElement, FunctionDescriptor, String> DEPRECATED_BINARY_MOD_AS_REM = DiagnosticFactory2.create(WARNING);
@@ -393,6 +393,7 @@ public class DefaultErrorMessages {
MAP.put(DEPRECATED_IDENTITY_EQUALS, "Identity equality for arguments of types {0} and {1} is deprecated", RENDER_TYPE, RENDER_TYPE);
MAP.put(IMPLICIT_BOXING_IN_IDENTITY_EQUALS, "Identity equality for arguments of types {0} and {1} can be unstable because of implicit boxing", RENDER_TYPE, RENDER_TYPE);
MAP.put(FORBIDDEN_IDENTITY_EQUALS, "Identity equality for arguments of types {0} and {1} is forbidden", RENDER_TYPE, RENDER_TYPE);
MAP.put(DEPRECATED_BINARY_MOD, "Deprecated convention for ''{0}''. Use ''{1}''", NAME, STRING);
MAP.put(DEPRECATED_BINARY_MOD_AS_REM, "''%'' is resolved to deprecated ''{0}'' operator. Replace with ''.{0}'' or add operator ''{1}''", NAME, STRING);
@@ -39,7 +39,6 @@ import org.jetbrains.kotlin.lexer.KtKeywordToken;
import org.jetbrains.kotlin.lexer.KtTokens;
import org.jetbrains.kotlin.name.Name;
import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.psi.psiUtil.KtPsiUtilKt;
import org.jetbrains.kotlin.psi.psiUtil.PsiUtilsKt;
import org.jetbrains.kotlin.psi.psiUtil.ReservedCheckingKt;
import org.jetbrains.kotlin.resolve.*;
@@ -1069,7 +1068,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
ensureNonemptyIntersectionOfOperandTypes(expression, context);
// TODO : Check comparison pointlessness
result = TypeInfoFactoryKt.createTypeInfo(components.builtIns.getBooleanType(), context);
checkIdentityOnPrimitiveTypes(expression, context);
checkIdentityOnPrimitiveOrInlineClassTypes(expression, context);
}
else if (OperatorConventions.IN_OPERATIONS.contains(operationType)) {
ValueArgument leftArgument = CallMaker.makeValueArgument(left, left != null ? left : operationSign);
@@ -1091,15 +1090,23 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
return components.dataFlowAnalyzer.checkType(result, expression, contextWithExpectedType);
}
private static void checkIdentityOnPrimitiveTypes(@NotNull KtBinaryExpression expression, @NotNull ExpressionTypingContext context) {
private static void checkIdentityOnPrimitiveOrInlineClassTypes(
@NotNull KtBinaryExpression expression,
@NotNull ExpressionTypingContext context
) {
if (expression.getLeft() == null || expression.getRight() == null) return;
KotlinType leftType = context.trace.getType(expression.getLeft());
KotlinType rightType = context.trace.getType(expression.getRight());
if (leftType == null || rightType == null) return;
if (KotlinTypeChecker.DEFAULT.equalTypes(leftType, rightType) && KotlinBuiltIns.isPrimitiveType(leftType)) {
context.trace.report(DEPRECATED_IDENTITY_EQUALS.on(expression, leftType, rightType));
if (KotlinTypeChecker.DEFAULT.equalTypes(leftType, rightType)) {
if (KotlinBuiltIns.isPrimitiveType(leftType)) {
context.trace.report(DEPRECATED_IDENTITY_EQUALS.on(expression, leftType, rightType));
}
else if (InlineClassesUtilsKt.isInlineClassType(leftType)) {
context.trace.report(FORBIDDEN_IDENTITY_EQUALS.on(expression, leftType, rightType));
}
}
else if (isIdentityComparedWithImplicitBoxing(leftType, rightType) || isIdentityComparedWithImplicitBoxing(rightType, leftType)) {
context.trace.report(IMPLICIT_BOXING_IN_IDENTITY_EQUALS.on(expression, leftType, rightType));