[FIR] Various checkers performance fixes
This commit is contained in:
+10
@@ -0,0 +1,10 @@
|
||||
open class A
|
||||
open class B : A()
|
||||
|
||||
open class First<T> {
|
||||
open fun test(item: T) {}
|
||||
}
|
||||
|
||||
open class Second : First<A>() {
|
||||
override fun test(item: A) {}
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
FILE: someOverridesTest.kt
|
||||
public open class A : R|kotlin/Any| {
|
||||
public constructor(): R|A| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
}
|
||||
public open class B : R|A| {
|
||||
public constructor(): R|B| {
|
||||
super<R|A|>()
|
||||
}
|
||||
|
||||
}
|
||||
public open class First<T> : R|kotlin/Any| {
|
||||
public constructor<T>(): R|First<T>| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public open fun test(item: R|T|): R|kotlin/Unit| {
|
||||
}
|
||||
|
||||
}
|
||||
public open class Second : R|First<A>| {
|
||||
public constructor(): R|Second| {
|
||||
super<R|First<A>|>()
|
||||
}
|
||||
|
||||
public open override fun test(item: R|A|): R|kotlin/Unit| {
|
||||
}
|
||||
|
||||
}
|
||||
Generated
+5
@@ -1056,6 +1056,11 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/sealedSupertype.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("someOverridesTest.kt")
|
||||
public void testSomeOverridesTest() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/someOverridesTest.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("superIsNotAnExpression.kt")
|
||||
public void testSuperIsNotAnExpression() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/superIsNotAnExpression.kt");
|
||||
|
||||
+5
@@ -1056,6 +1056,11 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/sealedSupertype.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("someOverridesTest.kt")
|
||||
public void testSomeOverridesTest() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/someOverridesTest.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("superIsNotAnExpression.kt")
|
||||
public void testSuperIsNotAnExpression() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/superIsNotAnExpression.kt");
|
||||
|
||||
+155
-63
@@ -9,9 +9,7 @@ import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.symbols.CallableId
|
||||
import org.jetbrains.kotlin.fir.types.FirErrorTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
@@ -19,78 +17,172 @@ import org.jetbrains.kotlin.name.Name
|
||||
* Provides representations for FirElement's.
|
||||
*/
|
||||
interface FirDeclarationPresenter {
|
||||
open class RepresentationBuilder {
|
||||
var receiver = ""
|
||||
var name = ""
|
||||
|
||||
open fun build() = "[$receiver] $name"
|
||||
fun StringBuilder.appendRepresentation(it: FirElement) {
|
||||
append("NO_REPRESENTATION")
|
||||
}
|
||||
|
||||
fun buildRepresentation(init: RepresentationBuilder.() -> Unit): String {
|
||||
return RepresentationBuilder().apply(init).build()
|
||||
fun StringBuilder.appendRepresentation(it: ClassId) {
|
||||
append(it.packageFqName.asString())
|
||||
append('/')
|
||||
append(it.relativeClassName.asString())
|
||||
}
|
||||
|
||||
class FunctionRepresentationBuilder : RepresentationBuilder() {
|
||||
var representsOperator = false
|
||||
var typeArguments = ""
|
||||
var parameters = ""
|
||||
|
||||
override fun build() = "<$typeArguments> [$receiver] ${if (representsOperator) "operator " else ""}$name ($parameters)"
|
||||
}
|
||||
|
||||
fun buildFunctionRepresentation(init: FunctionRepresentationBuilder.() -> Unit): String {
|
||||
return FunctionRepresentationBuilder().apply(init).build()
|
||||
}
|
||||
|
||||
fun represent(it: FirElement) = "NO_REPRESENTATION"
|
||||
|
||||
fun represent(it: ClassId) = it.packageFqName.asString() + '/' + it.relativeClassName.asString()
|
||||
|
||||
fun represent(it: CallableId) = if (it.className != null) {
|
||||
it.packageName.asString() + '/' + it.className + '.' + it.callableName
|
||||
} else {
|
||||
it.packageName.asString() + '/' + it.callableName
|
||||
}
|
||||
|
||||
fun represent(it: FirTypeRef) = when (it) {
|
||||
is FirResolvedTypeRef -> it.type.toString()
|
||||
is FirErrorTypeRef -> "ERROR"
|
||||
else -> "?"
|
||||
}
|
||||
|
||||
fun represent(it: FirTypeParameter) = it.name.asString() + " : " + it.bounds
|
||||
.map { represent(it) }
|
||||
.sorted()
|
||||
.joinToString()
|
||||
|
||||
fun represent(it: FirValueParameter): String {
|
||||
val prefix = if (it.isVararg) "vararg " else ""
|
||||
return prefix + " " + represent(it.returnTypeRef)
|
||||
}
|
||||
|
||||
fun represent(it: FirProperty) = buildRepresentation {
|
||||
it.receiverTypeRef?.let {
|
||||
receiver = represent(it)
|
||||
fun StringBuilder.appendRepresentation(it: CallableId) {
|
||||
if (it.className != null) {
|
||||
append(it.packageName.asString())
|
||||
append('/')
|
||||
append(it.className)
|
||||
append('.')
|
||||
append(it.callableName)
|
||||
} else {
|
||||
append(it.packageName.asString())
|
||||
append('/')
|
||||
append(it.callableName)
|
||||
}
|
||||
name = represent(it.symbol.callableId)
|
||||
}
|
||||
|
||||
fun represent(it: FirSimpleFunction) = buildFunctionRepresentation {
|
||||
typeArguments = it.typeParameters.joinToString { represent(it) }
|
||||
it.receiverTypeRef?.let {
|
||||
receiver = represent(it)
|
||||
fun StringBuilder.appendRepresentation(it: ConeTypeProjection) {
|
||||
when (it) {
|
||||
ConeStarProjection -> {
|
||||
append('*')
|
||||
}
|
||||
is ConeKotlinTypeProjectionIn -> {
|
||||
append("in ")
|
||||
appendRepresentation(it.type)
|
||||
}
|
||||
is ConeKotlinTypeProjectionOut -> {
|
||||
append("out ")
|
||||
appendRepresentation(it.type)
|
||||
}
|
||||
is ConeKotlinType -> {
|
||||
appendRepresentation(it)
|
||||
}
|
||||
}
|
||||
representsOperator = it.isOperator
|
||||
name = represent(it.symbol.callableId)
|
||||
parameters = it.valueParameters.joinToString { represent(it) }
|
||||
}
|
||||
|
||||
fun represent(it: FirTypeAlias) = buildRepresentation {
|
||||
name = represent(it.symbol.classId)
|
||||
fun StringBuilder.appendRepresentation(it: ConeKotlinType) {
|
||||
when (it) {
|
||||
is ConeDefinitelyNotNullType -> {
|
||||
appendRepresentation(it.original)
|
||||
append(it.nullability.suffix)
|
||||
}
|
||||
is ConeClassErrorType -> {
|
||||
append("ERROR(")
|
||||
append(it.diagnostic.reason)
|
||||
append(')')
|
||||
}
|
||||
is ConeCapturedType -> {
|
||||
append(it.constructor.projection)
|
||||
append(it.nullability.suffix)
|
||||
}
|
||||
is ConeClassLikeType -> {
|
||||
appendRepresentation(it.lookupTag.classId)
|
||||
if (it.typeArguments.isNotEmpty()) {
|
||||
append('<')
|
||||
it.typeArguments.forEach { that ->
|
||||
appendRepresentation(that)
|
||||
append(',')
|
||||
}
|
||||
append('>')
|
||||
}
|
||||
append(it.nullability.suffix)
|
||||
}
|
||||
is ConeLookupTagBasedType -> {
|
||||
append(it.lookupTag.name)
|
||||
append(it.nullability.suffix)
|
||||
}
|
||||
is ConeIntegerLiteralType -> {
|
||||
append(it.value)
|
||||
append(it.nullability.suffix)
|
||||
}
|
||||
is ConeFlexibleType,
|
||||
is ConeIntersectionType,
|
||||
is ConeStubType -> {
|
||||
append("ERROR")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun represent(it: FirRegularClass) = buildRepresentation {
|
||||
name = represent(it.symbol.classId)
|
||||
fun StringBuilder.appendRepresentation(it: FirTypeRef) {
|
||||
when (it) {
|
||||
is FirResolvedTypeRef -> appendRepresentation(it.type)
|
||||
is FirErrorTypeRef -> append("ERROR")
|
||||
else -> append("?")
|
||||
}
|
||||
}
|
||||
|
||||
fun StringBuilder.appendRepresentation(it: FirTypeParameter) {
|
||||
append(it.name.asString())
|
||||
append(':')
|
||||
when (it.bounds.size) {
|
||||
0 -> {
|
||||
}
|
||||
1 -> {
|
||||
appendRepresentation(it.bounds[0])
|
||||
}
|
||||
else -> {
|
||||
val set = sortedSetOf<String>()
|
||||
it.bounds.forEach { that ->
|
||||
set.add(buildString { appendRepresentation(that) })
|
||||
}
|
||||
set.forEach { that ->
|
||||
append(that)
|
||||
append(',')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun StringBuilder.appendRepresentation(it: FirValueParameter) {
|
||||
if (it.isVararg) {
|
||||
append("vararg ")
|
||||
}
|
||||
appendRepresentation(it.returnTypeRef)
|
||||
}
|
||||
|
||||
fun represent(it: FirProperty) = buildString {
|
||||
append('[')
|
||||
it.receiverTypeRef?.let {
|
||||
appendRepresentation(it)
|
||||
}
|
||||
append(']')
|
||||
appendRepresentation(it.symbol.callableId)
|
||||
}
|
||||
|
||||
fun represent(it: FirSimpleFunction) = buildString {
|
||||
append('<')
|
||||
it.typeParameters.forEach {
|
||||
appendRepresentation(it)
|
||||
append(',')
|
||||
}
|
||||
append('>')
|
||||
append('[')
|
||||
it.receiverTypeRef?.let {
|
||||
appendRepresentation(it)
|
||||
}
|
||||
append(']')
|
||||
if (it.isOperator) {
|
||||
append("operator ")
|
||||
}
|
||||
appendRepresentation(it.symbol.callableId)
|
||||
append('(')
|
||||
it.valueParameters.forEach {
|
||||
appendRepresentation(it)
|
||||
append(',')
|
||||
}
|
||||
append(')')
|
||||
}
|
||||
|
||||
fun represent(it: FirTypeAlias) = buildString {
|
||||
append('[')
|
||||
append(']')
|
||||
appendRepresentation(it.symbol.classId)
|
||||
}
|
||||
|
||||
fun represent(it: FirRegularClass) = buildString {
|
||||
append('[')
|
||||
append(']')
|
||||
appendRepresentation(it.symbol.classId)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -28,7 +28,7 @@ abstract class CheckerContext {
|
||||
* T instance or null if no such item could be found.
|
||||
*/
|
||||
inline fun <reified T : FirDeclaration> findClosest(): T? {
|
||||
for (it in containingDeclarations.reversed()) {
|
||||
for (it in containingDeclarations.asReversed()) {
|
||||
return it as? T ?: continue
|
||||
}
|
||||
|
||||
|
||||
+2
-3
@@ -27,7 +27,7 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
|
||||
FirConflictingProjectionChecker,
|
||||
)
|
||||
|
||||
override val memberDeclarationCheckers: List<FirMemberDeclarationChecker> = listOf(
|
||||
override val memberDeclarationCheckers: List<FirMemberDeclarationChecker> =listOf(
|
||||
FirInfixFunctionDeclarationChecker,
|
||||
FirExposedVisibilityDeclarationChecker,
|
||||
FirCommonConstructorDelegationIssuesChecker,
|
||||
@@ -41,11 +41,10 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
|
||||
FirEnumClassSimpleChecker,
|
||||
FirSealedSupertypeChecker,
|
||||
FirInapplicableLateinitChecker,
|
||||
FirTypeMismatchOnOverrideChecker,
|
||||
)
|
||||
|
||||
override val regularClassCheckers: List<FirRegularClassChecker> = listOf(
|
||||
|
||||
FirTypeMismatchOnOverrideChecker,
|
||||
)
|
||||
|
||||
override val constructorCheckers: List<FirConstructorChecker> = listOf(
|
||||
|
||||
+17
-17
@@ -13,25 +13,20 @@ import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.min
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
|
||||
object FirConflictingProjectionChecker : FirBasicDeclarationChecker() {
|
||||
override fun check(declaration: FirDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
// we can't just check for FirTypedDeclaration
|
||||
// because it leads to duplicate reports for
|
||||
// some cases. Maybe we should fix this via not
|
||||
// visiting the same firs twice instead.
|
||||
if (declaration is FirPropertyAccessor) {
|
||||
return
|
||||
}
|
||||
|
||||
if (declaration is FirTypedDeclaration) {
|
||||
checkTypeRef(declaration.returnTypeRef, context, reporter)
|
||||
}
|
||||
|
||||
when (declaration) {
|
||||
is FirPropertyAccessor -> {}
|
||||
is FirProperty -> {
|
||||
checkTypeRef(declaration.returnTypeRef, context, reporter)
|
||||
}
|
||||
is FirFunction<*> -> {
|
||||
for (it in declaration.valueParameters) {
|
||||
checkTypeRef(it.returnTypeRef, context, reporter)
|
||||
}
|
||||
checkTypeRef(declaration.returnTypeRef, context, reporter)
|
||||
}
|
||||
is FirClass<*> -> {
|
||||
for (it in declaration.superTypeRefs) {
|
||||
checkTypeRef(it, context, reporter)
|
||||
@@ -56,14 +51,19 @@ object FirConflictingProjectionChecker : FirBasicDeclarationChecker() {
|
||||
?.fir.safeAs<FirRegularClass>()
|
||||
?: return
|
||||
|
||||
declaration.typeParameters.zip(typeRef.coneType.typeArguments).forEach { (proto, actual) ->
|
||||
val size = min(declaration.typeParameters.size, typeRef.coneType.typeArguments.size)
|
||||
|
||||
for (it in 0 until size) {
|
||||
val proto = declaration.typeParameters[it]
|
||||
val actual = typeRef.coneType.typeArguments[it]
|
||||
|
||||
val protoVariance = proto.safeAs<FirTypeParameterRef>()
|
||||
?.symbol?.fir
|
||||
?.variance
|
||||
?: return@forEach
|
||||
?: continue
|
||||
|
||||
if (protoVariance == Variance.INVARIANT) {
|
||||
return@forEach
|
||||
continue
|
||||
}
|
||||
|
||||
if (
|
||||
|
||||
+7
-4
@@ -47,10 +47,13 @@ object FirDelegationInInterfaceChecker : FirMemberDeclarationChecker() {
|
||||
return -1
|
||||
}
|
||||
|
||||
private fun PsiElement.findSuperTypeDelegation() = if (children.isNotEmpty() && children[0] !is PsiErrorElement) {
|
||||
children[0].children.indexOfFirst { it is KtDelegatedSuperTypeEntry }
|
||||
} else {
|
||||
-1
|
||||
private fun PsiElement.findSuperTypeDelegation(): Int {
|
||||
val children = this.children // this is a method call and it collects children
|
||||
return if (children.isNotEmpty() && children[0] !is PsiErrorElement) {
|
||||
children[0].children.indexOfFirst { it is KtDelegatedSuperTypeEntry }
|
||||
} else {
|
||||
-1
|
||||
}
|
||||
}
|
||||
|
||||
private fun LighterASTNode.findSuperTypeDelegation(tree: FlyweightCapableTreeStructure<LighterASTNode>): Int {
|
||||
|
||||
+19
-6
@@ -34,13 +34,26 @@ object FirMethodOfAnyImplementedInInterfaceChecker : FirMemberDeclarationChecker
|
||||
inspector = this
|
||||
}
|
||||
|
||||
override fun represent(it: FirSimpleFunction) = buildFunctionRepresentation {
|
||||
typeArguments = it.typeParameters.joinToString { represent(it) }
|
||||
it.receiverTypeRef?.let {
|
||||
receiver = represent(it)
|
||||
@Suppress("DuplicatedCode")
|
||||
override fun represent(it: FirSimpleFunction) = buildString {
|
||||
append('<')
|
||||
it.typeParameters.forEach {
|
||||
appendRepresentation(it)
|
||||
append(',')
|
||||
}
|
||||
name = it.name.asString()
|
||||
parameters = it.valueParameters.joinToString { represent(it) }
|
||||
append('>')
|
||||
append('[')
|
||||
it.receiverTypeRef?.let {
|
||||
appendRepresentation(it)
|
||||
}
|
||||
append(']')
|
||||
append(it.name.asString())
|
||||
append('(')
|
||||
it.valueParameters.forEach {
|
||||
appendRepresentation(it)
|
||||
append(',')
|
||||
}
|
||||
append(')')
|
||||
}
|
||||
|
||||
override fun check(declaration: FirMemberDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
|
||||
+7
-4
@@ -47,10 +47,13 @@ object FirSupertypeInitializedInInterfaceChecker : FirMemberDeclarationChecker()
|
||||
return -1
|
||||
}
|
||||
|
||||
private fun PsiElement.findSuperTypeCall() = if (children.isNotEmpty() && children[0] !is PsiErrorElement) {
|
||||
children[0].children.indexOfFirst { it is KtSuperTypeCallEntry }
|
||||
} else {
|
||||
-1
|
||||
private fun PsiElement.findSuperTypeCall(): Int {
|
||||
val children = this.children // this is a method call and it collects children
|
||||
return if (children.isNotEmpty() && children[0] !is PsiErrorElement) {
|
||||
children[0].children.indexOfFirst { it is KtSuperTypeCallEntry }
|
||||
} else {
|
||||
-1
|
||||
}
|
||||
}
|
||||
|
||||
private fun LighterASTNode.findSuperTypeCall(tree: FlyweightCapableTreeStructure<LighterASTNode>): Int {
|
||||
|
||||
+1
@@ -52,6 +52,7 @@ object FirSupertypeInitializedWithoutPrimaryConstructor : FirMemberDeclarationCh
|
||||
}
|
||||
|
||||
private fun PsiElement.anySupertypeHasConstructorParentheses(): Boolean {
|
||||
val children = this.children // this is a method call and it collects children
|
||||
return children.isNotEmpty() && children[0] !is PsiErrorElement && children[0].children.any { it is KtSuperTypeCallEntry }
|
||||
}
|
||||
|
||||
|
||||
+10
-57
@@ -10,9 +10,7 @@ import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap
|
||||
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
||||
import org.jetbrains.kotlin.fir.scopes.*
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.toConeType
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
||||
@@ -23,14 +21,11 @@ import org.jetbrains.kotlin.fir.typeContext
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.types.AbstractTypeChecker
|
||||
import org.jetbrains.kotlin.types.AbstractTypeCheckerContext
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.min
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
|
||||
object FirTypeMismatchOnOverrideChecker : FirMemberDeclarationChecker() {
|
||||
override fun check(declaration: FirMemberDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
if (declaration !is FirRegularClass) {
|
||||
return
|
||||
}
|
||||
|
||||
object FirTypeMismatchOnOverrideChecker : FirRegularClassChecker() {
|
||||
override fun check(declaration: FirRegularClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
val typeCheckerContext = context.session.typeContext.newBaseTypeCheckerContext(
|
||||
errorTypesEqualToAnything = false,
|
||||
stubTypesEqualToAnything = false
|
||||
@@ -43,8 +38,8 @@ object FirTypeMismatchOnOverrideChecker : FirMemberDeclarationChecker() {
|
||||
|
||||
for (it in declaration.declarations) {
|
||||
when (it) {
|
||||
is FirSimpleFunction -> checkFunction(declaration, it, context, reporter, typeCheckerContext, firTypeScope)
|
||||
is FirProperty -> checkProperty(declaration, it, context, reporter, typeCheckerContext, firTypeScope)
|
||||
is FirSimpleFunction -> checkFunction(it, reporter, typeCheckerContext, firTypeScope)
|
||||
is FirProperty -> checkProperty(it, reporter, typeCheckerContext, firTypeScope)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -73,38 +68,6 @@ object FirTypeMismatchOnOverrideChecker : FirMemberDeclarationChecker() {
|
||||
return overriddenProperties.toList()
|
||||
}
|
||||
|
||||
private fun FirRegularClass.substituteAllSupertypeParameters(context: CheckerContext): ConeSubstitutor {
|
||||
val allSupertypesMapping = mutableMapOf<FirTypeParameterSymbol, ConeKotlinType>()
|
||||
val remapper = mutableMapOf<ConeKotlinType, ConeKotlinType>()
|
||||
|
||||
fun FirRegularClass.collectSupertypes() {
|
||||
for (it in superTypeRefs) {
|
||||
val fir = it.coneType.safeAs<ConeClassLikeType>()?.lookupTag?.toSymbol(context.session)
|
||||
?.fir.safeAs<FirRegularClass>()
|
||||
?: continue
|
||||
|
||||
if (it.coneType.typeArguments.size != fir.typeParameters.size) {
|
||||
continue
|
||||
}
|
||||
|
||||
for (that in fir.typeParameters.indices) {
|
||||
val proto = fir.typeParameters[that].symbol
|
||||
val actual = it.coneType.typeArguments[that].safeAs<ConeKotlinType>()
|
||||
?.lowerBoundIfFlexible()
|
||||
?: continue
|
||||
val value = remapper.getOrDefault(actual, actual)
|
||||
remapper[proto.fir.toConeType()] = value
|
||||
allSupertypesMapping[proto] = value
|
||||
}
|
||||
|
||||
fir.collectSupertypes()
|
||||
}
|
||||
}
|
||||
|
||||
collectSupertypes()
|
||||
return substitutorByMap(allSupertypesMapping)
|
||||
}
|
||||
|
||||
private fun ConeKotlinType.substituteAllTypeParameters(
|
||||
overrideDeclaration: FirCallableMemberDeclaration<*>,
|
||||
baseDeclarationSymbol: FirCallableSymbol<*>,
|
||||
@@ -117,32 +80,30 @@ object FirTypeMismatchOnOverrideChecker : FirMemberDeclarationChecker() {
|
||||
?: return this
|
||||
|
||||
val map = mutableMapOf<FirTypeParameterSymbol, ConeKotlinType>()
|
||||
val size = min(overrideDeclaration.typeParameters.size, parametersOwner.typeParameters.size)
|
||||
|
||||
for (it in 0 until size) {
|
||||
val to = overrideDeclaration.typeParameters[it]
|
||||
val from = parametersOwner.typeParameters[it]
|
||||
|
||||
overrideDeclaration.typeParameters.zip(parametersOwner.typeParameters).forEach { (to, from) ->
|
||||
map[from.symbol] = to.toConeType()
|
||||
}
|
||||
|
||||
return substitutorByMap(map).substituteOrSelf(this)
|
||||
}
|
||||
|
||||
private fun ConeKotlinType.substituteOrSelf(substitutor: ConeSubstitutor) = substitutor.substituteOrSelf(this)
|
||||
|
||||
private fun FirCallableMemberDeclaration<*>.checkReturnType(
|
||||
regularClass: FirRegularClass,
|
||||
overriddenSymbols: List<FirCallableSymbol<*>>,
|
||||
context: CheckerContext,
|
||||
typeCheckerContext: AbstractTypeCheckerContext,
|
||||
): FirMemberDeclaration? {
|
||||
val returnType = returnTypeRef.safeAs<FirResolvedTypeRef>()?.type
|
||||
?: return null
|
||||
|
||||
val bounds = overriddenSymbols.map { it.fir.returnTypeRef.coneType.upperBoundIfFlexible() }
|
||||
val supertypesParameterSubstitutor = regularClass.substituteAllSupertypeParameters(context)
|
||||
|
||||
for (it in bounds.indices) {
|
||||
val restriction = bounds[it]
|
||||
.substituteAllTypeParameters(this, overriddenSymbols[it])
|
||||
.substituteOrSelf(supertypesParameterSubstitutor)
|
||||
|
||||
if (!AbstractTypeChecker.isSubtypeOf(typeCheckerContext, returnType, restriction)) {
|
||||
return overriddenSymbols[it].fir.safeAs()
|
||||
@@ -153,9 +114,7 @@ object FirTypeMismatchOnOverrideChecker : FirMemberDeclarationChecker() {
|
||||
}
|
||||
|
||||
private fun checkFunction(
|
||||
regularClass: FirRegularClass,
|
||||
function: FirSimpleFunction,
|
||||
context: CheckerContext,
|
||||
reporter: DiagnosticReporter,
|
||||
typeCheckerContext: AbstractTypeCheckerContext,
|
||||
firTypeScope: FirTypeScope
|
||||
@@ -171,9 +130,7 @@ object FirTypeMismatchOnOverrideChecker : FirMemberDeclarationChecker() {
|
||||
}
|
||||
|
||||
val restriction = function.checkReturnType(
|
||||
regularClass = regularClass,
|
||||
overriddenSymbols = overriddenFunctionSymbols,
|
||||
context = context,
|
||||
typeCheckerContext = typeCheckerContext
|
||||
)
|
||||
|
||||
@@ -187,9 +144,7 @@ object FirTypeMismatchOnOverrideChecker : FirMemberDeclarationChecker() {
|
||||
}
|
||||
|
||||
private fun checkProperty(
|
||||
regularClass: FirRegularClass,
|
||||
property: FirProperty,
|
||||
context: CheckerContext,
|
||||
reporter: DiagnosticReporter,
|
||||
typeCheckerContext: AbstractTypeCheckerContext,
|
||||
firTypeScope: FirTypeScope
|
||||
@@ -205,9 +160,7 @@ object FirTypeMismatchOnOverrideChecker : FirMemberDeclarationChecker() {
|
||||
}
|
||||
|
||||
val restriction = property.checkReturnType(
|
||||
regularClass = regularClass,
|
||||
overriddenSymbols = overriddenPropertySymbols,
|
||||
context = context,
|
||||
typeCheckerContext = typeCheckerContext
|
||||
)
|
||||
|
||||
|
||||
+6
-2
@@ -8,13 +8,13 @@ package org.jetbrains.kotlin.fir.analysis.checkers.expression
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.isSuperclassOf
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
import org.jetbrains.kotlin.fir.declarations.FirClassLikeDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
||||
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
||||
import org.jetbrains.kotlin.fir.references.FirSuperReference
|
||||
import org.jetbrains.kotlin.fir.resolve.firSymbolProvider
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
||||
@@ -22,6 +22,10 @@ import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
|
||||
object FirSuperclassNotAccessibleFromInterfaceChecker : FirQualifiedAccessChecker() {
|
||||
override fun check(expression: FirQualifiedAccessExpression, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
expression.explicitReceiver.safeAs<FirQualifiedAccessExpression>()
|
||||
?.calleeReference.safeAs<FirSuperReference>()
|
||||
?: return
|
||||
|
||||
val closestClass = context.findClosest<FirRegularClass>() ?: return
|
||||
|
||||
if (closestClass.classKind == ClassKind.INTERFACE) {
|
||||
@@ -30,7 +34,7 @@ object FirSuperclassNotAccessibleFromInterfaceChecker : FirQualifiedAccessChecke
|
||||
?.fir
|
||||
?: return
|
||||
|
||||
if (origin.source != null && origin.isSuperclassOf(closestClass)) {
|
||||
if (origin.source != null && origin.classKind == ClassKind.CLASS) {
|
||||
reporter.report(expression.explicitReceiver?.source)
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -50,7 +50,8 @@ object FirTypeArgumentsNotAllowedExpressionChecker : FirQualifiedAccessChecker()
|
||||
}
|
||||
|
||||
private fun PsiElement.hasAnyArguments(): Boolean {
|
||||
return this.children.size > 1 && this.children[1] is KtTypeArgumentList
|
||||
val children = this.children // this is a method call and it collects children
|
||||
return children.size > 1 && children[1] is KtTypeArgumentList
|
||||
}
|
||||
|
||||
private fun LighterASTNode.hasAnyArguments(tree: FlyweightCapableTreeStructure<LighterASTNode>): Boolean {
|
||||
|
||||
+22
-7
@@ -35,13 +35,13 @@ object FirUpperBoundViolatedChecker : FirQualifiedAccessChecker() {
|
||||
?.fir.safeAs<FirTypeParameterRefsOwner>()
|
||||
?: return
|
||||
|
||||
val typeCheckerContext = context.session.typeContext.newBaseTypeCheckerContext(
|
||||
errorTypesEqualToAnything = false,
|
||||
stubTypesEqualToAnything = false
|
||||
)
|
||||
val count = min(calleeFir.typeParameters.size, expression.typeArguments.size)
|
||||
|
||||
if (count == 0) {
|
||||
return
|
||||
}
|
||||
|
||||
val parameterPairs = mutableMapOf<FirTypeParameterSymbol, FirResolvedTypeRef>()
|
||||
val count = min(calleeFir.typeParameters.size, expression.typeArguments.size)
|
||||
|
||||
for (it in 0 until count) {
|
||||
expression.typeArguments[it].safeAs<FirTypeProjectionWithVariance>()
|
||||
@@ -61,6 +61,11 @@ object FirUpperBoundViolatedChecker : FirQualifiedAccessChecker() {
|
||||
parameterPairs.mapValues { it.value.type }
|
||||
)
|
||||
|
||||
val typeCheckerContext = context.session.typeContext.newBaseTypeCheckerContext(
|
||||
errorTypesEqualToAnything = false,
|
||||
stubTypesEqualToAnything = false
|
||||
)
|
||||
|
||||
parameterPairs.forEach { (proto, actual) ->
|
||||
if (actual.source == null) {
|
||||
// inferred types don't report INAPPLICABLE_CANDIDATE for type aliases!
|
||||
@@ -122,9 +127,14 @@ object FirUpperBoundViolatedChecker : FirQualifiedAccessChecker() {
|
||||
?.type.safeAs<ConeClassLikeType>()
|
||||
?: return
|
||||
|
||||
val constructorsParameterPairs = mutableMapOf<FirTypeParameterSymbol, ConeSimpleKotlinType>()
|
||||
val count = min(protoConstructor.typeParameters.size, actualConstructor.typeArguments.size)
|
||||
|
||||
if (count == 0) {
|
||||
return
|
||||
}
|
||||
|
||||
val constructorsParameterPairs = mutableMapOf<FirTypeParameterSymbol, ConeSimpleKotlinType>()
|
||||
|
||||
for (it in 0 until count) {
|
||||
actualConstructor.typeArguments[it].safeAs<ConeSimpleKotlinType>()
|
||||
?.let { that ->
|
||||
@@ -182,9 +192,14 @@ object FirUpperBoundViolatedChecker : FirQualifiedAccessChecker() {
|
||||
?.fir.safeAs<FirRegularClass>()
|
||||
?: return false
|
||||
|
||||
val parameterPairs = mutableMapOf<FirTypeParameterSymbol, ConeClassLikeType>()
|
||||
val count = min(prototypeClass.typeParameters.size, type.typeArguments.size)
|
||||
|
||||
if (count == 0) {
|
||||
return false
|
||||
}
|
||||
|
||||
val parameterPairs = mutableMapOf<FirTypeParameterSymbol, ConeClassLikeType>()
|
||||
|
||||
for (it in 0 until count) {
|
||||
type.typeArguments[it].safeAs<ConeClassLikeType>()
|
||||
?.let { that ->
|
||||
|
||||
Reference in New Issue
Block a user