diff --git a/analysis/analysis-api/testData/components/psiTypeProvider/psiType/forDeclaration/suspendFunctionValueParameterNoStdlib.txt b/analysis/analysis-api/testData/components/psiTypeProvider/psiType/forDeclaration/suspendFunctionValueParameterNoStdlib.txt index 3bb58da41c5..9cc8d64b973 100644 --- a/analysis/analysis-api/testData/components/psiTypeProvider/psiType/forDeclaration/suspendFunctionValueParameterNoStdlib.txt +++ b/analysis/analysis-api/testData/components/psiTypeProvider/psiType/forDeclaration/suspendFunctionValueParameterNoStdlib.txt @@ -1,2 +1,2 @@ KtType: suspend (kotlin.Int) -> kotlin.Unit -PsiType: PsiType:Function2 +PsiType: PsiType:Function2, ? extends Object> diff --git a/analysis/analysis-api/testData/referenceResolve/withErrors/CoroutineSuspensionPoint.txt b/analysis/analysis-api/testData/referenceResolve/withErrors/CoroutineSuspensionPoint.txt index dae32552518..a181c6adcf5 100644 --- a/analysis/analysis-api/testData/referenceResolve/withErrors/CoroutineSuspensionPoint.txt +++ b/analysis/analysis-api/testData/referenceResolve/withErrors/CoroutineSuspensionPoint.txt @@ -1,2 +1,2 @@ Resolved to: -0: (in Controller) suspend fun suspendHere(x: ERROR_TYPE(Symbol not found for Continuation)) \ No newline at end of file +0: (in Controller) suspend fun suspendHere(x: ERROR_TYPE(Symbol not found for Continuation)) diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/lightClassUtils.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/lightClassUtils.kt index 601b25baa1c..cfc8913dbb4 100644 --- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/lightClassUtils.kt +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/lightClassUtils.kt @@ -12,11 +12,12 @@ import org.jetbrains.kotlin.analysis.api.KtAllowAnalysisOnEdt import org.jetbrains.kotlin.analysis.api.KtAnalysisSession import org.jetbrains.kotlin.analysis.api.analyze import org.jetbrains.kotlin.analysis.api.lifetime.allowAnalysisOnEdt +import org.jetbrains.kotlin.builtins.StandardNames import org.jetbrains.kotlin.analysis.project.structure.KtModule import org.jetbrains.kotlin.psi.KtElement internal fun PsiElement.nonExistentType(): PsiType = - JavaPsiFacade.getElementFactory(project).createTypeFromText("error.NonExistentClass", this) + JavaPsiFacade.getElementFactory(project).createTypeFromText(StandardNames.NON_EXISTENT_CLASS.asString(), this) @OptIn(KtAllowAnalysisOnEdt::class) private inline fun allowLightClassesOnEdt(crossinline action: () -> E): E = allowAnalysisOnEdt(action) diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.kt index c77f986c5a8..f5c4128bbd7 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.kt @@ -59,7 +59,6 @@ import org.jetbrains.kotlin.resolve.calls.model.VarargValueArgument import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns import org.jetbrains.kotlin.resolve.descriptorUtil.classId import org.jetbrains.kotlin.resolve.descriptorUtil.isPublishedApi -import org.jetbrains.kotlin.resolve.descriptorUtil.module import org.jetbrains.kotlin.resolve.jvm.AsmTypes.DEFAULT_CONSTRUCTOR_MARKER import org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE import org.jetbrains.kotlin.resolve.jvm.JAVA_LANG_RECORD_FQ_NAME @@ -76,6 +75,7 @@ import org.jetbrains.kotlin.types.checker.convertVariance import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.* import org.jetbrains.kotlin.types.model.* import org.jetbrains.kotlin.util.OperatorNameConventions +import org.jetbrains.kotlin.utils.addToStdlib.zipWithNulls import org.jetbrains.org.objectweb.asm.Opcodes.* import org.jetbrains.org.objectweb.asm.Type import org.jetbrains.org.objectweb.asm.commons.Method @@ -1446,10 +1446,10 @@ class KotlinTypeMapper @JvmOverloads constructor( SimpleClassicTypeSystemContext.getVarianceForWildcard(parameter, projection, mode) private fun TypeSystemCommonBackendContext.getVarianceForWildcard( - parameter: TypeParameterMarker, projection: TypeArgumentMarker, mode: TypeMappingMode + parameter: TypeParameterMarker?, projection: TypeArgumentMarker, mode: TypeMappingMode ): Variance { val projectionKind = projection.getVariance().convertVariance() - val parameterVariance = parameter.getVariance().convertVariance() + val parameterVariance = parameter?.getVariance()?.convertVariance() ?: Variance.INVARIANT if (parameterVariance == Variance.INVARIANT) { return projectionKind @@ -1465,7 +1465,7 @@ class KotlinTypeMapper @JvmOverloads constructor( return Variance.INVARIANT } - if (parameterVariance == Variance.IN_VARIANCE && isMostPreciseContravariantArgument(projection.getType(), parameter)) { + if (parameterVariance == Variance.IN_VARIANCE && isMostPreciseContravariantArgument(projection.getType())) { return Variance.INVARIANT } } @@ -1484,10 +1484,11 @@ class KotlinTypeMapper @JvmOverloads constructor( mode: TypeMappingMode, mapType: (KotlinTypeMarker, JvmSignatureWriter, TypeMappingMode) -> Type ) { - for ((parameter, argument) in parameters.zip(arguments)) { + for ((parameter, argument) in parameters.zipWithNulls(arguments)) { + if (argument == null) break if (argument.isStarProjection() || // In == In<*, Foo> -> In - argument.getType().isNothing() && parameter.getVariance() == TypeVariance.IN + argument.getType().isNothing() && parameter?.getVariance() == TypeVariance.IN ) { signatureVisitor.writeUnboundedWildcard() } else { @@ -1496,10 +1497,11 @@ class KotlinTypeMapper @JvmOverloads constructor( signatureVisitor.writeTypeArgument(projectionKind) + val parameterVariance = parameter?.getVariance()?.convertVariance() ?: Variance.INVARIANT mapType( argument.getType(), signatureVisitor, argumentMode.toGenericArgumentMode( - getEffectiveVariance(parameter.getVariance().convertVariance(), argument.getVariance().convertVariance()) + getEffectiveVariance(parameterVariance, argument.getVariance().convertVariance()) ) ) diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/typeMappingUtil.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/typeMappingUtil.kt index 17d39d6a5a5..fe37cc3befd 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/typeMappingUtil.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/typeMappingUtil.kt @@ -37,11 +37,8 @@ import org.jetbrains.kotlin.types.checker.SimpleClassicTypeSystemContext import org.jetbrains.kotlin.types.checker.convertVariance import org.jetbrains.kotlin.types.getEffectiveVariance import org.jetbrains.kotlin.types.model.KotlinTypeMarker -import org.jetbrains.kotlin.types.model.TypeParameterMarker -// TODO: probably class upper bound should be used -@Suppress("UNUSED_PARAMETER") -fun TypeSystemCommonBackendContext.isMostPreciseContravariantArgument(type: KotlinTypeMarker, parameter: TypeParameterMarker): Boolean = +fun TypeSystemCommonBackendContext.isMostPreciseContravariantArgument(type: KotlinTypeMarker): Boolean = type.typeConstructor().isAnyConstructor() fun TypeSystemCommonBackendContext.isMostPreciseCovariantArgument(type: KotlinTypeMarker): Boolean = @@ -62,7 +59,7 @@ private fun TypeSystemCommonBackendContext.canHaveSubtypesIgnoringNullability(ko val effectiveVariance = getEffectiveVariance(parameter.getVariance().convertVariance(), projectionKind) if (effectiveVariance == Variance.OUT_VARIANCE && !isMostPreciseCovariantArgument(type)) return true - if (effectiveVariance == Variance.IN_VARIANCE && !isMostPreciseContravariantArgument(type, parameter)) return true + if (effectiveVariance == Variance.IN_VARIANCE && !isMostPreciseContravariantArgument(type)) return true } return false diff --git a/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/ConeTypes.kt b/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/ConeTypes.kt index cd0f4839461..03b9e603493 100644 --- a/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/ConeTypes.kt +++ b/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/ConeTypes.kt @@ -43,14 +43,12 @@ class ConeClassLikeErrorLookupTag(override val classId: ClassId) : ConeClassLike class ConeErrorType( val diagnostic: ConeDiagnostic, val isUninferredParameter: Boolean = false, + override val typeArguments: Array = EMPTY_ARRAY, override val attributes: ConeAttributes = ConeAttributes.Empty ) : ConeClassLikeType() { override val lookupTag: ConeClassLikeLookupTag get() = ConeClassLikeErrorLookupTag(ClassId.fromString("")) - override val typeArguments: Array - get() = EMPTY_ARRAY - override val nullability: ConeNullability get() = ConeNullability.UNKNOWN diff --git a/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirJvmTypeMapper.kt b/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirJvmTypeMapper.kt index 02e8636647c..d573e9af358 100644 --- a/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirJvmTypeMapper.kt +++ b/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirJvmTypeMapper.kt @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.fir.backend.jvm +import org.jetbrains.kotlin.builtins.StandardNames import org.jetbrains.kotlin.builtins.functions.BuiltInFunctionArity import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap import org.jetbrains.kotlin.codegen.signature.JvmSignatureWriter @@ -25,6 +26,7 @@ import org.jetbrains.kotlin.fir.resolve.toSymbol import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag import org.jetbrains.kotlin.fir.symbols.ConeClassifierLookupTag import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterLookupTag +import org.jetbrains.kotlin.fir.symbols.impl.ConeClassLikeLookupTagImpl import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirTypeAliasSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol @@ -43,9 +45,16 @@ import org.jetbrains.kotlin.types.model.SimpleTypeMarker import org.jetbrains.kotlin.types.model.TypeConstructorMarker import org.jetbrains.kotlin.types.model.TypeParameterMarker import org.jetbrains.kotlin.utils.addToStdlib.runIf +import org.jetbrains.kotlin.utils.addToStdlib.runUnless import org.jetbrains.org.objectweb.asm.Type class FirJvmTypeMapper(val session: FirSession) : TypeMappingContext, FirSessionComponent { + companion object { + val NON_EXISTENT_ID = ClassId.topLevel(StandardNames.NON_EXISTENT_CLASS) + private val typeForNonExistentClass = ConeClassLikeLookupTagImpl(NON_EXISTENT_ID) + .constructClassType(emptyArray(), isNullable = false) + } + override val typeContext = ConeTypeSystemCommonBackendContextForTypeMapping(session.typeContext) fun mapType(type: ConeKotlinType, mode: TypeMappingMode = TypeMappingMode.DEFAULT, sw: JvmSignatureWriter? = null): Type { @@ -67,7 +76,7 @@ class FirJvmTypeMapper(val session: FirSession) : TypeMappingContext buildPossiblyInnerType(symbol, 0) @@ -107,7 +120,7 @@ class FirJvmTypeMapper(val session: FirSession) : TypeMappingContext null - } + } ?: createForError() } private fun ConeClassLikeType.parentClassOrNull(): FirRegularClassSymbol? { @@ -135,7 +148,7 @@ class FirJvmTypeMapper(val session: FirSession) : TypeMappingContext, private val outerType: PossiblyInnerConeType? ) { @@ -147,9 +160,9 @@ class FirJvmTypeMapper(val session: FirSession) : TypeMappingContext BuiltInFunctionArity.BIG_ARITY) @@ -183,16 +196,20 @@ class FirJvmTypeMapper(val session: FirSession) : TypeMappingContext T.withArguments(arguments: Array this + is ConeErrorType -> ConeErrorType(diagnostic, isUninferredParameter, arguments, attributes) as T is ConeClassLikeTypeImpl -> ConeClassLikeTypeImpl(lookupTag, arguments, nullability.isNullable) as T is ConeDefinitelyNotNullType -> ConeDefinitelyNotNullType(original.withArguments(arguments)) as T else -> error("Not supported: $this: ${this.renderForDebugging()}") diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/CompletionModeCalculator.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/CompletionModeCalculator.kt index edef27fe732..d36067373e4 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/CompletionModeCalculator.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/CompletionModeCalculator.kt @@ -127,7 +127,7 @@ private class CalculatorForNestedCall( ) { val unwrappedType = type.lowerBoundIfFlexible() val typeArgumentsCount = unwrappedType.argumentsCount() - if (typeArgumentsCount > 0) { + if (typeArgumentsCount > 0 && !unwrappedType.isError()) { for (position in 0 until typeArgumentsCount) { val argument = unwrappedType.getArgument(position) val parameter = unwrappedType.typeConstructor().getParameter(position) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/providers/impl/FirTypeResolverImpl.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/providers/impl/FirTypeResolverImpl.kt index c8bc714d771..82de531bd91 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/providers/impl/FirTypeResolverImpl.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/providers/impl/FirTypeResolverImpl.kt @@ -235,34 +235,6 @@ class FirTypeResolverImpl(private val session: FirSession) : FirTypeResolver() { TypeResolutionResult.Unresolved -> null to null } - if (symbol == null || symbol !is FirClassifierSymbol<*>) { - val diagnostic = when { - symbol?.fir is FirEnumEntry -> { - if (isOperandOfIsOperator) { - ConeSimpleDiagnostic("'is' operator can not be applied to an enum entry.", DiagnosticKind.IsEnumEntry) - } else { - ConeSimpleDiagnostic("An enum entry should not be used as a type.", DiagnosticKind.EnumEntryAsType) - } - } - result is TypeResolutionResult.Ambiguity -> { - ConeAmbiguityError(typeRef.qualifier.last().name, result.typeCandidates.first().applicability, result.typeCandidates) - } - else -> { - ConeUnresolvedTypeQualifierError(typeRef.qualifier, isNullable = typeRef.isMarkedNullable) - } - } - return ConeErrorType(diagnostic, attributes = typeRef.annotations.computeTypeAttributes(session)) - } - if (symbol is FirTypeParameterSymbol) { - for (part in typeRef.qualifier) { - if (part.typeArgumentList.typeArguments.isNotEmpty()) { - return ConeErrorType( - ConeUnexpectedTypeArgumentsError("Type arguments not allowed", part.typeArgumentList.source) - ) - } - } - } - val allTypeArguments = mutableListOf() var typeArgumentsCount = 0 @@ -351,8 +323,44 @@ class FirTypeResolverImpl(private val session: FirSession) : FirTypeResolver() { } } + val resultingArguments = allTypeArguments.toTypedArray() + + if (symbol == null || symbol !is FirClassifierSymbol<*>) { + val diagnostic = when { + symbol?.fir is FirEnumEntry -> { + if (isOperandOfIsOperator) { + ConeSimpleDiagnostic("'is' operator can not be applied to an enum entry.", DiagnosticKind.IsEnumEntry) + } else { + ConeSimpleDiagnostic("An enum entry should not be used as a type.", DiagnosticKind.EnumEntryAsType) + } + } + result is TypeResolutionResult.Ambiguity -> { + ConeAmbiguityError(typeRef.qualifier.last().name, result.typeCandidates.first().applicability, result.typeCandidates) + } + else -> { + ConeUnresolvedTypeQualifierError(typeRef.qualifier, isNullable = typeRef.isMarkedNullable) + } + } + return ConeErrorType( + diagnostic, + typeArguments = resultingArguments, + attributes = typeRef.annotations.computeTypeAttributes(session) + ) + } + + if (symbol is FirTypeParameterSymbol) { + for (part in typeRef.qualifier) { + if (part.typeArgumentList.typeArguments.isNotEmpty()) { + return ConeErrorType( + ConeUnexpectedTypeArgumentsError("Type arguments not allowed", part.typeArgumentList.source), + typeArguments = resultingArguments + ) + } + } + } + return symbol.constructType( - allTypeArguments.toTypedArray(), + resultingArguments, typeRef.isMarkedNullable, typeRef.annotations.computeTypeAttributes(session) ).also { diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightField.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightField.kt index bdf4fcd569c..1272783174e 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightField.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightField.kt @@ -17,6 +17,7 @@ import org.jetbrains.annotations.NotNull import org.jetbrains.kotlin.asJava.LightClassGenerationSupport import org.jetbrains.kotlin.asJava.builder.LightMemberOriginForDeclaration import org.jetbrains.kotlin.asJava.elements.* +import org.jetbrains.kotlin.builtins.StandardNames import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.PropertyDescriptor import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor @@ -142,7 +143,7 @@ internal open class KtUltraLightFieldImpl protected constructor( get() = type private val _type: PsiType by lazyPub { - fun nonExistent() = JavaPsiFacade.getElementFactory(project).createTypeFromText("error.NonExistentClass", declaration) + fun nonExistent() = JavaPsiFacade.getElementFactory(project).createTypeFromText(StandardNames.NON_EXISTENT_CLASS.asString(), declaration) when { (declaration is KtProperty && declaration.hasDelegate()) || declaration is KtEnumEntry || declaration is KtObjectDeclaration -> diff --git a/core/compiler.common/src/org/jetbrains/kotlin/builtins/StandardNames.kt b/core/compiler.common/src/org/jetbrains/kotlin/builtins/StandardNames.kt index bc52c5a83d1..50faf517a8f 100644 --- a/core/compiler.common/src/org/jetbrains/kotlin/builtins/StandardNames.kt +++ b/core/compiler.common/src/org/jetbrains/kotlin/builtins/StandardNames.kt @@ -79,6 +79,8 @@ object StandardNames { @JvmField val KOTLIN_INTERNAL_FQ_NAME = BUILT_INS_PACKAGE_FQ_NAME.child(Name.identifier("internal")) + val NON_EXISTENT_CLASS = FqName("error.NonExistentClass") + @JvmField val BUILT_INS_PACKAGE_FQ_NAMES = setOf( BUILT_INS_PACKAGE_FQ_NAME, diff --git a/core/util.runtime/src/org/jetbrains/kotlin/utils/addToStdlib.kt b/core/util.runtime/src/org/jetbrains/kotlin/utils/addToStdlib.kt index 7b62cdf7345..29fc1688c6c 100644 --- a/core/util.runtime/src/org/jetbrains/kotlin/utils/addToStdlib.kt +++ b/core/util.runtime/src/org/jetbrains/kotlin/utils/addToStdlib.kt @@ -300,3 +300,23 @@ fun > enumSetOf(element: T, vararg elements: T): EnumSet = EnumSe fun shouldNotBeCalled(message: String = "should not be called"): Nothing { error(message) } + +private inline fun Iterable.zipWithDefault(other: Iterable, leftDefault: () -> T, rightDefault: () -> R): List> { + val leftIterator = this.iterator() + val rightIterator = other.iterator() + return buildList { + while (leftIterator.hasNext() && rightIterator.hasNext()) { + add(leftIterator.next() to rightIterator.next()) + } + while (leftIterator.hasNext()) { + add(leftIterator.next() to rightDefault()) + } + while (rightIterator.hasNext()) { + add(leftDefault() to rightIterator.next()) + } + } +} + +fun Iterable.zipWithNulls(other: Iterable): List> { + return zipWithDefault(other, { null }, { null }) +}