From fa4d664a18eac86c05ca1e4c5b01ef35582d6566 Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Fri, 9 Apr 2021 15:42:28 +0300 Subject: [PATCH] FIR initializer: don't report type mismatch in SomeInt = Int case --- .../FirInitializerTypeMismatchChecker.kt | 13 ++++++++-- .../kotlin/fir/types/ConeTypeUtils.kt | 3 +++ .../binaryMinusIndependentExpType.fir.kt | 24 +++++++++---------- .../tests/evaluate/parentesized.fir.kt | 10 ++++---- .../unaryMinusIndependentExpType.fir.kt | 18 +++++++------- .../numbers/numbersInSimpleConstraints.fir.kt | 4 ++-- .../tests/regressions/kt2768.fir.kt | 4 ++-- 7 files changed, 44 insertions(+), 32 deletions(-) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirInitializerTypeMismatchChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirInitializerTypeMismatchChecker.kt index 5b3ce2835a4..05afb5df850 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirInitializerTypeMismatchChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirInitializerTypeMismatchChecker.kt @@ -12,9 +12,10 @@ import org.jetbrains.kotlin.fir.analysis.checkers.isSubtypeForTypeMismatch import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INITIALIZER_TYPE_MISMATCH import org.jetbrains.kotlin.fir.declarations.FirProperty +import org.jetbrains.kotlin.fir.resolve.fullyExpandedType import org.jetbrains.kotlin.fir.typeContext -import org.jetbrains.kotlin.fir.types.ConeKotlinType -import org.jetbrains.kotlin.fir.types.coneTypeSafe +import org.jetbrains.kotlin.fir.types.* +import org.jetbrains.kotlin.name.StandardClassIds object FirInitializerTypeMismatchChecker : FirPropertyChecker() { override fun check(declaration: FirProperty, context: CheckerContext, reporter: DiagnosticReporter) { @@ -26,6 +27,14 @@ object FirInitializerTypeMismatchChecker : FirPropertyChecker() { val typeContext = context.session.typeContext if (!isSubtypeForTypeMismatch(typeContext, subtype = expressionType, supertype = propertyType)) { + if (expressionType is ConeClassLikeType && + expressionType.lookupTag.classId == StandardClassIds.Int && + propertyType.fullyExpandedType(context.session).isIntegerTypeOrNullableIntegerTypeOfAnySize && + expressionType.nullability == ConeNullability.NOT_NULL + ) { + // val p: Byte = 42 or similar situation + return + } val source = declaration.source ?: return reporter.report(INITIALIZER_TYPE_MISMATCH.on(source, propertyType, expressionType), context) } diff --git a/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/ConeTypeUtils.kt b/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/ConeTypeUtils.kt index b31ce85763f..c6c3182c4c3 100644 --- a/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/ConeTypeUtils.kt +++ b/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/ConeTypeUtils.kt @@ -76,6 +76,9 @@ val ConeKotlinType.isNonPrimitiveArray: Boolean private val builtinUnsignedTypes = setOf(StandardClassIds.UInt, StandardClassIds.UByte, StandardClassIds.ULong, StandardClassIds.UShort) val ConeKotlinType.isUnsignedTypeOrNullableUnsignedType: Boolean get() = isAnyOfBuiltinType(builtinUnsignedTypes) +private val builtinIntegerTypes = setOf(StandardClassIds.Int, StandardClassIds.Byte, StandardClassIds.Long, StandardClassIds.Short) +val ConeKotlinType.isIntegerTypeOrNullableIntegerTypeOfAnySize: Boolean get() = isAnyOfBuiltinType(builtinIntegerTypes) + private fun ConeKotlinType.isBuiltinType(classId: ClassId, isNullable: Boolean): Boolean { if (this !is ConeClassLikeType) return false return lookupTag.classId == classId && type.isNullable == isNullable diff --git a/compiler/testData/diagnostics/tests/evaluate/binaryMinusIndependentExpType.fir.kt b/compiler/testData/diagnostics/tests/evaluate/binaryMinusIndependentExpType.fir.kt index b6dcb1386e7..2f524af2c1a 100644 --- a/compiler/testData/diagnostics/tests/evaluate/binaryMinusIndependentExpType.fir.kt +++ b/compiler/testData/diagnostics/tests/evaluate/binaryMinusIndependentExpType.fir.kt @@ -1,24 +1,24 @@ val p1: Int = 1 - 1 -val p2: Long = 1 - 1 -val p3: Byte = 1 - 1 -val p4: Short = 1 - 1 +val p2: Long = 1 - 1 +val p3: Byte = 1 - 1 +val p4: Short = 1 - 1 val l1: Long = 1 - 1.toLong() val l2: Byte = 1 - 1.toLong() val l3: Int = 1 - 1.toLong() val l4: Short = 1 - 1.toLong() -val b1: Byte = 1 - 1.toByte() +val b1: Byte = 1 - 1.toByte() val b2: Int = 1 - 1.toByte() -val b3: Long = 1 - 1.toByte() -val b4: Short = 1 - 1.toByte() +val b3: Long = 1 - 1.toByte() +val b4: Short = 1 - 1.toByte() -val i1: Byte = 1 - 1.toInt() +val i1: Byte = 1 - 1.toInt() val i2: Int = 1 - 1.toInt() -val i3: Long = 1 - 1.toInt() -val i4: Short = 1 - 1.toInt() +val i3: Long = 1 - 1.toInt() +val i4: Short = 1 - 1.toInt() -val s1: Byte = 1 - 1.toShort() +val s1: Byte = 1 - 1.toShort() val s2: Int = 1 - 1.toShort() -val s3: Long = 1 - 1.toShort() -val s4: Short = 1 - 1.toShort() +val s3: Long = 1 - 1.toShort() +val s4: Short = 1 - 1.toShort() diff --git a/compiler/testData/diagnostics/tests/evaluate/parentesized.fir.kt b/compiler/testData/diagnostics/tests/evaluate/parentesized.fir.kt index aeb47871192..1b35f47790b 100644 --- a/compiler/testData/diagnostics/tests/evaluate/parentesized.fir.kt +++ b/compiler/testData/diagnostics/tests/evaluate/parentesized.fir.kt @@ -1,10 +1,10 @@ -val p1: Byte = (1 + 2) * 2 -val p2: Short = (1 + 2) * 2 +val p1: Byte = (1 + 2) * 2 +val p2: Short = (1 + 2) * 2 val p3: Int = (1 + 2) * 2 -val p4: Long = (1 + 2) * 2 +val p4: Long = (1 + 2) * 2 -val b1: Byte = (1.toByte() + 2) * 2 -val b2: Short = (1.toShort() + 2) * 2 +val b1: Byte = (1.toByte() + 2) * 2 +val b2: Short = (1.toShort() + 2) * 2 val b3: Int = (1.toInt() + 2) * 2 val b4: Long = (1.toLong() + 2) * 2 diff --git a/compiler/testData/diagnostics/tests/evaluate/unaryMinusIndependentExpType.fir.kt b/compiler/testData/diagnostics/tests/evaluate/unaryMinusIndependentExpType.fir.kt index 372ec2bda6d..3d17ec1adef 100644 --- a/compiler/testData/diagnostics/tests/evaluate/unaryMinusIndependentExpType.fir.kt +++ b/compiler/testData/diagnostics/tests/evaluate/unaryMinusIndependentExpType.fir.kt @@ -13,17 +13,17 @@ val l2: Byte = -1.toLong() val l3: Int = -1.toLong() val l4: Short = -1.toLong() -val b1: Byte = -1.toByte() +val b1: Byte = -1.toByte() val b2: Int = -1.toByte() -val b3: Long = -1.toByte() -val b4: Short = -1.toByte() +val b3: Long = -1.toByte() +val b4: Short = -1.toByte() -val i1: Byte = -1.toInt() +val i1: Byte = -1.toInt() val i2: Int = -1.toInt() -val i3: Long = -1.toInt() -val i4: Short = -1.toInt() +val i3: Long = -1.toInt() +val i4: Short = -1.toInt() -val s1: Byte = -1.toShort() +val s1: Byte = -1.toShort() val s2: Int = -1.toShort() -val s3: Long = -1.toShort() -val s4: Short = -1.toShort() +val s3: Long = -1.toShort() +val s4: Short = -1.toShort() diff --git a/compiler/testData/diagnostics/tests/numbers/numbersInSimpleConstraints.fir.kt b/compiler/testData/diagnostics/tests/numbers/numbersInSimpleConstraints.fir.kt index ebdd8dc6deb..e692fb60343 100644 --- a/compiler/testData/diagnostics/tests/numbers/numbersInSimpleConstraints.fir.kt +++ b/compiler/testData/diagnostics/tests/numbers/numbersInSimpleConstraints.fir.kt @@ -17,7 +17,7 @@ fun otherGeneric(l: List) {} fun test() { val a: Byte = id(1) - val b: Byte = id(300) + val b: Byte = id(300) val c: Int = id(9223372036854775807) @@ -29,7 +29,7 @@ fun test() { val f: Byte = either(1, 2) - val g: Byte = either(1, 300) + val g: Byte = either(1, 300) other(11) diff --git a/compiler/testData/diagnostics/tests/regressions/kt2768.fir.kt b/compiler/testData/diagnostics/tests/regressions/kt2768.fir.kt index b5eacfa03c0..0670f633eb2 100644 --- a/compiler/testData/diagnostics/tests/regressions/kt2768.fir.kt +++ b/compiler/testData/diagnostics/tests/regressions/kt2768.fir.kt @@ -6,13 +6,13 @@ fun main() { val bytePos = 128.toByte() // Byte.MAX_VALUE + 1 assertEquals(-128, bytePos.toInt()) // correct, wrapped to Byte.MIN_VALUE - val byteNeg: Byte = -bytePos // should not compile, byteNeg should be Int + val byteNeg: Byte = -bytePos // should not compile, byteNeg should be Int assertEquals(128, byteNeg.toInt()) // passes, should not be possible val shortPos = 32768.toShort() // Short.MAX_VALUE + 1 assertEquals(-32768, shortPos.toInt()) // correct, wrapped to Short.MIN_VALUE - val shortNeg: Short = -shortPos // should not compile, shortNeg should be Int + val shortNeg: Short = -shortPos // should not compile, shortNeg should be Int assertEquals(32768, shortNeg.toInt()) // passes, should not be possible (-128).toByte()