FIR: support CONDITION_TYPE_MISMATCH diagnostic
We report CONDITION_TYPE_MISMATCH on - loop conditions - when branch conditions - binary logic arguments
This commit is contained in:
+2
-2
@@ -101,9 +101,9 @@ fun test(
|
|||||||
for (i in <!HAS_NEXT_MISSING, NEXT_MISSING!>notRange2<!>);
|
for (i in <!HAS_NEXT_MISSING, NEXT_MISSING!>notRange2<!>);
|
||||||
for (i in <!NEXT_MISSING!>notRange3<!>);
|
for (i in <!NEXT_MISSING!>notRange3<!>);
|
||||||
for (i in <!HAS_NEXT_MISSING!>notRange4<!>);
|
for (i in <!HAS_NEXT_MISSING!>notRange4<!>);
|
||||||
for (i in notRange5);
|
<!CONDITION_TYPE_MISMATCH!>for (i in notRange5)<!>;
|
||||||
for (i in notRange6);
|
for (i in notRange6);
|
||||||
for (i in notRange7);
|
<!CONDITION_TYPE_MISMATCH!>for (i in notRange7)<!>;
|
||||||
for (i in <!HAS_NEXT_MISSING!>notRange8<!>);
|
for (i in <!HAS_NEXT_MISSING!>notRange8<!>);
|
||||||
for (i in <!OPERATOR_MODIFIER_REQUIRED, OPERATOR_MODIFIER_REQUIRED, OPERATOR_MODIFIER_REQUIRED!>notRange9<!>);
|
for (i in <!OPERATOR_MODIFIER_REQUIRED, OPERATOR_MODIFIER_REQUIRED, OPERATOR_MODIFIER_REQUIRED!>notRange9<!>);
|
||||||
for (i in range0);
|
for (i in range0);
|
||||||
|
|||||||
+2
@@ -28,6 +28,8 @@ fun main(args: Array<String>) {
|
|||||||
alias<FirVariableAssignment>("VariableAssignmentChecker")
|
alias<FirVariableAssignment>("VariableAssignmentChecker")
|
||||||
alias<FirTryExpression>("TryExpressionChecker")
|
alias<FirTryExpression>("TryExpressionChecker")
|
||||||
alias<FirWhenExpression>("WhenExpressionChecker")
|
alias<FirWhenExpression>("WhenExpressionChecker")
|
||||||
|
alias<FirLoop>("LoopExpressionChecker")
|
||||||
|
alias<FirBinaryLogicExpression>("LogicExpressionChecker")
|
||||||
alias<FirReturnExpression>("ReturnExpressionChecker")
|
alias<FirReturnExpression>("ReturnExpressionChecker")
|
||||||
alias<FirBlock>("BlockChecker")
|
alias<FirBlock>("BlockChecker")
|
||||||
alias<FirAnnotationCall>("AnnotationCallChecker")
|
alias<FirAnnotationCall>("AnnotationCallChecker")
|
||||||
|
|||||||
+8
@@ -25,6 +25,10 @@ class ComposedExpressionCheckers : ExpressionCheckers() {
|
|||||||
get() = _tryExpressionCheckers
|
get() = _tryExpressionCheckers
|
||||||
override val whenExpressionCheckers: Set<FirWhenExpressionChecker>
|
override val whenExpressionCheckers: Set<FirWhenExpressionChecker>
|
||||||
get() = _whenExpressionCheckers
|
get() = _whenExpressionCheckers
|
||||||
|
override val loopExpressionCheckers: Set<FirLoopExpressionChecker>
|
||||||
|
get() = _loopExpressionCheckers
|
||||||
|
override val logicExpressionCheckers: Set<FirLogicExpressionChecker>
|
||||||
|
get() = _logicExpressionCheckers
|
||||||
override val returnExpressionCheckers: Set<FirReturnExpressionChecker>
|
override val returnExpressionCheckers: Set<FirReturnExpressionChecker>
|
||||||
get() = _returnExpressionCheckers
|
get() = _returnExpressionCheckers
|
||||||
override val blockCheckers: Set<FirBlockChecker>
|
override val blockCheckers: Set<FirBlockChecker>
|
||||||
@@ -56,6 +60,8 @@ class ComposedExpressionCheckers : ExpressionCheckers() {
|
|||||||
private val _variableAssignmentCheckers: MutableSet<FirVariableAssignmentChecker> = mutableSetOf()
|
private val _variableAssignmentCheckers: MutableSet<FirVariableAssignmentChecker> = mutableSetOf()
|
||||||
private val _tryExpressionCheckers: MutableSet<FirTryExpressionChecker> = mutableSetOf()
|
private val _tryExpressionCheckers: MutableSet<FirTryExpressionChecker> = mutableSetOf()
|
||||||
private val _whenExpressionCheckers: MutableSet<FirWhenExpressionChecker> = mutableSetOf()
|
private val _whenExpressionCheckers: MutableSet<FirWhenExpressionChecker> = mutableSetOf()
|
||||||
|
private val _loopExpressionCheckers: MutableSet<FirLoopExpressionChecker> = mutableSetOf()
|
||||||
|
private val _logicExpressionCheckers: MutableSet<FirLogicExpressionChecker> = mutableSetOf()
|
||||||
private val _returnExpressionCheckers: MutableSet<FirReturnExpressionChecker> = mutableSetOf()
|
private val _returnExpressionCheckers: MutableSet<FirReturnExpressionChecker> = mutableSetOf()
|
||||||
private val _blockCheckers: MutableSet<FirBlockChecker> = mutableSetOf()
|
private val _blockCheckers: MutableSet<FirBlockChecker> = mutableSetOf()
|
||||||
private val _annotationCallCheckers: MutableSet<FirAnnotationCallChecker> = mutableSetOf()
|
private val _annotationCallCheckers: MutableSet<FirAnnotationCallChecker> = mutableSetOf()
|
||||||
@@ -77,6 +83,8 @@ class ComposedExpressionCheckers : ExpressionCheckers() {
|
|||||||
_variableAssignmentCheckers += checkers.variableAssignmentCheckers
|
_variableAssignmentCheckers += checkers.variableAssignmentCheckers
|
||||||
_tryExpressionCheckers += checkers.tryExpressionCheckers
|
_tryExpressionCheckers += checkers.tryExpressionCheckers
|
||||||
_whenExpressionCheckers += checkers.whenExpressionCheckers
|
_whenExpressionCheckers += checkers.whenExpressionCheckers
|
||||||
|
_loopExpressionCheckers += checkers.loopExpressionCheckers
|
||||||
|
_logicExpressionCheckers += checkers.logicExpressionCheckers
|
||||||
_returnExpressionCheckers += checkers.returnExpressionCheckers
|
_returnExpressionCheckers += checkers.returnExpressionCheckers
|
||||||
_blockCheckers += checkers.blockCheckers
|
_blockCheckers += checkers.blockCheckers
|
||||||
_annotationCallCheckers += checkers.annotationCallCheckers
|
_annotationCallCheckers += checkers.annotationCallCheckers
|
||||||
|
|||||||
+4
@@ -23,6 +23,8 @@ abstract class ExpressionCheckers {
|
|||||||
open val variableAssignmentCheckers: Set<FirVariableAssignmentChecker> = emptySet()
|
open val variableAssignmentCheckers: Set<FirVariableAssignmentChecker> = emptySet()
|
||||||
open val tryExpressionCheckers: Set<FirTryExpressionChecker> = emptySet()
|
open val tryExpressionCheckers: Set<FirTryExpressionChecker> = emptySet()
|
||||||
open val whenExpressionCheckers: Set<FirWhenExpressionChecker> = emptySet()
|
open val whenExpressionCheckers: Set<FirWhenExpressionChecker> = emptySet()
|
||||||
|
open val loopExpressionCheckers: Set<FirLoopExpressionChecker> = emptySet()
|
||||||
|
open val logicExpressionCheckers: Set<FirLogicExpressionChecker> = emptySet()
|
||||||
open val returnExpressionCheckers: Set<FirReturnExpressionChecker> = emptySet()
|
open val returnExpressionCheckers: Set<FirReturnExpressionChecker> = emptySet()
|
||||||
open val blockCheckers: Set<FirBlockChecker> = emptySet()
|
open val blockCheckers: Set<FirBlockChecker> = emptySet()
|
||||||
open val annotationCallCheckers: Set<FirAnnotationCallChecker> = emptySet()
|
open val annotationCallCheckers: Set<FirAnnotationCallChecker> = emptySet()
|
||||||
@@ -42,6 +44,8 @@ abstract class ExpressionCheckers {
|
|||||||
@CheckersComponentInternal internal val allVariableAssignmentCheckers: Set<FirVariableAssignmentChecker> get() = variableAssignmentCheckers + basicExpressionCheckers
|
@CheckersComponentInternal internal val allVariableAssignmentCheckers: Set<FirVariableAssignmentChecker> get() = variableAssignmentCheckers + basicExpressionCheckers
|
||||||
@CheckersComponentInternal internal val allTryExpressionCheckers: Set<FirTryExpressionChecker> get() = tryExpressionCheckers + basicExpressionCheckers
|
@CheckersComponentInternal internal val allTryExpressionCheckers: Set<FirTryExpressionChecker> get() = tryExpressionCheckers + basicExpressionCheckers
|
||||||
@CheckersComponentInternal internal val allWhenExpressionCheckers: Set<FirWhenExpressionChecker> get() = whenExpressionCheckers + basicExpressionCheckers
|
@CheckersComponentInternal internal val allWhenExpressionCheckers: Set<FirWhenExpressionChecker> get() = whenExpressionCheckers + basicExpressionCheckers
|
||||||
|
@CheckersComponentInternal internal val allLoopExpressionCheckers: Set<FirLoopExpressionChecker> get() = loopExpressionCheckers + basicExpressionCheckers
|
||||||
|
@CheckersComponentInternal internal val allLogicExpressionCheckers: Set<FirLogicExpressionChecker> get() = logicExpressionCheckers + basicExpressionCheckers
|
||||||
@CheckersComponentInternal internal val allReturnExpressionCheckers: Set<FirReturnExpressionChecker> get() = returnExpressionCheckers + basicExpressionCheckers
|
@CheckersComponentInternal internal val allReturnExpressionCheckers: Set<FirReturnExpressionChecker> get() = returnExpressionCheckers + basicExpressionCheckers
|
||||||
@CheckersComponentInternal internal val allBlockCheckers: Set<FirBlockChecker> get() = blockCheckers + basicExpressionCheckers
|
@CheckersComponentInternal internal val allBlockCheckers: Set<FirBlockChecker> get() = blockCheckers + basicExpressionCheckers
|
||||||
@CheckersComponentInternal internal val allAnnotationCallCheckers: Set<FirAnnotationCallChecker> get() = annotationCallCheckers + basicExpressionCheckers
|
@CheckersComponentInternal internal val allAnnotationCallCheckers: Set<FirAnnotationCallChecker> get() = annotationCallCheckers + basicExpressionCheckers
|
||||||
|
|||||||
+4
@@ -12,12 +12,14 @@ package org.jetbrains.kotlin.fir.analysis.checkers.expression
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction
|
import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
|
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.FirBinaryLogicExpression
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirBlock
|
import org.jetbrains.kotlin.fir.expressions.FirBlock
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirCheckNotNullCall
|
import org.jetbrains.kotlin.fir.expressions.FirCheckNotNullCall
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirElvisExpression
|
import org.jetbrains.kotlin.fir.expressions.FirElvisExpression
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirEqualityOperatorCall
|
import org.jetbrains.kotlin.fir.expressions.FirEqualityOperatorCall
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
|
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirGetClassCall
|
import org.jetbrains.kotlin.fir.expressions.FirGetClassCall
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.FirLoop
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier
|
import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirReturnExpression
|
import org.jetbrains.kotlin.fir.expressions.FirReturnExpression
|
||||||
@@ -35,6 +37,8 @@ typealias FirFunctionCallChecker = FirExpressionChecker<FirFunctionCall>
|
|||||||
typealias FirVariableAssignmentChecker = FirExpressionChecker<FirVariableAssignment>
|
typealias FirVariableAssignmentChecker = FirExpressionChecker<FirVariableAssignment>
|
||||||
typealias FirTryExpressionChecker = FirExpressionChecker<FirTryExpression>
|
typealias FirTryExpressionChecker = FirExpressionChecker<FirTryExpression>
|
||||||
typealias FirWhenExpressionChecker = FirExpressionChecker<FirWhenExpression>
|
typealias FirWhenExpressionChecker = FirExpressionChecker<FirWhenExpression>
|
||||||
|
typealias FirLoopExpressionChecker = FirExpressionChecker<FirLoop>
|
||||||
|
typealias FirLogicExpressionChecker = FirExpressionChecker<FirBinaryLogicExpression>
|
||||||
typealias FirReturnExpressionChecker = FirExpressionChecker<FirReturnExpression>
|
typealias FirReturnExpressionChecker = FirExpressionChecker<FirReturnExpression>
|
||||||
typealias FirBlockChecker = FirExpressionChecker<FirBlock>
|
typealias FirBlockChecker = FirExpressionChecker<FirBlock>
|
||||||
typealias FirAnnotationCallChecker = FirExpressionChecker<FirAnnotationCall>
|
typealias FirAnnotationCallChecker = FirExpressionChecker<FirAnnotationCall>
|
||||||
|
|||||||
@@ -569,3 +569,12 @@ fun checkTypeMismatch(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal fun checkCondition(condition: FirExpression, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
|
val coneType = condition.typeRef.coneType.lowerBoundIfFlexible()
|
||||||
|
if (coneType !is ConeKotlinErrorType &&
|
||||||
|
!coneType.isSubtypeOf(context.session.typeContext, context.session.builtinTypes.booleanType.type)
|
||||||
|
) {
|
||||||
|
reporter.reportOn(condition.source, FirErrors.CONDITION_TYPE_MISMATCH, coneType, context)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
+18
@@ -0,0 +1,18 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.fir.analysis.checkers.expression
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.checkers.checkCondition
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.FirBinaryLogicExpression
|
||||||
|
|
||||||
|
object FirLogicExpressionTypeChecker : FirLogicExpressionChecker() {
|
||||||
|
override fun check(expression: FirBinaryLogicExpression, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
|
checkCondition(expression.leftOperand, context, reporter)
|
||||||
|
checkCondition(expression.rightOperand, context, reporter)
|
||||||
|
}
|
||||||
|
}
|
||||||
+23
@@ -0,0 +1,23 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.fir.analysis.checkers.expression
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.checkers.checkCondition
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.withSuppressedDiagnostics
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.FirErrorLoop
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.FirLoop
|
||||||
|
|
||||||
|
object FirLoopConditionChecker : FirLoopExpressionChecker() {
|
||||||
|
override fun check(expression: FirLoop, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
|
if (expression is FirErrorLoop) return
|
||||||
|
val condition = expression.condition
|
||||||
|
withSuppressedDiagnostics(condition, context) {
|
||||||
|
checkCondition(condition, context, reporter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+25
@@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.fir.analysis.checkers.expression
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.checkers.checkCondition
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.withSuppressedDiagnostics
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.FirWhenExpression
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.impl.FirElseIfTrueCondition
|
||||||
|
|
||||||
|
object FirWhenConditionChecker : FirWhenExpressionChecker() {
|
||||||
|
override fun check(expression: FirWhenExpression, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
|
for (branch in expression.branches) {
|
||||||
|
val condition = branch.condition
|
||||||
|
if (condition is FirElseIfTrueCondition) continue
|
||||||
|
withSuppressedDiagnostics(condition, context) {
|
||||||
|
checkCondition(condition, context, reporter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+13
-2
@@ -11,7 +11,6 @@ import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
|||||||
import org.jetbrains.kotlin.fir.analysis.checkers.expression.ExpressionCheckers
|
import org.jetbrains.kotlin.fir.analysis.checkers.expression.ExpressionCheckers
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirExpressionChecker
|
import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirExpressionChecker
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkersComponent
|
import org.jetbrains.kotlin.fir.analysis.checkersComponent
|
||||||
import org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollector
|
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction
|
import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction
|
||||||
import org.jetbrains.kotlin.fir.expressions.*
|
import org.jetbrains.kotlin.fir.expressions.*
|
||||||
@@ -63,8 +62,20 @@ class ExpressionCheckersDiagnosticComponent(
|
|||||||
checkers.allWhenExpressionCheckers.check(whenExpression, data, reporter)
|
checkers.allWhenExpressionCheckers.check(whenExpression, data, reporter)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun visitWhileLoop(whileLoop: FirWhileLoop, data: CheckerContext) {
|
||||||
|
checkers.allLoopExpressionCheckers.check(whileLoop, data, reporter)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitDoWhileLoop(doWhileLoop: FirDoWhileLoop, data: CheckerContext) {
|
||||||
|
checkers.allLoopExpressionCheckers.check(doWhileLoop, data, reporter)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitErrorLoop(errorLoop: FirErrorLoop, data: CheckerContext) {
|
||||||
|
checkers.allLoopExpressionCheckers.check(errorLoop, data, reporter)
|
||||||
|
}
|
||||||
|
|
||||||
override fun visitBinaryLogicExpression(binaryLogicExpression: FirBinaryLogicExpression, data: CheckerContext) {
|
override fun visitBinaryLogicExpression(binaryLogicExpression: FirBinaryLogicExpression, data: CheckerContext) {
|
||||||
checkers.allBasicExpressionCheckers.check(binaryLogicExpression, data, reporter)
|
checkers.allLogicExpressionCheckers.check(binaryLogicExpression, data, reporter)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitArrayOfCall(arrayOfCall: FirArrayOfCall, data: CheckerContext) {
|
override fun visitArrayOfCall(arrayOfCall: FirArrayOfCall, data: CheckerContext) {
|
||||||
|
|||||||
+12
-1
@@ -56,7 +56,18 @@ object CommonExpressionCheckers : ExpressionCheckers() {
|
|||||||
|
|
||||||
override val whenExpressionCheckers: Set<FirWhenExpressionChecker>
|
override val whenExpressionCheckers: Set<FirWhenExpressionChecker>
|
||||||
get() = setOf(
|
get() = setOf(
|
||||||
FirExhaustiveWhenChecker
|
FirExhaustiveWhenChecker,
|
||||||
|
FirWhenConditionChecker,
|
||||||
|
)
|
||||||
|
|
||||||
|
override val loopExpressionCheckers: Set<FirLoopExpressionChecker>
|
||||||
|
get() = setOf(
|
||||||
|
FirLoopConditionChecker,
|
||||||
|
)
|
||||||
|
|
||||||
|
override val logicExpressionCheckers: Set<FirLogicExpressionChecker>
|
||||||
|
get() = setOf(
|
||||||
|
FirLogicExpressionTypeChecker,
|
||||||
)
|
)
|
||||||
|
|
||||||
override val returnExpressionCheckers: Set<FirReturnExpressionChecker>
|
override val returnExpressionCheckers: Set<FirReturnExpressionChecker>
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ fun f(): Unit {
|
|||||||
<!ARGUMENT_TYPE_MISMATCH!>x<!> in 1..2
|
<!ARGUMENT_TYPE_MISMATCH!>x<!> in 1..2
|
||||||
|
|
||||||
val y : Boolean? = true
|
val y : Boolean? = true
|
||||||
false || y
|
false || <!CONDITION_TYPE_MISMATCH!>y<!>
|
||||||
y && true
|
<!CONDITION_TYPE_MISMATCH!>y<!> && true
|
||||||
y && 1
|
<!CONDITION_TYPE_MISMATCH!>y<!> && <!CONDITION_TYPE_MISMATCH!>1<!>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -82,9 +82,9 @@ fun test(notRange1: NotRange1, notRange2: NotRange2, notRange3: NotRange3, notRa
|
|||||||
for (i in <!HAS_NEXT_MISSING, NEXT_MISSING!>notRange2<!>);
|
for (i in <!HAS_NEXT_MISSING, NEXT_MISSING!>notRange2<!>);
|
||||||
for (i in <!NEXT_MISSING!>notRange3<!>);
|
for (i in <!NEXT_MISSING!>notRange3<!>);
|
||||||
for (i in <!HAS_NEXT_MISSING!>notRange4<!>);
|
for (i in <!HAS_NEXT_MISSING!>notRange4<!>);
|
||||||
for (i in notRange5);
|
<!CONDITION_TYPE_MISMATCH!>for (i in notRange5)<!>;
|
||||||
for (i in notRange6);
|
for (i in notRange6);
|
||||||
for (i in notRange7);
|
<!CONDITION_TYPE_MISMATCH!>for (i in notRange7)<!>;
|
||||||
for (i in <!HAS_NEXT_MISSING!>notRange8<!>);
|
for (i in <!HAS_NEXT_MISSING!>notRange8<!>);
|
||||||
for (i in range0);
|
for (i in range0);
|
||||||
for (i in range1);
|
for (i in range1);
|
||||||
|
|||||||
+4
-4
@@ -1,7 +1,7 @@
|
|||||||
// !WITH_NEW_INFERENCE
|
// !WITH_NEW_INFERENCE
|
||||||
fun foo1(b: Boolean, c: Int) {
|
fun foo1(b: Boolean, c: Int) {
|
||||||
if (b && c) {}
|
if (b && <!CONDITION_TYPE_MISMATCH!>c<!>) {}
|
||||||
if (b || c) {}
|
if (b || <!CONDITION_TYPE_MISMATCH!>c<!>) {}
|
||||||
if (c && b) {}
|
if (<!CONDITION_TYPE_MISMATCH!>c<!> && b) {}
|
||||||
if (c || b) {}
|
if (<!CONDITION_TYPE_MISMATCH!>c<!> || b) {}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,10 +7,10 @@ fun foo() =
|
|||||||
when {
|
when {
|
||||||
cond1() -> 12
|
cond1() -> 12
|
||||||
cond2() -> 2
|
cond2() -> 2
|
||||||
4 -> 34
|
<!CONDITION_TYPE_MISMATCH!>4<!> -> 34
|
||||||
Pair(1, 2) -> 3
|
<!CONDITION_TYPE_MISMATCH!>Pair(1, 2)<!> -> 3
|
||||||
in 1..10 -> 34
|
in 1..10 -> 34
|
||||||
4 -> 38
|
<!CONDITION_TYPE_MISMATCH!>4<!> -> 38
|
||||||
is Int -> 33
|
is Int -> 33
|
||||||
else -> 34
|
else -> 34
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// FIR_IDENTICAL
|
// FIR_IDENTICAL
|
||||||
// !DIAGNOSTICS: -UNUSED_EXPRESSION -UNUSED_PARAMETER -UNUSED_VARIABLE -NOTHING_TO_INLINE -ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE -UNUSED_VALUE -TYPE_MISMATCH
|
// !DIAGNOSTICS: -UNUSED_EXPRESSION -UNUSED_PARAMETER -UNUSED_VARIABLE -NOTHING_TO_INLINE -ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE -UNUSED_VALUE -TYPE_MISMATCH -CONDITION_TYPE_MISMATCH
|
||||||
|
|
||||||
inline fun inlineFunWithInvoke(s: (p: Int) -> Unit, ext: Int.(p: Int) -> Unit) {
|
inline fun inlineFunWithInvoke(s: (p: Int) -> Unit, ext: Int.(p: Int) -> Unit) {
|
||||||
<!USAGE_IS_NOT_INLINABLE!>s<!> && <!USAGE_IS_NOT_INLINABLE!>ext<!>
|
<!USAGE_IS_NOT_INLINABLE!>s<!> && <!USAGE_IS_NOT_INLINABLE!>ext<!>
|
||||||
|
|||||||
+5
-5
@@ -23,23 +23,23 @@ fun test() {
|
|||||||
val platformJ = J.staticJ
|
val platformJ = J.staticJ
|
||||||
|
|
||||||
if (platformNN) {}
|
if (platformNN) {}
|
||||||
if (platformN) {}
|
if (<!CONDITION_TYPE_MISMATCH!>platformN<!>) {}
|
||||||
if (platformJ) {}
|
if (platformJ) {}
|
||||||
|
|
||||||
while (platformNN) {}
|
while (platformNN) {}
|
||||||
while (platformN) {}
|
while (<!CONDITION_TYPE_MISMATCH!>platformN<!>) {}
|
||||||
while (platformJ) {}
|
while (platformJ) {}
|
||||||
|
|
||||||
do {} while (platformNN)
|
do {} while (platformNN)
|
||||||
do {} while (platformN)
|
do {} while (<!CONDITION_TYPE_MISMATCH!>platformN<!>)
|
||||||
do {} while (platformJ)
|
do {} while (platformJ)
|
||||||
|
|
||||||
platformNN && false
|
platformNN && false
|
||||||
platformN && false
|
<!CONDITION_TYPE_MISMATCH!>platformN<!> && false
|
||||||
platformJ && false
|
platformJ && false
|
||||||
|
|
||||||
platformNN || false
|
platformNN || false
|
||||||
platformN || false
|
<!CONDITION_TYPE_MISMATCH!>platformN<!> || false
|
||||||
platformJ || false
|
platformJ || false
|
||||||
|
|
||||||
!platformNN
|
!platformNN
|
||||||
|
|||||||
Vendored
+1
-1
@@ -12,7 +12,7 @@ fun isString(x: Any?): Boolean {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun incorrectPartDoesntMatter(x: Any?) {
|
fun incorrectPartDoesntMatter(x: Any?) {
|
||||||
if (isString(x) && 1) {
|
if (isString(x) && <!CONDITION_TYPE_MISMATCH!>1<!>) {
|
||||||
x.length
|
x.length
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|||||||
+3
-3
@@ -26,7 +26,7 @@ import checkSubtype
|
|||||||
*/
|
*/
|
||||||
fun case1() {
|
fun case1() {
|
||||||
val a: Any = true
|
val a: Any = true
|
||||||
if (a) { "true" } else "false"
|
if (<!CONDITION_TYPE_MISMATCH!>a<!>) { "true" } else "false"
|
||||||
<!NONE_APPLICABLE!>checkSubtype<!><Boolean>(a)
|
<!NONE_APPLICABLE!>checkSubtype<!><Boolean>(a)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -37,7 +37,7 @@ fun case1() {
|
|||||||
*/
|
*/
|
||||||
fun case2() {
|
fun case2() {
|
||||||
val a = JavaContainer.aO
|
val a = JavaContainer.aO
|
||||||
if (a) { "true" } else "false"
|
if (<!CONDITION_TYPE_MISMATCH!>a<!>) { "true" } else "false"
|
||||||
<!NONE_APPLICABLE!>checkSubtype<!><Boolean>(a)
|
<!NONE_APPLICABLE!>checkSubtype<!><Boolean>(a)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,7 +54,7 @@ public class JavaClassCase3{
|
|||||||
fun case3() {
|
fun case3() {
|
||||||
val x = JavaClassCase3.id(null) // Nothing!
|
val x = JavaClassCase3.id(null) // Nothing!
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing?")!>x<!>
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing?")!>x<!>
|
||||||
val a = if (x) {
|
val a = if (<!CONDITION_TYPE_MISMATCH!>x<!>) {
|
||||||
"NOK"
|
"NOK"
|
||||||
} else "NOK"
|
} else "NOK"
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-4
@@ -19,13 +19,13 @@ import checkType
|
|||||||
import check
|
import check
|
||||||
|
|
||||||
// TESTCASE NUMBER: 0
|
// TESTCASE NUMBER: 0
|
||||||
fun foo() = run { false && JavaClass.VALUE && throw Exception() }
|
fun foo() = run { false && <!CONDITION_TYPE_MISMATCH!>JavaClass.VALUE<!> && throw Exception() }
|
||||||
|
|
||||||
// TESTCASE NUMBER: 1
|
// TESTCASE NUMBER: 1
|
||||||
fun case1() {
|
fun case1() {
|
||||||
val a: Boolean? = false
|
val a: Boolean? = false
|
||||||
checkSubtype<Boolean?>(a)
|
checkSubtype<Boolean?>(a)
|
||||||
val x4 = a && true
|
val x4 = <!CONDITION_TYPE_MISMATCH!>a<!> && true
|
||||||
x4 <!OVERLOAD_RESOLUTION_AMBIGUITY!>checkType<!> { <!NONE_APPLICABLE!>check<!><Boolean>() }
|
x4 <!OVERLOAD_RESOLUTION_AMBIGUITY!>checkType<!> { <!NONE_APPLICABLE!>check<!><Boolean>() }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -33,7 +33,7 @@ fun case1() {
|
|||||||
fun case2() {
|
fun case2() {
|
||||||
val a: Any = false
|
val a: Any = false
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any")!>a<!>
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any")!>a<!>
|
||||||
val x4 = a && true
|
val x4 = <!CONDITION_TYPE_MISMATCH!>a<!> && true
|
||||||
x4 <!OVERLOAD_RESOLUTION_AMBIGUITY!>checkType<!> { <!NONE_APPLICABLE!>check<!><Boolean>() }
|
x4 <!OVERLOAD_RESOLUTION_AMBIGUITY!>checkType<!> { <!NONE_APPLICABLE!>check<!><Boolean>() }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,7 +43,7 @@ fun case3() {
|
|||||||
val a2 = JavaClass.VALUE
|
val a2 = JavaClass.VALUE
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any..kotlin.Any?!")!>a2<!>
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any..kotlin.Any?!")!>a2<!>
|
||||||
|
|
||||||
val x3 = a1 && a2
|
val x3 = a1 && <!CONDITION_TYPE_MISMATCH!>a2<!>
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Boolean")!>x3<!>
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Boolean")!>x3<!>
|
||||||
|
|
||||||
x3 <!OVERLOAD_RESOLUTION_AMBIGUITY!>checkType<!> { <!NONE_APPLICABLE!>check<!><Boolean>() }
|
x3 <!OVERLOAD_RESOLUTION_AMBIGUITY!>checkType<!> { <!NONE_APPLICABLE!>check<!><Boolean>() }
|
||||||
|
|||||||
+4
-4
@@ -19,13 +19,13 @@ import checkType
|
|||||||
import check
|
import check
|
||||||
|
|
||||||
// TESTCASE NUMBER: 0
|
// TESTCASE NUMBER: 0
|
||||||
fun foo() = run { false || JavaClass.VALUE || throw Exception() }
|
fun foo() = run { false || <!CONDITION_TYPE_MISMATCH!>JavaClass.VALUE<!> || throw Exception() }
|
||||||
|
|
||||||
// TESTCASE NUMBER: 1
|
// TESTCASE NUMBER: 1
|
||||||
fun case1() {
|
fun case1() {
|
||||||
val a: Boolean? = false
|
val a: Boolean? = false
|
||||||
checkSubtype<Boolean?>(a)
|
checkSubtype<Boolean?>(a)
|
||||||
val x4 = a || true
|
val x4 = <!CONDITION_TYPE_MISMATCH!>a<!> || true
|
||||||
x4 <!OVERLOAD_RESOLUTION_AMBIGUITY!>checkType<!> { <!NONE_APPLICABLE!>check<!><Boolean>() }
|
x4 <!OVERLOAD_RESOLUTION_AMBIGUITY!>checkType<!> { <!NONE_APPLICABLE!>check<!><Boolean>() }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -33,7 +33,7 @@ fun case1() {
|
|||||||
fun case2() {
|
fun case2() {
|
||||||
val a: Any = false
|
val a: Any = false
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any")!>a<!>
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any")!>a<!>
|
||||||
val x4 = a || true
|
val x4 = <!CONDITION_TYPE_MISMATCH!>a<!> || true
|
||||||
x4 <!OVERLOAD_RESOLUTION_AMBIGUITY!>checkType<!> { <!NONE_APPLICABLE!>check<!><Boolean>() }
|
x4 <!OVERLOAD_RESOLUTION_AMBIGUITY!>checkType<!> { <!NONE_APPLICABLE!>check<!><Boolean>() }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,7 +43,7 @@ fun case3() {
|
|||||||
val a2 = JavaClass.VALUE
|
val a2 = JavaClass.VALUE
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any..kotlin.Any?!")!>a2<!>
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any..kotlin.Any?!")!>a2<!>
|
||||||
|
|
||||||
val x3 = a1 || a2
|
val x3 = a1 || <!CONDITION_TYPE_MISMATCH!>a2<!>
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Boolean")!>x3<!>
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Boolean")!>x3<!>
|
||||||
|
|
||||||
x3 <!OVERLOAD_RESOLUTION_AMBIGUITY!>checkType<!> { <!NONE_APPLICABLE!>check<!><Boolean>() }
|
x3 <!OVERLOAD_RESOLUTION_AMBIGUITY!>checkType<!> { <!NONE_APPLICABLE!>check<!><Boolean>() }
|
||||||
|
|||||||
Vendored
+6
-6
@@ -3,12 +3,12 @@
|
|||||||
// TESTCASE NUMBER: 1
|
// TESTCASE NUMBER: 1
|
||||||
fun case_1(value_1: Int, value_2: String, value_3: TypesProvider): String {
|
fun case_1(value_1: Int, value_2: String, value_3: TypesProvider): String {
|
||||||
when {
|
when {
|
||||||
.012f / value_1 -> return ""
|
<!CONDITION_TYPE_MISMATCH!>.012f / value_1<!> -> return ""
|
||||||
"$value_2..." -> return ""
|
<!CONDITION_TYPE_MISMATCH!>"$value_2..."<!> -> return ""
|
||||||
'-' -> return ""
|
<!CONDITION_TYPE_MISMATCH!>'-'<!> -> return ""
|
||||||
{} -> return ""
|
<!CONDITION_TYPE_MISMATCH!>{}<!> -> return ""
|
||||||
value_3.getAny() -> return ""
|
<!CONDITION_TYPE_MISMATCH!>value_3.getAny()<!> -> return ""
|
||||||
-10..-1 -> return ""
|
<!CONDITION_TYPE_MISMATCH!>-10..-1<!> -> return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
return ""
|
return ""
|
||||||
|
|||||||
Vendored
+1
-1
@@ -5,7 +5,7 @@ fun case_1(value_1: TypesProvider) {
|
|||||||
when {
|
when {
|
||||||
getBoolean(), value_1.getBoolean() -> return
|
getBoolean(), value_1.getBoolean() -> return
|
||||||
value_1.getBoolean() && getBoolean(), getLong() == 1000L -> return
|
value_1.getBoolean() && getBoolean(), getLong() == 1000L -> return
|
||||||
Out<Int>(), getLong(), {}, Any(), throw Exception() -> return
|
<!CONDITION_TYPE_MISMATCH!>Out<Int>()<!>, getLong(), {}, Any(), throw Exception() -> return
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|||||||
+3
-3
@@ -5,19 +5,19 @@
|
|||||||
// TESTCASE NUMBER: 1
|
// TESTCASE NUMBER: 1
|
||||||
fun case1() {
|
fun case1() {
|
||||||
do {
|
do {
|
||||||
} while ("boo")
|
} while (<!CONDITION_TYPE_MISMATCH!>"boo"<!>)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TESTCASE NUMBER: 2
|
// TESTCASE NUMBER: 2
|
||||||
fun case2() {
|
fun case2() {
|
||||||
val condition: Any = true
|
val condition: Any = true
|
||||||
do {
|
do {
|
||||||
} while (condition)
|
} while (<!CONDITION_TYPE_MISMATCH!>condition<!>)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TESTCASE NUMBER: 3
|
// TESTCASE NUMBER: 3
|
||||||
fun case3() {
|
fun case3() {
|
||||||
val condition: Boolean? = true
|
val condition: Boolean? = true
|
||||||
do {
|
do {
|
||||||
} while (condition)
|
} while (<!CONDITION_TYPE_MISMATCH!>condition<!>)
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -6,13 +6,13 @@
|
|||||||
// TESTCASE NUMBER: 1
|
// TESTCASE NUMBER: 1
|
||||||
fun case1() {
|
fun case1() {
|
||||||
val condition: Any = true
|
val condition: Any = true
|
||||||
while (condition && "true") {
|
while (<!CONDITION_TYPE_MISMATCH!>condition<!> && <!CONDITION_TYPE_MISMATCH!>"true"<!>) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TESTCASE NUMBER: 2
|
// TESTCASE NUMBER: 2
|
||||||
fun case2() {
|
fun case2() {
|
||||||
val condition: Boolean? = true
|
val condition: Boolean? = true
|
||||||
while (condition) {
|
while (<!CONDITION_TYPE_MISMATCH!>condition<!>) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -108,7 +108,7 @@ fun case_11(x: Any?) {
|
|||||||
* ISSUES: KT-30376
|
* ISSUES: KT-30376
|
||||||
*/
|
*/
|
||||||
fun case_12(x: Any?) {
|
fun case_12(x: Any?) {
|
||||||
if (x!! as Boolean?) {
|
if (<!CONDITION_TYPE_MISMATCH!>x!! as Boolean?<!>) {
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & kotlin.Any")!>x<!>.<!UNRESOLVED_REFERENCE!>not<!>()
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & kotlin.Any")!>x<!>.<!UNRESOLVED_REFERENCE!>not<!>()
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any")!>select(x)<!>.<!UNRESOLVED_REFERENCE!>not<!>()
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any")!>select(x)<!>.<!UNRESOLVED_REFERENCE!>not<!>()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -613,7 +613,7 @@ fun case_30(a: ((Float) -> Int?)?, b: Float?) {
|
|||||||
|
|
||||||
// TESTCASE NUMBER: 31
|
// TESTCASE NUMBER: 31
|
||||||
fun case_31(z1: Boolean?, z: Nothing?) {
|
fun case_31(z1: Boolean?, z: Nothing?) {
|
||||||
if (false || EnumClassWithNullableProperty.A.prop_1 != z && z1 !== z && z1) {
|
if (false || EnumClassWithNullableProperty.A.prop_1 != z && z1 !== z && <!CONDITION_TYPE_MISMATCH!>z1<!>) {
|
||||||
EnumClassWithNullableProperty.A.prop_1
|
EnumClassWithNullableProperty.A.prop_1
|
||||||
EnumClassWithNullableProperty.A.prop_1<!UNSAFE_CALL!>.<!>equals(null)
|
EnumClassWithNullableProperty.A.prop_1<!UNSAFE_CALL!>.<!>equals(null)
|
||||||
EnumClassWithNullableProperty.A.prop_1.propT
|
EnumClassWithNullableProperty.A.prop_1.propT
|
||||||
|
|||||||
Reference in New Issue
Block a user