[FE] Show causing types in the INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION diagnostic
This commit is contained in:
committed by
teamcity
parent
6a34b184ac
commit
867ad24c86
+14
@@ -1982,6 +1982,20 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
|
|||||||
firDiagnostic.b.map { coneKotlinType ->
|
firDiagnostic.b.map { coneKotlinType ->
|
||||||
firSymbolBuilder.typeBuilder.buildKtType(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,
|
firDiagnostic as KtPsiDiagnostic,
|
||||||
token,
|
token,
|
||||||
)
|
)
|
||||||
|
|||||||
+10
@@ -1409,6 +1409,16 @@ sealed class KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
|
|||||||
override val diagnosticClass get() = InferredTypeVariableIntoEmptyIntersection::class
|
override val diagnosticClass get() = InferredTypeVariableIntoEmptyIntersection::class
|
||||||
abstract val typeVariableDescription: String
|
abstract val typeVariableDescription: String
|
||||||
abstract val incompatibleTypes: List<KtType>
|
abstract val incompatibleTypes: List<KtType>
|
||||||
|
abstract val description: String
|
||||||
|
abstract val causingTypes: String
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class InferredTypeVariableIntoPossibleEmptyIntersection : KtFirDiagnostic<PsiElement>() {
|
||||||
|
override val diagnosticClass get() = InferredTypeVariableIntoPossibleEmptyIntersection::class
|
||||||
|
abstract val typeVariableDescription: String
|
||||||
|
abstract val incompatibleTypes: List<KtType>
|
||||||
|
abstract val description: String
|
||||||
|
abstract val causingTypes: String
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class ExtensionInClassReferenceNotAllowed : KtFirDiagnostic<KtExpression>() {
|
abstract class ExtensionInClassReferenceNotAllowed : KtFirDiagnostic<KtExpression>() {
|
||||||
|
|||||||
+11
@@ -1690,10 +1690,21 @@ internal class PlatformClassMappedToKotlinImpl(
|
|||||||
internal class InferredTypeVariableIntoEmptyIntersectionImpl(
|
internal class InferredTypeVariableIntoEmptyIntersectionImpl(
|
||||||
override val typeVariableDescription: String,
|
override val typeVariableDescription: String,
|
||||||
override val incompatibleTypes: List<KtType>,
|
override val incompatibleTypes: List<KtType>,
|
||||||
|
override val description: String,
|
||||||
|
override val causingTypes: String,
|
||||||
override val firDiagnostic: KtPsiDiagnostic,
|
override val firDiagnostic: KtPsiDiagnostic,
|
||||||
override val token: KtLifetimeToken,
|
override val token: KtLifetimeToken,
|
||||||
) : KtFirDiagnostic.InferredTypeVariableIntoEmptyIntersection(), KtAbstractFirDiagnostic<PsiElement>
|
) : KtFirDiagnostic.InferredTypeVariableIntoEmptyIntersection(), KtAbstractFirDiagnostic<PsiElement>
|
||||||
|
|
||||||
|
internal class InferredTypeVariableIntoPossibleEmptyIntersectionImpl(
|
||||||
|
override val typeVariableDescription: String,
|
||||||
|
override val incompatibleTypes: List<KtType>,
|
||||||
|
override val description: String,
|
||||||
|
override val causingTypes: String,
|
||||||
|
override val firDiagnostic: KtPsiDiagnostic,
|
||||||
|
override val token: KtLifetimeToken,
|
||||||
|
) : KtFirDiagnostic.InferredTypeVariableIntoPossibleEmptyIntersection(), KtAbstractFirDiagnostic<PsiElement>
|
||||||
|
|
||||||
internal class ExtensionInClassReferenceNotAllowedImpl(
|
internal class ExtensionInClassReferenceNotAllowedImpl(
|
||||||
override val referencedDeclaration: KtCallableSymbol,
|
override val referencedDeclaration: KtCallableSymbol,
|
||||||
override val firDiagnostic: KtPsiDiagnostic,
|
override val firDiagnostic: KtPsiDiagnostic,
|
||||||
|
|||||||
+3
-2
@@ -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.api.lifetime.withValidityAssertion
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.LLFirResolveSession
|
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.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.analysis.low.level.api.fir.api.resolveToFirSymbolOfType
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
|
import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
|
||||||
import org.jetbrains.kotlin.fir.renderWithType
|
import org.jetbrains.kotlin.fir.renderWithType
|
||||||
@@ -89,7 +88,9 @@ internal class KtFirSymbolProvider(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun getAnonymousFunctionSymbol(psi: KtNamedFunction): KtAnonymousFunctionSymbol = withValidityAssertion {
|
override fun getAnonymousFunctionSymbol(psi: KtNamedFunction): KtAnonymousFunctionSymbol = withValidityAssertion {
|
||||||
firSymbolBuilder.functionLikeBuilder.buildAnonymousFunctionSymbol(psi.getOrBuildFirOfType(firResolveSession))
|
firSymbolBuilder.functionLikeBuilder.buildAnonymousFunctionSymbol(
|
||||||
|
psi.resolveToFirSymbolOfType<FirAnonymousFunctionSymbol>(firResolveSession)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getAnonymousFunctionSymbol(psi: KtFunctionLiteral): KtAnonymousFunctionSymbol = withValidityAssertion {
|
override fun getAnonymousFunctionSymbol(psi: KtFunctionLiteral): KtAnonymousFunctionSymbol = withValidityAssertion {
|
||||||
|
|||||||
+4
-1
@@ -688,12 +688,15 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
|
|||||||
val INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION by error<PsiElement> {
|
val INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION by error<PsiElement> {
|
||||||
parameter<String>("typeVariableDescription")
|
parameter<String>("typeVariableDescription")
|
||||||
parameter<Collection<ConeKotlinType>>("incompatibleTypes")
|
parameter<Collection<ConeKotlinType>>("incompatibleTypes")
|
||||||
parameter<String>("kind")
|
parameter<String>("description")
|
||||||
|
parameter<String>("causingTypes")
|
||||||
}
|
}
|
||||||
|
|
||||||
val INFERRED_TYPE_VARIABLE_INTO_POSSIBLE_EMPTY_INTERSECTION by warning<PsiElement> {
|
val INFERRED_TYPE_VARIABLE_INTO_POSSIBLE_EMPTY_INTERSECTION by warning<PsiElement> {
|
||||||
parameter<String>("typeVariableDescription")
|
parameter<String>("typeVariableDescription")
|
||||||
parameter<Collection<ConeKotlinType>>("incompatibleTypes")
|
parameter<Collection<ConeKotlinType>>("incompatibleTypes")
|
||||||
|
parameter<String>("description")
|
||||||
|
parameter<String>("causingTypes")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -412,8 +412,8 @@ object FirErrors {
|
|||||||
val SMARTCAST_IMPOSSIBLE by error4<KtExpression, ConeKotlinType, FirExpression, String, Boolean>()
|
val SMARTCAST_IMPOSSIBLE by error4<KtExpression, ConeKotlinType, FirExpression, String, Boolean>()
|
||||||
val REDUNDANT_NULLABLE by warning0<KtTypeReference>(SourceElementPositioningStrategies.REDUNDANT_NULLABLE)
|
val REDUNDANT_NULLABLE by warning0<KtTypeReference>(SourceElementPositioningStrategies.REDUNDANT_NULLABLE)
|
||||||
val PLATFORM_CLASS_MAPPED_TO_KOTLIN by warning1<PsiElement, FqName>(SourceElementPositioningStrategies.REFERENCED_NAME_BY_QUALIFIED)
|
val PLATFORM_CLASS_MAPPED_TO_KOTLIN by warning1<PsiElement, FqName>(SourceElementPositioningStrategies.REFERENCED_NAME_BY_QUALIFIED)
|
||||||
val INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION by error3<PsiElement, String, Collection<ConeKotlinType>, String>()
|
val INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION by error4<PsiElement, String, Collection<ConeKotlinType>, String, String>()
|
||||||
val INFERRED_TYPE_VARIABLE_INTO_POSSIBLE_EMPTY_INTERSECTION by warning2<PsiElement, String, Collection<ConeKotlinType>>()
|
val INFERRED_TYPE_VARIABLE_INTO_POSSIBLE_EMPTY_INTERSECTION by warning4<PsiElement, String, Collection<ConeKotlinType>, String, String>()
|
||||||
|
|
||||||
// Reflection
|
// Reflection
|
||||||
val EXTENSION_IN_CLASS_REFERENCE_NOT_ALLOWED by error1<KtExpression, FirCallableSymbol<*>>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
|
val EXTENSION_IN_CLASS_REFERENCE_NOT_ALLOWED by error1<KtExpression, FirCallableSymbol<*>>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
|
||||||
|
|||||||
+6
-3
@@ -950,16 +950,19 @@ object FirErrorsDefaultMessages : BaseDiagnosticRendererFactory() {
|
|||||||
map.put(INFERENCE_UNSUCCESSFUL_FORK, "Unsuccessful inference fork at position: {0}", TO_STRING)
|
map.put(INFERENCE_UNSUCCESSFUL_FORK, "Unsuccessful inference fork at position: {0}", TO_STRING)
|
||||||
map.put(
|
map.put(
|
||||||
INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION,
|
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,
|
TO_STRING,
|
||||||
RENDER_COLLECTION_OF_TYPES,
|
RENDER_COLLECTION_OF_TYPES,
|
||||||
|
TO_STRING,
|
||||||
TO_STRING
|
TO_STRING
|
||||||
)
|
)
|
||||||
map.put(
|
map.put(
|
||||||
INFERRED_TYPE_VARIABLE_INTO_POSSIBLE_EMPTY_INTERSECTION,
|
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,
|
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)
|
map.put(TYPE_MISMATCH, "Type mismatch: inferred type is {1} but {0} was expected", TO_STRING, TO_STRING, NOT_RENDERED)
|
||||||
|
|||||||
+11
-9
@@ -257,8 +257,9 @@ private fun mapInapplicableCandidateError(
|
|||||||
diagnostic.candidate
|
diagnostic.candidate
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
is InferredEmptyIntersectionDiagnostic ->
|
is InferredEmptyIntersectionDiagnostic -> reportInferredIntoEmptyIntersectionError(
|
||||||
reportInferredIntoEmptyIntersectionError(source, rootCause.typeVariable, rootCause.incompatibleTypes, rootCause.kind)
|
source, rootCause.typeVariable, rootCause.incompatibleTypes, rootCause.causingTypes, rootCause.kind
|
||||||
|
)
|
||||||
else -> genericDiagnostic
|
else -> genericDiagnostic
|
||||||
}
|
}
|
||||||
}.distinct()
|
}.distinct()
|
||||||
@@ -400,6 +401,7 @@ private fun ConstraintSystemError.toDiagnostic(
|
|||||||
source,
|
source,
|
||||||
typeVariable as ConeTypeVariable,
|
typeVariable as ConeTypeVariable,
|
||||||
incompatibleTypes as Collection<ConeKotlinType>,
|
incompatibleTypes as Collection<ConeKotlinType>,
|
||||||
|
causingTypes as Collection<ConeKotlinType>,
|
||||||
kind
|
kind
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -411,18 +413,18 @@ private fun reportInferredIntoEmptyIntersectionError(
|
|||||||
source: KtSourceElement,
|
source: KtSourceElement,
|
||||||
typeVariable: ConeTypeVariable,
|
typeVariable: ConeTypeVariable,
|
||||||
incompatibleTypes: Collection<ConeKotlinType>,
|
incompatibleTypes: Collection<ConeKotlinType>,
|
||||||
|
causingTypes: Collection<ConeKotlinType>,
|
||||||
kind: EmptyIntersectionTypeKind
|
kind: EmptyIntersectionTypeKind
|
||||||
): KtDiagnostic? {
|
): KtDiagnostic? {
|
||||||
val typeVariableText =
|
val typeVariableText =
|
||||||
(typeVariable.typeConstructor.originalTypeParameter as? ConeTypeParameterLookupTag)?.name?.asString()
|
(typeVariable.typeConstructor.originalTypeParameter as? ConeTypeParameterLookupTag)?.name?.asString()
|
||||||
?: typeVariable.toString()
|
?: typeVariable.toString()
|
||||||
return if (kind.isPossiblyEmpty()) {
|
val causingTypesText = if (incompatibleTypes == causingTypes) "" else ": ${causingTypes.joinToString()}"
|
||||||
FirErrors.INFERRED_TYPE_VARIABLE_INTO_POSSIBLE_EMPTY_INTERSECTION.createOn(source, typeVariableText, incompatibleTypes)
|
val factory = if (kind.isPossiblyEmpty())
|
||||||
} else {
|
FirErrors.INFERRED_TYPE_VARIABLE_INTO_POSSIBLE_EMPTY_INTERSECTION else
|
||||||
FirErrors.INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION.createOn(
|
FirErrors.INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION
|
||||||
source, typeVariableText, incompatibleTypes, kind.description?.let { " ($it)" }.orEmpty()
|
|
||||||
)
|
return factory.createOn(source, typeVariableText, incompatibleTypes, kind.description, causingTypesText)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private val NewConstraintError.lowerConeType: ConeKotlinType get() = lowerType as ConeKotlinType
|
private val NewConstraintError.lowerConeType: ConeKotlinType get() = lowerType as ConeKotlinType
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ import org.jetbrains.kotlin.fir.expressions.*
|
|||||||
import org.jetbrains.kotlin.fir.languageVersionSettings
|
import org.jetbrains.kotlin.fir.languageVersionSettings
|
||||||
import org.jetbrains.kotlin.fir.matchingParameterFunctionType
|
import org.jetbrains.kotlin.fir.matchingParameterFunctionType
|
||||||
import org.jetbrains.kotlin.fir.references.FirSuperReference
|
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.directExpansionType
|
||||||
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
|
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
|
||||||
import org.jetbrains.kotlin.fir.resolve.inference.ConeTypeParameterBasedTypeVariable
|
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() })
|
if (upperTypes.size <= 1 || variableWithConstraints.constraints.any { it.kind.isLower() })
|
||||||
continue
|
continue
|
||||||
|
|
||||||
val emptyIntersectionKind = candidate.system.getEmptyIntersectionTypeKind(upperTypes).takeIf { it.isDefinitelyEmpty() }
|
val emptyIntersectionTypeInfo = candidate.system.getEmptyIntersectionTypeKind(upperTypes) ?: continue
|
||||||
?: continue
|
|
||||||
|
|
||||||
sink.yieldDiagnostic(
|
sink.yieldDiagnostic(
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
InferredEmptyIntersectionDiagnostic(
|
InferredEmptyIntersectionDiagnostic(
|
||||||
upperTypes as Collection<ConeKotlinType>,
|
upperTypes as List<ConeKotlinType>,
|
||||||
|
emptyIntersectionTypeInfo.casingTypes.toList() as List<ConeKotlinType>,
|
||||||
variableWithConstraints.typeVariable as ConeTypeVariable,
|
variableWithConstraints.typeVariable as ConeTypeVariable,
|
||||||
emptyIntersectionKind
|
emptyIntersectionTypeInfo.kind
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -56,6 +56,7 @@ import org.jetbrains.kotlin.resolve.calls.tower.CandidateApplicability
|
|||||||
import org.jetbrains.kotlin.resolve.calls.tower.isSuccess
|
import org.jetbrains.kotlin.resolve.calls.tower.isSuccess
|
||||||
import org.jetbrains.kotlin.types.TypeApproximatorConfiguration
|
import org.jetbrains.kotlin.types.TypeApproximatorConfiguration
|
||||||
import org.jetbrains.kotlin.types.Variance
|
import org.jetbrains.kotlin.types.Variance
|
||||||
|
import org.jetbrains.kotlin.types.isDefinitelyEmpty
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.runIf
|
import org.jetbrains.kotlin.utils.addToStdlib.runIf
|
||||||
import kotlin.collections.component1
|
import kotlin.collections.component1
|
||||||
import kotlin.collections.component2
|
import kotlin.collections.component2
|
||||||
@@ -852,7 +853,7 @@ class FirCallCompletionResultsWriterTransformer(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun FirNamedReferenceWithCandidate.hasAdditionalResolutionErrors(): Boolean =
|
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 {
|
private fun FirNamedReferenceWithCandidate.toResolvedReference(): FirNamedReference {
|
||||||
val errorDiagnostic = when {
|
val errorDiagnostic = when {
|
||||||
|
|||||||
+1
@@ -31,6 +31,7 @@ class MixingNamedAndPositionArguments(override val argument: FirExpression) : In
|
|||||||
|
|
||||||
class InferredEmptyIntersectionDiagnostic(
|
class InferredEmptyIntersectionDiagnostic(
|
||||||
val incompatibleTypes: Collection<ConeKotlinType>,
|
val incompatibleTypes: Collection<ConeKotlinType>,
|
||||||
|
val causingTypes: Collection<ConeKotlinType>,
|
||||||
val typeVariable: ConeTypeVariable,
|
val typeVariable: ConeTypeVariable,
|
||||||
val kind: EmptyIntersectionTypeKind
|
val kind: EmptyIntersectionTypeKind
|
||||||
) : ResolutionDiagnostic(INAPPLICABLE)
|
) : ResolutionDiagnostic(INAPPLICABLE)
|
||||||
|
|||||||
@@ -899,10 +899,10 @@ public interface Errors {
|
|||||||
|
|
||||||
DiagnosticFactoryForDeprecation1<PsiElement, TypeParameterDescriptor> TYPE_INFERENCE_ONLY_INPUT_TYPES =
|
DiagnosticFactoryForDeprecation1<PsiElement, TypeParameterDescriptor> TYPE_INFERENCE_ONLY_INPUT_TYPES =
|
||||||
DiagnosticFactoryForDeprecation1.create(LanguageFeature.StrictOnlyInputTypesChecks);
|
DiagnosticFactoryForDeprecation1.create(LanguageFeature.StrictOnlyInputTypesChecks);
|
||||||
DiagnosticFactoryForDeprecation3<PsiElement, String, Collection<KotlinType>, String> INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION =
|
DiagnosticFactoryForDeprecation4<PsiElement, String, Collection<KotlinType>, String, String> INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION =
|
||||||
DiagnosticFactoryForDeprecation3.create(LanguageFeature.ForbidInferringTypeVariablesIntoEmptyIntersection);
|
DiagnosticFactoryForDeprecation4.create(LanguageFeature.ForbidInferringTypeVariablesIntoEmptyIntersection);
|
||||||
DiagnosticFactory2<PsiElement, String, Collection<KotlinType>> INFERRED_TYPE_VARIABLE_INTO_POSSIBLE_EMPTY_INTERSECTION =
|
DiagnosticFactory4<PsiElement, String, Collection<KotlinType>, String, String> INFERRED_TYPE_VARIABLE_INTO_POSSIBLE_EMPTY_INTERSECTION =
|
||||||
DiagnosticFactory2.create(WARNING);
|
DiagnosticFactory4.create(WARNING);
|
||||||
DiagnosticFactory1<PsiElement, InferenceErrorData> TYPE_INFERENCE_UPPER_BOUND_VIOLATED = DiagnosticFactory1.create(ERROR);
|
DiagnosticFactory1<PsiElement, InferenceErrorData> TYPE_INFERENCE_UPPER_BOUND_VIOLATED = DiagnosticFactory1.create(ERROR);
|
||||||
DiagnosticFactory2<KtElement, KotlinType, KotlinType> TYPE_INFERENCE_EXPECTED_TYPE_MISMATCH = DiagnosticFactory2.create(ERROR);
|
DiagnosticFactory2<KtElement, KotlinType, KotlinType> TYPE_INFERENCE_EXPECTED_TYPE_MISMATCH = DiagnosticFactory2.create(ERROR);
|
||||||
DiagnosticFactory0<PsiElement> TYPE_INFERENCE_CANDIDATE_WITH_SAM_AND_VARARG = DiagnosticFactory0.create(WARNING);
|
DiagnosticFactory0<PsiElement> TYPE_INFERENCE_CANDIDATE_WITH_SAM_AND_VARARG = DiagnosticFactory0.create(WARNING);
|
||||||
|
|||||||
+2
-2
@@ -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_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 " +
|
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);
|
"(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_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}", TO_STRING, RENDER_COLLECTION_OF_TYPES);
|
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_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_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.");
|
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.");
|
||||||
|
|||||||
+8
-3
@@ -610,14 +610,19 @@ class DiagnosticReporterByTrackingStrategy(
|
|||||||
?: typeVariable.toString()
|
?: typeVariable.toString()
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
val incompatibleTypes = error.incompatibleTypes as Collection<KotlinType>
|
val incompatibleTypes = error.incompatibleTypes as List<KotlinType>
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
val causingTypes = error.causingTypes as List<KotlinType>
|
||||||
|
val causingTypesText = if (incompatibleTypes == causingTypes) "" else ": ${causingTypes.joinToString()}"
|
||||||
val diagnostic = if (error.kind.isPossiblyEmpty()) {
|
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 {
|
} else {
|
||||||
INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION.on(
|
INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION.on(
|
||||||
context.languageVersionSettings, expression, typeVariableText,
|
context.languageVersionSettings, expression, typeVariableText,
|
||||||
incompatibleTypes, error.kind.description?.let { " ($it)" }.orEmpty()
|
incompatibleTypes, error.kind.description, causingTypesText
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -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.Constraint
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage
|
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintSystemError
|
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.KotlinTypeMarker
|
||||||
import org.jetbrains.kotlin.types.model.TypeVariableMarker
|
import org.jetbrains.kotlin.types.model.TypeVariableMarker
|
||||||
|
|
||||||
@@ -27,7 +27,7 @@ interface NewConstraintSystem {
|
|||||||
fun asPostponedArgumentsAnalyzerContext(): PostponedArgumentsAnalyzerContext
|
fun asPostponedArgumentsAnalyzerContext(): PostponedArgumentsAnalyzerContext
|
||||||
fun processForkConstraints()
|
fun processForkConstraints()
|
||||||
|
|
||||||
fun getEmptyIntersectionTypeKind(types: Collection<KotlinTypeMarker>): EmptyIntersectionTypeKind
|
fun getEmptyIntersectionTypeKind(types: Collection<KotlinTypeMarker>): EmptyIntersectionTypeInfo?
|
||||||
}
|
}
|
||||||
|
|
||||||
typealias ForkPointData = List<ConstraintsFromSingleFork>
|
typealias ForkPointData = List<ConstraintsFromSingleFork>
|
||||||
|
|||||||
+6
-3
@@ -137,19 +137,22 @@ class ConstrainingTypeIsError(
|
|||||||
class NoSuccessfulFork(val position: IncorporationConstraintPosition) : ConstraintSystemError(INAPPLICABLE)
|
class NoSuccessfulFork(val position: IncorporationConstraintPosition) : ConstraintSystemError(INAPPLICABLE)
|
||||||
|
|
||||||
sealed interface InferredEmptyIntersection {
|
sealed interface InferredEmptyIntersection {
|
||||||
val incompatibleTypes: Collection<KotlinTypeMarker>
|
val incompatibleTypes: List<KotlinTypeMarker>
|
||||||
|
val causingTypes: List<KotlinTypeMarker>
|
||||||
val typeVariable: TypeVariableMarker
|
val typeVariable: TypeVariableMarker
|
||||||
val kind: EmptyIntersectionTypeKind
|
val kind: EmptyIntersectionTypeKind
|
||||||
}
|
}
|
||||||
|
|
||||||
class InferredEmptyIntersectionWarning(
|
class InferredEmptyIntersectionWarning(
|
||||||
override val incompatibleTypes: Collection<KotlinTypeMarker>,
|
override val incompatibleTypes: List<KotlinTypeMarker>,
|
||||||
|
override val causingTypes: List<KotlinTypeMarker>,
|
||||||
override val typeVariable: TypeVariableMarker,
|
override val typeVariable: TypeVariableMarker,
|
||||||
override val kind: EmptyIntersectionTypeKind,
|
override val kind: EmptyIntersectionTypeKind,
|
||||||
) : ConstraintSystemError(RESOLVED), InferredEmptyIntersection
|
) : ConstraintSystemError(RESOLVED), InferredEmptyIntersection
|
||||||
|
|
||||||
class InferredEmptyIntersectionError(
|
class InferredEmptyIntersectionError(
|
||||||
override val incompatibleTypes: Collection<KotlinTypeMarker>,
|
override val incompatibleTypes: List<KotlinTypeMarker>,
|
||||||
|
override val causingTypes: List<KotlinTypeMarker>,
|
||||||
override val typeVariable: TypeVariableMarker,
|
override val typeVariable: TypeVariableMarker,
|
||||||
override val kind: EmptyIntersectionTypeKind,
|
override val kind: EmptyIntersectionTypeKind,
|
||||||
) : ConstraintSystemError(INAPPLICABLE), InferredEmptyIntersection
|
) : ConstraintSystemError(INAPPLICABLE), InferredEmptyIntersection
|
||||||
|
|||||||
+8
-5
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.config.LanguageVersionSettings
|
|||||||
import org.jetbrains.kotlin.resolve.calls.components.PostponedArgumentsAnalyzerContext
|
import org.jetbrains.kotlin.resolve.calls.components.PostponedArgumentsAnalyzerContext
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.*
|
import org.jetbrains.kotlin.resolve.calls.inference.*
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.components.*
|
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.*
|
||||||
import org.jetbrains.kotlin.types.model.*
|
import org.jetbrains.kotlin.types.model.*
|
||||||
import org.jetbrains.kotlin.utils.SmartList
|
import org.jetbrains.kotlin.utils.SmartList
|
||||||
@@ -38,7 +39,7 @@ class NewConstraintSystemImpl(
|
|||||||
private val typeVariablesTransaction: MutableList<TypeVariableMarker> = SmartList()
|
private val typeVariablesTransaction: MutableList<TypeVariableMarker> = SmartList()
|
||||||
private val properTypesCache: MutableSet<KotlinTypeMarker> = SmartSet.create()
|
private val properTypesCache: MutableSet<KotlinTypeMarker> = SmartSet.create()
|
||||||
private val notProperTypesCache: MutableSet<KotlinTypeMarker> = SmartSet.create()
|
private val notProperTypesCache: MutableSet<KotlinTypeMarker> = SmartSet.create()
|
||||||
private val intersectionTypesCache: MutableMap<Collection<KotlinTypeMarker>, EmptyIntersectionTypeKind> = mutableMapOf()
|
private val intersectionTypesCache: MutableMap<Collection<KotlinTypeMarker>, EmptyIntersectionTypeInfo?> = mutableMapOf()
|
||||||
private var couldBeResolvedWithUnrestrictedBuilderInference: Boolean = false
|
private var couldBeResolvedWithUnrestrictedBuilderInference: Boolean = false
|
||||||
|
|
||||||
override var atCompletionState: Boolean = false
|
override var atCompletionState: Boolean = false
|
||||||
@@ -441,7 +442,7 @@ class NewConstraintSystemImpl(
|
|||||||
doPostponedComputationsIfAllVariablesAreFixed()
|
doPostponedComputationsIfAllVariablesAreFixed()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getEmptyIntersectionTypeKind(types: Collection<KotlinTypeMarker>): EmptyIntersectionTypeKind {
|
override fun getEmptyIntersectionTypeKind(types: Collection<KotlinTypeMarker>): EmptyIntersectionTypeInfo? {
|
||||||
if (types in intersectionTypesCache)
|
if (types in intersectionTypesCache)
|
||||||
return intersectionTypesCache.getValue(types)
|
return intersectionTypesCache.getValue(types)
|
||||||
|
|
||||||
@@ -458,18 +459,20 @@ class NewConstraintSystemImpl(
|
|||||||
if (upperTypes.size <= 1 || storage.errors.any { it is InferredEmptyIntersection && it.incompatibleTypes == upperTypes })
|
if (upperTypes.size <= 1 || storage.errors.any { it is InferredEmptyIntersection && it.incompatibleTypes == upperTypes })
|
||||||
return
|
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
|
// Remove existing errors from the resolution stage because a completion stage error is always more precise
|
||||||
storage.errors.removeIf { it is InferredEmptyIntersection }
|
storage.errors.removeIf { it is InferredEmptyIntersection }
|
||||||
|
|
||||||
val isInferredEmptyIntersectionForbidden =
|
val isInferredEmptyIntersectionForbidden =
|
||||||
languageVersionSettings.supportsFeature(LanguageFeature.ForbidInferringTypeVariablesIntoEmptyIntersection)
|
languageVersionSettings.supportsFeature(LanguageFeature.ForbidInferringTypeVariablesIntoEmptyIntersection)
|
||||||
val errorFactory = if (emptyIntersectionKind.isDefinitelyEmpty() && isInferredEmptyIntersectionForbidden)
|
val errorFactory = if (emptyIntersectionTypeInfo.kind.isDefinitelyEmpty() && isInferredEmptyIntersectionForbidden)
|
||||||
::InferredEmptyIntersectionError
|
::InferredEmptyIntersectionError
|
||||||
else ::InferredEmptyIntersectionWarning
|
else ::InferredEmptyIntersectionWarning
|
||||||
|
|
||||||
addError(errorFactory(upperTypes, variable, emptyIntersectionKind))
|
addError(
|
||||||
|
errorFactory(upperTypes.toList(), emptyIntersectionTypeInfo.casingTypes.toList(), variable, emptyIntersectionTypeInfo.kind)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkMissedConstraints() {
|
private fun checkMissedConstraints() {
|
||||||
|
|||||||
+4
-3
@@ -67,10 +67,11 @@ class ClassicTypeSystemContextForCS(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun TypeSubstitutorMarker.safeSubstitute(type: KotlinTypeMarker): KotlinTypeMarker {
|
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) {
|
return when (this) {
|
||||||
is NewTypeSubstitutor -> safeSubstitute(type)
|
is NewTypeSubstitutor -> safeSubstitute(unwrappedType)
|
||||||
is TypeSubstitutor -> safeSubstitute(type, Variance.INVARIANT)
|
is TypeSubstitutor -> safeSubstitute(unwrappedType, Variance.INVARIANT)
|
||||||
else -> error(this.errorMessage())
|
else -> error(this.errorMessage())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+9
-3
@@ -902,15 +902,21 @@ internal object CheckIncompatibleTypeVariableUpperBounds : ResolutionPart() {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
val emptyIntersectionKind = constraintSystem.getEmptyIntersectionTypeKind(upperTypes).takeIf { it.isDefinitelyEmpty() }
|
val emptyIntersectionTypeInfo = constraintSystem.getEmptyIntersectionTypeKind(upperTypes) ?: continue
|
||||||
?: continue
|
|
||||||
val isInferredEmptyIntersectionForbidden = callComponents.languageVersionSettings.supportsFeature(
|
val isInferredEmptyIntersectionForbidden = callComponents.languageVersionSettings.supportsFeature(
|
||||||
LanguageFeature.ForbidInferringTypeVariablesIntoEmptyIntersection
|
LanguageFeature.ForbidInferringTypeVariablesIntoEmptyIntersection
|
||||||
)
|
)
|
||||||
val errorFactory =
|
val errorFactory =
|
||||||
if (isInferredEmptyIntersectionForbidden) ::InferredEmptyIntersectionError else ::InferredEmptyIntersectionWarning
|
if (isInferredEmptyIntersectionForbidden) ::InferredEmptyIntersectionError else ::InferredEmptyIntersectionWarning
|
||||||
|
|
||||||
addError(errorFactory(upperTypes, variableWithConstraints.typeVariable, emptyIntersectionKind))
|
addError(
|
||||||
|
errorFactory(
|
||||||
|
upperTypes,
|
||||||
|
emptyIntersectionTypeInfo.casingTypes.toList(),
|
||||||
|
variableWithConstraints.typeVariable,
|
||||||
|
emptyIntersectionTypeInfo.kind
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
/kt45461.kt:5:25: warning: parameter 'foo' is never used
|
/kt45461.kt:5:25: warning: parameter 'foo' is never used
|
||||||
fun <S : T> takeFoo(foo: Foo<in S>) {}
|
fun <S : T> takeFoo(foo: Foo<in S>) {}
|
||||||
^
|
^
|
||||||
/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<String>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31
|
Bar<String>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31
|
||||||
^
|
^
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
/kt45461_10.kt:7:25: warning: parameter 'foo' is never used
|
/kt45461_10.kt:7:25: warning: parameter 'foo' is never used
|
||||||
fun <S : T> takeFoo(foo: Foo<in S>) {}
|
fun <S : T> takeFoo(foo: Foo<in S>) {}
|
||||||
^
|
^
|
||||||
/kt45461_10.kt:16:21: warning: type argument for a type parameter S has possible incompatible upper bounds: Out<Int>, K
|
/kt45461_10.kt:16:21: warning: type argument for a type parameter S has possible incompatible upper bounds: Out<Int>, K (final class and interface: Int, A)
|
||||||
Bar<Out<Int>>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31
|
Bar<Out<Int>>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31
|
||||||
^
|
^
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
/kt45461_12.kt:5:25: warning: parameter 'foo' is never used
|
/kt45461_12.kt:5:25: warning: parameter 'foo' is never used
|
||||||
fun <S : T> takeFoo(foo: Foo<in S>) {}
|
fun <S : T> takeFoo(foo: Foo<in S>) {}
|
||||||
^
|
^
|
||||||
/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<String>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31
|
Bar<String>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31
|
||||||
^
|
^
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
/kt45461_13.kt:7:25: warning: parameter 'foo' is never used
|
/kt45461_13.kt:7:25: warning: parameter 'foo' is never used
|
||||||
fun <S : T> takeFoo(foo: Foo<in S>) {}
|
fun <S : T> takeFoo(foo: Foo<in S>) {}
|
||||||
^
|
^
|
||||||
/kt45461_13.kt:16:24: warning: type argument for a type parameter S has possible incompatible upper bounds: Out<String>, K
|
/kt45461_13.kt:16:24: warning: type argument for a type parameter S has possible incompatible upper bounds: Out<String>, K (final class and interface: String, A)
|
||||||
Bar<Out<String>>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31
|
Bar<Out<String>>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31
|
||||||
^
|
^
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
/kt45461_15.kt:5:25: warning: parameter 'foo' is never used
|
/kt45461_15.kt:5:25: warning: parameter 'foo' is never used
|
||||||
fun <S : T> takeFoo(foo: Foo<in S>) {}
|
fun <S : T> takeFoo(foo: Foo<in S>) {}
|
||||||
^
|
^
|
||||||
/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<Int>, 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<Int>, K (incompatible type arguments: Int, {A & Number}). This will become an error in Kotlin 1.9
|
||||||
Bar<Inv<Int>>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31
|
Bar<Inv<Int>>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31
|
||||||
^
|
^
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
/kt45461_19.kt:5:25: warning: parameter 'foo' is never used
|
/kt45461_19.kt:5:25: warning: parameter 'foo' is never used
|
||||||
fun <S : T> takeFoo(foo: Foo<in S>) {}
|
fun <S : T> takeFoo(foo: Foo<in S>) {}
|
||||||
^
|
^
|
||||||
/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<Inv<Int>>, 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<Inv<Int>>, K (incompatible type arguments: Int, Number). This will become an error in Kotlin 1.9
|
||||||
Bar<Out<Inv<Int>>>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31
|
Bar<Out<Inv<Int>>>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31
|
||||||
^
|
^
|
||||||
|
|||||||
+1
-1
@@ -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
|
/kt45461_2.kt:8:10: warning: 'Int' is a final type, and thus a value of the type parameter is predetermined
|
||||||
fun <K : Int> main() {
|
fun <K : Int> 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<String>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31
|
Bar<String>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31
|
||||||
^
|
^
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
/kt45461_21.kt:5:25: warning: parameter 'foo' is never used
|
/kt45461_21.kt:5:25: warning: parameter 'foo' is never used
|
||||||
fun <S : T> takeFoo(foo: Foo<in S>) {}
|
fun <S : T> takeFoo(foo: Foo<in S>) {}
|
||||||
^
|
^
|
||||||
/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<Inv<Int>>, 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<Inv<Int>>, K (incompatible type arguments: Int, Number). This will become an error in Kotlin 1.9
|
||||||
Bar<In<Inv<Int>>>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31
|
Bar<In<Inv<Int>>>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31
|
||||||
^
|
^
|
||||||
|
|||||||
+1
-1
@@ -4,6 +4,6 @@
|
|||||||
/kt45461_24.kt:10:10: warning: 'Inv<out Inv<out Int>>' is a final type, and thus a value of the type parameter is predetermined
|
/kt45461_24.kt:10:10: warning: 'Inv<out Inv<out Int>>' is a final type, and thus a value of the type parameter is predetermined
|
||||||
fun <K : Inv<out Inv<out Int>>> main() {
|
fun <K : Inv<out Inv<out Int>>> 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<in Inv<in Number>>, 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<in Inv<in Number>>, K (incompatible type arguments: Number, Int). This will become an error in Kotlin 1.9
|
||||||
Bar<Inv<in Inv<in Number>>>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31
|
Bar<Inv<in Inv<in Number>>>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31
|
||||||
^
|
^
|
||||||
|
|||||||
+1
-1
@@ -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<String>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31
|
val x: Float = Bar<String>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31
|
||||||
^
|
^
|
||||||
|
|||||||
+1
-1
@@ -8,5 +8,5 @@ class Bar<T> {
|
|||||||
|
|
||||||
fun <K : L, L : N, N: <!FINAL_UPPER_BOUND!>Int<!>> main() {
|
fun <K : L, L : N, N: <!FINAL_UPPER_BOUND!>Int<!>> main() {
|
||||||
val foo = Foo<K>()
|
val foo = Foo<K>()
|
||||||
val x: Float = Bar<String>().<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION("S; kotlin/String, K; multiple incompatible classes")!>takeFoo<!>(foo) // error in 1.3.72, no error in 1.4.31
|
val x: Float = Bar<String>().<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION("S; kotlin/String, K; multiple incompatible classes; : kotlin/String, kotlin/Int")!>takeFoo<!>(foo) // error in 1.3.72, no error in 1.4.31
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -8,5 +8,5 @@ class Bar<T> {
|
|||||||
|
|
||||||
fun <K : L, L : N, N: <!FINAL_UPPER_BOUND!>Int<!>> main() {
|
fun <K : L, L : N, N: <!FINAL_UPPER_BOUND!>Int<!>> main() {
|
||||||
val foo = Foo<K>()
|
val foo = Foo<K>()
|
||||||
val x: Float = Bar<String>().<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_ERROR("S; String, K, Float; (multiple incompatible classes)")!>takeFoo<!>(foo) // error in 1.3.72, no error in 1.4.31
|
val x: Float = Bar<String>().<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_ERROR("S; String, K, Float; multiple incompatible classes; : String, Int")!>takeFoo<!>(foo) // error in 1.3.72, no error in 1.4.31
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -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<String>, K, Out<Float>
|
/kt45461_26.kt:13:44: error: type argument for a type parameter S can't be inferred because it has incompatible upper bounds: Out<String>, K, Out<Float> (multiple incompatible classes: String, Int)
|
||||||
val x: Out<Float> = Bar<Out<String>>().takeFoo(foo)
|
val x: Out<Float> = Bar<Out<String>>().takeFoo(foo)
|
||||||
^
|
^
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -10,5 +10,5 @@ class Out<out K>
|
|||||||
|
|
||||||
fun <K : L, L : N, N: <!FINAL_UPPER_BOUND!>Out<Int><!>> main() {
|
fun <K : L, L : N, N: <!FINAL_UPPER_BOUND!>Out<Int><!>> main() {
|
||||||
val foo = Foo<K>()
|
val foo = Foo<K>()
|
||||||
val x: Out<Float> = Bar<Out<String>>().<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION("S; Out<kotlin/String>, K; multiple incompatible classes")!>takeFoo<!>(foo)
|
val x: Out<Float> = Bar<Out<String>>().<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION("S; Out<kotlin/String>, K; multiple incompatible classes; : kotlin/String, kotlin/Int")!>takeFoo<!>(foo)
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -10,5 +10,5 @@ class Out<out K>
|
|||||||
|
|
||||||
fun <K : L, L : N, N: <!FINAL_UPPER_BOUND!>Out<Int><!>> main() {
|
fun <K : L, L : N, N: <!FINAL_UPPER_BOUND!>Out<Int><!>> main() {
|
||||||
val foo = Foo<K>()
|
val foo = Foo<K>()
|
||||||
val x: Out<Float> = Bar<Out<String>>().<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_ERROR("S; Out<String>, K, Out<Float>; (multiple incompatible classes)")!>takeFoo<!>(foo)
|
val x: Out<Float> = Bar<Out<String>>().<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_ERROR("S; Out<String>, K, Out<Float>; multiple incompatible classes; : String, Int")!>takeFoo<!>(foo)
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -11,5 +11,5 @@ interface B : A<Int>
|
|||||||
|
|
||||||
fun <K : Out<A<String>>> main() {
|
fun <K : Out<A<String>>> main() {
|
||||||
val foo = Foo<K>()
|
val foo = Foo<K>()
|
||||||
Bar<Out<B>>().<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_WARNING("S; Out<B>, K; (incompatible supertypes)")!>takeFoo<!>(foo) // error in 1.3.72, no error in 1.4.31
|
Bar<Out<B>>().<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_WARNING("S; Out<B>, K; incompatible supertypes; : A<Int>, A<String>")!>takeFoo<!>(foo) // error in 1.3.72, no error in 1.4.31
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -11,5 +11,5 @@ class B : A<Int>
|
|||||||
|
|
||||||
fun <K : Out<A<String>>> main() {
|
fun <K : Out<A<String>>> main() {
|
||||||
val foo = Foo<K>()
|
val foo = Foo<K>()
|
||||||
Bar<Out<B>>().<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_WARNING("S; Out<B>, K; (incompatible supertypes)")!>takeFoo<!>(foo) // error in 1.3.72, no error in 1.4.31
|
Bar<Out<B>>().<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_WARNING("S; Out<B>, K; incompatible supertypes; : A<Int>, A<String>")!>takeFoo<!>(foo) // error in 1.3.72, no error in 1.4.31
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
/kt45461_5.kt:5:25: warning: parameter 'foo' is never used
|
/kt45461_5.kt:5:25: warning: parameter 'foo' is never used
|
||||||
fun <S : T> takeFoo(foo: Foo<in S>) {}
|
fun <S : T> takeFoo(foo: Foo<in S>) {}
|
||||||
^
|
^
|
||||||
/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<String>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31
|
Bar<String>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31
|
||||||
^
|
^
|
||||||
|
|||||||
+1
-1
@@ -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
|
/kt45461_8.kt:10:28: warning: 'Int' is a final type, and thus a value of the type parameter is predetermined
|
||||||
fun <K : Inv<L>, L : N, N: Int> main() {
|
fun <K : Inv<L>, 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<Number>, 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<Number>, K (incompatible type arguments: Number, Int). This will become an error in Kotlin 1.9
|
||||||
Bar<Inv<Number>>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31
|
Bar<Inv<Number>>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31
|
||||||
^
|
^
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
/kt45461_9.kt:5:25: warning: parameter 'foo' is never used
|
/kt45461_9.kt:5:25: warning: parameter 'foo' is never used
|
||||||
fun <S : T> takeFoo(foo: Foo<in S>) {}
|
fun <S : T> takeFoo(foo: Foo<in S>) {}
|
||||||
^
|
^
|
||||||
/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<Int>, Inv<Number>. 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<Int>, Inv<Number> (incompatible type arguments: Int, Number). This will become an error in Kotlin 1.9
|
||||||
Bar<Inv<Int>>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31
|
Bar<Inv<Int>>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31
|
||||||
^
|
^
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -4,7 +4,7 @@
|
|||||||
/kt48765.kt:4:52: warning: parameter 'x2' is never used
|
/kt48765.kt:4:52: warning: parameter 'x2' is never used
|
||||||
fun <T1: Number, T2: A<Float, T1>> foo(x1: T2, x2: T1) {}
|
fun <T1: Number, T2: A<Float, T1>> 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())
|
B().foo(x, foo())
|
||||||
^
|
^
|
||||||
/kt48765.kt:12:9: warning: 'String' is a final type, and thus a value of the type parameter is predetermined
|
/kt48765.kt:12:9: warning: 'String' is a final type, and thus a value of the type parameter is predetermined
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
/kt48935.kt:7:35: warning: parameter 'func' is never used
|
/kt48935.kt:7:35: warning: parameter 'func' is never used
|
||||||
fun <T, V> exampleGenericFunction(func: V) where T: Base, V: (T) -> Unit {
|
fun <T, V> 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
|
exampleGenericFunction(func) // expected this to be a compilation error as the T: Base constraint should not be satisfied
|
||||||
^
|
^
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -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<Int> { g() }
|
f<Int> { g() }
|
||||||
^
|
^
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -7,6 +7,6 @@ fun <V> genericIn(x: In<V>) {}
|
|||||||
/selectFromCovariantAndContravariantTypes.kt:13:20: warning: parameter 'x' is never used
|
/selectFromCovariantAndContravariantTypes.kt:13:20: warning: parameter 'x' is never used
|
||||||
fun <V> genericOut(x: Out<V>) {}
|
fun <V> genericOut(x: Out<V>) {}
|
||||||
^
|
^
|
||||||
/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))
|
genericIn(select(a, b))
|
||||||
^
|
^
|
||||||
|
|||||||
+1
-1
@@ -14,7 +14,7 @@ val a1: A = select(
|
|||||||
{ a: Int -> myPrint(a + this.length + 2) }
|
{ a: Int -> myPrint(a + this.length + 2) }
|
||||||
)
|
)
|
||||||
|
|
||||||
val a2 = <!INFERRED_TYPE_VARIABLE_INTO_POSSIBLE_EMPTY_INTERSECTION("")!>select<!>(
|
val a2 = <!INFERRED_TYPE_VARIABLE_INTO_POSSIBLE_EMPTY_INTERSECTION("TypeVariable(_RP1); CharSequence, Int; final class and interface")!>select<!>(
|
||||||
{ a: Int -> myPrint(a + this.<!UNRESOLVED_REFERENCE!>length<!> <!DEBUG_INFO_MISSING_UNRESOLVED!>+<!> 1) },
|
{ a: Int -> myPrint(a + this.<!UNRESOLVED_REFERENCE!>length<!> <!DEBUG_INFO_MISSING_UNRESOLVED!>+<!> 1) },
|
||||||
fun CharSequence.(a: Int) { myPrint(a + this.length + 2) },
|
fun CharSequence.(a: Int) { myPrint(a + this.length + 2) },
|
||||||
{ a: Int -> myPrint(a + this.<!UNRESOLVED_REFERENCE!>length<!> <!DEBUG_INFO_MISSING_UNRESOLVED!>+<!> 3) }
|
{ a: Int -> myPrint(a + this.<!UNRESOLVED_REFERENCE!>length<!> <!DEBUG_INFO_MISSING_UNRESOLVED!>+<!> 3) }
|
||||||
|
|||||||
+1
-1
@@ -13,7 +13,7 @@ fun testElvis(a: Int?, b: Int?) {
|
|||||||
if (a != null) {
|
if (a != null) {
|
||||||
doInt(b ?: a)
|
doInt(b ?: a)
|
||||||
}
|
}
|
||||||
<!INFERRED_TYPE_VARIABLE_INTO_POSSIBLE_EMPTY_INTERSECTION("T; a/A, kotlin/Int")!>doList<!>(getList() ?: emptyListOfA()) //should be an error
|
<!INFERRED_TYPE_VARIABLE_INTO_POSSIBLE_EMPTY_INTERSECTION("T; a/A, kotlin/Int; final class and interface")!>doList<!>(getList() ?: emptyListOfA()) //should be an error
|
||||||
doList(getList() ?: strangeList { doInt(it) }) //lambda was not analyzed
|
doList(getList() ?: strangeList { doInt(it) }) //lambda was not analyzed
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -13,7 +13,7 @@ fun testElvis(a: Int?, b: Int?) {
|
|||||||
if (a != null) {
|
if (a != null) {
|
||||||
doInt(b ?: <!DEBUG_INFO_SMARTCAST!>a<!>)
|
doInt(b ?: <!DEBUG_INFO_SMARTCAST!>a<!>)
|
||||||
}
|
}
|
||||||
<!INFERRED_TYPE_VARIABLE_INTO_POSSIBLE_EMPTY_INTERSECTION("")!>doList<!>(getList() ?: emptyListOfA()) //should be an error
|
<!INFERRED_TYPE_VARIABLE_INTO_POSSIBLE_EMPTY_INTERSECTION("T; A, Int; final class and interface")!>doList<!>(getList() ?: emptyListOfA()) //should be an error
|
||||||
doList(getList() ?: strangeList { doInt(it) }) //lambda was not analyzed
|
doList(getList() ?: strangeList { doInt(it) }) //lambda was not analyzed
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -12,7 +12,7 @@ fun <T: A> emptyNullableListOfA(): List<T>? = null
|
|||||||
//-------------------------------
|
//-------------------------------
|
||||||
|
|
||||||
fun testExclExcl() {
|
fun testExclExcl() {
|
||||||
<!INFERRED_TYPE_VARIABLE_INTO_POSSIBLE_EMPTY_INTERSECTION("T; a/A, kotlin/Int")!>doList<!>(emptyNullableListOfA()!!) //should be an error here
|
<!INFERRED_TYPE_VARIABLE_INTO_POSSIBLE_EMPTY_INTERSECTION("T; a/A, kotlin/Int; final class and interface")!>doList<!>(emptyNullableListOfA()!!) //should be an error here
|
||||||
val l: List<Int> = <!INITIALIZER_TYPE_MISMATCH, NEW_INFERENCE_ERROR!>id(emptyNullableListOfA()!!)<!>
|
val l: List<Int> = <!INITIALIZER_TYPE_MISMATCH, NEW_INFERENCE_ERROR!>id(emptyNullableListOfA()!!)<!>
|
||||||
|
|
||||||
doList(strangeNullableList { doInt(it) }!!) //lambda should be analyzed (at completion phase)
|
doList(strangeNullableList { doInt(it) }!!) //lambda should be analyzed (at completion phase)
|
||||||
|
|||||||
+1
-1
@@ -12,7 +12,7 @@ fun <T: A> emptyNullableListOfA(): List<T>? = null
|
|||||||
//-------------------------------
|
//-------------------------------
|
||||||
|
|
||||||
fun testExclExcl() {
|
fun testExclExcl() {
|
||||||
<!INFERRED_TYPE_VARIABLE_INTO_POSSIBLE_EMPTY_INTERSECTION("")!>doList<!>(emptyNullableListOfA()!!) //should be an error here
|
<!INFERRED_TYPE_VARIABLE_INTO_POSSIBLE_EMPTY_INTERSECTION("T; A, Int; final class and interface")!>doList<!>(emptyNullableListOfA()!!) //should be an error here
|
||||||
val l: List<Int> = <!TYPE_MISMATCH!><!TYPE_MISMATCH!>id<!>(<!TYPE_MISMATCH!>emptyNullableListOfA<!>()<!TYPE_MISMATCH!>!!<!>)<!>
|
val l: List<Int> = <!TYPE_MISMATCH!><!TYPE_MISMATCH!>id<!>(<!TYPE_MISMATCH!>emptyNullableListOfA<!>()<!TYPE_MISMATCH!>!!<!>)<!>
|
||||||
|
|
||||||
doList(strangeNullableList { doInt(it) }!!) //lambda should be analyzed (at completion phase)
|
doList(strangeNullableList { doInt(it) }!!) //lambda should be analyzed (at completion phase)
|
||||||
|
|||||||
+72
-78
@@ -12,16 +12,15 @@ import org.jetbrains.kotlin.types.isPossiblyEmpty
|
|||||||
import org.jetbrains.kotlin.types.model.*
|
import org.jetbrains.kotlin.types.model.*
|
||||||
|
|
||||||
internal object EmptyIntersectionTypeChecker {
|
internal object EmptyIntersectionTypeChecker {
|
||||||
fun computeEmptyIntersectionTypeKind(
|
fun computeEmptyIntersectionEmptiness(
|
||||||
context: TypeSystemInferenceExtensionContext,
|
context: TypeSystemInferenceExtensionContext,
|
||||||
types: Collection<KotlinTypeMarker>
|
types: Collection<KotlinTypeMarker>
|
||||||
): EmptyIntersectionTypeKind = with(context) {
|
): EmptyIntersectionTypeInfo? = with(context) {
|
||||||
if (types.isEmpty())
|
if (types.isEmpty()) return null
|
||||||
return EmptyIntersectionTypeKind.NOT_EMPTY_INTERSECTION
|
|
||||||
|
|
||||||
@Suppress("NAME_SHADOWING")
|
@Suppress("NAME_SHADOWING")
|
||||||
val types = types.toList()
|
val types = types.toList()
|
||||||
var possibleEmptyIntersectionKind: EmptyIntersectionTypeKind? = null
|
var possibleEmptyIntersectionTypeInfo: EmptyIntersectionTypeInfo? = null
|
||||||
|
|
||||||
for (i in 0 until types.size) {
|
for (i in 0 until types.size) {
|
||||||
val firstType = types[i]
|
val firstType = types[i]
|
||||||
@@ -39,22 +38,22 @@ internal object EmptyIntersectionTypeChecker {
|
|||||||
|
|
||||||
if (!mayCauseEmptyIntersection(secondSubstitutedType) && !mayCauseEmptyIntersection(firstSubstitutedType)) continue
|
if (!mayCauseEmptyIntersection(secondSubstitutedType) && !mayCauseEmptyIntersection(firstSubstitutedType)) continue
|
||||||
|
|
||||||
val kind = computeKindByHavingCommonSubtype(firstSubstitutedType, secondSubstitutedType)
|
val typeInfo = computeByHavingCommonSubtype(firstSubstitutedType, secondSubstitutedType) ?: continue
|
||||||
|
|
||||||
if (kind.isDefinitelyEmpty())
|
if (typeInfo.kind.isDefinitelyEmpty())
|
||||||
return kind
|
return typeInfo
|
||||||
|
|
||||||
if (kind.isPossiblyEmpty())
|
if (typeInfo.kind.isPossiblyEmpty())
|
||||||
possibleEmptyIntersectionKind = kind
|
possibleEmptyIntersectionTypeInfo = typeInfo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return possibleEmptyIntersectionKind ?: EmptyIntersectionTypeKind.NOT_EMPTY_INTERSECTION
|
return possibleEmptyIntersectionTypeInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun TypeSystemInferenceExtensionContext.computeKindByHavingCommonSubtype(
|
private fun TypeSystemInferenceExtensionContext.computeByHavingCommonSubtype(
|
||||||
first: KotlinTypeMarker, second: KotlinTypeMarker
|
first: KotlinTypeMarker, second: KotlinTypeMarker
|
||||||
): EmptyIntersectionTypeKind {
|
): EmptyIntersectionTypeInfo? {
|
||||||
fun extractIntersectionComponentsIfNeeded(type: KotlinTypeMarker) =
|
fun extractIntersectionComponentsIfNeeded(type: KotlinTypeMarker) =
|
||||||
if (type.typeConstructor() is IntersectionTypeConstructorMarker) {
|
if (type.typeConstructor() is IntersectionTypeConstructorMarker) {
|
||||||
type.typeConstructor().supertypes().toList()
|
type.typeConstructor().supertypes().toList()
|
||||||
@@ -62,7 +61,7 @@ internal object EmptyIntersectionTypeChecker {
|
|||||||
|
|
||||||
val expandedTypes = extractIntersectionComponentsIfNeeded(first) + extractIntersectionComponentsIfNeeded(second)
|
val expandedTypes = extractIntersectionComponentsIfNeeded(first) + extractIntersectionComponentsIfNeeded(second)
|
||||||
val typeCheckerState by lazy { newTypeCheckerState(errorTypesEqualToAnything = true, stubTypesEqualToAnything = true) }
|
val typeCheckerState by lazy { newTypeCheckerState(errorTypesEqualToAnything = true, stubTypesEqualToAnything = true) }
|
||||||
var possibleEmptyIntersectionKind: EmptyIntersectionTypeKind? = null
|
var possibleEmptyIntersectionKind: EmptyIntersectionTypeInfo? = null
|
||||||
|
|
||||||
for (i in expandedTypes.indices) {
|
for (i in expandedTypes.indices) {
|
||||||
val firstType = expandedTypes[i].withNullability(false)
|
val firstType = expandedTypes[i].withNullability(false)
|
||||||
@@ -89,7 +88,7 @@ internal object EmptyIntersectionTypeChecker {
|
|||||||
firstTypeConstructor.isDefinitelyClassTypeConstructor() && secondTypeConstructor.isDefinitelyClassTypeConstructor()
|
firstTypeConstructor.isDefinitelyClassTypeConstructor() && secondTypeConstructor.isDefinitelyClassTypeConstructor()
|
||||||
&& (firstTypeConstructor.parametersCount() == 0 || secondTypeConstructor.parametersCount() == 0)
|
&& (firstTypeConstructor.parametersCount() == 0 || secondTypeConstructor.parametersCount() == 0)
|
||||||
) {
|
) {
|
||||||
return EmptyIntersectionTypeKind.MULTIPLE_CLASSES
|
return EmptyIntersectionTypeInfo(EmptyIntersectionTypeKind.MULTIPLE_CLASSES, firstType, secondType)
|
||||||
}
|
}
|
||||||
|
|
||||||
val superTypeByFirstConstructor = AbstractTypeChecker.findCorrespondingSupertypes(
|
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
|
// Two classes can't have a common subtype if neither is a subtype of another
|
||||||
if (superTypeByFirstConstructor == null && superTypeBySecondConstructor == null && !anyInference)
|
if (superTypeByFirstConstructor == null && superTypeBySecondConstructor == null && !anyInference)
|
||||||
return EmptyIntersectionTypeKind.MULTIPLE_CLASSES
|
return EmptyIntersectionTypeInfo(EmptyIntersectionTypeKind.MULTIPLE_CLASSES, firstType, secondType)
|
||||||
|
|
||||||
if (anyInference && !canHaveCommonSubtypeWithInterface(firstType, secondType))
|
if (anyInference) {
|
||||||
return EmptyIntersectionTypeKind.INCOMPATIBLE_SUPERTYPES
|
val incompatibleSupertypes = getIncompatibleSuperTypes(firstType, secondType)
|
||||||
|
if (incompatibleSupertypes != null) {
|
||||||
|
return EmptyIntersectionTypeInfo(EmptyIntersectionTypeKind.INCOMPATIBLE_SUPERTYPES, *incompatibleSupertypes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (superTypeByFirstConstructor == null || superTypeBySecondConstructor == null) {
|
if (superTypeByFirstConstructor == null || superTypeBySecondConstructor == null) {
|
||||||
// don't have incompatible supertypes so can have a common subtype only if all types are interfaces
|
// don't have incompatible supertypes so can have a common subtype only if all types are interfaces
|
||||||
if (firstTypeConstructor.isFinalClassConstructor() || secondTypeConstructor.isFinalClassConstructor()) {
|
if (firstTypeConstructor.isFinalClassConstructor() || secondTypeConstructor.isFinalClassConstructor()) {
|
||||||
possibleEmptyIntersectionKind = EmptyIntersectionTypeKind.SINGLE_FINAL_CLASS
|
possibleEmptyIntersectionKind =
|
||||||
|
EmptyIntersectionTypeInfo(EmptyIntersectionTypeKind.SINGLE_FINAL_CLASS, firstType, secondType)
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
val argumentsIntersectionKind =
|
val argumentsIntersectionKind =
|
||||||
computeKindByCheckingTypeArguments(superTypeByFirstConstructor, superTypeBySecondConstructor)
|
computeByCheckingTypeArguments(superTypeByFirstConstructor, superTypeBySecondConstructor) ?: continue
|
||||||
|
|
||||||
if (argumentsIntersectionKind.isDefinitelyEmpty())
|
if (argumentsIntersectionKind.kind.isDefinitelyEmpty())
|
||||||
return argumentsIntersectionKind
|
return argumentsIntersectionKind
|
||||||
|
|
||||||
if (possibleEmptyIntersectionKind == null && argumentsIntersectionKind.isPossiblyEmpty())
|
if (possibleEmptyIntersectionKind == null && argumentsIntersectionKind.kind.isPossiblyEmpty())
|
||||||
possibleEmptyIntersectionKind = argumentsIntersectionKind
|
possibleEmptyIntersectionKind = argumentsIntersectionKind
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return possibleEmptyIntersectionKind ?: EmptyIntersectionTypeKind.NOT_EMPTY_INTERSECTION
|
return possibleEmptyIntersectionKind
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun TypeSystemInferenceExtensionContext.computeKindByCheckingTypeArguments(
|
private fun TypeSystemInferenceExtensionContext.computeByCheckingTypeArguments(
|
||||||
firstType: KotlinTypeMarker,
|
firstType: KotlinTypeMarker,
|
||||||
secondType: KotlinTypeMarker,
|
secondType: KotlinTypeMarker,
|
||||||
): EmptyIntersectionTypeKind {
|
): EmptyIntersectionTypeInfo? {
|
||||||
require(firstType.typeConstructor() == secondType.typeConstructor()) {
|
require(firstType.typeConstructor() == secondType.typeConstructor()) {
|
||||||
"Type constructors of the passed types should be the same to compare their arguments"
|
"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) =
|
fun areEqualTypes(firstType: KotlinTypeMarker, secondType: KotlinTypeMarker) =
|
||||||
AbstractTypeChecker.equalTypes(this, firstType, secondType)
|
AbstractTypeChecker.equalTypes(this, firstType, secondType)
|
||||||
|
|
||||||
fun Boolean.toEmptyIntersectionKind() =
|
fun Boolean.toEmptyIntersectionKind(vararg types: KotlinTypeMarker) =
|
||||||
if (this) EmptyIntersectionTypeKind.NOT_EMPTY_INTERSECTION else EmptyIntersectionTypeKind.INCOMPATIBLE_TYPE_ARGUMENTS
|
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()) {
|
for ((i, argumentOfFirst) in firstType.getArguments().withIndex()) {
|
||||||
@Suppress("NAME_SHADOWING")
|
@Suppress("NAME_SHADOWING")
|
||||||
@@ -161,43 +165,42 @@ internal object EmptyIntersectionTypeChecker {
|
|||||||
val argumentTypeOfSecond = argumentOfSecond.getType()
|
val argumentTypeOfSecond = argumentOfSecond.getType()
|
||||||
val intersectionKindOfArguments = when {
|
val intersectionKindOfArguments = when {
|
||||||
areArgumentsOfSpecifiedVariances(firstType, secondType, i, TypeVariance.INV, TypeVariance.INV) ->
|
areArgumentsOfSpecifiedVariances(firstType, secondType, i, TypeVariance.INV, TypeVariance.INV) ->
|
||||||
areEqualTypes(argumentTypeOfFirst, argumentTypeOfSecond).toEmptyIntersectionKind()
|
areEqualTypes(argumentTypeOfFirst, argumentTypeOfSecond)
|
||||||
areArgumentsOfSpecifiedVariances(firstType, secondType, i, TypeVariance.INV, TypeVariance.OUT) -> {
|
.toEmptyIntersectionKind(argumentTypeOfFirst, argumentTypeOfSecond)
|
||||||
isSubtypeOf(argumentTypeOfFirst, argumentTypeOfSecond).toEmptyIntersectionKind()
|
areArgumentsOfSpecifiedVariances(firstType, secondType, i, TypeVariance.INV, TypeVariance.OUT) ->
|
||||||
}
|
isSubtypeOf(argumentTypeOfFirst, argumentTypeOfSecond)
|
||||||
areArgumentsOfSpecifiedVariances(firstType, secondType, i, TypeVariance.INV, TypeVariance.IN) -> {
|
.toEmptyIntersectionKind(argumentTypeOfFirst, argumentTypeOfSecond)
|
||||||
isSubtypeOf(argumentTypeOfSecond, argumentTypeOfFirst).toEmptyIntersectionKind()
|
areArgumentsOfSpecifiedVariances(firstType, secondType, i, TypeVariance.INV, TypeVariance.IN) ->
|
||||||
}
|
isSubtypeOf(argumentTypeOfSecond, argumentTypeOfFirst)
|
||||||
|
.toEmptyIntersectionKind(argumentTypeOfFirst, argumentTypeOfSecond)
|
||||||
areArgumentsOfSpecifiedVariances(firstType, secondType, i, TypeVariance.IN, TypeVariance.OUT) -> {
|
areArgumentsOfSpecifiedVariances(firstType, secondType, i, TypeVariance.IN, TypeVariance.OUT) -> {
|
||||||
if (argumentTypeOfFirst.argumentsCount() == 0 && argumentTypeOfSecond.argumentsCount() == 0) {
|
if (argumentTypeOfFirst.argumentsCount() == 0 && argumentTypeOfSecond.argumentsCount() == 0) {
|
||||||
isSubtypeOf(argumentTypeOfFirst, argumentTypeOfSecond).toEmptyIntersectionKind()
|
isSubtypeOf(argumentTypeOfFirst, argumentTypeOfSecond)
|
||||||
|
.toEmptyIntersectionKind(argumentTypeOfFirst, argumentTypeOfSecond)
|
||||||
} else {
|
} else {
|
||||||
computeKindByHavingCommonSubtype(argumentTypeOfFirst, argumentTypeOfSecond)
|
computeByHavingCommonSubtype(argumentTypeOfFirst, argumentTypeOfSecond)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
areArgumentsOfSpecifiedVariances(firstType, secondType, i, TypeVariance.OUT, TypeVariance.OUT)
|
areArgumentsOfSpecifiedVariances(firstType, secondType, i, TypeVariance.OUT, TypeVariance.OUT)
|
||||||
|| areArgumentsOfSpecifiedVariances(firstType, secondType, i, TypeVariance.IN, TypeVariance.IN) -> {
|
|| 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
|
return intersectionKindOfArguments
|
||||||
|
|
||||||
if (possibleEmptyIntersectionKind == null && intersectionKindOfArguments.isPossiblyEmpty())
|
if (possibleEmptyIntersectionTypeInfo == null && intersectionKindOfArguments.kind.isPossiblyEmpty())
|
||||||
possibleEmptyIntersectionKind = intersectionKindOfArguments
|
possibleEmptyIntersectionTypeInfo = intersectionKindOfArguments
|
||||||
}
|
}
|
||||||
|
|
||||||
return possibleEmptyIntersectionKind ?: EmptyIntersectionTypeKind.NOT_EMPTY_INTERSECTION
|
return possibleEmptyIntersectionTypeInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun TypeSystemInferenceExtensionContext.canHaveCommonSubtypeWithInterface(
|
private fun TypeSystemInferenceExtensionContext.getIncompatibleSuperTypes(
|
||||||
firstType: KotlinTypeMarker, secondType: KotlinTypeMarker
|
firstType: KotlinTypeMarker, secondType: KotlinTypeMarker
|
||||||
): Boolean {
|
): Array<KotlinTypeMarker>? {
|
||||||
require(firstType.typeConstructor().isInterface() || secondType.typeConstructor().isInterface()) {
|
|
||||||
"One of the passed type should be an interface"
|
|
||||||
}
|
|
||||||
@Suppress("NAME_SHADOWING")
|
@Suppress("NAME_SHADOWING")
|
||||||
val firstType = firstType.eraseContainingTypeParameters()
|
val firstType = firstType.eraseContainingTypeParameters()
|
||||||
|
|
||||||
@@ -207,26 +210,7 @@ internal object EmptyIntersectionTypeChecker {
|
|||||||
// interface A<K>
|
// interface A<K>
|
||||||
// interface B: A<String>
|
// interface B: A<String>
|
||||||
// interface C: A<Int>
|
// interface C: A<Int>
|
||||||
// B & C can't have common subtype due to having incompatible supertypes: A<String> and A<Int>
|
// => B and C have incompatible supertypes
|
||||||
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<T>
|
|
||||||
// interface B : A<Int>
|
|
||||||
// interface C : A<String>
|
|
||||||
// => B and C have incompatible supertypes
|
|
||||||
private fun TypeSystemInferenceExtensionContext.hasIncompatibleSuperTypes(
|
|
||||||
firstType: KotlinTypeMarker, secondType: KotlinTypeMarker
|
|
||||||
): Boolean {
|
|
||||||
val superTypesOfFirst = firstType.typeConstructor().supertypes()
|
val superTypesOfFirst = firstType.typeConstructor().supertypes()
|
||||||
val firstTypeSubstitutor = createSubstitutorForSuperTypes(firstType)
|
val firstTypeSubstitutor = createSubstitutorForSuperTypes(firstType)
|
||||||
val superTypesOfSecond = secondType.typeConstructor().supertypes()
|
val superTypesOfSecond = secondType.typeConstructor().supertypes()
|
||||||
@@ -237,25 +221,33 @@ internal object EmptyIntersectionTypeChecker {
|
|||||||
val superTypeOfFirst = firstTypeSubstitutor?.safeSubstitute(superTypeOfFirst) ?: superTypeOfFirst
|
val superTypeOfFirst = firstTypeSubstitutor?.safeSubstitute(superTypeOfFirst) ?: superTypeOfFirst
|
||||||
|
|
||||||
if (areIncompatibleSuperTypes(superTypeOfFirst, secondType))
|
if (areIncompatibleSuperTypes(superTypeOfFirst, secondType))
|
||||||
return true
|
return arrayOf(superTypeOfFirst, secondType)
|
||||||
|
|
||||||
for (superTypeOfSecond in superTypesOfSecond) {
|
for (superTypeOfSecond in superTypesOfSecond) {
|
||||||
@Suppress("NAME_SHADOWING")
|
@Suppress("NAME_SHADOWING")
|
||||||
val superTypeOfSecond = secondTypeSubstitutor?.safeSubstitute(superTypeOfSecond) ?: superTypeOfSecond
|
val superTypeOfSecond = secondTypeSubstitutor?.safeSubstitute(superTypeOfSecond) ?: superTypeOfSecond
|
||||||
|
|
||||||
if (
|
if (areIncompatibleSuperTypes(firstType, superTypeOfSecond))
|
||||||
areIncompatibleSuperTypes(firstType, superTypeOfSecond)
|
return arrayOf(firstType, superTypeOfSecond)
|
||||||
|| areIncompatibleSuperTypes(superTypeOfFirst, superTypeOfSecond)
|
|
||||||
) return true
|
|
||||||
|
|
||||||
if (hasIncompatibleSuperTypes(superTypeOfFirst, superTypeOfSecond))
|
if (areIncompatibleSuperTypes(superTypeOfFirst, superTypeOfSecond))
|
||||||
return true
|
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 {
|
private fun TypeSystemInferenceExtensionContext.mayCauseEmptyIntersection(type: KotlinTypeMarker): Boolean {
|
||||||
val typeConstructor = type.typeConstructor()
|
val typeConstructor = type.typeConstructor()
|
||||||
|
|
||||||
@@ -294,4 +286,6 @@ internal object EmptyIntersectionTypeChecker {
|
|||||||
val type = argument.getType()
|
val type = argument.getType()
|
||||||
return if (type is CapturedTypeMarker) type.typeConstructorProjection() else argument
|
return if (type is CapturedTypeMarker) type.typeConstructorProjection() else argument
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class EmptyIntersectionTypeInfo(val kind: EmptyIntersectionTypeKind, vararg val casingTypes: KotlinTypeMarker)
|
||||||
@@ -5,13 +5,11 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.types
|
package org.jetbrains.kotlin.types
|
||||||
|
|
||||||
// TODO: add `SINGLE_FINAL_CLASS` later to report warnings
|
enum class EmptyIntersectionTypeKind(val description: String) {
|
||||||
enum class EmptyIntersectionTypeKind(val description: String? = null) {
|
|
||||||
NOT_EMPTY_INTERSECTION,
|
|
||||||
MULTIPLE_CLASSES("multiple incompatible classes"),
|
MULTIPLE_CLASSES("multiple incompatible classes"),
|
||||||
INCOMPATIBLE_SUPERTYPES("incompatible supertypes"),
|
INCOMPATIBLE_SUPERTYPES("incompatible supertypes"),
|
||||||
INCOMPATIBLE_TYPE_ARGUMENTS("incompatible type arguments"),
|
INCOMPATIBLE_TYPE_ARGUMENTS("incompatible type arguments"),
|
||||||
SINGLE_FINAL_CLASS
|
SINGLE_FINAL_CLASS("final class and interface")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun EmptyIntersectionTypeKind.isDefinitelyEmpty(): Boolean =
|
fun EmptyIntersectionTypeKind.isDefinitelyEmpty(): Boolean =
|
||||||
@@ -20,5 +18,3 @@ fun EmptyIntersectionTypeKind.isDefinitelyEmpty(): Boolean =
|
|||||||
|| this == EmptyIntersectionTypeKind.INCOMPATIBLE_TYPE_ARGUMENTS
|
|| this == EmptyIntersectionTypeKind.INCOMPATIBLE_TYPE_ARGUMENTS
|
||||||
|
|
||||||
fun EmptyIntersectionTypeKind.isPossiblyEmpty(): Boolean = this == EmptyIntersectionTypeKind.SINGLE_FINAL_CLASS
|
fun EmptyIntersectionTypeKind.isPossiblyEmpty(): Boolean = this == EmptyIntersectionTypeKind.SINGLE_FINAL_CLASS
|
||||||
|
|
||||||
fun EmptyIntersectionTypeKind.isEmpty(): Boolean = this != EmptyIntersectionTypeKind.NOT_EMPTY_INTERSECTION
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
package org.jetbrains.kotlin.types.model
|
package org.jetbrains.kotlin.types.model
|
||||||
|
|
||||||
import org.jetbrains.kotlin.resolve.checkers.EmptyIntersectionTypeChecker
|
import org.jetbrains.kotlin.resolve.checkers.EmptyIntersectionTypeChecker
|
||||||
|
import org.jetbrains.kotlin.resolve.checkers.EmptyIntersectionTypeInfo
|
||||||
import org.jetbrains.kotlin.types.*
|
import org.jetbrains.kotlin.types.*
|
||||||
import kotlin.contracts.ExperimentalContracts
|
import kotlin.contracts.ExperimentalContracts
|
||||||
import kotlin.contracts.contract
|
import kotlin.contracts.contract
|
||||||
@@ -326,8 +327,8 @@ interface TypeSystemInferenceExtensionContext : TypeSystemContext, TypeSystemBui
|
|||||||
|
|
||||||
fun createSubstitutorForSuperTypes(baseType: KotlinTypeMarker): TypeSubstitutorMarker?
|
fun createSubstitutorForSuperTypes(baseType: KotlinTypeMarker): TypeSubstitutorMarker?
|
||||||
|
|
||||||
fun computeEmptyIntersectionTypeKind(types: Collection<KotlinTypeMarker>): EmptyIntersectionTypeKind =
|
fun computeEmptyIntersectionTypeKind(types: Collection<KotlinTypeMarker>): EmptyIntersectionTypeInfo? =
|
||||||
EmptyIntersectionTypeChecker.computeEmptyIntersectionTypeKind(this, types)
|
EmptyIntersectionTypeChecker.computeEmptyIntersectionEmptiness(this, types)
|
||||||
|
|
||||||
private fun computeEffectiveVariance(parameter: TypeParameterMarker, argument: TypeArgumentMarker): TypeVariance? =
|
private fun computeEffectiveVariance(parameter: TypeParameterMarker, argument: TypeArgumentMarker): TypeVariance? =
|
||||||
AbstractTypeChecker.effectiveVariance(parameter.getVariance(), argument.getVariance())
|
AbstractTypeChecker.effectiveVariance(parameter.getVariance(), argument.getVariance())
|
||||||
|
|||||||
Reference in New Issue
Block a user