[FIR] Report top-level conflicts between TA constructors and funs
^KT-59880
This commit is contained in:
committed by
Space Team
parent
01d4f25363
commit
f719436d1f
+65
-15
@@ -15,14 +15,19 @@ import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
|||||||
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirNameConflictsTracker
|
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirNameConflictsTracker
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
import org.jetbrains.kotlin.fir.declarations.*
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirOuterClassTypeParameterRef
|
|
||||||
import org.jetbrains.kotlin.fir.declarations.impl.FirResolvedDeclarationStatusImpl.Companion.DEFAULT_STATUS_FOR_STATUSLESS_DECLARATIONS
|
import org.jetbrains.kotlin.fir.declarations.impl.FirResolvedDeclarationStatusImpl.Companion.DEFAULT_STATUS_FOR_STATUSLESS_DECLARATIONS
|
||||||
import org.jetbrains.kotlin.fir.declarations.impl.FirResolvedDeclarationStatusImpl.Companion.DEFAULT_STATUS_FOR_SUSPEND_MAIN_FUNCTION
|
import org.jetbrains.kotlin.fir.declarations.impl.FirResolvedDeclarationStatusImpl.Companion.DEFAULT_STATUS_FOR_SUSPEND_MAIN_FUNCTION
|
||||||
import org.jetbrains.kotlin.fir.declarations.impl.modifiersRepresentation
|
import org.jetbrains.kotlin.fir.declarations.impl.modifiersRepresentation
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.utils.expandedConeType
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirBlock
|
import org.jetbrains.kotlin.fir.expressions.FirBlock
|
||||||
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
|
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.outerType
|
||||||
import org.jetbrains.kotlin.fir.resolve.providers.firProvider
|
import org.jetbrains.kotlin.fir.resolve.providers.firProvider
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.scope
|
||||||
|
import org.jetbrains.kotlin.fir.scopes.FakeOverrideTypeCalculator
|
||||||
|
import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||||
import org.jetbrains.kotlin.fir.scopes.impl.FirPackageMemberScope
|
import org.jetbrains.kotlin.fir.scopes.impl.FirPackageMemberScope
|
||||||
|
import org.jetbrains.kotlin.fir.scopes.impl.TypeAliasConstructorsSubstitutingScope
|
||||||
import org.jetbrains.kotlin.fir.scopes.impl.toConeType
|
import org.jetbrains.kotlin.fir.scopes.impl.toConeType
|
||||||
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
|
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
|
||||||
@@ -90,7 +95,7 @@ private class DeclarationBuckets {
|
|||||||
val extensionProperties = mutableListOf<Pair<FirProperty, String>>()
|
val extensionProperties = mutableListOf<Pair<FirProperty, String>>()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun groupTopLevelByName(declarations: List<FirDeclaration>): Map<Name, DeclarationBuckets> {
|
private fun groupTopLevelByName(declarations: List<FirDeclaration>, context: CheckerContext): Map<Name, DeclarationBuckets> {
|
||||||
val groups = mutableMapOf<Name, DeclarationBuckets>()
|
val groups = mutableMapOf<Name, DeclarationBuckets>()
|
||||||
for (declaration in declarations) {
|
for (declaration in declarations) {
|
||||||
if (!declaration.isCollectable()) continue
|
if (!declaration.isCollectable()) continue
|
||||||
@@ -114,12 +119,20 @@ private fun groupTopLevelByName(declarations: List<FirDeclaration>): Map<Name, D
|
|||||||
if (declaration.classKind != ClassKind.OBJECT) {
|
if (declaration.classKind != ClassKind.OBJECT) {
|
||||||
declaration.declarations
|
declaration.declarations
|
||||||
.filterIsInstance<FirConstructor>()
|
.filterIsInstance<FirConstructor>()
|
||||||
.mapTo(group.constructors) { it to FirRedeclarationPresenter.represent(it, declaration) }
|
.mapTo(group.constructors) { it to FirRedeclarationPresenter.represent(it, declaration.symbol) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
is FirTypeAlias -> {
|
||||||
|
val group = groups.getOrPut(declaration.name, ::DeclarationBuckets)
|
||||||
|
group.classLikes += declaration to FirRedeclarationPresenter.represent(declaration)
|
||||||
|
|
||||||
|
@OptIn(SymbolInternals::class)
|
||||||
|
declaration.expandedClassWithConstructorsScope(context)?.let { (_, scopeWithConstructors) ->
|
||||||
|
scopeWithConstructors.processDeclaredConstructors {
|
||||||
|
group.constructors += it.fir to FirRedeclarationPresenter.represent(it.fir, declaration.symbol)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is FirTypeAlias ->
|
|
||||||
groups.getOrPut(declaration.name, ::DeclarationBuckets).classLikes +=
|
|
||||||
declaration to FirRedeclarationPresenter.represent(declaration)
|
|
||||||
else -> {}
|
else -> {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -173,8 +186,16 @@ fun collectConflictingLocalFunctionsFrom(block: FirBlock, context: CheckerContex
|
|||||||
is FirRegularClass ->
|
is FirRegularClass ->
|
||||||
// TODO, KT-61243: Use declaredMemberScope
|
// TODO, KT-61243: Use declaredMemberScope
|
||||||
collectable.declarations.filterIsInstance<FirConstructor>().forEach {
|
collectable.declarations.filterIsInstance<FirConstructor>().forEach {
|
||||||
inspector.collect(it, FirRedeclarationPresenter.represent(it, collectable), functionDeclarations)
|
inspector.collect(it, FirRedeclarationPresenter.represent(it, collectable.symbol), functionDeclarations)
|
||||||
}
|
}
|
||||||
|
is FirTypeAlias -> {
|
||||||
|
collectable.expandedClassWithConstructorsScope(context)?.let { (_, scopeWithConstructors) ->
|
||||||
|
scopeWithConstructors.processDeclaredConstructors {
|
||||||
|
@OptIn(SymbolInternals::class)
|
||||||
|
inspector.collect(it.fir, FirRedeclarationPresenter.represent(it.fir, collectable.symbol), functionDeclarations)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
else -> {}
|
else -> {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -224,7 +245,7 @@ private fun <D : FirDeclaration> FirDeclarationCollector<D>.collect(
|
|||||||
@Suppress("GrazieInspection")
|
@Suppress("GrazieInspection")
|
||||||
fun FirDeclarationCollector<FirDeclaration>.collectTopLevel(file: FirFile, packageMemberScope: FirPackageMemberScope) {
|
fun FirDeclarationCollector<FirDeclaration>.collectTopLevel(file: FirFile, packageMemberScope: FirPackageMemberScope) {
|
||||||
|
|
||||||
for ((declarationName, group) in groupTopLevelByName(file.declarations)) {
|
for ((declarationName, group) in groupTopLevelByName(file.declarations, context)) {
|
||||||
val groupHasClassLikesOrProperties = group.classLikes.isNotEmpty() || group.properties.isNotEmpty()
|
val groupHasClassLikesOrProperties = group.classLikes.isNotEmpty() || group.properties.isNotEmpty()
|
||||||
val groupHasSimpleFunctions = group.simpleFunctions.isNotEmpty()
|
val groupHasSimpleFunctions = group.simpleFunctions.isNotEmpty()
|
||||||
|
|
||||||
@@ -257,15 +278,21 @@ fun FirDeclarationCollector<FirDeclaration>.collectTopLevel(file: FirFile, packa
|
|||||||
collect(group.properties, conflictingSymbol, conflictingPresentation, conflictingFile)
|
collect(group.properties, conflictingSymbol, conflictingPresentation, conflictingFile)
|
||||||
|
|
||||||
if (groupHasSimpleFunctions) {
|
if (groupHasSimpleFunctions) {
|
||||||
if (conflictingSymbol !is FirRegularClassSymbol) return
|
val declaration = conflictingSymbol.fir
|
||||||
if (conflictingSymbol.classKind == ClassKind.OBJECT || conflictingSymbol.classKind == ClassKind.ENUM_ENTRY) return
|
|
||||||
|
|
||||||
conflictingSymbol.lazyResolveToPhase(FirResolvePhase.STATUS)
|
if (declaration !is FirClassLikeDeclaration) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
val classWithSameName = conflictingSymbol.fir
|
declaration.expandedClassWithConstructorsScope(context)?.let { (expandedClass, scopeWithConstructors) ->
|
||||||
classWithSameName.unsubstitutedScope(context).processDeclaredConstructors { constructor ->
|
if (expandedClass.classKind == ClassKind.OBJECT || expandedClass.classKind == ClassKind.ENUM_ENTRY) {
|
||||||
val ctorRepresentation = FirRedeclarationPresenter.represent(constructor.fir, classWithSameName)
|
return
|
||||||
collect(group.simpleFunctions, conflictingSymbol = constructor, conflictingPresentation = ctorRepresentation)
|
}
|
||||||
|
|
||||||
|
scopeWithConstructors.processDeclaredConstructors { constructor ->
|
||||||
|
val ctorRepresentation = FirRedeclarationPresenter.represent(constructor.fir, declaration.symbol)
|
||||||
|
collect(group.simpleFunctions, conflictingSymbol = constructor, conflictingPresentation = ctorRepresentation)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -311,6 +338,29 @@ fun FirDeclarationCollector<FirDeclaration>.collectTopLevel(file: FirFile, packa
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun FirClassLikeDeclaration.expandedClassWithConstructorsScope(context: CheckerContext): Pair<FirRegularClassSymbol, FirScope>? {
|
||||||
|
return when (this) {
|
||||||
|
is FirRegularClass -> symbol to unsubstitutedScope(context)
|
||||||
|
is FirTypeAlias -> {
|
||||||
|
val expandedType = expandedConeType
|
||||||
|
val expandedClass = expandedType?.toRegularClassSymbol(context.session)
|
||||||
|
val expandedTypeScope = expandedType?.scope(
|
||||||
|
context.session, context.scopeSession,
|
||||||
|
FakeOverrideTypeCalculator.DoNothing,
|
||||||
|
requiredMembersPhase = FirResolvePhase.STATUS,
|
||||||
|
)
|
||||||
|
|
||||||
|
if (expandedType != null && expandedClass != null && expandedTypeScope != null) {
|
||||||
|
val outerType = outerType(expandedType, context.session) { it.outerClassSymbol(context) }
|
||||||
|
expandedClass to TypeAliasConstructorsSubstitutingScope(symbol, expandedTypeScope, outerType)
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun FirDeclarationCollector<FirDeclaration>.collectTopLevelConflict(
|
private fun FirDeclarationCollector<FirDeclaration>.collectTopLevelConflict(
|
||||||
declaration: FirDeclaration,
|
declaration: FirDeclaration,
|
||||||
declarationPresentation: String,
|
declarationPresentation: String,
|
||||||
|
|||||||
+3
-3
@@ -7,7 +7,7 @@ package org.jetbrains.kotlin.fir.analysis.checkers
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.fir.declarations.*
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.isOperator
|
import org.jetbrains.kotlin.fir.declarations.utils.isOperator
|
||||||
import org.jetbrains.kotlin.fir.types.*
|
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
|
||||||
import org.jetbrains.kotlin.name.CallableId
|
import org.jetbrains.kotlin.name.CallableId
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
|
|
||||||
@@ -99,7 +99,7 @@ internal object FirRedeclarationPresenter {
|
|||||||
appendRepresentation(it.symbol.classId)
|
appendRepresentation(it.symbol.classId)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun represent(it: FirConstructor, owner: FirRegularClass) = buildString {
|
fun represent(it: FirConstructor, owner: FirClassLikeSymbol<*>) = buildString {
|
||||||
repeat(it.contextReceivers.size) {
|
repeat(it.contextReceivers.size) {
|
||||||
append(',')
|
append(',')
|
||||||
}
|
}
|
||||||
@@ -110,7 +110,7 @@ internal object FirRedeclarationPresenter {
|
|||||||
append('>')
|
append('>')
|
||||||
append('[')
|
append('[')
|
||||||
append(']')
|
append(']')
|
||||||
appendRepresentation(owner.symbol.classId)
|
appendRepresentation(owner.classId)
|
||||||
append('(')
|
append('(')
|
||||||
it.valueParameters.forEach {
|
it.valueParameters.forEach {
|
||||||
appendRepresentation(it)
|
appendRepresentation(it)
|
||||||
|
|||||||
+3
-1
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.fir.packageFqName
|
|||||||
import org.jetbrains.kotlin.fir.resolve.getContainingDeclaration
|
import org.jetbrains.kotlin.fir.resolve.getContainingDeclaration
|
||||||
import org.jetbrains.kotlin.fir.scopes.impl.FirPackageMemberScope
|
import org.jetbrains.kotlin.fir.scopes.impl.FirPackageMemberScope
|
||||||
import org.jetbrains.kotlin.fir.scopes.impl.PACKAGE_MEMBER
|
import org.jetbrains.kotlin.fir.scopes.impl.PACKAGE_MEMBER
|
||||||
|
import org.jetbrains.kotlin.fir.scopes.impl.typeAliasForConstructor
|
||||||
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
@@ -58,7 +59,8 @@ object FirConflictsDeclarationChecker : FirBasicDeclarationChecker() {
|
|||||||
declarationConflictingSymbols: Map<FirDeclaration, SmartSet<FirBasedSymbol<*>>>,
|
declarationConflictingSymbols: Map<FirDeclaration, SmartSet<FirBasedSymbol<*>>>,
|
||||||
) {
|
) {
|
||||||
declarationConflictingSymbols.forEach { (conflictingDeclaration, symbols) ->
|
declarationConflictingSymbols.forEach { (conflictingDeclaration, symbols) ->
|
||||||
val source = conflictingDeclaration.source
|
val typeAliasForConstructorSource = (conflictingDeclaration as? FirConstructor)?.typeAliasForConstructor?.source
|
||||||
|
val source = typeAliasForConstructorSource ?: conflictingDeclaration.source
|
||||||
if (symbols.isEmpty()) return@forEach
|
if (symbols.isEmpty()) return@forEach
|
||||||
|
|
||||||
val factory =
|
val factory =
|
||||||
|
|||||||
+2
-2
@@ -1,9 +1,9 @@
|
|||||||
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER -TOPLEVEL_TYPEALIASES_ONLY
|
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER -TOPLEVEL_TYPEALIASES_ONLY
|
||||||
class C(val x: Int)
|
class C(val x: Int)
|
||||||
|
|
||||||
typealias CC = C
|
<!CONFLICTING_OVERLOADS!>typealias CC = C<!>
|
||||||
|
|
||||||
fun CC(x: Int) = x
|
<!CONFLICTING_OVERLOADS!>fun CC(x: Int)<!> = x
|
||||||
|
|
||||||
class Outer {
|
class Outer {
|
||||||
class C(val x: Int)
|
class C(val x: Int)
|
||||||
|
|||||||
Reference in New Issue
Block a user