Fix false "useless cast" when target type is flexible
#KT-17820 Fixed
This commit is contained in:
@@ -213,13 +213,14 @@ object CastDiagnosticsUtil {
|
||||
return isRefinementUseless(possibleTypes, refinedTargetType, typeChecker, shouldCheckForExactType(expression, context.expectedType))
|
||||
}
|
||||
|
||||
// It is a warning "useless cast" for `as` and a warning "redundant is" for `is`
|
||||
fun isRefinementUseless(
|
||||
possibleTypes: Collection<KotlinType>,
|
||||
targetType: KotlinType,
|
||||
typeChecker: KotlinTypeChecker,
|
||||
shouldCheckForExactType: Boolean
|
||||
): Boolean {
|
||||
val intersectedType = TypeIntersector.intersectTypes(typeChecker, possibleTypes) ?: return false
|
||||
val intersectedType = TypeIntersector.intersectTypes(typeChecker, possibleTypes.map { it.upperIfFlexible() }) ?: return false
|
||||
|
||||
return if (shouldCheckForExactType)
|
||||
isExactTypeCast(intersectedType, targetType)
|
||||
|
||||
+1
-3
@@ -40,7 +40,6 @@ import org.jetbrains.kotlin.types.expressions.ControlStructureTypingUtils.*
|
||||
import org.jetbrains.kotlin.types.expressions.typeInfoFactory.createTypeInfo
|
||||
import org.jetbrains.kotlin.types.expressions.typeInfoFactory.noTypeInfo
|
||||
import org.jetbrains.kotlin.types.typeUtil.containsError
|
||||
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
|
||||
import java.util.*
|
||||
|
||||
class PatternMatchingTypingVisitor internal constructor(facade: ExpressionTypingInternals) : ExpressionTypingVisitor(facade) {
|
||||
@@ -464,8 +463,7 @@ class PatternMatchingTypingVisitor internal constructor(facade: ExpressionTyping
|
||||
if (subjectType.containsError() || targetType.containsError()) return
|
||||
|
||||
val possibleTypes = DataFlowAnalyzer.getAllPossibleTypes(subjectType, context, subjectDataFlowValue)
|
||||
val intersection = TypeIntersector.intersectTypes(KotlinTypeChecker.DEFAULT, possibleTypes.map { it.upperIfFlexible() })
|
||||
if (intersection?.isSubtypeOf(targetType) ?: false) {
|
||||
if (CastDiagnosticsUtil.isRefinementUseless(possibleTypes, targetType, KotlinTypeChecker.DEFAULT, false)) {
|
||||
context.trace.report(Errors.USELESS_IS_CHECK.on(isCheck, !negated))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
// FILE: Foo.java
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class Foo {
|
||||
static Foo create() { return null; }
|
||||
|
||||
@Nullable
|
||||
static Foo createN() { return null; }
|
||||
|
||||
@NotNull
|
||||
static Foo createNN() { return null; }
|
||||
}
|
||||
|
||||
// FILE: sample.kt
|
||||
|
||||
fun test() {
|
||||
Foo.create() as Foo
|
||||
Foo.createN() as Foo
|
||||
Foo.createNN() <!USELESS_CAST!>as Foo<!>
|
||||
|
||||
Foo.create() <!USELESS_CAST!>as Foo?<!>
|
||||
Foo.createN() <!USELESS_CAST!>as Foo?<!>
|
||||
Foo.createNN() <!USELESS_CAST!>as Foo?<!>
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package
|
||||
|
||||
public fun test(): kotlin.Unit
|
||||
|
||||
public open class Foo {
|
||||
public constructor Foo()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
|
||||
// Static members
|
||||
public/*package*/ open fun create(): Foo!
|
||||
@org.jetbrains.annotations.Nullable public/*package*/ open fun createN(): Foo?
|
||||
@org.jetbrains.annotations.NotNull public/*package*/ open fun createNN(): Foo
|
||||
}
|
||||
@@ -2746,6 +2746,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("FlexibleTargetType.kt")
|
||||
public void testFlexibleTargetType() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/cast/FlexibleTargetType.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("IsErasedAllowForDerivedWithOneSubstitutedAndOneSameGeneric.kt")
|
||||
public void testIsErasedAllowForDerivedWithOneSubstitutedAndOneSameGeneric() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/cast/IsErasedAllowForDerivedWithOneSubstitutedAndOneSameGeneric.kt");
|
||||
|
||||
Reference in New Issue
Block a user