[FIR] Implement ASSIGNMENT_TYPE_MISMATCH, RESULT_TYPE_MISMATCH diagnostics, fix tests
This commit is contained in:
committed by
TeamCityServer
parent
aa70c952eb
commit
e57108d4e8
+1
-1
@@ -107,7 +107,7 @@ fun foo() {
|
|||||||
if (bool) <!ASSIGNED_VALUE_IS_NEVER_READ!>a<!> = 4 else <!ASSIGNED_VALUE_IS_NEVER_READ!>a<!> = 42
|
if (bool) <!ASSIGNED_VALUE_IS_NEVER_READ!>a<!> = 4 else <!ASSIGNED_VALUE_IS_NEVER_READ!>a<!> = 42
|
||||||
val <!VARIABLE_NEVER_READ!>b<!>: String
|
val <!VARIABLE_NEVER_READ!>b<!>: String
|
||||||
|
|
||||||
<!ASSIGNED_VALUE_IS_NEVER_READ!>b<!> = false
|
<!ASSIGNED_VALUE_IS_NEVER_READ!>b<!> = <!ASSIGNMENT_TYPE_MISMATCH!>false<!>
|
||||||
}
|
}
|
||||||
|
|
||||||
fun cycles() {
|
fun cycles() {
|
||||||
|
|||||||
+1
-1
@@ -5,5 +5,5 @@ fun foo() {
|
|||||||
// now, Idea hightlights this code like error (cuz listVar
|
// now, Idea hightlights this code like error (cuz listVar
|
||||||
// is mutable and listVar + 4 is immutable) and like warning
|
// is mutable and listVar + 4 is immutable) and like warning
|
||||||
// (cuz can be replaced with +=)
|
// (cuz can be replaced with +=)
|
||||||
<!ASSIGNED_VALUE_IS_NEVER_READ!>listVar<!> = listVar + 4
|
<!ASSIGNED_VALUE_IS_NEVER_READ!>listVar<!> = <!ASSIGNMENT_TYPE_MISMATCH!>listVar + 4<!>
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -7,7 +7,7 @@ class B(p0: String) {
|
|||||||
p3 = p1
|
p3 = p1
|
||||||
}
|
}
|
||||||
init {
|
init {
|
||||||
p1 = p0.length
|
p1 = <!ASSIGNMENT_TYPE_MISMATCH!>p0.length<!>
|
||||||
p3 = ""
|
p3 = ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+10
@@ -272,6 +272,16 @@ object DIAGNOSTICS_LIST : DiagnosticList() {
|
|||||||
parameter<String>("name")
|
parameter<String>("name")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val ASSIGNMENT_TYPE_MISMATCH by error<KtExpression> {
|
||||||
|
parameter<ConeKotlinType>("expected")
|
||||||
|
parameter<ConeKotlinType>("actual")
|
||||||
|
}
|
||||||
|
|
||||||
|
val RESULT_TYPE_MISMATCH by error<KtExpression> {
|
||||||
|
parameter<ConeKotlinType>("expected")
|
||||||
|
parameter<ConeKotlinType>("actual")
|
||||||
|
}
|
||||||
|
|
||||||
val MANY_LAMBDA_EXPRESSION_ARGUMENTS by error<KtValueArgument>()
|
val MANY_LAMBDA_EXPRESSION_ARGUMENTS by error<KtValueArgument>()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -226,6 +226,8 @@ object FirErrors {
|
|||||||
val TOO_MANY_ARGUMENTS by error1<PsiElement, FirCallableDeclaration<*>>()
|
val TOO_MANY_ARGUMENTS by error1<PsiElement, FirCallableDeclaration<*>>()
|
||||||
val NO_VALUE_FOR_PARAMETER by error1<KtElement, FirValueParameter>(SourceElementPositioningStrategies.VALUE_ARGUMENTS)
|
val NO_VALUE_FOR_PARAMETER by error1<KtElement, FirValueParameter>(SourceElementPositioningStrategies.VALUE_ARGUMENTS)
|
||||||
val NAMED_PARAMETER_NOT_FOUND by error1<KtValueArgument, String>(SourceElementPositioningStrategies.NAME_OF_NAMED_ARGUMENT)
|
val NAMED_PARAMETER_NOT_FOUND by error1<KtValueArgument, String>(SourceElementPositioningStrategies.NAME_OF_NAMED_ARGUMENT)
|
||||||
|
val ASSIGNMENT_TYPE_MISMATCH by error2<KtExpression, ConeKotlinType, ConeKotlinType>()
|
||||||
|
val RESULT_TYPE_MISMATCH by error2<KtExpression, ConeKotlinType, ConeKotlinType>()
|
||||||
val MANY_LAMBDA_EXPRESSION_ARGUMENTS by error0<KtValueArgument>()
|
val MANY_LAMBDA_EXPRESSION_ARGUMENTS by error0<KtValueArgument>()
|
||||||
|
|
||||||
// Ambiguity
|
// Ambiguity
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.descriptors.Visibilities
|
|||||||
import org.jetbrains.kotlin.descriptors.Visibility
|
import org.jetbrains.kotlin.descriptors.Visibility
|
||||||
import org.jetbrains.kotlin.fir.*
|
import org.jetbrains.kotlin.fir.*
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.*
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.modalityModifier
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.modalityModifier
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.overrideModifier
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.overrideModifier
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.visibilityModifier
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.visibilityModifier
|
||||||
@@ -33,8 +34,7 @@ import org.jetbrains.kotlin.fir.symbols.impl.*
|
|||||||
import org.jetbrains.kotlin.fir.types.*
|
import org.jetbrains.kotlin.fir.types.*
|
||||||
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
|
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
|
||||||
import org.jetbrains.kotlin.lexer.KtTokens
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.*
|
||||||
import org.jetbrains.kotlin.name.FqName
|
|
||||||
import org.jetbrains.kotlin.psi.KtModifierList
|
import org.jetbrains.kotlin.psi.KtModifierList
|
||||||
import org.jetbrains.kotlin.psi.KtParameter.VAL_VAR_TOKEN_SET
|
import org.jetbrains.kotlin.psi.KtParameter.VAL_VAR_TOKEN_SET
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.visibilityModifierType
|
import org.jetbrains.kotlin.psi.psiUtil.visibilityModifierType
|
||||||
@@ -519,3 +519,45 @@ private val FirSimpleFunction.matchesHashCodeSignature: Boolean
|
|||||||
|
|
||||||
private val FirSimpleFunction.matchesToStringSignature: Boolean
|
private val FirSimpleFunction.matchesToStringSignature: Boolean
|
||||||
get() = valueParameters.isEmpty()
|
get() = valueParameters.isEmpty()
|
||||||
|
|
||||||
|
fun checkTypeMismatch(
|
||||||
|
lValueType: ConeKotlinType,
|
||||||
|
rValue: FirExpression,
|
||||||
|
context: CheckerContext,
|
||||||
|
source: FirSourceElement,
|
||||||
|
reporter: DiagnosticReporter,
|
||||||
|
isInitializer: Boolean
|
||||||
|
) {
|
||||||
|
val rValueType = rValue.typeRef.coneType
|
||||||
|
val typeContext = context.session.typeContext
|
||||||
|
|
||||||
|
if (!isSubtypeForTypeMismatch(typeContext, subtype = rValueType, supertype = lValueType)) {
|
||||||
|
if (rValueType is ConeClassLikeType &&
|
||||||
|
rValueType.lookupTag.classId == StandardClassIds.Int &&
|
||||||
|
lValueType.fullyExpandedType(context.session).isIntegerTypeOrNullableIntegerTypeOfAnySize &&
|
||||||
|
rValueType.nullability == ConeNullability.NOT_NULL
|
||||||
|
) {
|
||||||
|
// val p: Byte = 42 or similar situation
|
||||||
|
// TODO: remove after fix of KT-46047
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (lValueType.isExtensionFunctionType || rValueType.isExtensionFunctionType) {
|
||||||
|
// TODO: remove after fix of KT-45989
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (rValue.isNullLiteral && lValueType.nullability == ConeNullability.NOT_NULL) {
|
||||||
|
reporter.reportOn(rValue.source, FirErrors.NULL_FOR_NONNULL_TYPE, context)
|
||||||
|
} else {
|
||||||
|
val diagnosticFactory = when {
|
||||||
|
isInitializer ->
|
||||||
|
FirErrors.INITIALIZER_TYPE_MISMATCH
|
||||||
|
source.kind is FirFakeSourceElementKind.DesugaredIncrementOrDecrement ->
|
||||||
|
FirErrors.RESULT_TYPE_MISMATCH
|
||||||
|
else ->
|
||||||
|
FirErrors.ASSIGNMENT_TYPE_MISMATCH
|
||||||
|
}
|
||||||
|
|
||||||
|
reporter.report(diagnosticFactory.on(source, lValueType, rValueType), context)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+4
-31
@@ -7,18 +7,12 @@ package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.KtNodeTypes
|
import org.jetbrains.kotlin.KtNodeTypes
|
||||||
import org.jetbrains.kotlin.fir.FirRealSourceElementKind
|
import org.jetbrains.kotlin.fir.FirRealSourceElementKind
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.checkers.checkTypeMismatch
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.isSubtypeForTypeMismatch
|
import org.jetbrains.kotlin.fir.analysis.checkers.isComponentCall
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INITIALIZER_TYPE_MISMATCH
|
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirProperty
|
import org.jetbrains.kotlin.fir.declarations.FirProperty
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirComponentCall
|
import org.jetbrains.kotlin.fir.types.coneType
|
||||||
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
|
|
||||||
import org.jetbrains.kotlin.fir.typeContext
|
|
||||||
import org.jetbrains.kotlin.fir.types.*
|
|
||||||
import org.jetbrains.kotlin.name.StandardClassIds
|
|
||||||
|
|
||||||
object FirInitializerTypeMismatchChecker : FirPropertyChecker() {
|
object FirInitializerTypeMismatchChecker : FirPropertyChecker() {
|
||||||
override fun check(declaration: FirProperty, context: CheckerContext, reporter: DiagnosticReporter) {
|
override fun check(declaration: FirProperty, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
@@ -28,28 +22,7 @@ object FirInitializerTypeMismatchChecker : FirPropertyChecker() {
|
|||||||
if (initializer is FirComponentCall) return
|
if (initializer is FirComponentCall) return
|
||||||
if (declaration.returnTypeRef.source?.kind != FirRealSourceElementKind) return
|
if (declaration.returnTypeRef.source?.kind != FirRealSourceElementKind) return
|
||||||
val propertyType = declaration.returnTypeRef.coneType
|
val propertyType = declaration.returnTypeRef.coneType
|
||||||
val expressionType = initializer.typeRef.coneTypeSafe<ConeKotlinType>() ?: return
|
|
||||||
val typeContext = context.session.typeContext
|
|
||||||
|
|
||||||
if (!isSubtypeForTypeMismatch(typeContext, subtype = expressionType, supertype = propertyType)) {
|
checkTypeMismatch(propertyType, initializer, context, source, reporter, true)
|
||||||
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
|
|
||||||
// TODO: remove after fix of KT-46047
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (propertyType.isExtensionFunctionType || expressionType.isExtensionFunctionType) {
|
|
||||||
// TODO: remove after fix of KT-45989
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (initializer.isNullLiteral && propertyType.nullability == ConeNullability.NOT_NULL) {
|
|
||||||
reporter.reportOn(initializer.source, FirErrors.NULL_FOR_NONNULL_TYPE, context)
|
|
||||||
} else {
|
|
||||||
reporter.report(INITIALIZER_TYPE_MISMATCH.on(source, propertyType, expressionType), context)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+7
-11
@@ -5,25 +5,21 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.analysis.checkers.expression
|
package org.jetbrains.kotlin.fir.analysis.checkers.expression
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.checkers.checkTypeMismatch
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirVariableAssignment
|
import org.jetbrains.kotlin.fir.expressions.FirVariableAssignment
|
||||||
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
|
||||||
import org.jetbrains.kotlin.fir.types.ConeNullability
|
|
||||||
import org.jetbrains.kotlin.fir.types.coneType
|
import org.jetbrains.kotlin.fir.types.coneType
|
||||||
import org.jetbrains.kotlin.fir.types.isNullLiteral
|
|
||||||
|
|
||||||
object FirAssignmentTypeMismatchChecker : FirVariableAssignmentChecker() {
|
object FirAssignmentTypeMismatchChecker : FirVariableAssignmentChecker() {
|
||||||
override fun check(expression: FirVariableAssignment, context: CheckerContext, reporter: DiagnosticReporter) {
|
override fun check(expression: FirVariableAssignment, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
val rValue = expression.rValue
|
val source = expression.rValue.source ?: return
|
||||||
if (rValue.isNullLiteral) {
|
val lValueType =
|
||||||
val leftType = ((expression.lValue as? FirResolvedNamedReference)?.resolvedSymbol as? FirPropertySymbol)?.fir?.returnTypeRef
|
((expression.lValue as? FirResolvedNamedReference)?.resolvedSymbol as? FirPropertySymbol)?.fir?.returnTypeRef?.coneType
|
||||||
if (leftType?.coneType?.nullability == ConeNullability.NOT_NULL) {
|
?: return
|
||||||
reporter.reportOn(rValue.source, FirErrors.NULL_FOR_NONNULL_TYPE, context)
|
|
||||||
}
|
checkTypeMismatch(lValueType, expression.rValue, context, source, reporter, false)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+12
-12
@@ -22,10 +22,10 @@ class WrongIncDec() {
|
|||||||
|
|
||||||
fun testWrongIncDec() {
|
fun testWrongIncDec() {
|
||||||
var x = WrongIncDec()
|
var x = WrongIncDec()
|
||||||
x++
|
<!RESULT_TYPE_MISMATCH!>x++<!>
|
||||||
++x
|
<!RESULT_TYPE_MISMATCH!>++x<!>
|
||||||
x--
|
<!RESULT_TYPE_MISMATCH!>x--<!>
|
||||||
--x
|
<!RESULT_TYPE_MISMATCH!>--x<!>
|
||||||
}
|
}
|
||||||
|
|
||||||
class UnitIncDec() {
|
class UnitIncDec() {
|
||||||
@@ -35,12 +35,12 @@ class UnitIncDec() {
|
|||||||
|
|
||||||
fun testUnitIncDec() {
|
fun testUnitIncDec() {
|
||||||
var x = UnitIncDec()
|
var x = UnitIncDec()
|
||||||
x++
|
<!RESULT_TYPE_MISMATCH!>x++<!>
|
||||||
++x
|
<!RESULT_TYPE_MISMATCH!>++x<!>
|
||||||
x--
|
<!RESULT_TYPE_MISMATCH!>x--<!>
|
||||||
--x
|
<!RESULT_TYPE_MISMATCH!>--x<!>
|
||||||
x = x++
|
x = <!RESULT_TYPE_MISMATCH!>x++<!>
|
||||||
x = x--
|
x = <!RESULT_TYPE_MISMATCH!>x--<!>
|
||||||
x = ++x
|
x = <!RESULT_TYPE_MISMATCH!>++x<!>
|
||||||
x = --x
|
x = <!RESULT_TYPE_MISMATCH!>--x<!>
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -13,7 +13,7 @@ class Q {
|
|||||||
private var y = foo<String>()
|
private var y = foo<String>()
|
||||||
|
|
||||||
fun bar() {
|
fun bar() {
|
||||||
x = y
|
x = <!ASSIGNMENT_TYPE_MISMATCH!>y<!>
|
||||||
x = foo<CharSequence>()
|
x = foo<CharSequence>()
|
||||||
y = foo<String>()
|
y = foo<String>()
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ fun <E> commonSupertype(x: E, y: E): E = x
|
|||||||
|
|
||||||
fun foo() {
|
fun foo() {
|
||||||
var myIt = A<String>().iterator()
|
var myIt = A<String>().iterator()
|
||||||
myIt = A<Int>().iterator()
|
myIt = <!ASSIGNMENT_TYPE_MISMATCH!>A<Int>().iterator()<!>
|
||||||
|
|
||||||
val csIt: Iterator<CharSequence> = A<String>().iterator()
|
val csIt: Iterator<CharSequence> = A<String>().iterator()
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -11,7 +11,7 @@ class Outer<T> {
|
|||||||
z.checkType { _<Inner>() }
|
z.checkType { _<Inner>() }
|
||||||
z.checkType { _<Outer<T>.Inner>() }
|
z.checkType { _<Outer<T>.Inner>() }
|
||||||
|
|
||||||
inner = x
|
inner = <!ASSIGNMENT_TYPE_MISMATCH!>x<!>
|
||||||
}
|
}
|
||||||
|
|
||||||
class Nested
|
class Nested
|
||||||
|
|||||||
+2
-2
@@ -12,7 +12,7 @@ fun <T : CharSequence?> foo(x: T) {
|
|||||||
if (x != null) {}
|
if (x != null) {}
|
||||||
|
|
||||||
y1 = x
|
y1 = x
|
||||||
y2 = x
|
y2 = <!ASSIGNMENT_TYPE_MISMATCH!>x<!>
|
||||||
|
|
||||||
bar1(x)
|
bar1(x)
|
||||||
bar1<CharSequence>(x)
|
bar1<CharSequence>(x)
|
||||||
@@ -31,7 +31,7 @@ fun <T : CharSequence?> foo(x: T) {
|
|||||||
|
|
||||||
if (x is CharSequence) {
|
if (x is CharSequence) {
|
||||||
y1 = x
|
y1 = x
|
||||||
y2 = x
|
y2 = <!ASSIGNMENT_TYPE_MISMATCH!>x<!>
|
||||||
|
|
||||||
bar1(x)
|
bar1(x)
|
||||||
bar2(x)
|
bar2(x)
|
||||||
|
|||||||
@@ -24,10 +24,10 @@ class A<T : CharSequence?, E1 : T, E2: T?> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (1 == 1) {
|
if (1 == 1) {
|
||||||
t = tN
|
t = <!ASSIGNMENT_TYPE_MISMATCH!>tN<!>
|
||||||
}
|
}
|
||||||
|
|
||||||
t = y
|
t = <!ASSIGNMENT_TYPE_MISMATCH!>y<!>
|
||||||
|
|
||||||
if (y != null) {
|
if (y != null) {
|
||||||
t = y
|
t = y
|
||||||
|
|||||||
Vendored
+2
-2
@@ -5,6 +5,6 @@ interface Tr<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun test(t: Tr<*>) {
|
fun test(t: Tr<*>) {
|
||||||
t.v = t
|
t.v = <!ASSIGNMENT_TYPE_MISMATCH!>t<!>
|
||||||
t.v checkType { _<Tr<*>>() }
|
t.v checkType { _<Tr<*>>() }
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -8,7 +8,7 @@ interface Tr<T> {
|
|||||||
|
|
||||||
fun test(t: Tr<*>) {
|
fun test(t: Tr<*>) {
|
||||||
t.v = null!!
|
t.v = null!!
|
||||||
t.v = ""
|
t.v = <!ASSIGNMENT_TYPE_MISMATCH!>""<!>
|
||||||
t.v = <!NULL_FOR_NONNULL_TYPE!>null<!>
|
t.v = <!NULL_FOR_NONNULL_TYPE!>null<!>
|
||||||
t.v checkType { _<Any?>() }
|
t.v checkType { _<Any?>() }
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+2
-2
@@ -7,5 +7,5 @@ interface Tr<T> {
|
|||||||
fun test(t: Tr<out String>) {
|
fun test(t: Tr<out String>) {
|
||||||
// resolved as t.v = t.v + null!!, where type of right operand is String,
|
// resolved as t.v = t.v + null!!, where type of right operand is String,
|
||||||
// so TYPE_MISMATCH: String is not <: of Captured(out String)
|
// so TYPE_MISMATCH: String is not <: of Captured(out String)
|
||||||
t.v += null!!
|
<!ASSIGNMENT_TYPE_MISMATCH!>t.v += null!!<!>
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+17
-17
@@ -3,15 +3,15 @@ fun intBinEq() {
|
|||||||
x <!UNRESOLVED_REFERENCE!>+=<!> 'a'
|
x <!UNRESOLVED_REFERENCE!>+=<!> 'a'
|
||||||
x += 1.toByte()
|
x += 1.toByte()
|
||||||
x += 1.toShort()
|
x += 1.toShort()
|
||||||
x += 1L
|
<!ASSIGNMENT_TYPE_MISMATCH!>x += 1L<!>
|
||||||
x += 1f
|
<!ASSIGNMENT_TYPE_MISMATCH!>x += 1f<!>
|
||||||
x += 1.0
|
<!ASSIGNMENT_TYPE_MISMATCH!>x += 1.0<!>
|
||||||
x <!UNRESOLVED_REFERENCE!>*=<!> 'a'
|
x <!UNRESOLVED_REFERENCE!>*=<!> 'a'
|
||||||
x *= 1.toByte()
|
<!ASSIGNMENT_TYPE_MISMATCH!>x *= 1.toByte()<!>
|
||||||
x *= 1.toShort()
|
<!ASSIGNMENT_TYPE_MISMATCH!>x *= 1.toShort()<!>
|
||||||
x *= 1L
|
<!ASSIGNMENT_TYPE_MISMATCH!>x *= 1L<!>
|
||||||
x *= 1f
|
<!ASSIGNMENT_TYPE_MISMATCH!>x *= 1f<!>
|
||||||
x *= 1.0
|
<!ASSIGNMENT_TYPE_MISMATCH!>x *= 1.0<!>
|
||||||
}
|
}
|
||||||
|
|
||||||
fun shortBinEq() {
|
fun shortBinEq() {
|
||||||
@@ -19,16 +19,16 @@ fun shortBinEq() {
|
|||||||
x <!UNRESOLVED_REFERENCE!>+=<!> 'a'
|
x <!UNRESOLVED_REFERENCE!>+=<!> 'a'
|
||||||
x += 1.toByte()
|
x += 1.toByte()
|
||||||
x += 1.toShort()
|
x += 1.toShort()
|
||||||
x += 1L
|
<!ASSIGNMENT_TYPE_MISMATCH!>x += 1L<!>
|
||||||
x += 1f
|
<!ASSIGNMENT_TYPE_MISMATCH!>x += 1f<!>
|
||||||
x += 1.0
|
<!ASSIGNMENT_TYPE_MISMATCH!>x += 1.0<!>
|
||||||
|
|
||||||
x <!UNRESOLVED_REFERENCE!>*=<!> 'a'
|
x <!UNRESOLVED_REFERENCE!>*=<!> 'a'
|
||||||
x *= 1.toByte()
|
<!ASSIGNMENT_TYPE_MISMATCH!>x *= 1.toByte()<!>
|
||||||
x *= 1.toShort()
|
<!ASSIGNMENT_TYPE_MISMATCH!>x *= 1.toShort()<!>
|
||||||
x *= 1L
|
<!ASSIGNMENT_TYPE_MISMATCH!>x *= 1L<!>
|
||||||
x *= 1f
|
<!ASSIGNMENT_TYPE_MISMATCH!>x *= 1f<!>
|
||||||
x *= 1.0
|
<!ASSIGNMENT_TYPE_MISMATCH!>x *= 1.0<!>
|
||||||
}
|
}
|
||||||
|
|
||||||
class A {
|
class A {
|
||||||
@@ -44,5 +44,5 @@ fun overloading() {
|
|||||||
var y = A()
|
var y = A()
|
||||||
x += y
|
x += y
|
||||||
var z = B()
|
var z = B()
|
||||||
z += x
|
<!ASSIGNMENT_TYPE_MISMATCH!>z += x<!>
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -18,10 +18,10 @@ var n: J? = J()
|
|||||||
|
|
||||||
fun test() {
|
fun test() {
|
||||||
v = J.staticNN
|
v = J.staticNN
|
||||||
v = J.staticN
|
v = <!ASSIGNMENT_TYPE_MISMATCH!>J.staticN<!>
|
||||||
v = J.staticJ
|
v = J.staticJ
|
||||||
|
|
||||||
n = J.staticNN
|
n = J.staticNN
|
||||||
n = J.staticN
|
n = J.staticN
|
||||||
n = J.staticJ
|
n = J.staticJ
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -34,8 +34,8 @@ fun foo(c: C) {
|
|||||||
c.z checkType { _<String>() }
|
c.z checkType { _<String>() }
|
||||||
|
|
||||||
c.y = ""
|
c.y = ""
|
||||||
c.y = 1
|
c.y = <!ASSIGNMENT_TYPE_MISMATCH!>1<!>
|
||||||
|
|
||||||
c.z = ""
|
c.z = ""
|
||||||
c.z = 1
|
c.z = <!ASSIGNMENT_TYPE_MISMATCH!>1<!>
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -14,8 +14,8 @@ fun foo() {
|
|||||||
noSetter checkType { _<Int>() }
|
noSetter checkType { _<Int>() }
|
||||||
|
|
||||||
x = 1
|
x = 1
|
||||||
x = ""
|
x = <!ASSIGNMENT_TYPE_MISMATCH!>""<!>
|
||||||
|
|
||||||
noSetter = 2
|
noSetter = 2
|
||||||
noSetter = ""
|
noSetter = <!ASSIGNMENT_TYPE_MISMATCH!>""<!>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ fun a(c: Calendar) {
|
|||||||
A().apply {
|
A().apply {
|
||||||
c.apply {
|
c.apply {
|
||||||
timeInMillis = 5 // synthesized variable for get|setTimeInMillis
|
timeInMillis = 5 // synthesized variable for get|setTimeInMillis
|
||||||
timeInMillis = ""
|
timeInMillis = <!ASSIGNMENT_TYPE_MISMATCH!>""<!>
|
||||||
}
|
}
|
||||||
timeInMillis = ""
|
timeInMillis = ""
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ class IncDec {
|
|||||||
|
|
||||||
fun foo(): IncDec {
|
fun foo(): IncDec {
|
||||||
var x = IncDec()
|
var x = IncDec()
|
||||||
x = x++
|
x = <!RESULT_TYPE_MISMATCH!>x++<!>
|
||||||
x++
|
<!RESULT_TYPE_MISMATCH!>x++<!>
|
||||||
return x
|
return x
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// !DIAGNOSTICS: -ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE -UNUSED_VALUE
|
// !DIAGNOSTICS: -ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE -UNUSED_VALUE
|
||||||
fun test() {
|
fun test() {
|
||||||
var x = object {}
|
var x = object {}
|
||||||
x = object {}
|
x = <!ASSIGNMENT_TYPE_MISMATCH!>object<!> {}
|
||||||
}
|
}
|
||||||
@@ -15,5 +15,5 @@ private fun foo() = run {
|
|||||||
|
|
||||||
fun test() {
|
fun test() {
|
||||||
var x = foo(1)
|
var x = foo(1)
|
||||||
x = foo()
|
x = <!ASSIGNMENT_TYPE_MISMATCH!>foo()<!>
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
class Test {
|
class Test {
|
||||||
private var x = object {};
|
private var x = object {};
|
||||||
init {
|
init {
|
||||||
x = object {}
|
x = <!ASSIGNMENT_TYPE_MISMATCH!>object<!> {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+2
-2
@@ -19,5 +19,5 @@ private fun foo() = run {
|
|||||||
|
|
||||||
fun test() {
|
fun test() {
|
||||||
var x = foo(1)
|
var x = foo(1)
|
||||||
x = foo()
|
x = <!ASSIGNMENT_TYPE_MISMATCH!>foo()<!>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,5 +19,5 @@ private fun foo() = run {
|
|||||||
|
|
||||||
fun test() {
|
fun test() {
|
||||||
var x = foo(1)
|
var x = foo(1)
|
||||||
x = foo()
|
x = <!ASSIGNMENT_TYPE_MISMATCH!>foo()<!>
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -1,5 +1,5 @@
|
|||||||
private var x = object {}
|
private var x = object {}
|
||||||
|
|
||||||
fun test() {
|
fun test() {
|
||||||
x = object {}
|
x = <!ASSIGNMENT_TYPE_MISMATCH!>object<!> {}
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+1
-1
@@ -29,7 +29,7 @@ fun foo(k: KotlinClass) {
|
|||||||
useString(k.getSomething5())
|
useString(k.getSomething5())
|
||||||
useString(k.something5)
|
useString(k.something5)
|
||||||
k.setSomething5(1)
|
k.setSomething5(1)
|
||||||
k.something5 = 1
|
k.something5 = <!ASSIGNMENT_TYPE_MISMATCH!>1<!>
|
||||||
}
|
}
|
||||||
|
|
||||||
fun useInt(i: Int) {}
|
fun useInt(i: Int) {}
|
||||||
|
|||||||
Vendored
+1
-1
@@ -9,7 +9,7 @@ fun foo(k: KotlinClass) {
|
|||||||
if (k.something == null) return
|
if (k.something == null) return
|
||||||
|
|
||||||
k.setSomething(1)
|
k.setSomething(1)
|
||||||
k.something = 1
|
k.something = <!ASSIGNMENT_TYPE_MISMATCH!>1<!>
|
||||||
}
|
}
|
||||||
|
|
||||||
fun useString(i: String) {}
|
fun useString(i: String) {}
|
||||||
|
|||||||
Vendored
+2
-2
@@ -4,7 +4,7 @@ fun foo(o: JavaClass2) {
|
|||||||
useString(o.something)
|
useString(o.something)
|
||||||
o.something = ""
|
o.something = ""
|
||||||
o.setSomething(1)
|
o.setSomething(1)
|
||||||
o.something = 1 // we generate extension property for JavaClass2 with more specific type
|
o.something = <!ASSIGNMENT_TYPE_MISMATCH!>1<!> // we generate extension property for JavaClass2 with more specific type
|
||||||
o.something += "1"
|
o.something += "1"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -19,4 +19,4 @@ public class JavaClass1 {
|
|||||||
// FILE: JavaClass2.java
|
// FILE: JavaClass2.java
|
||||||
public class JavaClass2 extends JavaClass1 {
|
public class JavaClass2 extends JavaClass1 {
|
||||||
public String getSomething() { return ""; }
|
public String getSomething() { return ""; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
class My {
|
class My {
|
||||||
var x: String = ""
|
var x: String = ""
|
||||||
set(vararg value) {
|
set(vararg value) {
|
||||||
x = value
|
x = <!ASSIGNMENT_TYPE_MISMATCH!>value<!>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
fun case1() {
|
fun case1() {
|
||||||
var a = Case1()
|
var a = Case1()
|
||||||
val res: Any? = ++a
|
val res: Any? = <!RESULT_TYPE_MISMATCH!>++a<!>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -23,7 +23,7 @@ class B() {}
|
|||||||
|
|
||||||
fun case2() {
|
fun case2() {
|
||||||
var a = Case2()
|
var a = Case2()
|
||||||
val res: Any? = ++a
|
val res: Any? = <!RESULT_TYPE_MISMATCH!>++a<!>
|
||||||
}
|
}
|
||||||
|
|
||||||
class Case2() : C() {
|
class Case2() : C() {
|
||||||
|
|||||||
+2
-2
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
fun case1() {
|
fun case1() {
|
||||||
var a = Case1()
|
var a = Case1()
|
||||||
val res: Any? = --a
|
val res: Any? = <!RESULT_TYPE_MISMATCH!>--a<!>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -23,7 +23,7 @@ class B() {}
|
|||||||
|
|
||||||
fun case2() {
|
fun case2() {
|
||||||
var a = Case2()
|
var a = Case2()
|
||||||
val res: Any? = --a
|
val res: Any? = <!RESULT_TYPE_MISMATCH!>--a<!>
|
||||||
}
|
}
|
||||||
|
|
||||||
class Case2() : C() {
|
class Case2() : C() {
|
||||||
|
|||||||
Vendored
+1
-1
@@ -53,7 +53,7 @@ fun case_9() {
|
|||||||
// TESTCASE NUMBER: 10
|
// TESTCASE NUMBER: 10
|
||||||
fun case_10(x: Int?) {
|
fun case_10(x: Int?) {
|
||||||
var y = 10
|
var y = 10
|
||||||
y = x
|
y = <!ASSIGNMENT_TYPE_MISMATCH!>x<!>
|
||||||
}
|
}
|
||||||
|
|
||||||
// TESTCASE NUMBER: 11
|
// TESTCASE NUMBER: 11
|
||||||
|
|||||||
+16
@@ -914,6 +914,22 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
|
|||||||
token,
|
token,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
add(FirErrors.ASSIGNMENT_TYPE_MISMATCH) { firDiagnostic ->
|
||||||
|
AssignmentTypeMismatchImpl(
|
||||||
|
firSymbolBuilder.typeBuilder.buildKtType(firDiagnostic.a),
|
||||||
|
firSymbolBuilder.typeBuilder.buildKtType(firDiagnostic.b),
|
||||||
|
firDiagnostic as FirPsiDiagnostic<*>,
|
||||||
|
token,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
add(FirErrors.RESULT_TYPE_MISMATCH) { firDiagnostic ->
|
||||||
|
ResultTypeMismatchImpl(
|
||||||
|
firSymbolBuilder.typeBuilder.buildKtType(firDiagnostic.a),
|
||||||
|
firSymbolBuilder.typeBuilder.buildKtType(firDiagnostic.b),
|
||||||
|
firDiagnostic as FirPsiDiagnostic<*>,
|
||||||
|
token,
|
||||||
|
)
|
||||||
|
}
|
||||||
add(FirErrors.OVERLOAD_RESOLUTION_AMBIGUITY) { firDiagnostic ->
|
add(FirErrors.OVERLOAD_RESOLUTION_AMBIGUITY) { firDiagnostic ->
|
||||||
OverloadResolutionAmbiguityImpl(
|
OverloadResolutionAmbiguityImpl(
|
||||||
firDiagnostic.a.map { abstractFirBasedSymbol ->
|
firDiagnostic.a.map { abstractFirBasedSymbol ->
|
||||||
|
|||||||
+12
@@ -649,6 +649,18 @@ sealed class KtFirDiagnostic<PSI: PsiElement> : KtDiagnosticWithPsi<PSI> {
|
|||||||
abstract val name: String
|
abstract val name: String
|
||||||
}
|
}
|
||||||
|
|
||||||
|
abstract class AssignmentTypeMismatch : KtFirDiagnostic<KtExpression>() {
|
||||||
|
override val diagnosticClass get() = AssignmentTypeMismatch::class
|
||||||
|
abstract val expected: KtType
|
||||||
|
abstract val actual: KtType
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class ResultTypeMismatch : KtFirDiagnostic<KtExpression>() {
|
||||||
|
override val diagnosticClass get() = ResultTypeMismatch::class
|
||||||
|
abstract val expected: KtType
|
||||||
|
abstract val actual: KtType
|
||||||
|
}
|
||||||
|
|
||||||
abstract class ManyLambdaExpressionArguments : KtFirDiagnostic<KtValueArgument>() {
|
abstract class ManyLambdaExpressionArguments : KtFirDiagnostic<KtValueArgument>() {
|
||||||
override val diagnosticClass get() = ManyLambdaExpressionArguments::class
|
override val diagnosticClass get() = ManyLambdaExpressionArguments::class
|
||||||
}
|
}
|
||||||
|
|||||||
+18
@@ -1046,6 +1046,24 @@ internal class NamedParameterNotFoundImpl(
|
|||||||
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
|
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal class AssignmentTypeMismatchImpl(
|
||||||
|
override val expected: KtType,
|
||||||
|
override val actual: KtType,
|
||||||
|
firDiagnostic: FirPsiDiagnostic<*>,
|
||||||
|
override val token: ValidityToken,
|
||||||
|
) : KtFirDiagnostic.AssignmentTypeMismatch(), KtAbstractFirDiagnostic<KtExpression> {
|
||||||
|
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class ResultTypeMismatchImpl(
|
||||||
|
override val expected: KtType,
|
||||||
|
override val actual: KtType,
|
||||||
|
firDiagnostic: FirPsiDiagnostic<*>,
|
||||||
|
override val token: ValidityToken,
|
||||||
|
) : KtFirDiagnostic.ResultTypeMismatch(), KtAbstractFirDiagnostic<KtExpression> {
|
||||||
|
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
|
||||||
|
}
|
||||||
|
|
||||||
internal class ManyLambdaExpressionArgumentsImpl(
|
internal class ManyLambdaExpressionArgumentsImpl(
|
||||||
firDiagnostic: FirPsiDiagnostic<*>,
|
firDiagnostic: FirPsiDiagnostic<*>,
|
||||||
override val token: ValidityToken,
|
override val token: ValidityToken,
|
||||||
|
|||||||
Vendored
+12
-12
@@ -22,10 +22,10 @@ class WrongIncDec() {
|
|||||||
|
|
||||||
fun testWrongIncDec() {
|
fun testWrongIncDec() {
|
||||||
var x = WrongIncDec()
|
var x = WrongIncDec()
|
||||||
x++
|
<error descr="[RESULT_TYPE_MISMATCH] WrongIncDec, kotlin/Int">x++</error>
|
||||||
++x
|
<error descr="[RESULT_TYPE_MISMATCH] WrongIncDec, kotlin/Int">++x</error>
|
||||||
x--
|
<error descr="[RESULT_TYPE_MISMATCH] WrongIncDec, kotlin/Int">x--</error>
|
||||||
--x
|
<error descr="[RESULT_TYPE_MISMATCH] WrongIncDec, kotlin/Int">--x</error>
|
||||||
}
|
}
|
||||||
|
|
||||||
class UnitIncDec() {
|
class UnitIncDec() {
|
||||||
@@ -35,12 +35,12 @@ class UnitIncDec() {
|
|||||||
|
|
||||||
fun testUnitIncDec() {
|
fun testUnitIncDec() {
|
||||||
var x = UnitIncDec()
|
var x = UnitIncDec()
|
||||||
x++
|
<error descr="[RESULT_TYPE_MISMATCH] UnitIncDec, kotlin/Unit">x++</error>
|
||||||
++x
|
<error descr="[RESULT_TYPE_MISMATCH] UnitIncDec, kotlin/Unit">++x</error>
|
||||||
x--
|
<error descr="[RESULT_TYPE_MISMATCH] UnitIncDec, kotlin/Unit">x--</error>
|
||||||
--x
|
<error descr="[RESULT_TYPE_MISMATCH] UnitIncDec, kotlin/Unit">--x</error>
|
||||||
x = x++
|
x = <error descr="[RESULT_TYPE_MISMATCH] UnitIncDec, kotlin/Unit">x++</error>
|
||||||
x = x--
|
x = <error descr="[RESULT_TYPE_MISMATCH] UnitIncDec, kotlin/Unit">x--</error>
|
||||||
x = ++x
|
x = <error descr="[RESULT_TYPE_MISMATCH] UnitIncDec, kotlin/Unit">++x</error>
|
||||||
x = --x
|
x = <error descr="[RESULT_TYPE_MISMATCH] UnitIncDec, kotlin/Unit">--x</error>
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user