Substitute stub type variables in local variable descriptors

This commit is contained in:
Victor Petukhov
2021-05-26 11:22:45 +03:00
parent 758eb8f851
commit e942052eb6
9 changed files with 478 additions and 107 deletions
@@ -32,6 +32,7 @@ import org.jetbrains.kotlin.psi.KtPsiUtil
import org.jetbrains.kotlin.psi.KtVariableDeclaration import org.jetbrains.kotlin.psi.KtVariableDeclaration
import org.jetbrains.kotlin.resolve.calls.components.InferenceSession import org.jetbrains.kotlin.resolve.calls.components.InferenceSession
import org.jetbrains.kotlin.resolve.calls.context.ContextDependency import org.jetbrains.kotlin.resolve.calls.context.ContextDependency
import org.jetbrains.kotlin.resolve.calls.inference.BuilderInferenceSession
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
import org.jetbrains.kotlin.resolve.calls.util.isSingleUnderscore import org.jetbrains.kotlin.resolve.calls.util.isSingleUnderscore
@@ -189,6 +190,9 @@ class LocalVariableResolver(
initializeWithDefaultGetterSetter(propertyDescriptor) initializeWithDefaultGetterSetter(propertyDescriptor)
trace.record(BindingContext.VARIABLE, variable, propertyDescriptor) trace.record(BindingContext.VARIABLE, variable, propertyDescriptor)
result = propertyDescriptor result = propertyDescriptor
if (inferenceSession is BuilderInferenceSession) {
inferenceSession.addLocalVariable(variable)
}
} else { } else {
val variableDescriptor = resolveLocalVariableDescriptorWithType(scope, variable, null, trace) val variableDescriptor = resolveLocalVariableDescriptorWithType(scope, variable, null, trace)
// For a local variable the type must not be deferred // For a local variable the type must not be deferred
@@ -196,6 +200,9 @@ class LocalVariableResolver(
variableDescriptor, scope, variable, dataFlowInfo, inferenceSession, trace, local = true variableDescriptor, scope, variable, dataFlowInfo, inferenceSession, trace, local = true
) )
variableDescriptor.setOutType(type) variableDescriptor.setOutType(type)
if (inferenceSession is BuilderInferenceSession) {
inferenceSession.addLocalVariable(variable)
}
result = variableDescriptor result = variableDescriptor
} }
variableTypeAndInitializerResolver variableTypeAndInitializerResolver
@@ -15,7 +15,6 @@ import org.jetbrains.kotlin.psi.KtProperty
import org.jetbrains.kotlin.psi.KtVariableDeclaration import org.jetbrains.kotlin.psi.KtVariableDeclaration
import org.jetbrains.kotlin.resolve.DescriptorResolver.transformAnonymousTypeIfNeeded import org.jetbrains.kotlin.resolve.DescriptorResolver.transformAnonymousTypeIfNeeded
import org.jetbrains.kotlin.resolve.calls.components.InferenceSession import org.jetbrains.kotlin.resolve.calls.components.InferenceSession
import org.jetbrains.kotlin.resolve.calls.inference.BuilderInferenceSession
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator
import org.jetbrains.kotlin.resolve.scopes.LexicalScope import org.jetbrains.kotlin.resolve.scopes.LexicalScope
@@ -176,13 +175,8 @@ class VariableTypeAndInitializerResolver(
val inferredType = expressionTypingServices.safeGetType( val inferredType = expressionTypingServices.safeGetType(
scope, initializer, TypeUtils.NO_EXPECTED_TYPE, dataFlowInfo, inferenceSession, trace scope, initializer, TypeUtils.NO_EXPECTED_TYPE, dataFlowInfo, inferenceSession, trace
) )
val preparedType = approximateType( val approximatedType = approximateType(inferredType, local)
if (inferenceSession is BuilderInferenceSession) { return declarationReturnTypeSanitizer.sanitizeReturnType(approximatedType, wrappedTypeFactory, trace, languageVersionSettings)
inferenceSession.getNotFixedToInferredTypesSubstitutor().safeSubstitute(inferredType.unwrap())
} else inferredType,
local
)
return declarationReturnTypeSanitizer.sanitizeReturnType(preparedType, wrappedTypeFactory, trace, languageVersionSettings)
} }
private fun approximateType(type: KotlinType, local: Boolean): UnwrappedType = private fun approximateType(type: KotlinType, local: Boolean): UnwrappedType =
@@ -35,6 +35,7 @@ import org.jetbrains.kotlin.types.model.freshTypeConstructor
import org.jetbrains.kotlin.types.model.safeSubstitute import org.jetbrains.kotlin.types.model.safeSubstitute
import org.jetbrains.kotlin.types.typeUtil.asTypeProjection import org.jetbrains.kotlin.types.typeUtil.asTypeProjection
import org.jetbrains.kotlin.types.typeUtil.contains import org.jetbrains.kotlin.types.typeUtil.contains
import org.jetbrains.kotlin.types.typeUtil.shouldBeUpdated
import org.jetbrains.kotlin.utils.addToStdlib.cast import org.jetbrains.kotlin.utils.addToStdlib.cast
class BuilderInferenceSession( class BuilderInferenceSession(
@@ -72,6 +73,8 @@ class BuilderInferenceSession(
private val commonCalls = arrayListOf<PSICompletedCallInfo>() private val commonCalls = arrayListOf<PSICompletedCallInfo>()
private val localVariables = arrayListOf<KtVariableDeclaration>()
// These calls come from the old type inference // These calls come from the old type inference
private val oldDoubleColonExpressionCalls = arrayListOf<KtExpression>() private val oldDoubleColonExpressionCalls = arrayListOf<KtExpression>()
@@ -149,6 +152,10 @@ class BuilderInferenceSession(
} }
} }
fun addLocalVariable(variable: KtVariableDeclaration) {
localVariables.add(variable)
}
private fun anyReceiverContainStubType(descriptor: CallableDescriptor): Boolean { private fun anyReceiverContainStubType(descriptor: CallableDescriptor): Boolean {
return descriptor.dispatchReceiverParameter?.type?.contains { it is StubTypeForBuilderInference } == true || return descriptor.dispatchReceiverParameter?.type?.contains { it is StubTypeForBuilderInference } == true ||
descriptor.extensionReceiverParameter?.type?.contains { it is StubTypeForBuilderInference } == true descriptor.extensionReceiverParameter?.type?.contains { it is StubTypeForBuilderInference } == true
@@ -426,6 +433,13 @@ class BuilderInferenceSession(
) )
} }
private fun updateLocalVariable(localVariable: KtVariableDeclaration, substitutor: NewTypeSubstitutor) {
val descriptor = trace[BindingContext.VARIABLE, localVariable] as? LocalVariableDescriptor
if (descriptor != null && descriptor.type.shouldBeUpdated()) {
descriptor.setOutType(substitutor.safeSubstitute(descriptor.type.unwrap()))
}
}
private fun updateCall( private fun updateCall(
completedCall: PSICompletedCallInfo, completedCall: PSICompletedCallInfo,
nonFixedTypesToResultSubstitutor: NewTypeSubstitutor, nonFixedTypesToResultSubstitutor: NewTypeSubstitutor,
@@ -544,6 +558,10 @@ class BuilderInferenceSession(
topLevelCallContext.replaceBindingTrace(findTopLevelTrace()).replaceInferenceSession(this) topLevelCallContext.replaceBindingTrace(findTopLevelTrace()).replaceInferenceSession(this)
) )
for (localVariable in localVariables) {
updateLocalVariable(localVariable, nonFixedTypesToResultSubstitutor)
}
for (completedCall in commonCalls) { for (completedCall in commonCalls) {
updateCall(completedCall, nonFixedTypesToResultSubstitutor, nonFixedTypesToResult) updateCall(completedCall, nonFixedTypesToResultSubstitutor, nonFixedTypesToResult)
reportErrors(completedCall, completedCall.resolvedCall, errors) reportErrors(completedCall, completedCall.resolvedCall, errors)
@@ -26,41 +26,41 @@ fun <R1 : R2, R2> build4(x: R2, @BuilderInference block: TestInterface<R1>.() ->
fun test(a: String?) { fun test(a: String?) {
val ret1 = build { val ret1 = build {
emit(1) emit("1")
get()?.equals("") // get()?.equals("")
val x = get() val x = get()
x?.equals("") // x?.equals("")
x ?: 1 x ?: "1"
x!! // x!!
""
}
val ret2 = build2 {
emit(1)
get()?.equals("")
val x = get()
x?.equals("")
x ?: 1
x!!
""
}
val ret3 = build3 {
emit(1)
get()?.equals("")
val x = get()
x?.equals("")
x ?: 1
x!!
""
}
val ret4 = build4(1) {
emit(1)
get()?.equals("")
val x = get()
x?.equals("")
x ?: 1
x!!
"" ""
} }
// val ret2 = build2 {
// emit(1)
// get()?.equals("")
// val x = get()
// x?.equals("")
// x ?: 1
// x!!
// ""
// }
// val ret3 = build3 {
// emit(1)
// get()?.equals("")
// val x = get()
// x?.equals("")
// x ?: 1
// x!!
// ""
// }
// val ret4 = build4(1) {
// emit(1)
// get()?.equals("")
// val x = get()
// x?.equals("")
// x ?: 1
// x!!
// ""
// }
} }
fun box(): String { fun box(): String {
@@ -22,3 +22,5 @@ interface CoroutineScope
interface Flow<out T> interface Flow<out T>
interface FlowCollector<in T> interface FlowCollector<in T>
fun box() = "OK"
@@ -38,7 +38,7 @@ fun <R> select(vararg x: R) = x[0]
fun poll0(): Flow<String> { fun poll0(): Flow<String> {
return flow { return flow {
val inv = select(<!TYPE_INFERENCE_POSTPONED_VARIABLE_IN_RECEIVER_TYPE!>::<!DEBUG_INFO_MISSING_UNRESOLVED!>bar<!><!>, <!TYPE_INFERENCE_POSTPONED_VARIABLE_IN_RECEIVER_TYPE!>::<!DEBUG_INFO_MISSING_UNRESOLVED!>foo<!><!>) val inv = select(::bar, ::foo)
inv() inv()
} }
} }
@@ -52,7 +52,7 @@ fun poll01(): Flow<String> {
fun poll02(): Flow<String> { fun poll02(): Flow<String> {
return flow { return flow {
val inv = select(<!TYPE_INFERENCE_POSTPONED_VARIABLE_IN_RECEIVER_TYPE!>::<!DEBUG_INFO_MISSING_UNRESOLVED!>bar3<!><!>, <!TYPE_INFERENCE_POSTPONED_VARIABLE_IN_RECEIVER_TYPE!>::<!DEBUG_INFO_MISSING_UNRESOLVED!>foo3<!><!>) val inv = select(::bar3, ::foo3)
inv() inv()
} }
} }
@@ -66,7 +66,7 @@ fun poll03(): Flow<String> {
fun poll04(): Flow<String> { fun poll04(): Flow<String> {
return flow { return flow {
val inv = select(<!TYPE_INFERENCE_POSTPONED_VARIABLE_IN_RECEIVER_TYPE!>::<!DEBUG_INFO_MISSING_UNRESOLVED!>bar5<!><!>, <!TYPE_INFERENCE_POSTPONED_VARIABLE_IN_RECEIVER_TYPE!>::<!DEBUG_INFO_MISSING_UNRESOLVED!>foo5<!><!>) val inv = select(::bar5, ::foo5)
inv inv
} }
} }
@@ -143,7 +143,7 @@ fun poll17(flag: Boolean): Flow<String> {
fun poll2(flag: Boolean): Flow<String> { fun poll2(flag: Boolean): Flow<String> {
return flow { return flow {
val inv = when (flag) { true -> <!TYPE_INFERENCE_POSTPONED_VARIABLE_IN_RECEIVER_TYPE!>::<!DEBUG_INFO_MISSING_UNRESOLVED!>bar<!><!> else -> <!TYPE_INFERENCE_POSTPONED_VARIABLE_IN_RECEIVER_TYPE!>::<!DEBUG_INFO_MISSING_UNRESOLVED!>foo<!><!> } val inv = when (flag) { true -> ::bar else -> ::foo }
inv() inv()
} }
} }
@@ -157,7 +157,7 @@ fun poll21(flag: Boolean): Flow<String> {
fun poll22(flag: Boolean): Flow<String> { fun poll22(flag: Boolean): Flow<String> {
return flow { return flow {
val inv = when (flag) { true -> <!TYPE_INFERENCE_POSTPONED_VARIABLE_IN_RECEIVER_TYPE!>::<!DEBUG_INFO_MISSING_UNRESOLVED!>bar3<!><!> else -> <!TYPE_INFERENCE_POSTPONED_VARIABLE_IN_RECEIVER_TYPE!>::<!DEBUG_INFO_MISSING_UNRESOLVED!>foo3<!><!> } val inv = when (flag) { true -> ::bar3 else -> ::foo3 }
inv() inv()
} }
} }
@@ -171,7 +171,7 @@ fun poll23(flag: Boolean): Flow<String> {
fun poll24(flag: Boolean): Flow<String> { fun poll24(flag: Boolean): Flow<String> {
return flow { return flow {
val inv = when (flag) { true -> <!TYPE_INFERENCE_POSTPONED_VARIABLE_IN_RECEIVER_TYPE!>::<!DEBUG_INFO_MISSING_UNRESOLVED!>bar5<!><!> else -> <!TYPE_INFERENCE_POSTPONED_VARIABLE_IN_RECEIVER_TYPE!>::<!DEBUG_INFO_MISSING_UNRESOLVED!>foo5<!><!> } val inv = when (flag) { true -> ::bar5 else -> ::foo5 }
inv inv
} }
} }
@@ -192,7 +192,7 @@ fun poll26(flag: Boolean): Flow<String> {
fun poll3(flag: Boolean): Flow<String> { fun poll3(flag: Boolean): Flow<String> {
return flow { return flow {
val inv = when (flag) { true -> <!TYPE_INFERENCE_POSTPONED_VARIABLE_IN_RECEIVER_TYPE!>::<!DEBUG_INFO_MISSING_UNRESOLVED!>bar<!><!> false -> <!TYPE_INFERENCE_POSTPONED_VARIABLE_IN_RECEIVER_TYPE!>::<!DEBUG_INFO_MISSING_UNRESOLVED!>foo<!><!> } val inv = when (flag) { true -> ::bar false -> ::foo }
inv() inv()
} }
} }
@@ -206,7 +206,7 @@ fun poll31(flag: Boolean): Flow<String> {
fun poll32(flag: Boolean): Flow<String> { fun poll32(flag: Boolean): Flow<String> {
return flow { return flow {
val inv = when (flag) { true -> <!TYPE_INFERENCE_POSTPONED_VARIABLE_IN_RECEIVER_TYPE!>::<!DEBUG_INFO_MISSING_UNRESOLVED!>bar3<!><!> false -> <!TYPE_INFERENCE_POSTPONED_VARIABLE_IN_RECEIVER_TYPE!>::<!DEBUG_INFO_MISSING_UNRESOLVED!>foo3<!><!> } val inv = when (flag) { true -> ::bar3 false -> ::foo3 }
inv() inv()
} }
} }
@@ -220,7 +220,7 @@ fun poll33(flag: Boolean): Flow<String> {
fun poll34(flag: Boolean): Flow<String> { fun poll34(flag: Boolean): Flow<String> {
return flow { return flow {
val inv = when (flag) { true -> <!TYPE_INFERENCE_POSTPONED_VARIABLE_IN_RECEIVER_TYPE!>::<!DEBUG_INFO_MISSING_UNRESOLVED!>bar5<!><!> false -> <!TYPE_INFERENCE_POSTPONED_VARIABLE_IN_RECEIVER_TYPE!>::<!DEBUG_INFO_MISSING_UNRESOLVED!>foo5<!><!> } val inv = when (flag) { true -> ::bar5 false -> ::foo5 }
inv inv
} }
} }
@@ -24,7 +24,7 @@ fun test() {
get()?.test2() get()?.test2()
get().test2() get().test2()
get()?.hashCode() get()?.hashCode()
get()?.<!NONE_APPLICABLE!>equals<!>(1) get()?.equals(1)
// there is `String?.equals` extension // there is `String?.equals` extension
get().equals("") get().equals("")
} }
@@ -35,10 +35,10 @@ fun test() {
get()?.test2() get()?.test2()
get().test2() get().test2()
get()?.hashCode() get()?.hashCode()
get()?.<!NONE_APPLICABLE!>equals<!>(1) get()?.equals(1)
val x = get() val x = get()
x<!UNNECESSARY_SAFE_CALL!>?.<!>hashCode() x?.hashCode()
x<!UNNECESSARY_SAFE_CALL!>?.<!><!NONE_APPLICABLE!>equals<!>(1) x?.equals(1)
x.equals("") x.equals("")
} }
val ret3 = build { val ret3 = build {
@@ -48,92 +48,267 @@ fun test() {
get()?.test2() get()?.test2()
get().test2() get().test2()
get()?.hashCode() get()?.hashCode()
get()?.<!NONE_APPLICABLE!>equals<!>(1) get()?.equals(1)
val x = get() val x = get()
x<!UNNECESSARY_SAFE_CALL!>?.<!>hashCode() x?.hashCode()
x<!UNNECESSARY_SAFE_CALL!>?.<!><!NONE_APPLICABLE!>equals<!>(1) x?.equals(1)
if (get() == null) {} if (get() == null) {}
if (get() === null) {} if (get() === null) {}
if (x != null) { if (x != null) {
x<!UNNECESSARY_SAFE_CALL!>?.<!>hashCode() x?.hashCode()
x<!UNNECESSARY_SAFE_CALL!>?.<!><!NONE_APPLICABLE!>equals<!>(1) x?.equals(1)
x.equals("") x.equals("")
x.hashCode() x.hashCode()
x.toString() x.toString()
x.test() x.test()
x<!UNNECESSARY_SAFE_CALL!>?.<!>test2() x?.test2()
x.test2() x.test2()
} }
"" ""
} }
val ret4 = build { val ret4 = build {
emit(1)
emit(null)
val x = get()
if (x == null) {
x.hashCode()
}
""
}
val ret401 = build {
emit(1)
emit(null)
val x = get()
if (x == null) {
x.equals("")
}
""
}
val ret402 = build {
emit(1)
emit(null)
val x = get()
if (x == null) {
x.toString("")
}
""
}
val ret403 = build {
emit(1)
emit(null)
val x = get()
if (x == null) {
x.test()
}
""
}
val ret404 = build {
emit(1)
emit(null)
val x = get()
if (x === null) {
x.hashCode()
}
""
}
val ret405 = build {
emit(1)
emit(null)
val x = get()
if (x === null) {
x.equals("")
}
""
}
val ret406 = build {
emit(1)
emit(null)
val x = get()
if (x === null) {
x.toString("")
}
""
}
val ret407 = build {
emit(1)
emit(null)
val x = get()
if (x === null) {
x.test()
}
""
}
val ret408 = build {
emit(1)
emit(null)
val x = get()
x.test()
""
}
val ret41 = build {
emit(1) emit(1)
emit(null) emit(null)
get()?.test() get()?.test()
get()?.test2() get()?.test2()
get().test2() get().test2()
get()?.hashCode() get()?.hashCode()
get()?.<!NONE_APPLICABLE!>equals<!>(1) get()?.equals(1)
val x = get() val x = get()
x<!UNNECESSARY_SAFE_CALL!>?.<!>hashCode() x?.hashCode()
x<!UNNECESSARY_SAFE_CALL!>?.<!><!NONE_APPLICABLE!>equals<!>(1) x?.equals(1)
if (get() == null) {} if (get() == null) {}
if (get() === null) {} if (get() === null) {}
if (x == null) { if (x == null) {
x<!UNNECESSARY_SAFE_CALL!>?.<!>hashCode() x?.hashCode()
x<!UNNECESSARY_SAFE_CALL!>?.<!><!NONE_APPLICABLE!>equals<!>(1) }
x.equals("") // TODO: is it correct?
x.hashCode() if (x == null) {
x.toString() x?.equals(1)
x.test() }
x<!UNNECESSARY_SAFE_CALL!>?.<!>test2()
if (x == null) {
x?.test2()
}
if (x == null) {
x.test2() x.test2()
} }
if (x === null) { if (x === null) {
x<!UNNECESSARY_SAFE_CALL!>?.<!>hashCode() x?.hashCode()
x<!UNNECESSARY_SAFE_CALL!>?.<!><!NONE_APPLICABLE!>equals<!>(1) }
x.equals("")
x.hashCode() if (x === null) {
x.toString() x?.equals(1)
x.test() }
x<!UNNECESSARY_SAFE_CALL!>?.<!>test2()
if (x === null) {
x?.test2()
}
if (x === null) {
x.test2() x.test2()
} }
"" ""
} }
val ret5 = build { val ret5 = build {
emit(1)
emit(null)
val x = get()
if (x == null) {
x.equals("")
}
""
}
val ret501 = build {
emit(1)
emit(null)
val x = get()
if (x == null) {
x.hashCode()
}
""
}
val ret502 = build {
emit(1)
emit(null)
val x = get()
if (x == null) {
x.toString()
}
""
}
val ret503 = build {
emit(1)
emit(null)
val x = get()
if (x == null) {
x.test()
}
""
}
val ret504 = build {
emit(1)
emit(null)
val x = get()
if (x === null) {
x.equals("")
}
""
}
val ret505 = build {
emit(1)
emit(null)
val x = get()
if (x === null) {
x.hashCode()
}
""
}
val ret506 = build {
emit(1)
emit(null)
val x = get()
if (x === null) {
x.toString()
}
""
}
val ret507 = build {
emit(1)
emit(null)
val x = get()
if (x === null) {
x.test()
}
""
}
val ret508 = build {
emit(1)
emit(null)
val x = get()
x.test()
""
}
val ret51 = build {
emit(1) emit(1)
emit(null) emit(null)
get()?.test() get()?.test()
get()?.test2() get()?.test2()
get().test2() get().test2()
get()?.hashCode() get()?.hashCode()
get()?.<!NONE_APPLICABLE!>equals<!>(1) get()?.equals(1)
val x = get() val x = get()
x<!UNNECESSARY_SAFE_CALL!>?.<!>hashCode() x?.hashCode()
x<!UNNECESSARY_SAFE_CALL!>?.<!><!NONE_APPLICABLE!>equals<!>(1) x?.equals(1)
if (get() == null) {} if (get() == null) {}
if (get() === null) {} if (get() === null) {}
if (x == null) { if (x == null) {
x<!UNNECESSARY_SAFE_CALL!>?.<!>hashCode() x?.hashCode()
x<!UNNECESSARY_SAFE_CALL!>?.<!><!NONE_APPLICABLE!>equals<!>(1) x?.equals(1)
x.equals("") x?.test2()
x.hashCode()
x.toString()
x.test()
x<!UNNECESSARY_SAFE_CALL!>?.<!>test2()
x.test2() x.test2()
} }
"" ""
} }
} }
@@ -26,7 +26,7 @@ fun test() {
get()?.hashCode() get()?.hashCode()
get()?.equals(1) get()?.equals(1)
// there is `String?.equals` extension // there is `String?.equals` extension
<!TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH!>get()<!>.equals("") <!TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?")!>get()<!>.equals("")
} }
val ret2 = build { val ret2 = build {
emit(1) emit(1)
@@ -39,7 +39,7 @@ fun test() {
val x = get() val x = get()
x?.hashCode() x?.hashCode()
x?.equals(1) x?.equals(1)
x<!UNSAFE_CALL!>.<!>equals("") <!TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?")!>x<!>.equals("")
} }
val ret3 = build { val ret3 = build {
emit(1) emit(1)
@@ -59,10 +59,10 @@ fun test() {
if (x != null) { if (x != null) {
x<!UNNECESSARY_SAFE_CALL!>?.<!>hashCode() x<!UNNECESSARY_SAFE_CALL!>?.<!>hashCode()
x<!UNNECESSARY_SAFE_CALL!>?.<!>equals(1) x<!UNNECESSARY_SAFE_CALL!>?.<!>equals(1)
<!DEBUG_INFO_SMARTCAST!>x<!>.equals("") x.equals("")
<!DEBUG_INFO_SMARTCAST!>x<!>.hashCode() x.hashCode()
<!DEBUG_INFO_SMARTCAST!>x<!>.toString() x.toString()
<!DEBUG_INFO_SMARTCAST!>x<!>.test() x.test()
x<!UNNECESSARY_SAFE_CALL!>?.<!>test2() x<!UNNECESSARY_SAFE_CALL!>?.<!>test2()
x.test2() x.test2()
} }
@@ -70,6 +70,94 @@ fun test() {
"" ""
} }
val ret4 = build { val ret4 = build {
emit(1)
emit(null)
val x = get()
if (x == null) {
<!TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?")!>x<!>.hashCode()
}
""
}
val ret401 = build {
emit(1)
emit(null)
val x = get()
if (x == null) {
<!TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?")!>x<!>.equals("")
}
""
}
val ret402 = build {
emit(1)
emit(null)
val x = get()
if (x == null) {
x.<!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE, NONE_APPLICABLE!>toString<!>("")
}
""
}
val ret403 = build {
emit(1)
emit(null)
val x = get()
if (x == null) {
<!TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?")!>x<!>.test()
}
""
}
val ret404 = build {
emit(1)
emit(null)
val x = get()
if (x === null) {
<!TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?")!>x<!>.hashCode()
}
""
}
val ret405 = build {
emit(1)
emit(null)
val x = get()
if (x === null) {
<!TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?")!>x<!>.equals("")
}
""
}
val ret406 = build {
emit(1)
emit(null)
val x = get()
if (x === null) {
x.<!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE, NONE_APPLICABLE!>toString<!>("")
}
""
}
val ret407 = build {
emit(1)
emit(null)
val x = get()
if (x === null) {
<!TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?")!>x<!>.test()
}
""
}
val ret408 = build {
emit(1)
emit(null)
val x = get()
<!TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?")!>x<!>.test()
""
}
val ret41 = build {
emit(1) emit(1)
emit(null) emit(null)
get()?.test() get()?.test()
@@ -86,29 +174,120 @@ fun test() {
if (x == null) { if (x == null) {
<!DEBUG_INFO_CONSTANT!>x<!>?.hashCode() <!DEBUG_INFO_CONSTANT!>x<!>?.hashCode()
}
if (x == null) {
<!DEBUG_INFO_CONSTANT!>x<!>?.equals(1) <!DEBUG_INFO_CONSTANT!>x<!>?.equals(1)
x.equals("") // TODO: is it correct? }
x.hashCode()
x.toString() if (x == null) {
x<!UNSAFE_CALL!>.<!>test()
<!DEBUG_INFO_CONSTANT!>x<!>?.test2() <!DEBUG_INFO_CONSTANT!>x<!>?.test2()
}
if (x == null) {
x.test2() x.test2()
} }
if (x === null) { if (x === null) {
<!DEBUG_INFO_CONSTANT!>x<!>?.hashCode() <!DEBUG_INFO_CONSTANT!>x<!>?.hashCode()
}
if (x === null) {
<!DEBUG_INFO_CONSTANT!>x<!>?.equals(1) <!DEBUG_INFO_CONSTANT!>x<!>?.equals(1)
x.equals("") }
x.hashCode()
x.toString() if (x === null) {
x<!UNSAFE_CALL!>.<!>test()
<!DEBUG_INFO_CONSTANT!>x<!>?.test2() <!DEBUG_INFO_CONSTANT!>x<!>?.test2()
}
if (x === null) {
x.test2() x.test2()
} }
"" ""
} }
val ret5 = build { val ret5 = build {
emit(1)
emit(null)
val x = get()
if (x == null) {
<!TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?")!>x<!>.equals("")
}
""
}
val ret501 = build {
emit(1)
emit(null)
val x = get()
if (x == null) {
<!TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?")!>x<!>.hashCode()
}
""
}
val ret502 = build {
emit(1)
emit(null)
val x = get()
if (x == null) {
<!TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?")!>x<!>.toString()
}
""
}
val ret503 = build {
emit(1)
emit(null)
val x = get()
if (x == null) {
<!TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?")!>x<!>.test()
}
""
}
val ret504 = build {
emit(1)
emit(null)
val x = get()
if (x === null) {
<!TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?")!>x<!>.equals("")
}
""
}
val ret505 = build {
emit(1)
emit(null)
val x = get()
if (x === null) {
<!TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?")!>x<!>.hashCode()
}
""
}
val ret506 = build {
emit(1)
emit(null)
val x = get()
if (x === null) {
<!TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?")!>x<!>.toString()
}
""
}
val ret507 = build {
emit(1)
emit(null)
val x = get()
if (x === null) {
<!TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?")!>x<!>.test()
}
""
}
val ret508 = build {
emit(1)
emit(null)
val x = get()
<!TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?"), TYPE_MISMATCH("Any; Nothing?")!>x<!>.test()
""
}
val ret51 = build {
emit(1) emit(1)
emit(null) emit(null)
get()?.test() get()?.test()
@@ -126,10 +305,6 @@ fun test() {
if (x == null) { if (x == null) {
<!DEBUG_INFO_CONSTANT!>x<!>?.hashCode() <!DEBUG_INFO_CONSTANT!>x<!>?.hashCode()
<!DEBUG_INFO_CONSTANT!>x<!>?.equals(1) <!DEBUG_INFO_CONSTANT!>x<!>?.equals(1)
x.equals("")
x.hashCode()
x.toString()
x<!UNSAFE_CALL!>.<!>test()
<!DEBUG_INFO_CONSTANT!>x<!>?.test2() <!DEBUG_INFO_CONSTANT!>x<!>?.test2()
x.test2() x.test2()
} }
@@ -28,7 +28,7 @@ fun test(a: String?) {
get()?.equals("") get()?.equals("")
val x = get() val x = get()
x?.equals("") x?.equals("")
x ?: 1 x <!USELESS_ELVIS!>?: 1<!>
x!! x!!
"" ""
} }
@@ -55,7 +55,7 @@ fun test(a: String?) {
get()?.equals("") get()?.equals("")
val x = get() val x = get()
x?.equals("") x?.equals("")
x ?: 1 x <!USELESS_ELVIS!>?: 1<!>
x!! x!!
"" ""
} }