diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt index 2626bed7c6c..157eede8671 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt @@ -1982,6 +1982,20 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert firDiagnostic.b.map { coneKotlinType -> firSymbolBuilder.typeBuilder.buildKtType(coneKotlinType) }, + firDiagnostic.c, + firDiagnostic.d, + firDiagnostic as KtPsiDiagnostic, + token, + ) + } + add(FirErrors.INFERRED_TYPE_VARIABLE_INTO_POSSIBLE_EMPTY_INTERSECTION) { firDiagnostic -> + InferredTypeVariableIntoPossibleEmptyIntersectionImpl( + firDiagnostic.a, + firDiagnostic.b.map { coneKotlinType -> + firSymbolBuilder.typeBuilder.buildKtType(coneKotlinType) + }, + firDiagnostic.c, + firDiagnostic.d, firDiagnostic as KtPsiDiagnostic, token, ) diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt index e2d01de278e..68a6b7516c5 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt @@ -1409,6 +1409,16 @@ sealed class KtFirDiagnostic : KtDiagnosticWithPsi { override val diagnosticClass get() = InferredTypeVariableIntoEmptyIntersection::class abstract val typeVariableDescription: String abstract val incompatibleTypes: List + abstract val description: String + abstract val causingTypes: String + } + + abstract class InferredTypeVariableIntoPossibleEmptyIntersection : KtFirDiagnostic() { + override val diagnosticClass get() = InferredTypeVariableIntoPossibleEmptyIntersection::class + abstract val typeVariableDescription: String + abstract val incompatibleTypes: List + abstract val description: String + abstract val causingTypes: String } abstract class ExtensionInClassReferenceNotAllowed : KtFirDiagnostic() { diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt index 88b53081127..1923ca04805 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt @@ -1690,10 +1690,21 @@ internal class PlatformClassMappedToKotlinImpl( internal class InferredTypeVariableIntoEmptyIntersectionImpl( override val typeVariableDescription: String, override val incompatibleTypes: List, + override val description: String, + override val causingTypes: String, override val firDiagnostic: KtPsiDiagnostic, override val token: KtLifetimeToken, ) : KtFirDiagnostic.InferredTypeVariableIntoEmptyIntersection(), KtAbstractFirDiagnostic +internal class InferredTypeVariableIntoPossibleEmptyIntersectionImpl( + override val typeVariableDescription: String, + override val incompatibleTypes: List, + override val description: String, + override val causingTypes: String, + override val firDiagnostic: KtPsiDiagnostic, + override val token: KtLifetimeToken, +) : KtFirDiagnostic.InferredTypeVariableIntoPossibleEmptyIntersection(), KtAbstractFirDiagnostic + internal class ExtensionInClassReferenceNotAllowedImpl( override val referencedDeclaration: KtCallableSymbol, override val firDiagnostic: KtPsiDiagnostic, diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/symbols/KtFirSymbolProvider.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/symbols/KtFirSymbolProvider.kt index 157700b52e0..9bf0188c148 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/symbols/KtFirSymbolProvider.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/symbols/KtFirSymbolProvider.kt @@ -14,7 +14,6 @@ import org.jetbrains.kotlin.analysis.api.lifetime.KtLifetimeToken import org.jetbrains.kotlin.analysis.api.lifetime.withValidityAssertion import org.jetbrains.kotlin.analysis.low.level.api.fir.api.LLFirResolveSession import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getOrBuildFirFile -import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getOrBuildFirOfType import org.jetbrains.kotlin.analysis.low.level.api.fir.api.resolveToFirSymbolOfType import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin import org.jetbrains.kotlin.fir.renderWithType @@ -89,7 +88,9 @@ internal class KtFirSymbolProvider( } override fun getAnonymousFunctionSymbol(psi: KtNamedFunction): KtAnonymousFunctionSymbol = withValidityAssertion { - firSymbolBuilder.functionLikeBuilder.buildAnonymousFunctionSymbol(psi.getOrBuildFirOfType(firResolveSession)) + firSymbolBuilder.functionLikeBuilder.buildAnonymousFunctionSymbol( + psi.resolveToFirSymbolOfType(firResolveSession) + ) } override fun getAnonymousFunctionSymbol(psi: KtFunctionLiteral): KtAnonymousFunctionSymbol = withValidityAssertion { diff --git a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt index 4aeaf464cbe..a2140f2387a 100644 --- a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt +++ b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt @@ -688,12 +688,15 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") { val INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION by error { parameter("typeVariableDescription") parameter>("incompatibleTypes") - parameter("kind") + parameter("description") + parameter("causingTypes") } val INFERRED_TYPE_VARIABLE_INTO_POSSIBLE_EMPTY_INTERSECTION by warning { parameter("typeVariableDescription") parameter>("incompatibleTypes") + parameter("description") + parameter("causingTypes") } } diff --git a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt index 291ebd642f4..acdf4649cc7 100644 --- a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt +++ b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt @@ -412,8 +412,8 @@ object FirErrors { val SMARTCAST_IMPOSSIBLE by error4() val REDUNDANT_NULLABLE by warning0(SourceElementPositioningStrategies.REDUNDANT_NULLABLE) val PLATFORM_CLASS_MAPPED_TO_KOTLIN by warning1(SourceElementPositioningStrategies.REFERENCED_NAME_BY_QUALIFIED) - val INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION by error3, String>() - val INFERRED_TYPE_VARIABLE_INTO_POSSIBLE_EMPTY_INTERSECTION by warning2>() + val INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION by error4, String, String>() + val INFERRED_TYPE_VARIABLE_INTO_POSSIBLE_EMPTY_INTERSECTION by warning4, String, String>() // Reflection val EXTENSION_IN_CLASS_REFERENCE_NOT_ALLOWED by error1>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt index 0bc8c9d54e7..62762991be9 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt @@ -950,16 +950,19 @@ object FirErrorsDefaultMessages : BaseDiagnosticRendererFactory() { map.put(INFERENCE_UNSUCCESSFUL_FORK, "Unsuccessful inference fork at position: {0}", TO_STRING) map.put( INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION, - "Type argument for a type parameter {0} can''t be inferred because it has incompatible upper bounds ({2}): {1}", + "Type argument for a type parameter {0} can''t be inferred because it has incompatible upper bounds: {1} ({2}{3})", TO_STRING, RENDER_COLLECTION_OF_TYPES, + TO_STRING, TO_STRING ) map.put( INFERRED_TYPE_VARIABLE_INTO_POSSIBLE_EMPTY_INTERSECTION, - "Type argument for a type parameter {0} has possible incompatible upper bounds: {1}", + "Type argument for a type parameter {0} has possible incompatible upper bounds: {1} ({2}{3})", TO_STRING, - RENDER_COLLECTION_OF_TYPES + RENDER_COLLECTION_OF_TYPES, + TO_STRING, + TO_STRING ) map.put(TYPE_MISMATCH, "Type mismatch: inferred type is {1} but {0} was expected", TO_STRING, TO_STRING, NOT_RENDERED) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/coneDiagnosticToFirDiagnostic.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/coneDiagnosticToFirDiagnostic.kt index 07f64286430..69c5f30d60e 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/coneDiagnosticToFirDiagnostic.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/coneDiagnosticToFirDiagnostic.kt @@ -257,8 +257,9 @@ private fun mapInapplicableCandidateError( diagnostic.candidate ) } - is InferredEmptyIntersectionDiagnostic -> - reportInferredIntoEmptyIntersectionError(source, rootCause.typeVariable, rootCause.incompatibleTypes, rootCause.kind) + is InferredEmptyIntersectionDiagnostic -> reportInferredIntoEmptyIntersectionError( + source, rootCause.typeVariable, rootCause.incompatibleTypes, rootCause.causingTypes, rootCause.kind + ) else -> genericDiagnostic } }.distinct() @@ -400,6 +401,7 @@ private fun ConstraintSystemError.toDiagnostic( source, typeVariable as ConeTypeVariable, incompatibleTypes as Collection, + causingTypes as Collection, kind ) } @@ -411,18 +413,18 @@ private fun reportInferredIntoEmptyIntersectionError( source: KtSourceElement, typeVariable: ConeTypeVariable, incompatibleTypes: Collection, + causingTypes: Collection, kind: EmptyIntersectionTypeKind ): KtDiagnostic? { val typeVariableText = (typeVariable.typeConstructor.originalTypeParameter as? ConeTypeParameterLookupTag)?.name?.asString() ?: typeVariable.toString() - return if (kind.isPossiblyEmpty()) { - FirErrors.INFERRED_TYPE_VARIABLE_INTO_POSSIBLE_EMPTY_INTERSECTION.createOn(source, typeVariableText, incompatibleTypes) - } else { - FirErrors.INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION.createOn( - source, typeVariableText, incompatibleTypes, kind.description?.let { " ($it)" }.orEmpty() - ) - } + val causingTypesText = if (incompatibleTypes == causingTypes) "" else ": ${causingTypes.joinToString()}" + val factory = if (kind.isPossiblyEmpty()) + FirErrors.INFERRED_TYPE_VARIABLE_INTO_POSSIBLE_EMPTY_INTERSECTION else + FirErrors.INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION + + return factory.createOn(source, typeVariableText, incompatibleTypes, kind.description, causingTypesText) } private val NewConstraintError.lowerConeType: ConeKotlinType get() = lowerType as ConeKotlinType diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolutionStages.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolutionStages.kt index e1a663889e8..584b26e90c7 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolutionStages.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolutionStages.kt @@ -14,7 +14,6 @@ import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.languageVersionSettings import org.jetbrains.kotlin.fir.matchingParameterFunctionType import org.jetbrains.kotlin.fir.references.FirSuperReference -import org.jetbrains.kotlin.fir.resolve.dfa.symbol import org.jetbrains.kotlin.fir.resolve.directExpansionType import org.jetbrains.kotlin.fir.resolve.fullyExpandedType import org.jetbrains.kotlin.fir.resolve.inference.ConeTypeParameterBasedTypeVariable @@ -582,15 +581,15 @@ internal object CheckIncompatibleTypeVariableUpperBounds : ResolutionStage() { if (upperTypes.size <= 1 || variableWithConstraints.constraints.any { it.kind.isLower() }) continue - val emptyIntersectionKind = candidate.system.getEmptyIntersectionTypeKind(upperTypes).takeIf { it.isDefinitelyEmpty() } - ?: continue + val emptyIntersectionTypeInfo = candidate.system.getEmptyIntersectionTypeKind(upperTypes) ?: continue sink.yieldDiagnostic( @Suppress("UNCHECKED_CAST") InferredEmptyIntersectionDiagnostic( - upperTypes as Collection, + upperTypes as List, + emptyIntersectionTypeInfo.casingTypes.toList() as List, variableWithConstraints.typeVariable as ConeTypeVariable, - emptyIntersectionKind + emptyIntersectionTypeInfo.kind ) ) } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirCallCompletionResultsWriterTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirCallCompletionResultsWriterTransformer.kt index c6f67176d44..988ba7c9ff0 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirCallCompletionResultsWriterTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirCallCompletionResultsWriterTransformer.kt @@ -56,6 +56,7 @@ import org.jetbrains.kotlin.resolve.calls.tower.CandidateApplicability import org.jetbrains.kotlin.resolve.calls.tower.isSuccess import org.jetbrains.kotlin.types.TypeApproximatorConfiguration import org.jetbrains.kotlin.types.Variance +import org.jetbrains.kotlin.types.isDefinitelyEmpty import org.jetbrains.kotlin.utils.addToStdlib.runIf import kotlin.collections.component1 import kotlin.collections.component2 @@ -852,7 +853,7 @@ class FirCallCompletionResultsWriterTransformer( } private fun FirNamedReferenceWithCandidate.hasAdditionalResolutionErrors(): Boolean = - candidate.system.errors.any { it is InferredEmptyIntersection } + candidate.system.errors.any { it is InferredEmptyIntersection && it.kind.isDefinitelyEmpty() } private fun FirNamedReferenceWithCandidate.toResolvedReference(): FirNamedReference { val errorDiagnostic = when { diff --git a/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/calls/ResolutionDiagnostic.kt b/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/calls/ResolutionDiagnostic.kt index a0d38d4bb87..47a3fef3ebf 100644 --- a/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/calls/ResolutionDiagnostic.kt +++ b/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/calls/ResolutionDiagnostic.kt @@ -31,6 +31,7 @@ class MixingNamedAndPositionArguments(override val argument: FirExpression) : In class InferredEmptyIntersectionDiagnostic( val incompatibleTypes: Collection, + val causingTypes: Collection, val typeVariable: ConeTypeVariable, val kind: EmptyIntersectionTypeKind ) : ResolutionDiagnostic(INAPPLICABLE) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java index 4d2704d8964..fc000e85849 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java @@ -899,10 +899,10 @@ public interface Errors { DiagnosticFactoryForDeprecation1 TYPE_INFERENCE_ONLY_INPUT_TYPES = DiagnosticFactoryForDeprecation1.create(LanguageFeature.StrictOnlyInputTypesChecks); - DiagnosticFactoryForDeprecation3, String> INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION = - DiagnosticFactoryForDeprecation3.create(LanguageFeature.ForbidInferringTypeVariablesIntoEmptyIntersection); - DiagnosticFactory2> INFERRED_TYPE_VARIABLE_INTO_POSSIBLE_EMPTY_INTERSECTION = - DiagnosticFactory2.create(WARNING); + DiagnosticFactoryForDeprecation4, String, String> INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION = + DiagnosticFactoryForDeprecation4.create(LanguageFeature.ForbidInferringTypeVariablesIntoEmptyIntersection); + DiagnosticFactory4, String, String> INFERRED_TYPE_VARIABLE_INTO_POSSIBLE_EMPTY_INTERSECTION = + DiagnosticFactory4.create(WARNING); DiagnosticFactory1 TYPE_INFERENCE_UPPER_BOUND_VIOLATED = DiagnosticFactory1.create(ERROR); DiagnosticFactory2 TYPE_INFERENCE_EXPECTED_TYPE_MISMATCH = DiagnosticFactory2.create(ERROR); DiagnosticFactory0 TYPE_INFERENCE_CANDIDATE_WITH_SAM_AND_VARARG = DiagnosticFactory0.create(WARNING); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java index ce938f8688a..20cfb2a9388 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java @@ -965,8 +965,8 @@ public class DefaultErrorMessages { MAP.put(TYPE_INFERENCE_INCORPORATION_ERROR, "Type inference failed. Please try to specify type arguments explicitly."); MAP.put(TYPE_INFERENCE_ONLY_INPUT_TYPES, "Type inference failed. The value of the type parameter {0} should be mentioned in input types " + "(argument types, receiver type or expected type). Try to specify it explicitly.", NAME); - MAP.put(INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION, "Type argument for a type parameter {0} can''t be inferred because it has incompatible upper bounds {2}: {1}", TO_STRING, RENDER_COLLECTION_OF_TYPES, TO_STRING); - MAP.put(INFERRED_TYPE_VARIABLE_INTO_POSSIBLE_EMPTY_INTERSECTION, "Type argument for a type parameter {0} has possible incompatible upper bounds: {1}", TO_STRING, RENDER_COLLECTION_OF_TYPES); + MAP.put(INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION, "Type argument for a type parameter {0} can''t be inferred because it has incompatible upper bounds: {1} ({2}{3})", TO_STRING, RENDER_COLLECTION_OF_TYPES, TO_STRING, TO_STRING); + MAP.put(INFERRED_TYPE_VARIABLE_INTO_POSSIBLE_EMPTY_INTERSECTION, "Type argument for a type parameter {0} has possible incompatible upper bounds: {1} ({2}{3})", TO_STRING, RENDER_COLLECTION_OF_TYPES, TO_STRING, TO_STRING); MAP.put(TYPE_INFERENCE_UPPER_BOUND_VIOLATED, "{0}", TYPE_INFERENCE_UPPER_BOUND_VIOLATED_RENDERER); MAP.put(TYPE_INFERENCE_EXPECTED_TYPE_MISMATCH, "Type inference failed. Expected type mismatch: inferred type is {1} but {0} was expected", RENDER_TYPE, RENDER_TYPE); MAP.put(TYPE_INFERENCE_CANDIDATE_WITH_SAM_AND_VARARG, "Please use spread operator to pass an array as vararg. It will be an error in 1.5."); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/DiagnosticReporterByTrackingStrategy.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/DiagnosticReporterByTrackingStrategy.kt index 7a04738f5a1..a875767ab4a 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/DiagnosticReporterByTrackingStrategy.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/DiagnosticReporterByTrackingStrategy.kt @@ -610,14 +610,19 @@ class DiagnosticReporterByTrackingStrategy( ?: typeVariable.toString() @Suppress("UNCHECKED_CAST") - val incompatibleTypes = error.incompatibleTypes as Collection + val incompatibleTypes = error.incompatibleTypes as List + @Suppress("UNCHECKED_CAST") + val causingTypes = error.causingTypes as List + val causingTypesText = if (incompatibleTypes == causingTypes) "" else ": ${causingTypes.joinToString()}" val diagnostic = if (error.kind.isPossiblyEmpty()) { - INFERRED_TYPE_VARIABLE_INTO_POSSIBLE_EMPTY_INTERSECTION.on(expression, typeVariableText, incompatibleTypes) + INFERRED_TYPE_VARIABLE_INTO_POSSIBLE_EMPTY_INTERSECTION.on( + expression, typeVariableText, incompatibleTypes, error.kind.description, causingTypesText + ) } else { INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION.on( context.languageVersionSettings, expression, typeVariableText, - incompatibleTypes, error.kind.description?.let { " ($it)" }.orEmpty() + incompatibleTypes, error.kind.description, causingTypesText ) } diff --git a/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/NewConstraintSystem.kt b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/NewConstraintSystem.kt index 9af06743a10..21b8a5a17af 100644 --- a/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/NewConstraintSystem.kt +++ b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/NewConstraintSystem.kt @@ -10,7 +10,7 @@ import org.jetbrains.kotlin.resolve.calls.inference.components.ConstraintSystemC import org.jetbrains.kotlin.resolve.calls.inference.model.Constraint import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintSystemError -import org.jetbrains.kotlin.types.EmptyIntersectionTypeKind +import org.jetbrains.kotlin.resolve.checkers.EmptyIntersectionTypeInfo import org.jetbrains.kotlin.types.model.KotlinTypeMarker import org.jetbrains.kotlin.types.model.TypeVariableMarker @@ -27,7 +27,7 @@ interface NewConstraintSystem { fun asPostponedArgumentsAnalyzerContext(): PostponedArgumentsAnalyzerContext fun processForkConstraints() - fun getEmptyIntersectionTypeKind(types: Collection): EmptyIntersectionTypeKind + fun getEmptyIntersectionTypeKind(types: Collection): EmptyIntersectionTypeInfo? } typealias ForkPointData = List diff --git a/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/model/ConstraintPositionAndErrors.kt b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/model/ConstraintPositionAndErrors.kt index d890d5a0ef3..7a8e61d2813 100644 --- a/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/model/ConstraintPositionAndErrors.kt +++ b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/model/ConstraintPositionAndErrors.kt @@ -137,19 +137,22 @@ class ConstrainingTypeIsError( class NoSuccessfulFork(val position: IncorporationConstraintPosition) : ConstraintSystemError(INAPPLICABLE) sealed interface InferredEmptyIntersection { - val incompatibleTypes: Collection + val incompatibleTypes: List + val causingTypes: List val typeVariable: TypeVariableMarker val kind: EmptyIntersectionTypeKind } class InferredEmptyIntersectionWarning( - override val incompatibleTypes: Collection, + override val incompatibleTypes: List, + override val causingTypes: List, override val typeVariable: TypeVariableMarker, override val kind: EmptyIntersectionTypeKind, ) : ConstraintSystemError(RESOLVED), InferredEmptyIntersection class InferredEmptyIntersectionError( - override val incompatibleTypes: Collection, + override val incompatibleTypes: List, + override val causingTypes: List, override val typeVariable: TypeVariableMarker, override val kind: EmptyIntersectionTypeKind, ) : ConstraintSystemError(INAPPLICABLE), InferredEmptyIntersection diff --git a/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/model/NewConstraintSystemImpl.kt b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/model/NewConstraintSystemImpl.kt index 7810ed98ede..13097eea20d 100644 --- a/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/model/NewConstraintSystemImpl.kt +++ b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/model/NewConstraintSystemImpl.kt @@ -10,6 +10,7 @@ import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.resolve.calls.components.PostponedArgumentsAnalyzerContext import org.jetbrains.kotlin.resolve.calls.inference.* import org.jetbrains.kotlin.resolve.calls.inference.components.* +import org.jetbrains.kotlin.resolve.checkers.EmptyIntersectionTypeInfo import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.model.* import org.jetbrains.kotlin.utils.SmartList @@ -38,7 +39,7 @@ class NewConstraintSystemImpl( private val typeVariablesTransaction: MutableList = SmartList() private val properTypesCache: MutableSet = SmartSet.create() private val notProperTypesCache: MutableSet = SmartSet.create() - private val intersectionTypesCache: MutableMap, EmptyIntersectionTypeKind> = mutableMapOf() + private val intersectionTypesCache: MutableMap, EmptyIntersectionTypeInfo?> = mutableMapOf() private var couldBeResolvedWithUnrestrictedBuilderInference: Boolean = false override var atCompletionState: Boolean = false @@ -441,7 +442,7 @@ class NewConstraintSystemImpl( doPostponedComputationsIfAllVariablesAreFixed() } - override fun getEmptyIntersectionTypeKind(types: Collection): EmptyIntersectionTypeKind { + override fun getEmptyIntersectionTypeKind(types: Collection): EmptyIntersectionTypeInfo? { if (types in intersectionTypesCache) return intersectionTypesCache.getValue(types) @@ -458,18 +459,20 @@ class NewConstraintSystemImpl( if (upperTypes.size <= 1 || storage.errors.any { it is InferredEmptyIntersection && it.incompatibleTypes == upperTypes }) return - val emptyIntersectionKind = getEmptyIntersectionTypeKind(upperTypes).takeIf { it.isEmpty() } ?: return + val emptyIntersectionTypeInfo = getEmptyIntersectionTypeKind(upperTypes) ?: return // Remove existing errors from the resolution stage because a completion stage error is always more precise storage.errors.removeIf { it is InferredEmptyIntersection } val isInferredEmptyIntersectionForbidden = languageVersionSettings.supportsFeature(LanguageFeature.ForbidInferringTypeVariablesIntoEmptyIntersection) - val errorFactory = if (emptyIntersectionKind.isDefinitelyEmpty() && isInferredEmptyIntersectionForbidden) + val errorFactory = if (emptyIntersectionTypeInfo.kind.isDefinitelyEmpty() && isInferredEmptyIntersectionForbidden) ::InferredEmptyIntersectionError else ::InferredEmptyIntersectionWarning - addError(errorFactory(upperTypes, variable, emptyIntersectionKind)) + addError( + errorFactory(upperTypes.toList(), emptyIntersectionTypeInfo.casingTypes.toList(), variable, emptyIntersectionTypeInfo.kind) + ) } private fun checkMissedConstraints() { diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ClassicTypeSystemContextForCS.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ClassicTypeSystemContextForCS.kt index 2bf30bb7f68..ec5c1cd8463 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ClassicTypeSystemContextForCS.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ClassicTypeSystemContextForCS.kt @@ -67,10 +67,11 @@ class ClassicTypeSystemContextForCS( } override fun TypeSubstitutorMarker.safeSubstitute(type: KotlinTypeMarker): KotlinTypeMarker { - require(type is UnwrappedType, type::errorMessage) + require(type is KotlinType, type::errorMessage) + val unwrappedType = type.unwrap() return when (this) { - is NewTypeSubstitutor -> safeSubstitute(type) - is TypeSubstitutor -> safeSubstitute(type, Variance.INVARIANT) + is NewTypeSubstitutor -> safeSubstitute(unwrappedType) + is TypeSubstitutor -> safeSubstitute(unwrappedType, Variance.INVARIANT) else -> error(this.errorMessage()) } } diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ResolutionParts.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ResolutionParts.kt index ba1fa2cff33..b0a2c6d639e 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ResolutionParts.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ResolutionParts.kt @@ -902,15 +902,21 @@ internal object CheckIncompatibleTypeVariableUpperBounds : ResolutionPart() { continue } else -> { - val emptyIntersectionKind = constraintSystem.getEmptyIntersectionTypeKind(upperTypes).takeIf { it.isDefinitelyEmpty() } - ?: continue + val emptyIntersectionTypeInfo = constraintSystem.getEmptyIntersectionTypeKind(upperTypes) ?: continue val isInferredEmptyIntersectionForbidden = callComponents.languageVersionSettings.supportsFeature( LanguageFeature.ForbidInferringTypeVariablesIntoEmptyIntersection ) val errorFactory = if (isInferredEmptyIntersectionForbidden) ::InferredEmptyIntersectionError else ::InferredEmptyIntersectionWarning - addError(errorFactory(upperTypes, variableWithConstraints.typeVariable, emptyIntersectionKind)) + addError( + errorFactory( + upperTypes, + emptyIntersectionTypeInfo.casingTypes.toList(), + variableWithConstraints.typeVariable, + emptyIntersectionTypeInfo.kind + ) + ) } } } diff --git a/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461.diag.txt b/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461.diag.txt index 1b990ee3fda..e2e1d59a0bd 100644 --- a/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461.diag.txt +++ b/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461.diag.txt @@ -1,6 +1,6 @@ /kt45461.kt:5:25: warning: parameter 'foo' is never used fun takeFoo(foo: Foo) {} ^ -/kt45461.kt:10:19: warning: type argument for a type parameter S can't be inferred because it has incompatible upper bounds (multiple incompatible classes): String, Int. This will become an error in Kotlin 1.9 +/kt45461.kt:10:19: warning: type argument for a type parameter S can't be inferred because it has incompatible upper bounds: String, Int (multiple incompatible classes). This will become an error in Kotlin 1.9 Bar().takeFoo(foo) // error in 1.3.72, no error in 1.4.31 ^ diff --git a/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_10.diag.txt b/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_10.diag.txt index 2c9847bdf2e..fcf5f0a0bb0 100644 --- a/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_10.diag.txt +++ b/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_10.diag.txt @@ -1,7 +1,7 @@ /kt45461_10.kt:7:25: warning: parameter 'foo' is never used fun takeFoo(foo: Foo) {} ^ -/kt45461_10.kt:16:21: warning: type argument for a type parameter S has possible incompatible upper bounds: Out, K +/kt45461_10.kt:16:21: warning: type argument for a type parameter S has possible incompatible upper bounds: Out, K (final class and interface: Int, A) Bar>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31 ^ diff --git a/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_12.diag.txt b/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_12.diag.txt index 569aa64f905..ed7c399c3aa 100644 --- a/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_12.diag.txt +++ b/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_12.diag.txt @@ -1,7 +1,7 @@ /kt45461_12.kt:5:25: warning: parameter 'foo' is never used fun takeFoo(foo: Foo) {} ^ -/kt45461_12.kt:12:19: warning: type argument for a type parameter S can't be inferred because it has incompatible upper bounds (multiple incompatible classes): String, K. This will become an error in Kotlin 1.9 +/kt45461_12.kt:12:19: warning: type argument for a type parameter S can't be inferred because it has incompatible upper bounds: String, K (multiple incompatible classes: String, Number). This will become an error in Kotlin 1.9 Bar().takeFoo(foo) // error in 1.3.72, no error in 1.4.31 ^ diff --git a/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_13.diag.txt b/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_13.diag.txt index cc9a358d925..5fadb0bc7dd 100644 --- a/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_13.diag.txt +++ b/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_13.diag.txt @@ -1,7 +1,7 @@ /kt45461_13.kt:7:25: warning: parameter 'foo' is never used fun takeFoo(foo: Foo) {} ^ -/kt45461_13.kt:16:24: warning: type argument for a type parameter S has possible incompatible upper bounds: Out, K +/kt45461_13.kt:16:24: warning: type argument for a type parameter S has possible incompatible upper bounds: Out, K (final class and interface: String, A) Bar>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31 ^ diff --git a/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_15.diag.txt b/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_15.diag.txt index 66c25773319..6d17cb635bc 100644 --- a/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_15.diag.txt +++ b/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_15.diag.txt @@ -1,6 +1,6 @@ /kt45461_15.kt:5:25: warning: parameter 'foo' is never used fun takeFoo(foo: Foo) {} ^ -/kt45461_15.kt:14:21: warning: type argument for a type parameter S can't be inferred because it has incompatible upper bounds (incompatible type arguments): Inv, K. This will become an error in Kotlin 1.9 +/kt45461_15.kt:14:21: warning: type argument for a type parameter S can't be inferred because it has incompatible upper bounds: Inv, K (incompatible type arguments: Int, {A & Number}). This will become an error in Kotlin 1.9 Bar>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31 ^ diff --git a/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_19.diag.txt b/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_19.diag.txt index 2956863849c..c668c3981d0 100644 --- a/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_19.diag.txt +++ b/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_19.diag.txt @@ -1,6 +1,6 @@ /kt45461_19.kt:5:25: warning: parameter 'foo' is never used fun takeFoo(foo: Foo) {} ^ -/kt45461_19.kt:13:26: warning: type argument for a type parameter S can't be inferred because it has incompatible upper bounds (incompatible type arguments): Out>, K. This will become an error in Kotlin 1.9 +/kt45461_19.kt:13:26: warning: type argument for a type parameter S can't be inferred because it has incompatible upper bounds: Out>, K (incompatible type arguments: Int, Number). This will become an error in Kotlin 1.9 Bar>>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31 ^ diff --git a/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_2.diag.txt b/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_2.diag.txt index 7ee69dc9f53..3b066de193e 100644 --- a/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_2.diag.txt +++ b/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_2.diag.txt @@ -4,7 +4,7 @@ /kt45461_2.kt:8:10: warning: 'Int' is a final type, and thus a value of the type parameter is predetermined fun main() { ^ -/kt45461_2.kt:10:19: warning: type argument for a type parameter S can't be inferred because it has incompatible upper bounds (multiple incompatible classes): String, K. This will become an error in Kotlin 1.9 +/kt45461_2.kt:10:19: warning: type argument for a type parameter S can't be inferred because it has incompatible upper bounds: String, K (multiple incompatible classes: String, Int). This will become an error in Kotlin 1.9 Bar().takeFoo(foo) // error in 1.3.72, no error in 1.4.31 ^ diff --git a/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_21.diag.txt b/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_21.diag.txt index 9e2e1202fb2..46c72d19b8b 100644 --- a/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_21.diag.txt +++ b/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_21.diag.txt @@ -1,6 +1,6 @@ /kt45461_21.kt:5:25: warning: parameter 'foo' is never used fun takeFoo(foo: Foo) {} ^ -/kt45461_21.kt:13:25: warning: type argument for a type parameter S can't be inferred because it has incompatible upper bounds (incompatible type arguments): In>, K. This will become an error in Kotlin 1.9 +/kt45461_21.kt:13:25: warning: type argument for a type parameter S can't be inferred because it has incompatible upper bounds: In>, K (incompatible type arguments: Int, Number). This will become an error in Kotlin 1.9 Bar>>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31 ^ diff --git a/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_24.diag.txt b/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_24.diag.txt index 97b33b76bf8..61cf7586f58 100644 --- a/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_24.diag.txt +++ b/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_24.diag.txt @@ -4,6 +4,6 @@ /kt45461_24.kt:10:10: warning: 'Inv>' is a final type, and thus a value of the type parameter is predetermined fun >> main() { ^ -/kt45461_24.kt:12:35: warning: type argument for a type parameter S can't be inferred because it has incompatible upper bounds (incompatible type arguments): Inv>, K. This will become an error in Kotlin 1.9 +/kt45461_24.kt:12:35: warning: type argument for a type parameter S can't be inferred because it has incompatible upper bounds: Inv>, K (incompatible type arguments: Number, Int). This will become an error in Kotlin 1.9 Bar>>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31 ^ diff --git a/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_25.diag.txt b/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_25.diag.txt index ee162d75610..ce17a845c9c 100644 --- a/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_25.diag.txt +++ b/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_25.diag.txt @@ -1,3 +1,3 @@ -/kt45461_25.kt:11:34: error: type argument for a type parameter S can't be inferred because it has incompatible upper bounds (multiple incompatible classes): String, K, Float +/kt45461_25.kt:11:34: error: type argument for a type parameter S can't be inferred because it has incompatible upper bounds: String, K, Float (multiple incompatible classes: String, Int) val x: Float = Bar().takeFoo(foo) // error in 1.3.72, no error in 1.4.31 ^ diff --git a/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_25.fir.kt b/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_25.fir.kt index 017a1cfe576..ec10f168ad0 100644 --- a/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_25.fir.kt +++ b/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_25.fir.kt @@ -8,5 +8,5 @@ class Bar { fun Int> main() { val foo = Foo() - val x: Float = Bar().takeFoo(foo) // error in 1.3.72, no error in 1.4.31 + val x: Float = Bar().takeFoo(foo) // error in 1.3.72, no error in 1.4.31 } diff --git a/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_25.kt b/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_25.kt index 515bb9a4209..c41a044445b 100644 --- a/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_25.kt +++ b/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_25.kt @@ -8,5 +8,5 @@ class Bar { fun Int> main() { val foo = Foo() - val x: Float = Bar().takeFoo(foo) // error in 1.3.72, no error in 1.4.31 + val x: Float = Bar().takeFoo(foo) // error in 1.3.72, no error in 1.4.31 } diff --git a/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_26.diag.txt b/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_26.diag.txt index 6c3395a5721..e524b415033 100644 --- a/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_26.diag.txt +++ b/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_26.diag.txt @@ -1,4 +1,4 @@ -/kt45461_26.kt:13:44: error: type argument for a type parameter S can't be inferred because it has incompatible upper bounds (multiple incompatible classes): Out, K, Out +/kt45461_26.kt:13:44: error: type argument for a type parameter S can't be inferred because it has incompatible upper bounds: Out, K, Out (multiple incompatible classes: String, Int) val x: Out = Bar>().takeFoo(foo) ^ diff --git a/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_26.fir.kt b/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_26.fir.kt index 27f18809bf2..ddbdb55da4e 100644 --- a/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_26.fir.kt +++ b/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_26.fir.kt @@ -10,5 +10,5 @@ class Out fun Out> main() { val foo = Foo() - val x: Out = Bar>()., K; multiple incompatible classes")!>takeFoo(foo) + val x: Out = Bar>()., K; multiple incompatible classes; : kotlin/String, kotlin/Int")!>takeFoo(foo) } diff --git a/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_26.kt b/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_26.kt index f7d0a58ee92..2f887847a81 100644 --- a/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_26.kt +++ b/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_26.kt @@ -10,5 +10,5 @@ class Out fun Out> main() { val foo = Foo() - val x: Out = Bar>()., K, Out; (multiple incompatible classes)")!>takeFoo(foo) + val x: Out = Bar>()., K, Out; multiple incompatible classes; : String, Int")!>takeFoo(foo) } diff --git a/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_31.kt b/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_31.kt index 090e9e009e1..6052625fe1a 100644 --- a/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_31.kt +++ b/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_31.kt @@ -11,5 +11,5 @@ interface B : A fun >> main() { val foo = Foo() - Bar>()., K; (incompatible supertypes)")!>takeFoo(foo) // error in 1.3.72, no error in 1.4.31 + Bar>()., K; incompatible supertypes; : A, A")!>takeFoo(foo) // error in 1.3.72, no error in 1.4.31 } diff --git a/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_34.kt b/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_34.kt index 4754e4b11f6..d4a1f9c7dcf 100644 --- a/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_34.kt +++ b/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_34.kt @@ -11,5 +11,5 @@ class B : A fun >> main() { val foo = Foo() - Bar>()., K; (incompatible supertypes)")!>takeFoo(foo) // error in 1.3.72, no error in 1.4.31 + Bar>()., K; incompatible supertypes; : A, A")!>takeFoo(foo) // error in 1.3.72, no error in 1.4.31 } diff --git a/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_5.diag.txt b/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_5.diag.txt index cfdd003dfcf..10e291d7b89 100644 --- a/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_5.diag.txt +++ b/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_5.diag.txt @@ -1,6 +1,6 @@ /kt45461_5.kt:5:25: warning: parameter 'foo' is never used fun takeFoo(foo: Foo) {} ^ -/kt45461_5.kt:10:19: warning: type argument for a type parameter S can't be inferred because it has incompatible upper bounds (multiple incompatible classes): String, K. This will become an error in Kotlin 1.9 +/kt45461_5.kt:10:19: warning: type argument for a type parameter S can't be inferred because it has incompatible upper bounds: String, K (multiple incompatible classes: String, Number). This will become an error in Kotlin 1.9 Bar().takeFoo(foo) // error in 1.3.72, no error in 1.4.31 ^ diff --git a/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_8.diag.txt b/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_8.diag.txt index 60ec5d6efbb..106f9f552b7 100644 --- a/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_8.diag.txt +++ b/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_8.diag.txt @@ -4,6 +4,6 @@ /kt45461_8.kt:10:28: warning: 'Int' is a final type, and thus a value of the type parameter is predetermined fun , L : N, N: Int> main() { ^ -/kt45461_8.kt:12:24: warning: type argument for a type parameter S can't be inferred because it has incompatible upper bounds (incompatible type arguments): Inv, K. This will become an error in Kotlin 1.9 +/kt45461_8.kt:12:24: warning: type argument for a type parameter S can't be inferred because it has incompatible upper bounds: Inv, K (incompatible type arguments: Number, Int). This will become an error in Kotlin 1.9 Bar>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31 ^ diff --git a/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_9.diag.txt b/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_9.diag.txt index fbc76d0fc73..e0660259e84 100644 --- a/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_9.diag.txt +++ b/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt45461_9.diag.txt @@ -1,7 +1,7 @@ /kt45461_9.kt:5:25: warning: parameter 'foo' is never used fun takeFoo(foo: Foo) {} ^ -/kt45461_9.kt:12:21: warning: type argument for a type parameter S can't be inferred because it has incompatible upper bounds (incompatible type arguments): Inv, Inv. This will become an error in Kotlin 1.9 +/kt45461_9.kt:12:21: warning: type argument for a type parameter S can't be inferred because it has incompatible upper bounds: Inv, Inv (incompatible type arguments: Int, Number). This will become an error in Kotlin 1.9 Bar>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31 ^ diff --git a/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt48765.diag.txt b/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt48765.diag.txt index 98adcd66db6..7b5f0cdd21b 100644 --- a/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt48765.diag.txt +++ b/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt48765.diag.txt @@ -4,7 +4,7 @@ /kt48765.kt:4:52: warning: parameter 'x2' is never used fun > foo(x1: T2, x2: T1) {} ^ -/kt48765.kt:8:13: warning: type argument for a type parameter T can't be inferred because it has incompatible upper bounds (multiple incompatible classes): String, Number. This will become an error in Kotlin 1.9 +/kt48765.kt:8:13: warning: type argument for a type parameter T can't be inferred because it has incompatible upper bounds: String, Number (multiple incompatible classes). This will become an error in Kotlin 1.9 B().foo(x, foo()) ^ /kt48765.kt:12:9: warning: 'String' is a final type, and thus a value of the type parameter is predetermined diff --git a/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt48935.diag.txt b/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt48935.diag.txt index 53515f07872..cd9d8450834 100644 --- a/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt48935.diag.txt +++ b/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt48935.diag.txt @@ -1,7 +1,7 @@ /kt48935.kt:7:35: warning: parameter 'func' is never used fun exampleGenericFunction(func: V) where T: Base, V: (T) -> Unit { ^ -/kt48935.kt:13:5: warning: type argument for a type parameter T has possible incompatible upper bounds: Base, DoesNotImplementBase +/kt48935.kt:13:5: warning: type argument for a type parameter T has possible incompatible upper bounds: Base, DoesNotImplementBase (final class and interface) exampleGenericFunction(func) // expected this to be a compilation error as the T: Base constraint should not be satisfied ^ diff --git a/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt49661.diag.txt b/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt49661.diag.txt index 293d53104fd..33f2b83623e 100644 --- a/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt49661.diag.txt +++ b/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/kt49661.diag.txt @@ -1,4 +1,4 @@ -/kt49661.kt:10:5: warning: type argument for a type parameter T can't be inferred because it has incompatible upper bounds (multiple incompatible classes): Foo, Int. This will become an error in Kotlin 1.9 +/kt49661.kt:10:5: warning: type argument for a type parameter T can't be inferred because it has incompatible upper bounds: Foo, Int (multiple incompatible classes). This will become an error in Kotlin 1.9 f { g() } ^ diff --git a/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/selectFromCovariantAndContravariantTypes.diag.txt b/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/selectFromCovariantAndContravariantTypes.diag.txt index 78919205927..e56b3ad6895 100644 --- a/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/selectFromCovariantAndContravariantTypes.diag.txt +++ b/compiler/testData/diagnostics/tests/inference/emptyIntersectionTypes/selectFromCovariantAndContravariantTypes.diag.txt @@ -7,6 +7,6 @@ fun genericIn(x: In) {} /selectFromCovariantAndContravariantTypes.kt:13:20: warning: parameter 'x' is never used fun genericOut(x: Out) {} ^ -/selectFromCovariantAndContravariantTypes.kt:16:5: warning: type argument for a type parameter V can't be inferred because it has incompatible upper bounds (multiple incompatible classes): A, B. This will become an error in Kotlin 1.9 +/selectFromCovariantAndContravariantTypes.kt:16:5: warning: type argument for a type parameter V can't be inferred because it has incompatible upper bounds: A, B (multiple incompatible classes). This will become an error in Kotlin 1.9 genericIn(select(a, b)) ^ diff --git a/compiler/testData/diagnostics/tests/inference/selectOfLambdaWithExtensionDisabled.kt b/compiler/testData/diagnostics/tests/inference/selectOfLambdaWithExtensionDisabled.kt index b8244de011b..aec82036eed 100644 --- a/compiler/testData/diagnostics/tests/inference/selectOfLambdaWithExtensionDisabled.kt +++ b/compiler/testData/diagnostics/tests/inference/selectOfLambdaWithExtensionDisabled.kt @@ -14,7 +14,7 @@ val a1: A = select( { a: Int -> myPrint(a + this.length + 2) } ) -val a2 = select( +val a2 = select( { a: Int -> myPrint(a + this.length + 1) }, fun CharSequence.(a: Int) { myPrint(a + this.length + 2) }, { a: Int -> myPrint(a + this.length + 3) } diff --git a/compiler/testData/diagnostics/tests/resolve/specialConstructions/elvisAsCall.fir.kt b/compiler/testData/diagnostics/tests/resolve/specialConstructions/elvisAsCall.fir.kt index 861dc646a0a..150646a4e85 100644 --- a/compiler/testData/diagnostics/tests/resolve/specialConstructions/elvisAsCall.fir.kt +++ b/compiler/testData/diagnostics/tests/resolve/specialConstructions/elvisAsCall.fir.kt @@ -13,7 +13,7 @@ fun testElvis(a: Int?, b: Int?) { if (a != null) { doInt(b ?: a) } - doList(getList() ?: emptyListOfA()) //should be an error + doList(getList() ?: emptyListOfA()) //should be an error doList(getList() ?: strangeList { doInt(it) }) //lambda was not analyzed } diff --git a/compiler/testData/diagnostics/tests/resolve/specialConstructions/elvisAsCall.kt b/compiler/testData/diagnostics/tests/resolve/specialConstructions/elvisAsCall.kt index 214fd36720f..023a3675ee7 100644 --- a/compiler/testData/diagnostics/tests/resolve/specialConstructions/elvisAsCall.kt +++ b/compiler/testData/diagnostics/tests/resolve/specialConstructions/elvisAsCall.kt @@ -13,7 +13,7 @@ fun testElvis(a: Int?, b: Int?) { if (a != null) { doInt(b ?: a) } - doList(getList() ?: emptyListOfA()) //should be an error + doList(getList() ?: emptyListOfA()) //should be an error doList(getList() ?: strangeList { doInt(it) }) //lambda was not analyzed } diff --git a/compiler/testData/diagnostics/tests/resolve/specialConstructions/exclExclAsCall.fir.kt b/compiler/testData/diagnostics/tests/resolve/specialConstructions/exclExclAsCall.fir.kt index 14b8e5b0926..5e327ec4a2b 100644 --- a/compiler/testData/diagnostics/tests/resolve/specialConstructions/exclExclAsCall.fir.kt +++ b/compiler/testData/diagnostics/tests/resolve/specialConstructions/exclExclAsCall.fir.kt @@ -12,7 +12,7 @@ fun emptyNullableListOfA(): List? = null //------------------------------- fun testExclExcl() { - doList(emptyNullableListOfA()!!) //should be an error here + doList(emptyNullableListOfA()!!) //should be an error here val l: List = id(emptyNullableListOfA()!!) doList(strangeNullableList { doInt(it) }!!) //lambda should be analyzed (at completion phase) diff --git a/compiler/testData/diagnostics/tests/resolve/specialConstructions/exclExclAsCall.kt b/compiler/testData/diagnostics/tests/resolve/specialConstructions/exclExclAsCall.kt index 7f91e8af42a..f1fbb0fe387 100644 --- a/compiler/testData/diagnostics/tests/resolve/specialConstructions/exclExclAsCall.kt +++ b/compiler/testData/diagnostics/tests/resolve/specialConstructions/exclExclAsCall.kt @@ -12,7 +12,7 @@ fun emptyNullableListOfA(): List? = null //------------------------------- fun testExclExcl() { - doList(emptyNullableListOfA()!!) //should be an error here + doList(emptyNullableListOfA()!!) //should be an error here val l: List = id(emptyNullableListOfA()!!) doList(strangeNullableList { doInt(it) }!!) //lambda should be analyzed (at completion phase) diff --git a/core/compiler.common/src/org/jetbrains/kotlin/resolve/checkers/EmptyIntersectionTypeChecker.kt b/core/compiler.common/src/org/jetbrains/kotlin/resolve/checkers/EmptyIntersectionTypeChecker.kt index 0aee2d10bb5..326fd9bcdd4 100644 --- a/core/compiler.common/src/org/jetbrains/kotlin/resolve/checkers/EmptyIntersectionTypeChecker.kt +++ b/core/compiler.common/src/org/jetbrains/kotlin/resolve/checkers/EmptyIntersectionTypeChecker.kt @@ -12,16 +12,15 @@ import org.jetbrains.kotlin.types.isPossiblyEmpty import org.jetbrains.kotlin.types.model.* internal object EmptyIntersectionTypeChecker { - fun computeEmptyIntersectionTypeKind( + fun computeEmptyIntersectionEmptiness( context: TypeSystemInferenceExtensionContext, types: Collection - ): EmptyIntersectionTypeKind = with(context) { - if (types.isEmpty()) - return EmptyIntersectionTypeKind.NOT_EMPTY_INTERSECTION + ): EmptyIntersectionTypeInfo? = with(context) { + if (types.isEmpty()) return null @Suppress("NAME_SHADOWING") val types = types.toList() - var possibleEmptyIntersectionKind: EmptyIntersectionTypeKind? = null + var possibleEmptyIntersectionTypeInfo: EmptyIntersectionTypeInfo? = null for (i in 0 until types.size) { val firstType = types[i] @@ -39,22 +38,22 @@ internal object EmptyIntersectionTypeChecker { if (!mayCauseEmptyIntersection(secondSubstitutedType) && !mayCauseEmptyIntersection(firstSubstitutedType)) continue - val kind = computeKindByHavingCommonSubtype(firstSubstitutedType, secondSubstitutedType) + val typeInfo = computeByHavingCommonSubtype(firstSubstitutedType, secondSubstitutedType) ?: continue - if (kind.isDefinitelyEmpty()) - return kind + if (typeInfo.kind.isDefinitelyEmpty()) + return typeInfo - if (kind.isPossiblyEmpty()) - possibleEmptyIntersectionKind = kind + if (typeInfo.kind.isPossiblyEmpty()) + possibleEmptyIntersectionTypeInfo = typeInfo } } - return possibleEmptyIntersectionKind ?: EmptyIntersectionTypeKind.NOT_EMPTY_INTERSECTION + return possibleEmptyIntersectionTypeInfo } - private fun TypeSystemInferenceExtensionContext.computeKindByHavingCommonSubtype( + private fun TypeSystemInferenceExtensionContext.computeByHavingCommonSubtype( first: KotlinTypeMarker, second: KotlinTypeMarker - ): EmptyIntersectionTypeKind { + ): EmptyIntersectionTypeInfo? { fun extractIntersectionComponentsIfNeeded(type: KotlinTypeMarker) = if (type.typeConstructor() is IntersectionTypeConstructorMarker) { type.typeConstructor().supertypes().toList() @@ -62,7 +61,7 @@ internal object EmptyIntersectionTypeChecker { val expandedTypes = extractIntersectionComponentsIfNeeded(first) + extractIntersectionComponentsIfNeeded(second) val typeCheckerState by lazy { newTypeCheckerState(errorTypesEqualToAnything = true, stubTypesEqualToAnything = true) } - var possibleEmptyIntersectionKind: EmptyIntersectionTypeKind? = null + var possibleEmptyIntersectionKind: EmptyIntersectionTypeInfo? = null for (i in expandedTypes.indices) { val firstType = expandedTypes[i].withNullability(false) @@ -89,7 +88,7 @@ internal object EmptyIntersectionTypeChecker { firstTypeConstructor.isDefinitelyClassTypeConstructor() && secondTypeConstructor.isDefinitelyClassTypeConstructor() && (firstTypeConstructor.parametersCount() == 0 || secondTypeConstructor.parametersCount() == 0) ) { - return EmptyIntersectionTypeKind.MULTIPLE_CLASSES + return EmptyIntersectionTypeInfo(EmptyIntersectionTypeKind.MULTIPLE_CLASSES, firstType, secondType) } val superTypeByFirstConstructor = AbstractTypeChecker.findCorrespondingSupertypes( @@ -103,37 +102,42 @@ internal object EmptyIntersectionTypeChecker { // Two classes can't have a common subtype if neither is a subtype of another if (superTypeByFirstConstructor == null && superTypeBySecondConstructor == null && !anyInference) - return EmptyIntersectionTypeKind.MULTIPLE_CLASSES + return EmptyIntersectionTypeInfo(EmptyIntersectionTypeKind.MULTIPLE_CLASSES, firstType, secondType) - if (anyInference && !canHaveCommonSubtypeWithInterface(firstType, secondType)) - return EmptyIntersectionTypeKind.INCOMPATIBLE_SUPERTYPES + if (anyInference) { + val incompatibleSupertypes = getIncompatibleSuperTypes(firstType, secondType) + if (incompatibleSupertypes != null) { + return EmptyIntersectionTypeInfo(EmptyIntersectionTypeKind.INCOMPATIBLE_SUPERTYPES, *incompatibleSupertypes) + } + } if (superTypeByFirstConstructor == null || superTypeBySecondConstructor == null) { // don't have incompatible supertypes so can have a common subtype only if all types are interfaces if (firstTypeConstructor.isFinalClassConstructor() || secondTypeConstructor.isFinalClassConstructor()) { - possibleEmptyIntersectionKind = EmptyIntersectionTypeKind.SINGLE_FINAL_CLASS + possibleEmptyIntersectionKind = + EmptyIntersectionTypeInfo(EmptyIntersectionTypeKind.SINGLE_FINAL_CLASS, firstType, secondType) } continue } val argumentsIntersectionKind = - computeKindByCheckingTypeArguments(superTypeByFirstConstructor, superTypeBySecondConstructor) + computeByCheckingTypeArguments(superTypeByFirstConstructor, superTypeBySecondConstructor) ?: continue - if (argumentsIntersectionKind.isDefinitelyEmpty()) + if (argumentsIntersectionKind.kind.isDefinitelyEmpty()) return argumentsIntersectionKind - if (possibleEmptyIntersectionKind == null && argumentsIntersectionKind.isPossiblyEmpty()) + if (possibleEmptyIntersectionKind == null && argumentsIntersectionKind.kind.isPossiblyEmpty()) possibleEmptyIntersectionKind = argumentsIntersectionKind } } - return possibleEmptyIntersectionKind ?: EmptyIntersectionTypeKind.NOT_EMPTY_INTERSECTION + return possibleEmptyIntersectionKind } - private fun TypeSystemInferenceExtensionContext.computeKindByCheckingTypeArguments( + private fun TypeSystemInferenceExtensionContext.computeByCheckingTypeArguments( firstType: KotlinTypeMarker, secondType: KotlinTypeMarker, - ): EmptyIntersectionTypeKind { + ): EmptyIntersectionTypeInfo? { require(firstType.typeConstructor() == secondType.typeConstructor()) { "Type constructors of the passed types should be the same to compare their arguments" } @@ -144,10 +148,10 @@ internal object EmptyIntersectionTypeChecker { fun areEqualTypes(firstType: KotlinTypeMarker, secondType: KotlinTypeMarker) = AbstractTypeChecker.equalTypes(this, firstType, secondType) - fun Boolean.toEmptyIntersectionKind() = - if (this) EmptyIntersectionTypeKind.NOT_EMPTY_INTERSECTION else EmptyIntersectionTypeKind.INCOMPATIBLE_TYPE_ARGUMENTS + fun Boolean.toEmptyIntersectionKind(vararg types: KotlinTypeMarker) = + if (this) null else EmptyIntersectionTypeInfo(EmptyIntersectionTypeKind.INCOMPATIBLE_TYPE_ARGUMENTS, *types) - var possibleEmptyIntersectionKind: EmptyIntersectionTypeKind? = null + var possibleEmptyIntersectionTypeInfo: EmptyIntersectionTypeInfo? = null for ((i, argumentOfFirst) in firstType.getArguments().withIndex()) { @Suppress("NAME_SHADOWING") @@ -161,43 +165,42 @@ internal object EmptyIntersectionTypeChecker { val argumentTypeOfSecond = argumentOfSecond.getType() val intersectionKindOfArguments = when { areArgumentsOfSpecifiedVariances(firstType, secondType, i, TypeVariance.INV, TypeVariance.INV) -> - areEqualTypes(argumentTypeOfFirst, argumentTypeOfSecond).toEmptyIntersectionKind() - areArgumentsOfSpecifiedVariances(firstType, secondType, i, TypeVariance.INV, TypeVariance.OUT) -> { - isSubtypeOf(argumentTypeOfFirst, argumentTypeOfSecond).toEmptyIntersectionKind() - } - areArgumentsOfSpecifiedVariances(firstType, secondType, i, TypeVariance.INV, TypeVariance.IN) -> { - isSubtypeOf(argumentTypeOfSecond, argumentTypeOfFirst).toEmptyIntersectionKind() - } + areEqualTypes(argumentTypeOfFirst, argumentTypeOfSecond) + .toEmptyIntersectionKind(argumentTypeOfFirst, argumentTypeOfSecond) + areArgumentsOfSpecifiedVariances(firstType, secondType, i, TypeVariance.INV, TypeVariance.OUT) -> + isSubtypeOf(argumentTypeOfFirst, argumentTypeOfSecond) + .toEmptyIntersectionKind(argumentTypeOfFirst, argumentTypeOfSecond) + areArgumentsOfSpecifiedVariances(firstType, secondType, i, TypeVariance.INV, TypeVariance.IN) -> + isSubtypeOf(argumentTypeOfSecond, argumentTypeOfFirst) + .toEmptyIntersectionKind(argumentTypeOfFirst, argumentTypeOfSecond) areArgumentsOfSpecifiedVariances(firstType, secondType, i, TypeVariance.IN, TypeVariance.OUT) -> { if (argumentTypeOfFirst.argumentsCount() == 0 && argumentTypeOfSecond.argumentsCount() == 0) { - isSubtypeOf(argumentTypeOfFirst, argumentTypeOfSecond).toEmptyIntersectionKind() + isSubtypeOf(argumentTypeOfFirst, argumentTypeOfSecond) + .toEmptyIntersectionKind(argumentTypeOfFirst, argumentTypeOfSecond) } else { - computeKindByHavingCommonSubtype(argumentTypeOfFirst, argumentTypeOfSecond) + computeByHavingCommonSubtype(argumentTypeOfFirst, argumentTypeOfSecond) } } areArgumentsOfSpecifiedVariances(firstType, secondType, i, TypeVariance.OUT, TypeVariance.OUT) || areArgumentsOfSpecifiedVariances(firstType, secondType, i, TypeVariance.IN, TypeVariance.IN) -> { - computeKindByHavingCommonSubtype(argumentTypeOfFirst, argumentTypeOfSecond) + computeByHavingCommonSubtype(argumentTypeOfFirst, argumentTypeOfSecond) } - else -> true.toEmptyIntersectionKind() - } + else -> true.toEmptyIntersectionKind(argumentTypeOfFirst, argumentTypeOfSecond) + } ?: continue - if (intersectionKindOfArguments.isDefinitelyEmpty()) + if (intersectionKindOfArguments.kind.isDefinitelyEmpty()) return intersectionKindOfArguments - if (possibleEmptyIntersectionKind == null && intersectionKindOfArguments.isPossiblyEmpty()) - possibleEmptyIntersectionKind = intersectionKindOfArguments + if (possibleEmptyIntersectionTypeInfo == null && intersectionKindOfArguments.kind.isPossiblyEmpty()) + possibleEmptyIntersectionTypeInfo = intersectionKindOfArguments } - return possibleEmptyIntersectionKind ?: EmptyIntersectionTypeKind.NOT_EMPTY_INTERSECTION + return possibleEmptyIntersectionTypeInfo } - private fun TypeSystemInferenceExtensionContext.canHaveCommonSubtypeWithInterface( + private fun TypeSystemInferenceExtensionContext.getIncompatibleSuperTypes( firstType: KotlinTypeMarker, secondType: KotlinTypeMarker - ): Boolean { - require(firstType.typeConstructor().isInterface() || secondType.typeConstructor().isInterface()) { - "One of the passed type should be an interface" - } + ): Array? { @Suppress("NAME_SHADOWING") val firstType = firstType.eraseContainingTypeParameters() @@ -207,26 +210,7 @@ internal object EmptyIntersectionTypeChecker { // interface A // interface B: A // interface C: A - // B & C can't have common subtype due to having incompatible supertypes: A and A - return !hasIncompatibleSuperTypes(firstType, secondType) - } - - private fun TypeSystemInferenceExtensionContext.areIncompatibleSuperTypes( - firstType: KotlinTypeMarker, secondType: KotlinTypeMarker - ): Boolean = firstType.typeConstructor() == secondType.typeConstructor() - && !AbstractTypeChecker.equalTypes( - newTypeCheckerState(errorTypesEqualToAnything = true, stubTypesEqualToAnything = true), - firstType, - secondType - ) - - // interface A - // interface B : A - // interface C : A - // => B and C have incompatible supertypes - private fun TypeSystemInferenceExtensionContext.hasIncompatibleSuperTypes( - firstType: KotlinTypeMarker, secondType: KotlinTypeMarker - ): Boolean { + // => B and C have incompatible supertypes val superTypesOfFirst = firstType.typeConstructor().supertypes() val firstTypeSubstitutor = createSubstitutorForSuperTypes(firstType) val superTypesOfSecond = secondType.typeConstructor().supertypes() @@ -237,25 +221,33 @@ internal object EmptyIntersectionTypeChecker { val superTypeOfFirst = firstTypeSubstitutor?.safeSubstitute(superTypeOfFirst) ?: superTypeOfFirst if (areIncompatibleSuperTypes(superTypeOfFirst, secondType)) - return true + return arrayOf(superTypeOfFirst, secondType) for (superTypeOfSecond in superTypesOfSecond) { @Suppress("NAME_SHADOWING") val superTypeOfSecond = secondTypeSubstitutor?.safeSubstitute(superTypeOfSecond) ?: superTypeOfSecond - if ( - areIncompatibleSuperTypes(firstType, superTypeOfSecond) - || areIncompatibleSuperTypes(superTypeOfFirst, superTypeOfSecond) - ) return true + if (areIncompatibleSuperTypes(firstType, superTypeOfSecond)) + return arrayOf(firstType, superTypeOfSecond) - if (hasIncompatibleSuperTypes(superTypeOfFirst, superTypeOfSecond)) - return true + if (areIncompatibleSuperTypes(superTypeOfFirst, superTypeOfSecond)) + return arrayOf(superTypeOfFirst, superTypeOfSecond) + + getIncompatibleSuperTypes(superTypeOfFirst, superTypeOfSecond)?.let { return it } } } - return false + return null } + private fun TypeSystemInferenceExtensionContext.areIncompatibleSuperTypes( + firstType: KotlinTypeMarker, secondType: KotlinTypeMarker + ): Boolean = firstType.typeConstructor() == secondType.typeConstructor() + && !AbstractTypeChecker.equalTypes( + newTypeCheckerState(errorTypesEqualToAnything = true, stubTypesEqualToAnything = true), + firstType, secondType + ) + private fun TypeSystemInferenceExtensionContext.mayCauseEmptyIntersection(type: KotlinTypeMarker): Boolean { val typeConstructor = type.typeConstructor() @@ -294,4 +286,6 @@ internal object EmptyIntersectionTypeChecker { val type = argument.getType() return if (type is CapturedTypeMarker) type.typeConstructorProjection() else argument } -} \ No newline at end of file +} + +class EmptyIntersectionTypeInfo(val kind: EmptyIntersectionTypeKind, vararg val casingTypes: KotlinTypeMarker) \ No newline at end of file diff --git a/core/compiler.common/src/org/jetbrains/kotlin/types/EmptyIntersectionTypeKind.kt b/core/compiler.common/src/org/jetbrains/kotlin/types/EmptyIntersectionTypeKind.kt index d285fe5373b..6671e650a94 100644 --- a/core/compiler.common/src/org/jetbrains/kotlin/types/EmptyIntersectionTypeKind.kt +++ b/core/compiler.common/src/org/jetbrains/kotlin/types/EmptyIntersectionTypeKind.kt @@ -5,13 +5,11 @@ package org.jetbrains.kotlin.types -// TODO: add `SINGLE_FINAL_CLASS` later to report warnings -enum class EmptyIntersectionTypeKind(val description: String? = null) { - NOT_EMPTY_INTERSECTION, +enum class EmptyIntersectionTypeKind(val description: String) { MULTIPLE_CLASSES("multiple incompatible classes"), INCOMPATIBLE_SUPERTYPES("incompatible supertypes"), INCOMPATIBLE_TYPE_ARGUMENTS("incompatible type arguments"), - SINGLE_FINAL_CLASS + SINGLE_FINAL_CLASS("final class and interface") } fun EmptyIntersectionTypeKind.isDefinitelyEmpty(): Boolean = @@ -20,5 +18,3 @@ fun EmptyIntersectionTypeKind.isDefinitelyEmpty(): Boolean = || this == EmptyIntersectionTypeKind.INCOMPATIBLE_TYPE_ARGUMENTS fun EmptyIntersectionTypeKind.isPossiblyEmpty(): Boolean = this == EmptyIntersectionTypeKind.SINGLE_FINAL_CLASS - -fun EmptyIntersectionTypeKind.isEmpty(): Boolean = this != EmptyIntersectionTypeKind.NOT_EMPTY_INTERSECTION diff --git a/core/compiler.common/src/org/jetbrains/kotlin/types/model/TypeSystemContext.kt b/core/compiler.common/src/org/jetbrains/kotlin/types/model/TypeSystemContext.kt index 235419bdbf3..6123013605c 100644 --- a/core/compiler.common/src/org/jetbrains/kotlin/types/model/TypeSystemContext.kt +++ b/core/compiler.common/src/org/jetbrains/kotlin/types/model/TypeSystemContext.kt @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.types.model import org.jetbrains.kotlin.resolve.checkers.EmptyIntersectionTypeChecker +import org.jetbrains.kotlin.resolve.checkers.EmptyIntersectionTypeInfo import org.jetbrains.kotlin.types.* import kotlin.contracts.ExperimentalContracts import kotlin.contracts.contract @@ -326,8 +327,8 @@ interface TypeSystemInferenceExtensionContext : TypeSystemContext, TypeSystemBui fun createSubstitutorForSuperTypes(baseType: KotlinTypeMarker): TypeSubstitutorMarker? - fun computeEmptyIntersectionTypeKind(types: Collection): EmptyIntersectionTypeKind = - EmptyIntersectionTypeChecker.computeEmptyIntersectionTypeKind(this, types) + fun computeEmptyIntersectionTypeKind(types: Collection): EmptyIntersectionTypeInfo? = + EmptyIntersectionTypeChecker.computeEmptyIntersectionEmptiness(this, types) private fun computeEffectiveVariance(parameter: TypeParameterMarker, argument: TypeArgumentMarker): TypeVariance? = AbstractTypeChecker.effectiveVariance(parameter.getVariance(), argument.getVariance())