K2: Don't report BUILDER_INFERENCE_STUB_RECEIVER for members of Any
This commit actually does two things: - Adds Any scope to stub type - Makes CheckDispatchReceiver treat stub types as non-null for the unsafe call check to make such candidates viable Related to KT-59369
This commit is contained in:
committed by
Space Team
parent
0ed6256bcc
commit
299d279915
@@ -91,7 +91,25 @@ private fun ConeKotlinType.scope(
|
|||||||
intersectionType.scope(useSiteSession, scopeSession, requiredMembersPhase) ?: FirTypeScope.Empty
|
intersectionType.scope(useSiteSession, scopeSession, requiredMembersPhase) ?: FirTypeScope.Empty
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
is ConeStubTypeForChainInference -> {
|
||||||
|
// Actually, it should be the intersection of bounds, but K1 doesn't think so.
|
||||||
|
// interface ABC {
|
||||||
|
// fun foo()
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// class Buildee<out U : ABC> {
|
||||||
|
// fun get(): U = null!!
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// fun <F: ABC> buildsome(l: Buildee<F>.() -> Unit) {}
|
||||||
|
//
|
||||||
|
// fun test() {
|
||||||
|
// buildsome {
|
||||||
|
// this.get().foo()
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
useSiteSession.builtinTypes.anyType.type.scope(useSiteSession, scopeSession, requiredMembersPhase)
|
||||||
|
}
|
||||||
is ConeRawType -> lowerBound.scope(useSiteSession, scopeSession, requiredMembersPhase)
|
is ConeRawType -> lowerBound.scope(useSiteSession, scopeSession, requiredMembersPhase)
|
||||||
is ConeDynamicType -> useSiteSession.dynamicMembersStorage.getDynamicScopeFor(scopeSession)
|
is ConeDynamicType -> useSiteSession.dynamicMembersStorage.getDynamicScopeFor(scopeSession)
|
||||||
is ConeFlexibleType -> lowerBound.scope(useSiteSession, scopeSession, requiredMembersPhase)
|
is ConeFlexibleType -> lowerBound.scope(useSiteSession, scopeSession, requiredMembersPhase)
|
||||||
|
|||||||
@@ -184,7 +184,15 @@ object CheckDispatchReceiver : ResolutionStage() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val dispatchReceiverValueType = candidate.dispatchReceiver?.resolvedType ?: return
|
val dispatchReceiverValueType = candidate.dispatchReceiver?.resolvedType ?: return
|
||||||
val isReceiverNullable = !AbstractNullabilityChecker.isSubtypeOfAny(context.session.typeContext, dispatchReceiverValueType)
|
|
||||||
|
// TODO: Actually, we should treat stub types as non-nullable for the isReceiverNullable check
|
||||||
|
// Otherwise, we won't able to resolve to member toString/hashCode due to UnsafeCall error
|
||||||
|
// It was possible in K1, due to the fact that K1 doesn't use AbstractNullabilityChecker directly
|
||||||
|
// But, AbstractNullabilityChecker.isSubtypeOfAny doesn't respect stubTypeEqualToAnything
|
||||||
|
val isStubType = dispatchReceiverValueType is ConeStubTypeForChainInference
|
||||||
|
val isReceiverNullable =
|
||||||
|
!AbstractNullabilityChecker.isSubtypeOfAny(context.session.typeContext, dispatchReceiverValueType) && !isStubType
|
||||||
|
|
||||||
|
|
||||||
val isCandidateFromUnstableSmartcast =
|
val isCandidateFromUnstableSmartcast =
|
||||||
(candidate.originScope as? FirUnstableSmartcastTypeScope)?.isSymbolFromUnstableSmartcast(candidate.symbol) == true
|
(candidate.originScope as? FirUnstableSmartcastTypeScope)?.isSymbolFromUnstableSmartcast(candidate.symbol) == true
|
||||||
|
|||||||
Vendored
+20
-20
@@ -23,10 +23,10 @@ fun test() {
|
|||||||
<!BUILDER_INFERENCE_STUB_RECEIVER!>get()?.test()<!>
|
<!BUILDER_INFERENCE_STUB_RECEIVER!>get()?.test()<!>
|
||||||
<!BUILDER_INFERENCE_STUB_RECEIVER!>get()?.test2()<!>
|
<!BUILDER_INFERENCE_STUB_RECEIVER!>get()?.test2()<!>
|
||||||
<!BUILDER_INFERENCE_STUB_RECEIVER!>get().test2()<!>
|
<!BUILDER_INFERENCE_STUB_RECEIVER!>get().test2()<!>
|
||||||
<!BUILDER_INFERENCE_STUB_RECEIVER!>get()?.hashCode()<!>
|
get()?.hashCode()
|
||||||
get()?.<!NONE_APPLICABLE!>equals<!>(1)
|
get()?.equals(1)
|
||||||
// there is `String?.equals` extension
|
// there is `String?.equals` extension
|
||||||
<!BUILDER_INFERENCE_STUB_RECEIVER!>get().equals("")<!>
|
get().equals("")
|
||||||
}
|
}
|
||||||
val ret2 = build {
|
val ret2 = build {
|
||||||
emit(1)
|
emit(1)
|
||||||
@@ -34,12 +34,12 @@ fun test() {
|
|||||||
<!BUILDER_INFERENCE_STUB_RECEIVER!>get()?.test()<!>
|
<!BUILDER_INFERENCE_STUB_RECEIVER!>get()?.test()<!>
|
||||||
<!BUILDER_INFERENCE_STUB_RECEIVER!>get()?.test2()<!>
|
<!BUILDER_INFERENCE_STUB_RECEIVER!>get()?.test2()<!>
|
||||||
<!BUILDER_INFERENCE_STUB_RECEIVER!>get().test2()<!>
|
<!BUILDER_INFERENCE_STUB_RECEIVER!>get().test2()<!>
|
||||||
<!BUILDER_INFERENCE_STUB_RECEIVER!>get()?.hashCode()<!>
|
get()?.hashCode()
|
||||||
get()?.<!NONE_APPLICABLE!>equals<!>(1)
|
get()?.equals(1)
|
||||||
val x = get()
|
val x = get()
|
||||||
<!BUILDER_INFERENCE_STUB_RECEIVER!>x?.hashCode()<!>
|
x?.hashCode()
|
||||||
x?.<!NONE_APPLICABLE!>equals<!>(1)
|
x?.equals(1)
|
||||||
<!BUILDER_INFERENCE_STUB_RECEIVER!>x.equals("")<!>
|
x.equals("")
|
||||||
}
|
}
|
||||||
val ret3 = build {
|
val ret3 = build {
|
||||||
emit(1)
|
emit(1)
|
||||||
@@ -47,11 +47,11 @@ fun test() {
|
|||||||
<!BUILDER_INFERENCE_STUB_RECEIVER!>get()?.test()<!>
|
<!BUILDER_INFERENCE_STUB_RECEIVER!>get()?.test()<!>
|
||||||
<!BUILDER_INFERENCE_STUB_RECEIVER!>get()?.test2()<!>
|
<!BUILDER_INFERENCE_STUB_RECEIVER!>get()?.test2()<!>
|
||||||
<!BUILDER_INFERENCE_STUB_RECEIVER!>get().test2()<!>
|
<!BUILDER_INFERENCE_STUB_RECEIVER!>get().test2()<!>
|
||||||
<!BUILDER_INFERENCE_STUB_RECEIVER!>get()?.hashCode()<!>
|
get()?.hashCode()
|
||||||
get()?.<!NONE_APPLICABLE!>equals<!>(1)
|
get()?.equals(1)
|
||||||
val x = get()
|
val x = get()
|
||||||
<!BUILDER_INFERENCE_STUB_RECEIVER!>x?.hashCode()<!>
|
x?.hashCode()
|
||||||
x?.<!NONE_APPLICABLE!>equals<!>(1)
|
x?.equals(1)
|
||||||
|
|
||||||
if (get() == null) {}
|
if (get() == null) {}
|
||||||
if (<!FORBIDDEN_IDENTITY_EQUALS_WARNING!>get() === null<!>) {}
|
if (<!FORBIDDEN_IDENTITY_EQUALS_WARNING!>get() === null<!>) {}
|
||||||
@@ -163,11 +163,11 @@ fun test() {
|
|||||||
<!BUILDER_INFERENCE_STUB_RECEIVER!>get()?.test()<!>
|
<!BUILDER_INFERENCE_STUB_RECEIVER!>get()?.test()<!>
|
||||||
<!BUILDER_INFERENCE_STUB_RECEIVER!>get()?.test2()<!>
|
<!BUILDER_INFERENCE_STUB_RECEIVER!>get()?.test2()<!>
|
||||||
<!BUILDER_INFERENCE_STUB_RECEIVER!>get().test2()<!>
|
<!BUILDER_INFERENCE_STUB_RECEIVER!>get().test2()<!>
|
||||||
<!BUILDER_INFERENCE_STUB_RECEIVER!>get()?.hashCode()<!>
|
get()?.hashCode()
|
||||||
get()?.<!NONE_APPLICABLE!>equals<!>(1)
|
get()?.equals(1)
|
||||||
val x = get()
|
val x = get()
|
||||||
<!BUILDER_INFERENCE_STUB_RECEIVER!>x?.hashCode()<!>
|
x?.hashCode()
|
||||||
x?.<!NONE_APPLICABLE!>equals<!>(1)
|
x?.equals(1)
|
||||||
|
|
||||||
if (get() == null) {}
|
if (get() == null) {}
|
||||||
if (<!FORBIDDEN_IDENTITY_EQUALS_WARNING!>get() === null<!>) {}
|
if (<!FORBIDDEN_IDENTITY_EQUALS_WARNING!>get() === null<!>) {}
|
||||||
@@ -293,11 +293,11 @@ fun test() {
|
|||||||
<!BUILDER_INFERENCE_STUB_RECEIVER!>get()?.test()<!>
|
<!BUILDER_INFERENCE_STUB_RECEIVER!>get()?.test()<!>
|
||||||
<!BUILDER_INFERENCE_STUB_RECEIVER!>get()?.test2()<!>
|
<!BUILDER_INFERENCE_STUB_RECEIVER!>get()?.test2()<!>
|
||||||
<!BUILDER_INFERENCE_STUB_RECEIVER!>get().test2()<!>
|
<!BUILDER_INFERENCE_STUB_RECEIVER!>get().test2()<!>
|
||||||
<!BUILDER_INFERENCE_STUB_RECEIVER!>get()?.hashCode()<!>
|
get()?.hashCode()
|
||||||
get()?.<!NONE_APPLICABLE!>equals<!>(1)
|
get()?.equals(1)
|
||||||
val x = get()
|
val x = get()
|
||||||
<!BUILDER_INFERENCE_STUB_RECEIVER!>x?.hashCode()<!>
|
x?.hashCode()
|
||||||
x?.<!NONE_APPLICABLE!>equals<!>(1)
|
x?.equals(1)
|
||||||
|
|
||||||
if (get() == null) {}
|
if (get() == null) {}
|
||||||
if (<!FORBIDDEN_IDENTITY_EQUALS_WARNING!>get() === null<!>) {}
|
if (<!FORBIDDEN_IDENTITY_EQUALS_WARNING!>get() === null<!>) {}
|
||||||
|
|||||||
Vendored
+6
-6
@@ -25,27 +25,27 @@ fun <R1 : R2, R2> build4(x: R2, block: TestInterface<R1>.() -> Unit): R1 = TODO(
|
|||||||
fun test(a: String?) {
|
fun test(a: String?) {
|
||||||
val ret1 = build {
|
val ret1 = build {
|
||||||
emit(1)
|
emit(1)
|
||||||
<!BUILDER_INFERENCE_STUB_RECEIVER!>get()<!UNNECESSARY_SAFE_CALL!>?.<!>equals("")<!>
|
get()<!UNNECESSARY_SAFE_CALL!>?.<!>equals("")
|
||||||
val x = get()
|
val x = get()
|
||||||
<!BUILDER_INFERENCE_STUB_RECEIVER!>x<!UNNECESSARY_SAFE_CALL!>?.<!>equals("")<!>
|
x<!UNNECESSARY_SAFE_CALL!>?.<!>equals("")
|
||||||
x <!USELESS_ELVIS!>?: 1<!>
|
x <!USELESS_ELVIS!>?: 1<!>
|
||||||
x<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>
|
x<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>
|
||||||
""
|
""
|
||||||
}
|
}
|
||||||
val ret2 = build2 {
|
val ret2 = build2 {
|
||||||
emit(1)
|
emit(1)
|
||||||
<!BUILDER_INFERENCE_STUB_RECEIVER!>get()<!UNNECESSARY_SAFE_CALL!>?.<!>equals("")<!>
|
get()<!UNNECESSARY_SAFE_CALL!>?.<!>equals("")
|
||||||
val x = get()
|
val x = get()
|
||||||
<!BUILDER_INFERENCE_STUB_RECEIVER!>x<!UNNECESSARY_SAFE_CALL!>?.<!>equals("")<!>
|
x<!UNNECESSARY_SAFE_CALL!>?.<!>equals("")
|
||||||
x <!USELESS_ELVIS!>?: 1<!>
|
x <!USELESS_ELVIS!>?: 1<!>
|
||||||
x<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>
|
x<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>
|
||||||
""
|
""
|
||||||
}
|
}
|
||||||
val ret3 = build3 {
|
val ret3 = build3 {
|
||||||
emit(1)
|
emit(1)
|
||||||
<!BUILDER_INFERENCE_STUB_RECEIVER!>get()<!UNNECESSARY_SAFE_CALL!>?.<!>equals("")<!>
|
get()<!UNNECESSARY_SAFE_CALL!>?.<!>equals("")
|
||||||
val x = get()
|
val x = get()
|
||||||
<!BUILDER_INFERENCE_STUB_RECEIVER!>x<!UNNECESSARY_SAFE_CALL!>?.<!>equals("")<!>
|
x<!UNNECESSARY_SAFE_CALL!>?.<!>equals("")
|
||||||
x <!USELESS_ELVIS!>?: 1<!>
|
x <!USELESS_ELVIS!>?: 1<!>
|
||||||
x<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>
|
x<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>
|
||||||
""
|
""
|
||||||
|
|||||||
-19
@@ -1,19 +0,0 @@
|
|||||||
// !OPT_IN: kotlin.RequiresOptIn
|
|
||||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
|
||||||
|
|
||||||
import kotlin.experimental.ExperimentalTypeInference
|
|
||||||
|
|
||||||
class TypeDefinition<KotlinType : Any> {
|
|
||||||
fun parse(parser: (serializedValue: String) -> KotlinType?): Unit = TODO()
|
|
||||||
fun serialize(parser: (value: KotlinType) -> Any?): Unit = TODO()
|
|
||||||
}
|
|
||||||
|
|
||||||
@OptIn(ExperimentalTypeInference::class)
|
|
||||||
fun <KotlinType : Any> defineType(definition: TypeDefinition<KotlinType>.() -> Unit): Unit = TODO()
|
|
||||||
|
|
||||||
fun main() {
|
|
||||||
defineType {
|
|
||||||
parse { it.toInt() }
|
|
||||||
serialize { <!BUILDER_INFERENCE_STUB_RECEIVER!>it.toString()<!> }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
// !OPT_IN: kotlin.RequiresOptIn
|
// !OPT_IN: kotlin.RequiresOptIn
|
||||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user