More precise diagnostics of smart cast impossible #KT-7240 Fixed
This commit is contained in:
@@ -92,7 +92,7 @@ public object RuntimeAssertionsTypeChecker : AdditionalTypeChecker {
|
|||||||
expressionType,
|
expressionType,
|
||||||
object : RuntimeAssertionInfo.DataFlowExtras {
|
object : RuntimeAssertionInfo.DataFlowExtras {
|
||||||
override val canBeNull: Boolean
|
override val canBeNull: Boolean
|
||||||
get() = c.dataFlowInfo.getNullability(dataFlowValue).canBeNull()
|
get() = c.dataFlowInfo.getPredictableNullability(dataFlowValue).canBeNull()
|
||||||
override val possibleTypes: Set<KotlinType>
|
override val possibleTypes: Set<KotlinType>
|
||||||
get() = c.dataFlowInfo.getPossibleTypes(dataFlowValue)
|
get() = c.dataFlowInfo.getPossibleTypes(dataFlowValue)
|
||||||
override val presentableText: String
|
override val presentableText: String
|
||||||
|
|||||||
+2
-2
@@ -71,7 +71,7 @@ public class JavaNullabilityWarningsChecker : AdditionalTypeChecker {
|
|||||||
if (TypeUtils.noExpectedType(expectedType)) return
|
if (TypeUtils.noExpectedType(expectedType)) return
|
||||||
|
|
||||||
val expectedMustNotBeNull = expectedType.mustNotBeNull()
|
val expectedMustNotBeNull = expectedType.mustNotBeNull()
|
||||||
if (dataFlowInfo.getNullability(dataFlowValue) == Nullability.NOT_NULL) return
|
if (dataFlowInfo.getPredictableNullability(dataFlowValue) == Nullability.NOT_NULL) return
|
||||||
|
|
||||||
val actualMayBeNull = expressionType.mayBeNull()
|
val actualMayBeNull = expressionType.mayBeNull()
|
||||||
|
|
||||||
@@ -155,7 +155,7 @@ public class JavaNullabilityWarningsChecker : AdditionalTypeChecker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun <T: Any> doIfNotNull(dataFlowValue: DataFlowValue, c: ResolutionContext<*>, body: () -> T): T? {
|
private fun <T: Any> doIfNotNull(dataFlowValue: DataFlowValue, c: ResolutionContext<*>, body: () -> T): T? {
|
||||||
if (c.dataFlowInfo.getNullability(dataFlowValue).canBeNull()
|
if (c.dataFlowInfo.getPredictableNullability(dataFlowValue).canBeNull()
|
||||||
&& dataFlowValue.type.mustNotBeNull() == ErrorsJvm.NullabilityInformationSource.JAVA) {
|
&& dataFlowValue.type.mustNotBeNull() == ErrorsJvm.NullabilityInformationSource.JAVA) {
|
||||||
return body()
|
return body()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -475,7 +475,7 @@ public class CandidateResolver(
|
|||||||
|
|
||||||
val bindingContext = trace.bindingContext
|
val bindingContext = trace.bindingContext
|
||||||
val receiverValue = DataFlowValueFactory.createDataFlowValue(receiverArgument, bindingContext, scope.ownerDescriptor)
|
val receiverValue = DataFlowValueFactory.createDataFlowValue(receiverArgument, bindingContext, scope.ownerDescriptor)
|
||||||
if (safeAccess && !dataFlowInfo.getNullability(receiverValue).canBeNull()) {
|
if (safeAccess && !dataFlowInfo.getPredictableNullability(receiverValue).canBeNull()) {
|
||||||
tracing.unnecessarySafeCall(trace, receiverArgument.type)
|
tracing.unnecessarySafeCall(trace, receiverArgument.type)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -37,9 +37,19 @@ public interface DataFlowInfo {
|
|||||||
@NotNull
|
@NotNull
|
||||||
SetMultimap<DataFlowValue, KotlinType> getCompleteTypeInfo();
|
SetMultimap<DataFlowValue, KotlinType> getCompleteTypeInfo();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns collected nullability for the given value, NOT taking its predictability into account.
|
||||||
|
*/
|
||||||
@NotNull
|
@NotNull
|
||||||
Nullability getNullability(@NotNull DataFlowValue key);
|
Nullability getNullability(@NotNull DataFlowValue key);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns collected nullability for the given value if it's predictable.
|
||||||
|
* Otherwise basic value nullability is returned
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
Nullability getPredictableNullability(@NotNull DataFlowValue key);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* IMPORTANT: by default, the original (native) type for this value
|
* IMPORTANT: by default, the original (native) type for this value
|
||||||
* are NOT included. So it's quite possible to get an empty set here.
|
* are NOT included. So it's quite possible to get an empty set here.
|
||||||
|
|||||||
+12
-2
@@ -111,7 +111,18 @@ import static org.jetbrains.kotlin.resolve.calls.smartcasts.Nullability.NOT_NULL
|
|||||||
@Override
|
@Override
|
||||||
@NotNull
|
@NotNull
|
||||||
public Nullability getNullability(@NotNull DataFlowValue key) {
|
public Nullability getNullability(@NotNull DataFlowValue key) {
|
||||||
if (!key.isPredictable()) return key.getImmanentNullability();
|
return getNullability(key, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NotNull
|
||||||
|
public Nullability getPredictableNullability(@NotNull DataFlowValue key) {
|
||||||
|
return getNullability(key, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private Nullability getNullability(@NotNull DataFlowValue key, boolean predictableOnly) {
|
||||||
|
if (predictableOnly && !key.isPredictable()) return key.getImmanentNullability();
|
||||||
Nullability nullability = nullabilityInfo.get(key);
|
Nullability nullability = nullabilityInfo.get(key);
|
||||||
return nullability != null ? nullability :
|
return nullability != null ? nullability :
|
||||||
parent != null ? parent.getNullability(key) :
|
parent != null ? parent.getNullability(key) :
|
||||||
@@ -123,7 +134,6 @@ import static org.jetbrains.kotlin.resolve.calls.smartcasts.Nullability.NOT_NULL
|
|||||||
@NotNull DataFlowValue value,
|
@NotNull DataFlowValue value,
|
||||||
@NotNull Nullability nullability
|
@NotNull Nullability nullability
|
||||||
) {
|
) {
|
||||||
if (!value.isPredictable()) return false;
|
|
||||||
map.put(value, nullability);
|
map.put(value, nullability);
|
||||||
return nullability != getNullability(value);
|
return nullability != getNullability(value);
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-3
@@ -892,7 +892,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
|
|
||||||
private static boolean isKnownToBeNotNull(KtExpression expression, KotlinType jetType, ExpressionTypingContext context) {
|
private static boolean isKnownToBeNotNull(KtExpression expression, KotlinType jetType, ExpressionTypingContext context) {
|
||||||
DataFlowValue dataFlowValue = createDataFlowValue(expression, jetType, context);
|
DataFlowValue dataFlowValue = createDataFlowValue(expression, jetType, context);
|
||||||
return !context.dataFlowInfo.getNullability(dataFlowValue).canBeNull();
|
return !context.dataFlowInfo.getPredictableNullability(dataFlowValue).canBeNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1191,7 +1191,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
DataFlowInfo rightDataFlowInfo = resolvedCall.getDataFlowInfoForArguments().getResultInfo();
|
DataFlowInfo rightDataFlowInfo = resolvedCall.getDataFlowInfoForArguments().getResultInfo();
|
||||||
// left argument is considered not-null if it's not-null also in right part or if we have jump in right part
|
// left argument is considered not-null if it's not-null also in right part or if we have jump in right part
|
||||||
if ((rightType != null && KotlinBuiltIns.isNothingOrNullableNothing(rightType) && !rightType.isMarkedNullable())
|
if ((rightType != null && KotlinBuiltIns.isNothingOrNullableNothing(rightType) && !rightType.isMarkedNullable())
|
||||||
|| !rightDataFlowInfo.getNullability(leftValue).canBeNull()) {
|
|| !rightDataFlowInfo.getPredictableNullability(leftValue).canBeNull()) {
|
||||||
dataFlowInfo = dataFlowInfo.disequate(leftValue, DataFlowValue.nullValue(components.builtIns));
|
dataFlowInfo = dataFlowInfo.disequate(leftValue, DataFlowValue.nullValue(components.builtIns));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1298,7 +1298,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
new Function1<DataFlowValue, Nullability>() {
|
new Function1<DataFlowValue, Nullability>() {
|
||||||
@Override
|
@Override
|
||||||
public Nullability invoke(DataFlowValue value) {
|
public Nullability invoke(DataFlowValue value) {
|
||||||
return context.dataFlowInfo.getNullability(value);
|
return context.dataFlowInfo.getPredictableNullability(value);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ fun foo(arg: Int?) {
|
|||||||
if (x == null) return
|
if (x == null) return
|
||||||
run {
|
run {
|
||||||
// Not safe: x = null later in the owner
|
// Not safe: x = null later in the owner
|
||||||
x<!UNSAFE_CALL!>.<!>hashCode()
|
<!SMARTCAST_IMPOSSIBLE!>x<!>.hashCode()
|
||||||
}
|
}
|
||||||
x = null
|
x = null
|
||||||
}
|
}
|
||||||
@@ -8,8 +8,8 @@ fun foo() {
|
|||||||
i = null
|
i = null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
i<!UNSAFE_CALL!>.<!>hashCode()
|
<!SMARTCAST_IMPOSSIBLE!>i<!>.hashCode()
|
||||||
Changing().bar()
|
Changing().bar()
|
||||||
i<!UNSAFE_CALL!>.<!>hashCode()
|
<!SMARTCAST_IMPOSSIBLE!>i<!>.hashCode()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ fun foo() {
|
|||||||
i = null
|
i = null
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
i<!UNSAFE_CALL!>.<!>hashCode()
|
<!SMARTCAST_IMPOSSIBLE!>i<!>.hashCode()
|
||||||
trans(<!TYPE_MISMATCH!>i<!>, ::can)
|
trans(<!SMARTCAST_IMPOSSIBLE!>i<!>, ::can)
|
||||||
i<!UNSAFE_CALL!>.<!>hashCode()
|
<!SMARTCAST_IMPOSSIBLE!>i<!>.hashCode()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,6 @@ fun foo() {
|
|||||||
i = null
|
i = null
|
||||||
}
|
}
|
||||||
}.bar()
|
}.bar()
|
||||||
i<!UNSAFE_CALL!>.<!>hashCode()
|
<!SMARTCAST_IMPOSSIBLE!>i<!>.hashCode()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -6,10 +6,10 @@ fun foo(arg: Int?) {
|
|||||||
if (x == null) return
|
if (x == null) return
|
||||||
run {
|
run {
|
||||||
// Unsafe because of owner modification
|
// Unsafe because of owner modification
|
||||||
x<!UNSAFE_CALL!>.<!>hashCode()
|
<!SMARTCAST_IMPOSSIBLE!>x<!>.hashCode()
|
||||||
x = null
|
x = null
|
||||||
}
|
}
|
||||||
if (x != null) x = 42
|
if (x != null) x = 42
|
||||||
// Unsafe because of lambda
|
// Unsafe because of lambda
|
||||||
x<!UNSAFE_CALL!>.<!>hashCode()
|
<!SMARTCAST_IMPOSSIBLE!>x<!>.hashCode()
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
class Immutable(val x: String?) {
|
||||||
|
fun foo(): String {
|
||||||
|
if (x != null) return <!DEBUG_INFO_SMARTCAST!>x<!>
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Mutable(var y: String?) {
|
||||||
|
fun foo(): String {
|
||||||
|
if (y != null) return <!SMARTCAST_IMPOSSIBLE!>y<!>
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public final class Immutable {
|
||||||
|
public constructor Immutable(/*0*/ x: kotlin.String?)
|
||||||
|
public final val x: kotlin.String?
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public final fun foo(): kotlin.String
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class Mutable {
|
||||||
|
public constructor Mutable(/*0*/ y: kotlin.String?)
|
||||||
|
public final var y: kotlin.String?
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public final fun foo(): kotlin.String
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
@@ -5,7 +5,7 @@ public class X {
|
|||||||
public fun fn(): Int {
|
public fun fn(): Int {
|
||||||
if (y != null)
|
if (y != null)
|
||||||
// With non-default getter smartcast is not possible
|
// With non-default getter smartcast is not possible
|
||||||
return y<!UNSAFE_CALL!>.<!>length
|
return <!SMARTCAST_IMPOSSIBLE!>y<!>.length
|
||||||
else
|
else
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ class Example {
|
|||||||
|
|
||||||
public fun foo(): String {
|
public fun foo(): String {
|
||||||
// Smart cast is not possible if property is delegated
|
// Smart cast is not possible if property is delegated
|
||||||
return if (p != null) <!TYPE_MISMATCH!>p<!> else ""
|
return if (p != null) <!SMARTCAST_IMPOSSIBLE!>p<!> else ""
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun bar(): String {
|
public fun bar(): String {
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ import a.X
|
|||||||
public fun X.gav(): Int {
|
public fun X.gav(): Int {
|
||||||
if (x != null)
|
if (x != null)
|
||||||
// Smart cast is not possible if definition is in another module
|
// Smart cast is not possible if definition is in another module
|
||||||
return x<!UNSAFE_CALL!>.<!>length
|
return <!SMARTCAST_IMPOSSIBLE!>x<!>.length
|
||||||
else
|
else
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
@@ -29,7 +29,7 @@ package a
|
|||||||
public fun X.gav(): Int {
|
public fun X.gav(): Int {
|
||||||
if (x != null)
|
if (x != null)
|
||||||
// Even if it's in the same package
|
// Even if it's in the same package
|
||||||
return x<!UNSAFE_CALL!>.<!>length
|
return <!SMARTCAST_IMPOSSIBLE!>x<!>.length
|
||||||
else
|
else
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ public class X {
|
|||||||
public fun fn(): Int {
|
public fun fn(): Int {
|
||||||
if (x != null)
|
if (x != null)
|
||||||
// Smartcast is not possible for variable properties
|
// Smartcast is not possible for variable properties
|
||||||
return x<!UNSAFE_CALL!>.<!>length
|
return <!SMARTCAST_IMPOSSIBLE!>x<!>.length
|
||||||
else if (y != null)
|
else if (y != null)
|
||||||
// Even if they are private
|
// Even if they are private
|
||||||
return y<!UNSAFE_CALL!>.<!>length
|
return <!SMARTCAST_IMPOSSIBLE!>y<!>.length
|
||||||
else
|
else
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -7,11 +7,11 @@ public fun foo() {
|
|||||||
} else if (s == null) {
|
} else if (s == null) {
|
||||||
return -2
|
return -2
|
||||||
} else {
|
} else {
|
||||||
return s<!UNSAFE_CALL!>.<!>length // Here smartcast is possible, at least in principle
|
return <!SMARTCAST_IMPOSSIBLE!>s<!>.length // Here smartcast is possible, at least in principle
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (s != null) {
|
if (s != null) {
|
||||||
System.out.println(closure())
|
System.out.println(closure())
|
||||||
System.out.println(s<!UNSAFE_CALL!>.<!>length) // Here smartcast is not possible due to a closure predecessor
|
System.out.println(<!SMARTCAST_IMPOSSIBLE!>s<!>.length) // Here smartcast is not possible due to a closure predecessor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+1
-1
@@ -8,7 +8,7 @@ fun IntArray.forEachIndexed( op: (i: Int, value: Int) -> Unit) {
|
|||||||
fun max(a: IntArray): Int? {
|
fun max(a: IntArray): Int? {
|
||||||
var maxI: Int? = null
|
var maxI: Int? = null
|
||||||
a.forEachIndexed { i, value ->
|
a.forEachIndexed { i, value ->
|
||||||
if (maxI == null || value >= a[<!TYPE_MISMATCH!>maxI<!>])
|
if (maxI == null || value >= a[<!SMARTCAST_IMPOSSIBLE!>maxI<!>])
|
||||||
maxI = i
|
maxI = i
|
||||||
}
|
}
|
||||||
return maxI
|
return maxI
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
fun indexOfMax(a: IntArray): Int? {
|
fun indexOfMax(a: IntArray): Int? {
|
||||||
var maxI: Int? = null
|
var maxI: Int? = null
|
||||||
a.forEachIndexed { i, value ->
|
a.forEachIndexed { i, value ->
|
||||||
if (maxI == null || value >= a[<!TYPE_MISMATCH!>maxI<!>]) {
|
if (maxI == null || value >= a[<!SMARTCAST_IMPOSSIBLE!>maxI<!>]) {
|
||||||
maxI = i
|
maxI = i
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -4,6 +4,6 @@ fun foo(y: String?) {
|
|||||||
var x: String? = ""
|
var x: String? = ""
|
||||||
if (x != null) {
|
if (x != null) {
|
||||||
y?.let { x = null }
|
y?.let { x = null }
|
||||||
x<!UNSAFE_CALL!>.<!>length // Smart cast is not possible
|
<!SMARTCAST_IMPOSSIBLE!>x<!>.length // Smart cast is not possible
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -6,6 +6,6 @@ fun foo(y: String?) {
|
|||||||
var x: String? = ""
|
var x: String? = ""
|
||||||
if (x != null) {
|
if (x != null) {
|
||||||
bar(y?.let { x = null; it })<!UNSAFE_CALL!>.<!>length
|
bar(y?.let { x = null; it })<!UNSAFE_CALL!>.<!>length
|
||||||
x<!UNSAFE_CALL!>.<!>length // Smart cast is not possible
|
<!SMARTCAST_IMPOSSIBLE!>x<!>.length // Smart cast is not possible
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -4,6 +4,6 @@ fun foo(y: String?) {
|
|||||||
var x: String? = null
|
var x: String? = null
|
||||||
if (x != null) {
|
if (x != null) {
|
||||||
y?.let { x = it }
|
y?.let { x = it }
|
||||||
x<!UNSAFE_CALL!>.<!>length // not-null or not-null
|
<!SMARTCAST_IMPOSSIBLE!>x<!>.length // not-null or not-null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -3,8 +3,8 @@ fun foo(y: String?) {
|
|||||||
if (x != null) {
|
if (x != null) {
|
||||||
with(y?.let { x = null; it }) {
|
with(y?.let { x = null; it }) {
|
||||||
this<!UNSAFE_CALL!>.<!>length
|
this<!UNSAFE_CALL!>.<!>length
|
||||||
x<!UNSAFE_CALL!>.<!>length
|
<!SMARTCAST_IMPOSSIBLE!>x<!>.length
|
||||||
}
|
}
|
||||||
x<!UNSAFE_CALL!>.<!>length
|
<!SMARTCAST_IMPOSSIBLE!>x<!>.length
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14619,6 +14619,12 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("propertyToNotNull.kt")
|
||||||
|
public void testPropertyToNotNull() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/smartCasts/propertyToNotNull.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("thisWithLabel.kt")
|
@TestMetadata("thisWithLabel.kt")
|
||||||
public void testThisWithLabel() throws Exception {
|
public void testThisWithLabel() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/smartCasts/thisWithLabel.kt");
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/smartCasts/thisWithLabel.kt");
|
||||||
|
|||||||
+1
-2
@@ -231,8 +231,7 @@ class Mutable(var <info descr="This property has a backing field">x</info>: Stri
|
|||||||
return <error descr="[SMARTCAST_IMPOSSIBLE] Smart cast to 'kotlin.String' is impossible, because 'x' is a member variable that can be changed from another thread">x</error>
|
return <error descr="[SMARTCAST_IMPOSSIBLE] Smart cast to 'kotlin.String' is impossible, because 'x' is a member variable that can be changed from another thread">x</error>
|
||||||
}
|
}
|
||||||
if (x != null) {
|
if (x != null) {
|
||||||
// It would be better to have smart cast impossible also here
|
return <error descr="[SMARTCAST_IMPOSSIBLE] Smart cast to 'kotlin.String' is impossible, because 'x' is a member variable that can be changed from another thread">x</error>
|
||||||
return <error descr="[TYPE_MISMATCH] Type mismatch: inferred type is kotlin.String? but kotlin.String was expected">x</error>
|
|
||||||
}
|
}
|
||||||
if (xx is String) {
|
if (xx is String) {
|
||||||
return <error descr="[SMARTCAST_IMPOSSIBLE] Smart cast to 'kotlin.String' is impossible, because 'xx' is a member value that has open or custom getter">xx</error>
|
return <error descr="[SMARTCAST_IMPOSSIBLE] Smart cast to 'kotlin.String' is impossible, because 'xx' is a member value that has open or custom getter">xx</error>
|
||||||
|
|||||||
-14
@@ -1,14 +0,0 @@
|
|||||||
// SUGGESTED_NAMES: i, getKm
|
|
||||||
// PARAM_TYPES: A
|
|
||||||
// PARAM_DESCRIPTOR: val a: A defined in test
|
|
||||||
class A {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
val A.meters: Int? get() = 1
|
|
||||||
|
|
||||||
fun test() {
|
|
||||||
val a = A()
|
|
||||||
if (a.meters == null) return
|
|
||||||
val km = <selection>a.meters / 10</selection>
|
|
||||||
}
|
|
||||||
-16
@@ -1,16 +0,0 @@
|
|||||||
// SUGGESTED_NAMES: i, getKm
|
|
||||||
// PARAM_TYPES: A
|
|
||||||
// PARAM_DESCRIPTOR: val a: A defined in test
|
|
||||||
class A {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
val A.meters: Int? get() = 1
|
|
||||||
|
|
||||||
fun test() {
|
|
||||||
val a = A()
|
|
||||||
if (a.meters == null) return
|
|
||||||
val km = i(a)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun i(a: A) = a.meters / 10
|
|
||||||
-6
@@ -504,12 +504,6 @@ public class JetExtractionTestGenerated extends AbstractJetExtractionTest {
|
|||||||
doExtractFunctionTest(fileName);
|
doExtractFunctionTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("extensionValUnderSmartCast.kt")
|
|
||||||
public void testExtensionValUnderSmartCast() throws Exception {
|
|
||||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/extractFunction/basic/extensionValUnderSmartCast.kt");
|
|
||||||
doExtractFunctionTest(fileName);
|
|
||||||
}
|
|
||||||
|
|
||||||
@TestMetadata("extractBlockContent.kt")
|
@TestMetadata("extractBlockContent.kt")
|
||||||
public void testExtractBlockContent() throws Exception {
|
public void testExtractBlockContent() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/extractFunction/basic/extractBlockContent.kt");
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/extractFunction/basic/extractBlockContent.kt");
|
||||||
|
|||||||
@@ -12,4 +12,4 @@ Compiling files:
|
|||||||
src/usage.kt
|
src/usage.kt
|
||||||
End of files
|
End of files
|
||||||
COMPILATION FAILED
|
COMPILATION FAILED
|
||||||
Only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type kotlin.Int?
|
Smart cast to 'kotlin.Int' is impossible, because 'a.x' is a member value that has open or custom getter
|
||||||
+1
-1
@@ -6,7 +6,7 @@ Compiling files:
|
|||||||
src/usage.kt
|
src/usage.kt
|
||||||
End of files
|
End of files
|
||||||
COMPILATION FAILED
|
COMPILATION FAILED
|
||||||
Only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type kotlin.Int?
|
Smart cast to 'kotlin.Int' is impossible, because 'a.x' is a member value that has open or custom getter
|
||||||
|
|
||||||
|
|
||||||
Cleaning output files:
|
Cleaning output files:
|
||||||
|
|||||||
Reference in New Issue
Block a user