NI: intersect DFI types before capturing
^KT-37887 Fixed
This commit is contained in:
+5
@@ -1866,6 +1866,11 @@ public class FirOldFrontendDiagnosticsTestWithStdlibGenerated extends AbstractFi
|
|||||||
runTest("compiler/testData/diagnostics/testsWithStdLib/inference/integerLiterals.kt");
|
runTest("compiler/testData/diagnostics/testsWithStdLib/inference/integerLiterals.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("intersectDfiTypesBeforeCapturing.kt")
|
||||||
|
public void testIntersectDfiTypesBeforeCapturing() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/testsWithStdLib/inference/intersectDfiTypesBeforeCapturing.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("intersectionInputType.kt")
|
@TestMetadata("intersectionInputType.kt")
|
||||||
public void testIntersectionInputType() throws Exception {
|
public void testIntersectionInputType() throws Exception {
|
||||||
runTest("compiler/testData/diagnostics/testsWithStdLib/inference/intersectionInputType.kt");
|
runTest("compiler/testData/diagnostics/testsWithStdLib/inference/intersectionInputType.kt");
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ class ParseErrorKotlinCallArgument(
|
|||||||
) : ExpressionKotlinCallArgument, SimplePSIKotlinCallArgument() {
|
) : ExpressionKotlinCallArgument, SimplePSIKotlinCallArgument() {
|
||||||
override val receiver = ReceiverValueWithSmartCastInfo(
|
override val receiver = ReceiverValueWithSmartCastInfo(
|
||||||
TransientReceiver(ErrorUtils.createErrorType("Error type for ParseError-argument $valueArgument")),
|
TransientReceiver(ErrorUtils.createErrorType("Error type for ParseError-argument $valueArgument")),
|
||||||
possibleTypes = emptySet(),
|
typesFromSmartCasts = emptySet(),
|
||||||
isStable = true
|
isStable = true
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -471,7 +471,7 @@ class PSICallResolver(
|
|||||||
private fun createReceiverCallArgument(variable: KotlinResolutionCandidate): SimpleKotlinCallArgument {
|
private fun createReceiverCallArgument(variable: KotlinResolutionCandidate): SimpleKotlinCallArgument {
|
||||||
variable.forceResolution()
|
variable.forceResolution()
|
||||||
val variableReceiver = createReceiverValueWithSmartCastInfo(variable)
|
val variableReceiver = createReceiverValueWithSmartCastInfo(variable)
|
||||||
if (variableReceiver.possibleTypes.isNotEmpty()) {
|
if (variableReceiver.hasTypesFromSmartCasts()) {
|
||||||
return ReceiverExpressionKotlinCallArgument(
|
return ReceiverExpressionKotlinCallArgument(
|
||||||
createReceiverValueWithSmartCastInfo(variable),
|
createReceiverValueWithSmartCastInfo(variable),
|
||||||
isForImplicitInvoke = true
|
isForImplicitInvoke = true
|
||||||
|
|||||||
+27
-4
@@ -31,6 +31,7 @@ import org.jetbrains.kotlin.resolve.multiplatform.ExpectedActualResolver
|
|||||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValueWithSmartCastInfo
|
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValueWithSmartCastInfo
|
||||||
import org.jetbrains.kotlin.types.UnwrappedType
|
import org.jetbrains.kotlin.types.UnwrappedType
|
||||||
import org.jetbrains.kotlin.types.checker.intersectWrappedTypes
|
import org.jetbrains.kotlin.types.checker.intersectWrappedTypes
|
||||||
|
import org.jetbrains.kotlin.types.checker.prepareArgumentTypeRegardingCaptureTypes
|
||||||
import org.jetbrains.kotlin.utils.DFS
|
import org.jetbrains.kotlin.utils.DFS
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||||
|
|
||||||
@@ -40,15 +41,37 @@ internal fun unexpectedArgument(argument: KotlinCallArgument): Nothing =
|
|||||||
// if expression is not stable and has smart casts, then we create this type
|
// if expression is not stable and has smart casts, then we create this type
|
||||||
internal val ReceiverValueWithSmartCastInfo.unstableType: UnwrappedType?
|
internal val ReceiverValueWithSmartCastInfo.unstableType: UnwrappedType?
|
||||||
get() {
|
get() {
|
||||||
if (isStable || possibleTypes.isEmpty()) return null
|
if (isStable || !hasTypesFromSmartCasts())
|
||||||
return intersectWrappedTypes(possibleTypes + receiverValue.type)
|
return if (isStable) null else receiverValue.type.unwrap()
|
||||||
|
|
||||||
|
val intersectionType = intersectWrappedTypes(allOriginalTypes)
|
||||||
|
|
||||||
|
return prepareArgumentTypeRegardingCaptureTypes(intersectionType) ?: intersectionType
|
||||||
}
|
}
|
||||||
|
|
||||||
// with all smart casts if stable
|
// with all smart casts if stable
|
||||||
val ReceiverValueWithSmartCastInfo.stableType: UnwrappedType
|
val ReceiverValueWithSmartCastInfo.stableType: UnwrappedType
|
||||||
get() {
|
get() {
|
||||||
if (!isStable || possibleTypes.isEmpty()) return receiverValue.type.unwrap()
|
if (!isStable || !hasTypesFromSmartCasts())
|
||||||
return intersectWrappedTypes(possibleTypes + receiverValue.type)
|
return receiverValue.type.unwrap()
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We have to intersect types first as after capturing, subtyping relation may change and some type won't be excluded from intersection type.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* allOriginalTypes = [Inv<out CharSequence>, Inv<String>]
|
||||||
|
* intersect(Inv<out CharSequence>, Inv<String>) = Inv<String>
|
||||||
|
* capture(Inv<String>) = Inv<String>
|
||||||
|
* But with capturing first:
|
||||||
|
* capture(Inv<out CharSequence>) = Inv<CapturedType(out CharSequence)>
|
||||||
|
* capture(Inv<String>) = Inv<String>
|
||||||
|
* intersect(Inv<CapturedType(out CharSequence)>, Inv<String>) = Inv<CapturedType(out CharSequence)> & Inv<String>
|
||||||
|
*
|
||||||
|
* Such redundant type with captured argument may further lead to contradiction in constraint system or less exact solution.
|
||||||
|
*/
|
||||||
|
val intersectionType = intersectWrappedTypes(allOriginalTypes)
|
||||||
|
|
||||||
|
return prepareArgumentTypeRegardingCaptureTypes(intersectionType) ?: intersectionType
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun KotlinCallArgument.getExpectedType(parameter: ParameterDescriptor, languageVersionSettings: LanguageVersionSettings) =
|
internal fun KotlinCallArgument.getExpectedType(parameter: ParameterDescriptor, languageVersionSettings: LanguageVersionSettings) =
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ internal class MemberScopeTowerLevel(
|
|||||||
val unstableError = if (dispatchReceiver.isStable) null else UnstableSmartCastDiagnostic
|
val unstableError = if (dispatchReceiver.isStable) null else UnstableSmartCastDiagnostic
|
||||||
val unstableCandidates = if (unstableError != null) ArrayList<CandidateWithBoundDispatchReceiver>(0) else null
|
val unstableCandidates = if (unstableError != null) ArrayList<CandidateWithBoundDispatchReceiver>(0) else null
|
||||||
|
|
||||||
for (possibleType in dispatchReceiver.possibleTypes) {
|
for (possibleType in dispatchReceiver.typesFromSmartCasts) {
|
||||||
possibleType.memberScope.getMembers(possibleType).mapTo(unstableCandidates ?: result) {
|
possibleType.memberScope.getMembers(possibleType).mapTo(unstableCandidates ?: result) {
|
||||||
createCandidateDescriptor(
|
createCandidateDescriptor(
|
||||||
it,
|
it,
|
||||||
@@ -107,7 +107,7 @@ internal class MemberScopeTowerLevel(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dispatchReceiver.possibleTypes.isNotEmpty()) {
|
if (dispatchReceiver.hasTypesFromSmartCasts()) {
|
||||||
if (unstableCandidates == null) {
|
if (unstableCandidates == null) {
|
||||||
result.retainAll(result.selectMostSpecificInEachOverridableGroup { descriptor.approximateCapturedTypes(typeApproximator) })
|
result.retainAll(result.selectMostSpecificInEachOverridableGroup { descriptor.approximateCapturedTypes(typeApproximator) })
|
||||||
} else {
|
} else {
|
||||||
@@ -156,7 +156,7 @@ internal class MemberScopeTowerLevel(
|
|||||||
if (receiverValue !is ImplicitClassReceiver) return this
|
if (receiverValue !is ImplicitClassReceiver) return this
|
||||||
|
|
||||||
val newReceiverValue = CastImplicitClassReceiver(receiverValue.classDescriptor, targetType)
|
val newReceiverValue = CastImplicitClassReceiver(receiverValue.classDescriptor, targetType)
|
||||||
return ReceiverValueWithSmartCastInfo(newReceiverValue, possibleTypes, isStable)
|
return ReceiverValueWithSmartCastInfo(newReceiverValue, typesFromSmartCasts, isStable)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getVariables(
|
override fun getVariables(
|
||||||
@@ -184,9 +184,8 @@ internal class MemberScopeTowerLevel(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun recordLookup(name: Name) {
|
override fun recordLookup(name: Name) {
|
||||||
dispatchReceiver.receiverValue.type.memberScope.recordLookup(name, location)
|
for (type in dispatchReceiver.allOriginalTypes) {
|
||||||
dispatchReceiver.possibleTypes.forEach {
|
type.memberScope.recordLookup(name, location)
|
||||||
it.memberScope.recordLookup(name, location)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -292,16 +291,13 @@ internal class SyntheticScopeBasedTowerLevel(
|
|||||||
scopeTower: ImplicitScopeTower,
|
scopeTower: ImplicitScopeTower,
|
||||||
private val syntheticScopes: SyntheticScopes
|
private val syntheticScopes: SyntheticScopes
|
||||||
) : AbstractScopeTowerLevel(scopeTower) {
|
) : AbstractScopeTowerLevel(scopeTower) {
|
||||||
private val ReceiverValueWithSmartCastInfo.allTypes: Set<KotlinType>
|
|
||||||
get() = possibleTypes + receiverValue.type
|
|
||||||
|
|
||||||
override fun getVariables(
|
override fun getVariables(
|
||||||
name: Name,
|
name: Name,
|
||||||
extensionReceiver: ReceiverValueWithSmartCastInfo?
|
extensionReceiver: ReceiverValueWithSmartCastInfo?
|
||||||
): Collection<CandidateWithBoundDispatchReceiver> {
|
): Collection<CandidateWithBoundDispatchReceiver> {
|
||||||
if (extensionReceiver == null) return emptyList()
|
if (extensionReceiver == null) return emptyList()
|
||||||
|
|
||||||
return syntheticScopes.collectSyntheticExtensionProperties(extensionReceiver.allTypes, name, location).map {
|
return syntheticScopes.collectSyntheticExtensionProperties(extensionReceiver.allOriginalTypes, name, location).map {
|
||||||
createCandidateDescriptor(it, dispatchReceiver = null)
|
createCandidateDescriptor(it, dispatchReceiver = null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -240,8 +240,8 @@ class TowerResolver {
|
|||||||
|
|
||||||
private fun ReceiverValueWithSmartCastInfo.mayFitForName(name: Name): Boolean {
|
private fun ReceiverValueWithSmartCastInfo.mayFitForName(name: Name): Boolean {
|
||||||
if (receiverValue.type.mayFitForName(name)) return true
|
if (receiverValue.type.mayFitForName(name)) return true
|
||||||
if (possibleTypes.isEmpty()) return false
|
if (!hasTypesFromSmartCasts()) return false
|
||||||
return possibleTypes.any { it.mayFitForName(name) }
|
return typesFromSmartCasts.any { it.mayFitForName(name) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun KotlinType.mayFitForName(name: Name) =
|
private fun KotlinType.mayFitForName(name: Name) =
|
||||||
|
|||||||
+15
-12
@@ -19,17 +19,26 @@ package org.jetbrains.kotlin.resolve.scopes.receivers
|
|||||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlin.types.checker.prepareArgumentTypeRegardingCaptureTypes
|
import org.jetbrains.kotlin.types.checker.*
|
||||||
import org.jetbrains.kotlin.utils.newLinkedHashSetWithExpectedSize
|
|
||||||
|
|
||||||
// this receiver used only for resolution. see subtypes
|
// this receiver used only for resolution. see subtypes
|
||||||
interface DetailedReceiver
|
interface DetailedReceiver
|
||||||
|
|
||||||
class ReceiverValueWithSmartCastInfo(
|
class ReceiverValueWithSmartCastInfo(
|
||||||
val receiverValue: ReceiverValue,
|
val receiverValue: ReceiverValue,
|
||||||
val possibleTypes: Set<KotlinType>, // doesn't include receiver.type
|
/*
|
||||||
val isStable: Boolean
|
* It doesn't include receiver.type and is used only to special marking such types (e.g. for IDE green highlighting)
|
||||||
|
* but not to construct the resulting type
|
||||||
|
*/
|
||||||
|
val typesFromSmartCasts: Set<KotlinType>,
|
||||||
|
val isStable: Boolean,
|
||||||
|
originalBaseType: KotlinType = receiverValue.type
|
||||||
) : DetailedReceiver {
|
) : DetailedReceiver {
|
||||||
|
// It's used to construct the resulting type
|
||||||
|
val allOriginalTypes = typesFromSmartCasts + originalBaseType
|
||||||
|
|
||||||
|
fun hasTypesFromSmartCasts() = typesFromSmartCasts.isNotEmpty()
|
||||||
|
|
||||||
override fun toString() = receiverValue.toString()
|
override fun toString() = receiverValue.toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,13 +55,7 @@ interface QualifierReceiver : Receiver, DetailedReceiver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun ReceiverValueWithSmartCastInfo.prepareReceiverRegardingCaptureTypes(): ReceiverValueWithSmartCastInfo {
|
fun ReceiverValueWithSmartCastInfo.prepareReceiverRegardingCaptureTypes(): ReceiverValueWithSmartCastInfo {
|
||||||
val preparedBaseType = prepareArgumentTypeRegardingCaptureTypes(receiverValue.type.unwrap())
|
val preparedBaseType = prepareArgumentTypeRegardingCaptureTypes(receiverValue.type.unwrap()) ?: return this
|
||||||
if (preparedBaseType == null && possibleTypes.isEmpty()) return this
|
|
||||||
|
|
||||||
val newPossibleTypes = possibleTypes.mapTo(newLinkedHashSetWithExpectedSize(possibleTypes.size)) {
|
return ReceiverValueWithSmartCastInfo(receiverValue.replaceType(preparedBaseType), typesFromSmartCasts, isStable, receiverValue.type)
|
||||||
prepareArgumentTypeRegardingCaptureTypes(it.unwrap()) ?: it
|
|
||||||
}
|
|
||||||
val newReceiver = if (preparedBaseType != null) receiverValue.replaceType(preparedBaseType) else receiverValue
|
|
||||||
|
|
||||||
return ReceiverValueWithSmartCastInfo(newReceiver, newPossibleTypes, isStable)
|
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -36,5 +36,5 @@ fun foo(coneSymbol: AbstractFirBasedSymbol<*>) {
|
|||||||
coneSymbol.phasedFir() checkType { _<FirVariable<*>>() }
|
coneSymbol.phasedFir() checkType { _<FirVariable<*>>() }
|
||||||
|
|
||||||
if (coneSymbol !is FirPropertySymbol) return
|
if (coneSymbol !is FirPropertySymbol) return
|
||||||
coneSymbol.phasedFir() checkType { _<FirVariable<*>>() }
|
coneSymbol.phasedFir() checkType { _<FirProperty>() }
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -36,5 +36,5 @@ fun foo(coneSymbol: AbstractFirBasedSymbol<*>) {
|
|||||||
coneSymbol.phasedFir() checkType { _<FirVariable<*>>() }
|
coneSymbol.phasedFir() checkType { _<FirVariable<*>>() }
|
||||||
|
|
||||||
if (coneSymbol !is FirPropertySymbol) return
|
if (coneSymbol !is FirPropertySymbol) return
|
||||||
coneSymbol.phasedFir() checkType { _<FirVariable<*>>() }
|
coneSymbol.phasedFir() checkType { _<FirProperty>() }
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+28
@@ -0,0 +1,28 @@
|
|||||||
|
// !DIAGNOSTICS: -UNCHECKED_CAST -UNUSED_DESTRUCTURED_PARAMETER_ENTRY -USELESS_CAST -UNUSED_PARAMETER -UNUSED_EXPRESSION
|
||||||
|
|
||||||
|
class Inv<T>(val y: T)
|
||||||
|
|
||||||
|
fun <K> takeTwoInv(x: Inv<K>, y: Inv<K>) = x.y
|
||||||
|
|
||||||
|
fun <K> takeTwoInvOut(x: Inv<out K>, y: Inv<out K>) : K = x.y
|
||||||
|
|
||||||
|
fun test1(y: Any) {
|
||||||
|
y as Map<String, Any?>
|
||||||
|
y as Map<*, *>
|
||||||
|
y.forEach { (k: String, u: Any?) -> }
|
||||||
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.collections.Map<kotlin.String, kotlin.Any?> & kotlin.Any")!>y<!>
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test2(x: Any, y: Inv<String>) {
|
||||||
|
x as Inv<String>
|
||||||
|
x as Inv<out CharSequence>
|
||||||
|
val z = takeTwoInv(x, y)
|
||||||
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String")!>z<!>
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test3(x: Any, y: Inv<String>) {
|
||||||
|
x as Inv<out CharSequence>
|
||||||
|
x as Inv<String>
|
||||||
|
val z = takeTwoInvOut(x, y)
|
||||||
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String")!>z<!>
|
||||||
|
}
|
||||||
Vendored
+28
@@ -0,0 +1,28 @@
|
|||||||
|
// !DIAGNOSTICS: -UNCHECKED_CAST -UNUSED_DESTRUCTURED_PARAMETER_ENTRY -USELESS_CAST -UNUSED_PARAMETER -UNUSED_EXPRESSION
|
||||||
|
|
||||||
|
class Inv<T>(val y: T)
|
||||||
|
|
||||||
|
fun <K> takeTwoInv(x: Inv<K>, y: Inv<K>) = x.y
|
||||||
|
|
||||||
|
fun <K> takeTwoInvOut(x: Inv<out K>, y: Inv<out K>) : K = x.y
|
||||||
|
|
||||||
|
fun test1(y: Any) {
|
||||||
|
y as Map<String, Any?>
|
||||||
|
y as Map<*, *>
|
||||||
|
<!DEBUG_INFO_SMARTCAST!>y<!>.forEach { (k: String, u: Any?) -> }
|
||||||
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any & kotlin.collections.Map<*, *> & kotlin.collections.Map<kotlin.String, kotlin.Any?>")!>y<!>
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test2(x: Any, y: Inv<String>) {
|
||||||
|
x as Inv<String>
|
||||||
|
x as Inv<out CharSequence>
|
||||||
|
val z = takeTwoInv(<!DEBUG_INFO_SMARTCAST!>x<!>, y)
|
||||||
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String")!>z<!>
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test3(x: Any, y: Inv<String>) {
|
||||||
|
x as Inv<out CharSequence>
|
||||||
|
x as Inv<String>
|
||||||
|
val z = takeTwoInvOut(<!DEBUG_INFO_SMARTCAST!>x<!>, y)
|
||||||
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String")!>z<!>
|
||||||
|
}
|
||||||
Vendored
+15
@@ -0,0 +1,15 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public fun </*0*/ K> takeTwoInv(/*0*/ x: Inv<K>, /*1*/ y: Inv<K>): K
|
||||||
|
public fun </*0*/ K> takeTwoInvOut(/*0*/ x: Inv<out K>, /*1*/ y: Inv<out K>): K
|
||||||
|
public fun test1(/*0*/ y: kotlin.Any): kotlin.Unit
|
||||||
|
public fun test2(/*0*/ x: kotlin.Any, /*1*/ y: Inv<kotlin.String>): kotlin.Unit
|
||||||
|
public fun test3(/*0*/ x: kotlin.Any, /*1*/ y: Inv<kotlin.String>): kotlin.Unit
|
||||||
|
|
||||||
|
public final class Inv</*0*/ T> {
|
||||||
|
public constructor Inv</*0*/ T>(/*0*/ y: T)
|
||||||
|
public final val y: T
|
||||||
|
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
|
||||||
|
}
|
||||||
+5
@@ -2881,6 +2881,11 @@ public class DiagnosticsTestWithStdLibGenerated extends AbstractDiagnosticsTestW
|
|||||||
runTest("compiler/testData/diagnostics/testsWithStdLib/inference/integerLiterals.kt");
|
runTest("compiler/testData/diagnostics/testsWithStdLib/inference/integerLiterals.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("intersectDfiTypesBeforeCapturing.kt")
|
||||||
|
public void testIntersectDfiTypesBeforeCapturing() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/testsWithStdLib/inference/intersectDfiTypesBeforeCapturing.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("intersectionInputType.kt")
|
@TestMetadata("intersectionInputType.kt")
|
||||||
public void testIntersectionInputType() throws Exception {
|
public void testIntersectionInputType() throws Exception {
|
||||||
runTest("compiler/testData/diagnostics/testsWithStdLib/inference/intersectionInputType.kt");
|
runTest("compiler/testData/diagnostics/testsWithStdLib/inference/intersectionInputType.kt");
|
||||||
|
|||||||
compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsTestWithStdLibUsingJavacGenerated.java
Generated
+5
@@ -2881,6 +2881,11 @@ public class DiagnosticsTestWithStdLibUsingJavacGenerated extends AbstractDiagno
|
|||||||
runTest("compiler/testData/diagnostics/testsWithStdLib/inference/integerLiterals.kt");
|
runTest("compiler/testData/diagnostics/testsWithStdLib/inference/integerLiterals.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("intersectDfiTypesBeforeCapturing.kt")
|
||||||
|
public void testIntersectDfiTypesBeforeCapturing() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/testsWithStdLib/inference/intersectDfiTypesBeforeCapturing.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("intersectionInputType.kt")
|
@TestMetadata("intersectionInputType.kt")
|
||||||
public void testIntersectionInputType() throws Exception {
|
public void testIntersectionInputType() throws Exception {
|
||||||
runTest("compiler/testData/diagnostics/testsWithStdLib/inference/intersectionInputType.kt");
|
runTest("compiler/testData/diagnostics/testsWithStdLib/inference/intersectionInputType.kt");
|
||||||
|
|||||||
@@ -303,6 +303,7 @@ object AbstractTypeChecker {
|
|||||||
|
|
||||||
if (!anyNonOutParameter && isSubtypeForSameConstructor(newArguments, superType)) return true
|
if (!anyNonOutParameter && isSubtypeForSameConstructor(newArguments, superType)) return true
|
||||||
|
|
||||||
|
// TODO: rethink this; now components order in intersection type affects semantic due to run subtyping (which can add constraints) only until the first successful candidate
|
||||||
return supertypesWithSameConstructor.any { isSubtypeForSameConstructor(it.asArgumentList(), superType) }
|
return supertypesWithSameConstructor.any { isSubtypeForSameConstructor(it.asArgumentList(), superType) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user