From 451464d635cefb0caac0f8eaf4bc8a5e34ad91cc Mon Sep 17 00:00:00 2001 From: Ilya Kirillov Date: Tue, 28 Sep 2021 19:16:32 +0200 Subject: [PATCH] FIR: do not leak ConeTypeVariableType via diagnostics ConeTypeVariableType is an internal part of type inference and should not be leaked outside it --- .../coneDiagnosticToFirDiagnostic.kt | 23 +++++++------ .../diagnostics/removeTypeVariableTypes.kt | 33 +++++++++++++++++++ .../fir/resolve/diagnostics/FirDiagnostics.kt | 4 +++ .../cli/jvm/instanceAccessBeforeSuperCall.out | 4 +-- 4 files changed, 52 insertions(+), 12 deletions(-) create mode 100644 compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/removeTypeVariableTypes.kt diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/coneDiagnosticToFirDiagnostic.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/coneDiagnosticToFirDiagnostic.kt index 5a4e9be2de1..b91c8d66667 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/coneDiagnosticToFirDiagnostic.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/coneDiagnosticToFirDiagnostic.kt @@ -190,12 +190,15 @@ private fun mapInapplicableCandidateError( rootCause.argument.source, rootCause.forbiddenNamedArgumentsTarget ) - is ArgumentTypeMismatch -> FirErrors.ARGUMENT_TYPE_MISMATCH.createOn( - rootCause.argument.source ?: source, - rootCause.expectedType, - rootCause.actualType, - rootCause.isMismatchDueToNullability - ) + is ArgumentTypeMismatch -> { + val typeContext = diagnostic.candidate.callInfo.session.typeContext + FirErrors.ARGUMENT_TYPE_MISMATCH.createOn( + rootCause.argument.source ?: source, + rootCause.expectedType.removeTypeVariableTypes(typeContext), + rootCause.argument.typeRef.coneType.removeTypeVariableTypes(typeContext), + rootCause.isMismatchDueToNullability + ) + } is NullForNotNullType -> FirErrors.NULL_FOR_NONNULL_TYPE.createOn( rootCause.argument.source ?: source ) @@ -299,8 +302,8 @@ private fun ConstraintSystemError.toDiagnostic( argument?.let { return FirErrors.ARGUMENT_TYPE_MISMATCH.createOn( it.source ?: source, - lowerConeType, - upperConeType, + lowerConeType.removeTypeVariableTypes(typeContext), + upperConeType.removeTypeVariableTypes(typeContext), typeMismatchDueToNullability ) } @@ -319,8 +322,8 @@ private fun ConstraintSystemError.toDiagnostic( FirErrors.TYPE_MISMATCH.createOn( qualifiedAccessSource ?: source, - upperConeType, - inferredType, + upperConeType.removeTypeVariableTypes(typeContext), + inferredType.removeTypeVariableTypes(typeContext), typeMismatchDueToNullability ) } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/removeTypeVariableTypes.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/removeTypeVariableTypes.kt new file mode 100644 index 00000000000..66205d99d13 --- /dev/null +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/removeTypeVariableTypes.kt @@ -0,0 +1,33 @@ +/* + * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.fir.analysis.diagnostics + +import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeUnknownLambdaParameterTypeDiagnostic +import org.jetbrains.kotlin.fir.resolve.substitution.AbstractConeSubstitutor +import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterLookupTag +import org.jetbrains.kotlin.fir.types.* +import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl + +internal fun ConeKotlinType.removeTypeVariableTypes(typeContext: ConeTypeContext): ConeKotlinType { + val substitutor = TypeVariableTypeRemovingSubstitutor(typeContext) + return substitutor.substituteOrSelf(this) +} + +private class TypeVariableTypeRemovingSubstitutor(typeContext: ConeTypeContext) : AbstractConeSubstitutor(typeContext) { + override fun substituteType(type: ConeKotlinType): ConeKotlinType? = when (type) { + is ConeTypeVariableType -> convertTypeVariableType(type) + else -> null + } + + private fun convertTypeVariableType(type: ConeTypeVariableType): ConeKotlinType { + val originalTypeParameter = type.lookupTag.originalTypeParameter + if (originalTypeParameter != null) { + check(originalTypeParameter is ConeTypeParameterLookupTag) + return ConeTypeParameterTypeImpl(originalTypeParameter, type.isNullable, type.attributes) + } + return ConeClassErrorType(ConeUnknownLambdaParameterTypeDiagnostic()) + } +} diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/diagnostics/FirDiagnostics.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/diagnostics/FirDiagnostics.kt index 6bef1a4778b..5663db23d90 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/diagnostics/FirDiagnostics.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/diagnostics/FirDiagnostics.kt @@ -216,6 +216,10 @@ class ConePropertyAsOperator(val symbol: FirPropertySymbol) : ConeDiagnostic { override val reason: String get() = "Cannot use a property as an operator" } +class ConeUnknownLambdaParameterTypeDiagnostic : ConeDiagnostic { + override val reason: String get() = "Unknown return lambda parameter type" +} + private fun describeSymbol(symbol: FirBasedSymbol<*>): String { return when (symbol) { is FirClassLikeSymbol<*> -> symbol.classId.asString() diff --git a/compiler/testData/cli/jvm/instanceAccessBeforeSuperCall.out b/compiler/testData/cli/jvm/instanceAccessBeforeSuperCall.out index b4081d81db5..d61d7a63fb2 100644 --- a/compiler/testData/cli/jvm/instanceAccessBeforeSuperCall.out +++ b/compiler/testData/cli/jvm/instanceAccessBeforeSuperCall.out @@ -13,10 +13,10 @@ compiler/testData/cli/jvm/instanceAccessBeforeSuperCall.kt:2:74: error: unresolv compiler/testData/cli/jvm/instanceAccessBeforeSuperCall.kt:7:20: error: 'this' is not defined in this context class B(other: B = this) ^ -compiler/testData/cli/jvm/instanceAccessBeforeSuperCall.kt:10:32: error: argument type mismatch: actual type is kotlin/Int but kotlin/Function0 was expected +compiler/testData/cli/jvm/instanceAccessBeforeSuperCall.kt:10:32: error: argument type mismatch: actual type is kotlin/Function0'' before superclass constructor has been called> but kotlin/Int was expected constructor(x: Int) : this({ ^ -compiler/testData/cli/jvm/instanceAccessBeforeSuperCall.kt:12:9: error: argument type mismatch: actual type is ERROR CLASS: Cannot access '''' before superclass constructor has been called but TypeVariable(_L) was expected +compiler/testData/cli/jvm/instanceAccessBeforeSuperCall.kt:12:9: error: argument type mismatch: actual type is ERROR CLASS: Cannot access '''' before superclass constructor has been called but ERROR CLASS: Unknown return lambda parameter type was expected this ^ compiler/testData/cli/jvm/instanceAccessBeforeSuperCall.kt:12:9: error: cannot access '' before superclass constructor has been called