[FIR] Rewrite redeclaration checks

#KT-60124 Fixed
#KT-60573 Fixed
This commit is contained in:
Kirill Rakhman
2023-07-20 11:17:02 +02:00
committed by Space Team
parent b56f84b533
commit 951b299268
55 changed files with 1075 additions and 837 deletions
@@ -19,11 +19,14 @@ import org.jetbrains.kotlin.fir.analysis.FirOverridesBackwardCompatibilityHelper
import org.jetbrains.kotlin.fir.analysis.checkers.FirPlatformDiagnosticSuppressor
import org.jetbrains.kotlin.fir.analysis.js.checkers.FirJsPlatformDiagnosticSuppressor
import org.jetbrains.kotlin.fir.analysis.jvm.FirJvmOverridesBackwardCompatibilityHelper
import org.jetbrains.kotlin.fir.declarations.FirTypeSpecificityComparatorProvider
import org.jetbrains.kotlin.fir.resolve.calls.ConeCallConflictResolverFactory
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider
import org.jetbrains.kotlin.fir.scopes.FirKotlinScopeProvider
import org.jetbrains.kotlin.fir.scopes.FirPlatformClassMapper
import org.jetbrains.kotlin.fir.session.JsCallConflictResolverFactory
import org.jetbrains.kotlin.fir.types.typeContext
import org.jetbrains.kotlin.js.resolve.JsTypeSpecificityComparatorWithoutDelegate
@OptIn(SessionConfiguration::class)
internal class LLFirJsSessionFactory(project: Project) : LLFirAbstractSessionFactory(project) {
@@ -83,6 +86,10 @@ internal class LLFirJsSessionFactory(project: Project) : LLFirAbstractSessionFac
private fun LLFirSession.registerModuleIndependentJsComponents() {
register(FirVisibilityChecker::class, FirVisibilityChecker.Default)
register(ConeCallConflictResolverFactory::class, JsCallConflictResolverFactory)
register(
FirTypeSpecificityComparatorProvider::class,
FirTypeSpecificityComparatorProvider(JsTypeSpecificityComparatorWithoutDelegate(typeContext))
)
register(FirPlatformClassMapper::class, FirPlatformClassMapper.Default)
register(FirOverridesBackwardCompatibilityHelper::class, FirJvmOverridesBackwardCompatibilityHelper)
register(FirPlatformDiagnosticSuppressor::class, FirJsPlatformDiagnosticSuppressor())
@@ -25967,39 +25967,15 @@ public class DiagnosticCompilerTestFE10TestdataTestGenerated extends AbstractDia
}
@Test
@TestMetadata("RedeclarationMainInMultiFile.kt")
public void testRedeclarationMainInMultiFile() throws Exception {
runTest("compiler/testData/diagnostics/tests/redeclarations/RedeclarationMainInMultiFile.kt");
@TestMetadata("RedeclarationOfMain.kt")
public void testRedeclarationOfMain() throws Exception {
runTest("compiler/testData/diagnostics/tests/redeclarations/RedeclarationOfMain.kt");
}
@Test
@TestMetadata("RedeclarationParameterlessMain.kt")
public void testRedeclarationParameterlessMain() throws Exception {
runTest("compiler/testData/diagnostics/tests/redeclarations/RedeclarationParameterlessMain.kt");
}
@Test
@TestMetadata("RedeclarationParameterlessMainInvalid.kt")
public void testRedeclarationParameterlessMainInvalid() throws Exception {
runTest("compiler/testData/diagnostics/tests/redeclarations/RedeclarationParameterlessMainInvalid.kt");
}
@Test
@TestMetadata("RedeclarationParameterlessMain_before.kt")
public void testRedeclarationParameterlessMain_before() throws Exception {
runTest("compiler/testData/diagnostics/tests/redeclarations/RedeclarationParameterlessMain_before.kt");
}
@Test
@TestMetadata("RedeclarationSuspendMainInMultiFile.kt")
public void testRedeclarationSuspendMainInMultiFile() throws Exception {
runTest("compiler/testData/diagnostics/tests/redeclarations/RedeclarationSuspendMainInMultiFile.kt");
}
@Test
@TestMetadata("RedeclarationSuspendMainInMultiFile_before.kt")
public void testRedeclarationSuspendMainInMultiFile_before() throws Exception {
runTest("compiler/testData/diagnostics/tests/redeclarations/RedeclarationSuspendMainInMultiFile_before.kt");
@TestMetadata("RedeclarationOfMain_before.kt")
public void testRedeclarationOfMain_before() throws Exception {
runTest("compiler/testData/diagnostics/tests/redeclarations/RedeclarationOfMain_before.kt");
}
@Test
@@ -25967,39 +25967,15 @@ public class LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated
}
@Test
@TestMetadata("RedeclarationMainInMultiFile.kt")
public void testRedeclarationMainInMultiFile() throws Exception {
runTest("compiler/testData/diagnostics/tests/redeclarations/RedeclarationMainInMultiFile.kt");
@TestMetadata("RedeclarationOfMain.kt")
public void testRedeclarationOfMain() throws Exception {
runTest("compiler/testData/diagnostics/tests/redeclarations/RedeclarationOfMain.kt");
}
@Test
@TestMetadata("RedeclarationParameterlessMain.kt")
public void testRedeclarationParameterlessMain() throws Exception {
runTest("compiler/testData/diagnostics/tests/redeclarations/RedeclarationParameterlessMain.kt");
}
@Test
@TestMetadata("RedeclarationParameterlessMainInvalid.kt")
public void testRedeclarationParameterlessMainInvalid() throws Exception {
runTest("compiler/testData/diagnostics/tests/redeclarations/RedeclarationParameterlessMainInvalid.kt");
}
@Test
@TestMetadata("RedeclarationParameterlessMain_before.kt")
public void testRedeclarationParameterlessMain_before() throws Exception {
runTest("compiler/testData/diagnostics/tests/redeclarations/RedeclarationParameterlessMain_before.kt");
}
@Test
@TestMetadata("RedeclarationSuspendMainInMultiFile.kt")
public void testRedeclarationSuspendMainInMultiFile() throws Exception {
runTest("compiler/testData/diagnostics/tests/redeclarations/RedeclarationSuspendMainInMultiFile.kt");
}
@Test
@TestMetadata("RedeclarationSuspendMainInMultiFile_before.kt")
public void testRedeclarationSuspendMainInMultiFile_before() throws Exception {
runTest("compiler/testData/diagnostics/tests/redeclarations/RedeclarationSuspendMainInMultiFile_before.kt");
@TestMetadata("RedeclarationOfMain_before.kt")
public void testRedeclarationOfMain_before() throws Exception {
runTest("compiler/testData/diagnostics/tests/redeclarations/RedeclarationOfMain_before.kt");
}
@Test
@@ -1,8 +1,8 @@
<!CONFLICTING_OVERLOADS!>@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
@kotlin.internal.LowPriorityInOverloadResolution
fun foo(): Int<!> = 1
fun foo(): Int = 1
<!CONFLICTING_OVERLOADS!>fun foo(): String<!> = ""
fun foo(): String = ""
fun test() {
val s = foo()
@@ -25967,39 +25967,15 @@ public class FirLightTreeOldFrontendDiagnosticsTestGenerated extends AbstractFir
}
@Test
@TestMetadata("RedeclarationMainInMultiFile.kt")
public void testRedeclarationMainInMultiFile() throws Exception {
runTest("compiler/testData/diagnostics/tests/redeclarations/RedeclarationMainInMultiFile.kt");
@TestMetadata("RedeclarationOfMain.kt")
public void testRedeclarationOfMain() throws Exception {
runTest("compiler/testData/diagnostics/tests/redeclarations/RedeclarationOfMain.kt");
}
@Test
@TestMetadata("RedeclarationParameterlessMain.kt")
public void testRedeclarationParameterlessMain() throws Exception {
runTest("compiler/testData/diagnostics/tests/redeclarations/RedeclarationParameterlessMain.kt");
}
@Test
@TestMetadata("RedeclarationParameterlessMainInvalid.kt")
public void testRedeclarationParameterlessMainInvalid() throws Exception {
runTest("compiler/testData/diagnostics/tests/redeclarations/RedeclarationParameterlessMainInvalid.kt");
}
@Test
@TestMetadata("RedeclarationParameterlessMain_before.kt")
public void testRedeclarationParameterlessMain_before() throws Exception {
runTest("compiler/testData/diagnostics/tests/redeclarations/RedeclarationParameterlessMain_before.kt");
}
@Test
@TestMetadata("RedeclarationSuspendMainInMultiFile.kt")
public void testRedeclarationSuspendMainInMultiFile() throws Exception {
runTest("compiler/testData/diagnostics/tests/redeclarations/RedeclarationSuspendMainInMultiFile.kt");
}
@Test
@TestMetadata("RedeclarationSuspendMainInMultiFile_before.kt")
public void testRedeclarationSuspendMainInMultiFile_before() throws Exception {
runTest("compiler/testData/diagnostics/tests/redeclarations/RedeclarationSuspendMainInMultiFile_before.kt");
@TestMetadata("RedeclarationOfMain_before.kt")
public void testRedeclarationOfMain_before() throws Exception {
runTest("compiler/testData/diagnostics/tests/redeclarations/RedeclarationOfMain_before.kt");
}
@Test
@@ -25973,39 +25973,15 @@ public class FirPsiOldFrontendDiagnosticsTestGenerated extends AbstractFirPsiDia
}
@Test
@TestMetadata("RedeclarationMainInMultiFile.kt")
public void testRedeclarationMainInMultiFile() throws Exception {
runTest("compiler/testData/diagnostics/tests/redeclarations/RedeclarationMainInMultiFile.kt");
@TestMetadata("RedeclarationOfMain.kt")
public void testRedeclarationOfMain() throws Exception {
runTest("compiler/testData/diagnostics/tests/redeclarations/RedeclarationOfMain.kt");
}
@Test
@TestMetadata("RedeclarationParameterlessMain.kt")
public void testRedeclarationParameterlessMain() throws Exception {
runTest("compiler/testData/diagnostics/tests/redeclarations/RedeclarationParameterlessMain.kt");
}
@Test
@TestMetadata("RedeclarationParameterlessMainInvalid.kt")
public void testRedeclarationParameterlessMainInvalid() throws Exception {
runTest("compiler/testData/diagnostics/tests/redeclarations/RedeclarationParameterlessMainInvalid.kt");
}
@Test
@TestMetadata("RedeclarationParameterlessMain_before.kt")
public void testRedeclarationParameterlessMain_before() throws Exception {
runTest("compiler/testData/diagnostics/tests/redeclarations/RedeclarationParameterlessMain_before.kt");
}
@Test
@TestMetadata("RedeclarationSuspendMainInMultiFile.kt")
public void testRedeclarationSuspendMainInMultiFile() throws Exception {
runTest("compiler/testData/diagnostics/tests/redeclarations/RedeclarationSuspendMainInMultiFile.kt");
}
@Test
@TestMetadata("RedeclarationSuspendMainInMultiFile_before.kt")
public void testRedeclarationSuspendMainInMultiFile_before() throws Exception {
runTest("compiler/testData/diagnostics/tests/redeclarations/RedeclarationSuspendMainInMultiFile_before.kt");
@TestMetadata("RedeclarationOfMain_before.kt")
public void testRedeclarationOfMain_before() throws Exception {
runTest("compiler/testData/diagnostics/tests/redeclarations/RedeclarationOfMain_before.kt");
}
@Test
@@ -12,9 +12,6 @@ import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.diagnostics.reportOn
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirMethodOfAnyImplementedInInterfaceChecker.appendRepresentation
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirMethodOfAnyImplementedInInterfaceChecker.appendRepresentationAfterCallableId
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirMethodOfAnyImplementedInInterfaceChecker.appendRepresentationBeforeCallableId
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirNameConflictsTracker
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.declarations.*
@@ -22,249 +19,274 @@ 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_SUSPEND_MAIN_FUNCTION
import org.jetbrains.kotlin.fir.declarations.impl.modifiersRepresentation
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
import org.jetbrains.kotlin.fir.resolve.providers.firProvider
import org.jetbrains.kotlin.fir.scopes.impl.FirPackageMemberScope
import org.jetbrains.kotlin.fir.scopes.impl.toConeType
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirClassifierSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.util.ListMultimap
import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid
import org.jetbrains.kotlin.name.CallableId
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.SpecialNames
import org.jetbrains.kotlin.utils.SmartSet
internal class FirDefaultDeclarationPresenter : FirDeclarationPresenter
private val MAIN_FUNCTION_SHAPES = setOf(
"<>[]():kotlin/Unit",
"<>[](kotlin/Array<kotlin/String,>,):kotlin/Unit",
"<>[](vararg kotlin/String,):kotlin/Unit",
)
val DEFAULT_STATUS_FOR_NORMAL_MAIN_FUNCTION = DEFAULT_STATUS_FOR_STATUSLESS_DECLARATIONS
private val FirSimpleFunction.hasMainFunctionStatus
get() = when (status.modifiersRepresentation) {
DEFAULT_STATUS_FOR_NORMAL_MAIN_FUNCTION.modifiersRepresentation,
DEFAULT_STATUS_FOR_SUSPEND_MAIN_FUNCTION.modifiersRepresentation -> true
DEFAULT_STATUS_FOR_SUSPEND_MAIN_FUNCTION.modifiersRepresentation,
-> true
else -> false
}
private val CallableId.isTopLevel get() = className == null
private val FirSimpleFunction.representsMainFunctionAllowingConflictingOverloads
get(): Boolean = when {
name != StandardNames.MAIN || !symbol.callableId.isTopLevel || !hasMainFunctionStatus -> false
else -> buildString {
appendRepresentationBeforeCallableId(this@representsMainFunctionAllowingConflictingOverloads)
appendRepresentationAfterCallableId(this@representsMainFunctionAllowingConflictingOverloads)
append(':')
appendRepresentation(returnTypeRef)
} in MAIN_FUNCTION_SHAPES
private fun FirDeclaration.isCollectable(): Boolean {
if (this is FirCallableDeclaration) {
if (contextReceivers.any { it.typeRef.coneType.hasError() }) return false
if (typeParameters.any { it.toConeType().hasError() }) return false
if (receiverParameter?.typeRef?.coneType?.hasError() == true) return false
if (this is FirFunction && valueParameters.any { it.returnTypeRef.coneType.hasError() }) return false
}
// - see testEnumValuesValueOf.
// it generates a static function that has
// the same signature as the function defined
// explicitly.
// - see tests with `fun () {}`.
// you can't redeclare something that has no name.
private fun FirDeclaration.isCollectable() = when (this) {
is FirSimpleFunction -> source?.kind !is KtFakeSourceElementKind && name != SpecialNames.NO_NAME_PROVIDED
is FirProperty -> source?.kind !is KtFakeSourceElementKind.EnumGeneratedDeclaration
is FirRegularClass -> name != SpecialNames.NO_NAME_PROVIDED
else -> true
return when (this) {
// - see tests with `fun () {}`.
// you can't redeclare something that has no name.
is FirSimpleFunction -> source?.kind !is KtFakeSourceElementKind && name != SpecialNames.NO_NAME_PROVIDED
is FirRegularClass -> name != SpecialNames.NO_NAME_PROVIDED
// - see testEnumValuesValueOf.
// it generates a static function that has
// the same signature as the function defined
// explicitly.
is FirProperty -> source?.kind !is KtFakeSourceElementKind.EnumGeneratedDeclaration
// class delegation field will be renamed after by the IR backend in a case of a name clash
is FirField -> source?.kind != KtFakeSourceElementKind.ClassDelegationField
else -> true
}
}
private fun isExpectAndActual(declaration1: FirDeclaration, declaration2: FirDeclaration): Boolean {
if (declaration1 !is FirMemberDeclaration) return false
if (declaration2 !is FirMemberDeclaration) return false
return (declaration1.status.isExpect && declaration2.status.isActual) ||
(declaration1.status.isActual && declaration2.status.isExpect)
}
private class DeclarationBuckets {
val simpleFunctions = mutableListOf<Pair<FirSimpleFunction, String>>()
val constructors = mutableListOf<Pair<FirConstructor, String>>()
val classLikes = mutableListOf<Pair<FirClassLikeDeclaration, String>>()
val properties = mutableListOf<Pair<FirProperty, String>>()
val extensionProperties = mutableListOf<Pair<FirProperty, String>>()
}
private fun groupTopLevelByName(declarations: List<FirDeclaration>): Map<Name, DeclarationBuckets> {
val groups = mutableMapOf<Name, DeclarationBuckets>()
for (declaration in declarations) {
if (!declaration.isCollectable()) continue
when (declaration) {
is FirSimpleFunction ->
groups.getOrPut(declaration.name, ::DeclarationBuckets).simpleFunctions +=
declaration to FirRedeclarationPresenter.represent(declaration)
is FirProperty -> {
val group = groups.getOrPut(declaration.name, ::DeclarationBuckets)
val representation = FirRedeclarationPresenter.represent(declaration)
if (declaration.receiverParameter != null) {
group.extensionProperties += declaration to representation
} else {
group.properties += declaration to representation
}
}
is FirRegularClass -> {
val group = groups.getOrPut(declaration.name, ::DeclarationBuckets)
group.classLikes += declaration to FirRedeclarationPresenter.represent(declaration)
if (declaration.classKind != ClassKind.OBJECT) {
declaration.declarations
.filterIsInstance<FirConstructor>()
.mapTo(group.constructors) { it to FirRedeclarationPresenter.represent(it, declaration) }
}
}
is FirTypeAlias ->
groups.getOrPut(declaration.name, ::DeclarationBuckets).classLikes +=
declaration to FirRedeclarationPresenter.represent(declaration)
else -> {}
}
}
return groups
}
/**
* Collects FirDeclarations for further analysis.
*/
class FirDeclarationInspector {
class FirDeclarationInspector(
private val session: FirSession,
) {
val declarationConflictingSymbols: HashMap<FirDeclaration, SmartSet<FirBasedSymbol<*>>> = hashMapOf()
private val presenter: FirDeclarationPresenter = FirDefaultDeclarationPresenter()
private val otherDeclarations = mutableMapOf<String, MutableList<FirDeclaration>>()
private val functionDeclarations = mutableMapOf<String, MutableList<FirSimpleFunction>>()
fun collect(declaration: FirDeclaration) {
when {
!declaration.isCollectable() -> {}
declaration is FirSimpleFunction -> collectFunction(presenter.represent(declaration), declaration)
declaration is FirRegularClass -> collectNonFunctionDeclaration(presenter.represent(declaration), declaration)
declaration is FirTypeAlias -> collectNonFunctionDeclaration(presenter.represent(declaration), declaration)
declaration is FirVariable -> collectNonFunctionDeclaration(presenter.represent(declaration), declaration)
fun collectClassMembers(klass: FirRegularClass) {
val otherDeclarations = mutableMapOf<String, MutableList<FirDeclaration>>()
val functionDeclarations = mutableMapOf<String, MutableList<FirDeclaration>>()
for (it in klass.declarations) {
if (!it.isCollectable()) continue
when (it) {
is FirSimpleFunction -> collect(it, FirRedeclarationPresenter.represent(it), functionDeclarations)
is FirRegularClass -> collect(it, FirRedeclarationPresenter.represent(it), otherDeclarations)
is FirTypeAlias -> collect(it, FirRedeclarationPresenter.represent(it), otherDeclarations)
is FirVariable -> collect(it, FirRedeclarationPresenter.represent(it), otherDeclarations)
else -> {}
}
}
}
fun collectWithExternalConflicts(
declaration: FirDeclaration,
containingFile: FirFile,
session: FirSession,
packageMemberScope: FirPackageMemberScope
) {
collect(declaration)
var declarationName: Name? = null
val declarationPresentation = presenter.represent(declaration) ?: return
when (declaration) {
is FirSimpleFunction -> {
declarationName = declaration.name
if (!declarationName.isSpecial) {
packageMemberScope.processFunctionsByName(declarationName) {
collectExternalConflict(
declaration, declarationPresentation, containingFile, it, null, null, session
)
}
packageMemberScope.processClassifiersByNameWithSubstitution(declarationName) { symbol, _ ->
symbol.lazyResolveToPhase(FirResolvePhase.STATUS)
@OptIn(SymbolInternals::class)
val classWithSameName = symbol.fir as? FirRegularClass
classWithSameName?.onConstructors { constructor ->
collectExternalConflict(
declaration, declarationPresentation, containingFile,
constructor.symbol, presenter.represent(constructor, classWithSameName), null,
session
)
}
}
}
}
is FirVariable -> {
declarationName = declaration.name
if (!declarationName.isSpecial) {
packageMemberScope.processPropertiesByName(declarationName) {
collectExternalConflict(
declaration, declarationPresentation, containingFile, it, null, null, session
)
}
}
}
is FirRegularClass -> {
declarationName = declaration.name
if (!declarationName.isSpecial) {
packageMemberScope.processClassifiersByNameWithSubstitution(declarationName) { symbol, _ ->
collectExternalConflict(
declaration, declarationPresentation, containingFile, symbol, null, null, session
)
}
declaration.onConstructors { constructor ->
packageMemberScope.processFunctionsByName(declarationName!!) {
collectExternalConflict(
constructor, presenter.represent(constructor, declaration), containingFile,
it, null, null, session
)
}
}
session.nameConflictsTracker?.let { it as? FirNameConflictsTracker }
?.redeclaredClassifiers?.get(declaration.symbol.classId)?.forEach {
collectExternalConflict(
declaration,
declarationPresentation,
containingFile,
it.classifier,
null,
it.file,
session
)
}
}
}
is FirTypeAlias -> {
declarationName = declaration.name
if (!declarationName.isSpecial) {
packageMemberScope.processClassifiersByNameWithSubstitution(declarationName) { symbol, _ ->
collectExternalConflict(
declaration, declarationPresentation, containingFile, symbol, null, null, session
)
}
session.nameConflictsTracker?.let { it as? FirNameConflictsTracker }
?.redeclaredClassifiers?.get(declaration.symbol.classId)?.forEach {
collectExternalConflict(
declaration,
declarationPresentation,
containingFile,
it.classifier,
null,
it.file,
session
)
}
}
}
else -> {
}
}
if (declarationName != null) {
session.lookupTracker?.recordLookup(
declarationName, containingFile.packageFqName.asString(), declaration.source, containingFile.source
)
}
}
private fun collectNonFunctionDeclaration(key: String, declaration: FirDeclaration): MutableList<FirDeclaration> =
otherDeclarations.getOrPut(key) {
mutableListOf()
}.also {
private fun collect(declaration: FirDeclaration, representation: String, map: MutableMap<String, MutableList<FirDeclaration>>) {
map.getOrPut(representation, ::mutableListOf).also {
it.add(declaration)
collectLocalConflicts(declaration, it)
}
private fun collectFunction(key: String, declaration: FirSimpleFunction): MutableList<FirSimpleFunction> =
functionDeclarations.getOrPut(key) {
mutableListOf()
}.also {
it.add(declaration)
collectLocalConflicts(declaration, it)
}
val conflicts = SmartSet.create<FirBasedSymbol<*>>()
for (otherDeclaration in it) {
if (otherDeclaration != declaration && !isOverloadable(declaration, otherDeclaration)) {
conflicts.add(otherDeclaration.symbol)
declarationConflictingSymbols.getOrPut(otherDeclaration) { SmartSet.create() }.add(declaration.symbol)
}
}
private fun collectLocalConflicts(declaration: FirDeclaration, conflicting: List<FirDeclaration>) {
val localConflicts = SmartSet.create<FirBasedSymbol<*>>()
for (otherDeclaration in conflicting) {
if (otherDeclaration is FirField && otherDeclaration.source?.kind == KtFakeSourceElementKind.ClassDelegationField) {
// class delegation field will be renamed after by the IR backend in a case of a name clash
continue
}
if (otherDeclaration != declaration && !isExpectAndActual(declaration, otherDeclaration)) {
localConflicts.add(otherDeclaration.symbol)
declarationConflictingSymbols.getOrPut(otherDeclaration) { SmartSet.create() }.add(declaration.symbol)
}
declarationConflictingSymbols[declaration] = conflicts
}
declarationConflictingSymbols[declaration] = localConflicts
}
private fun isExpectAndActual(declaration1: FirDeclaration, declaration2: FirDeclaration): Boolean {
if (declaration1 !is FirMemberDeclaration) return false
if (declaration2 !is FirMemberDeclaration) return false
return (declaration1.status.isExpect && declaration2.status.isActual) ||
(declaration1.status.isActual && declaration2.status.isExpect)
/**
* To check top-level declarations for redeclarations, we check multiple sources (the packageMemberScope's properties, functions
* and classifiers), redeclared classifiers from session.nameConflictsTracker and the file's declarations themselves.
* To prevent inspecting the same source multiple times, we group the declarations in the file by name and subdivide them into
* buckets (the properties of DeclarationGroup).
*
* Depending on the presence of declarations in the buckets, some checks can be omitted.
* E.g., if there are no functions and no classes with constructors in the file, we don't need to inspect functions.
*
* #### Matrix of possible conflicts between "sources" and "buckets"
*
* | | simpleFunctions | constructors | classLikes | Properties | extensionProperties |
* |-------------------------|-----------------|--------------|------------|------------|---------------------|
* | functions | X | X | | | |
* | classifiers | | | X | X | |
* | constructors of classes | X | | | | |
* | properties | | | X | X | X |
*/
@Suppress("GrazieInspection")
fun collectTopLevel(file: FirFile, packageMemberScope: FirPackageMemberScope) {
for ((declarationName, group) in groupTopLevelByName(file.declarations)) {
val groupHasClassLikesOrProperties = group.classLikes.isNotEmpty() || group.properties.isNotEmpty()
val groupHasSimpleFunctions = group.simpleFunctions.isNotEmpty()
fun collect(
declarations: List<Pair<FirDeclaration, String>>,
conflictingSymbol: FirBasedSymbol<*>,
conflictingPresentation: String? = null,
conflictingFile: FirFile? = null,
) {
for ((declaration, declarationPresentation) in declarations) {
collectTopLevelConflict(
declaration,
declarationPresentation,
file,
conflictingSymbol,
conflictingPresentation,
conflictingFile
)
session.lookupTracker?.recordLookup(declarationName, file.packageFqName.asString(), declaration.source, file.source)
}
}
fun collectFromClassifierSource(
conflictingSymbol: FirClassifierSymbol<*>,
conflictingPresentation: String? = null,
conflictingFile: FirFile? = null,
) {
collect(group.classLikes, conflictingSymbol, conflictingPresentation, conflictingFile)
collect(group.properties, conflictingSymbol, conflictingPresentation, conflictingFile)
if (groupHasSimpleFunctions) {
if (conflictingSymbol !is FirRegularClassSymbol) return
if (conflictingSymbol.classKind == ClassKind.OBJECT || conflictingSymbol.classKind == ClassKind.ENUM_ENTRY) return
conflictingSymbol.lazyResolveToPhase(FirResolvePhase.STATUS)
@OptIn(SymbolInternals::class)
val classWithSameName = conflictingSymbol.fir
classWithSameName.declarations.filterIsInstance<FirConstructor>().forEach { constructor ->
val ctorRepresentation = FirRedeclarationPresenter.represent(constructor, classWithSameName)
collect(group.simpleFunctions, conflictingSymbol = constructor.symbol, conflictingPresentation = ctorRepresentation)
}
}
}
// Check sources in the order from the table above. Skip the check if all relevant buckets are empty.
// Function source
if (groupHasSimpleFunctions || group.constructors.isNotEmpty()) {
packageMemberScope.processFunctionsByName(declarationName) {
collect(group.simpleFunctions, it)
collect(group.constructors, it)
}
}
// Classifier sources, collectForClassifierSource will also check constructors.
if (groupHasClassLikesOrProperties || groupHasSimpleFunctions) {
// Scope will only return one classifier per name
packageMemberScope.processClassifiersByNameWithSubstitution(declarationName) { symbol, _ ->
collectFromClassifierSource(conflictingSymbol = symbol)
}
// session.nameConflictsTracker will contain more classifiers with the same name.
session.nameConflictsTracker?.let { it as? FirNameConflictsTracker }
?.redeclaredClassifiers?.get(ClassId(file.packageFqName, declarationName))?.forEach {
collectFromClassifierSource(conflictingSymbol = it.classifier, conflictingFile = it.file)
}
// session.nameConflictsTracker doesn't seem to work for LL API for redeclarations in the same file, for this reason
// we explicitly check classLikes in the same file, too.
for ((classLike, representation) in group.classLikes) {
collectFromClassifierSource(classLike.symbol, conflictingPresentation = representation, conflictingFile = file)
}
}
// Property source
if (groupHasClassLikesOrProperties || group.extensionProperties.isNotEmpty()) {
packageMemberScope.processPropertiesByName(declarationName) {
collect(group.classLikes, conflictingSymbol = it)
collect(group.properties, conflictingSymbol = it)
collect(group.extensionProperties, conflictingSymbol = it)
}
}
}
}
private fun areCompatibleMainFunctions(
declaration1: FirDeclaration, file1: FirFile, declaration2: FirDeclaration, file2: FirFile?
) = file1 != file2
&& declaration1 is FirSimpleFunction
&& declaration2 is FirSimpleFunction
&& declaration1.representsMainFunctionAllowingConflictingOverloads
&& declaration2.representsMainFunctionAllowingConflictingOverloads
private fun collectExternalConflict(
private fun collectTopLevelConflict(
declaration: FirDeclaration,
declarationPresentation: String,
containingFile: FirFile,
conflictingSymbol: FirBasedSymbol<*>,
conflictingPresentation: String?,
conflictingFile: FirFile?,
session: FirSession
conflictingPresentation: String? = null,
conflictingFile: FirFile? = null,
) {
conflictingSymbol.lazyResolveToPhase(FirResolvePhase.STATUS)
@OptIn(SymbolInternals::class)
val conflicting = conflictingSymbol.fir
if (conflicting == declaration || declaration.moduleData != conflicting.moduleData) return
val actualConflictingPresentation = conflictingPresentation ?: presenter.represent(conflicting)
val actualConflictingPresentation = conflictingPresentation ?: FirRedeclarationPresenter.represent(conflicting)
if (actualConflictingPresentation != declarationPresentation) return
val actualConflictingFile =
conflictingFile ?: when (conflictingSymbol) {
@@ -272,54 +294,60 @@ class FirDeclarationInspector {
is FirCallableSymbol<*> -> session.firProvider.getFirCallableContainerFile(conflictingSymbol)
else -> null
}
if (containingFile == actualConflictingFile && conflicting.origin == FirDeclarationOrigin.Precompiled) {
return // TODO: rewrite local decls checker to the same logic and then remove the check
}
if (!conflicting.isCollectable()) return
if (areCompatibleMainFunctions(declaration, containingFile, conflicting, actualConflictingFile)) return
if (isExpectAndActual(declaration, conflicting)) return
if (
conflicting is FirMemberDeclaration &&
!session.visibilityChecker.isVisible(conflicting, session, containingFile, emptyList(), dispatchReceiver = null)
) return
val declarationIsLowPriority = hasLowPriorityAnnotation(declaration.annotations)
val conflictingIsLowPriority = hasLowPriorityAnnotation(conflicting.annotations)
if (declarationIsLowPriority != conflictingIsLowPriority) return
if (isOverloadable(declaration, conflicting)) return
declarationConflictingSymbols.getOrPut(declaration) { SmartSet.create() }.add(conflictingSymbol)
}
private fun FirDeclarationPresenter.represent(declaration: FirDeclaration): String? =
when (declaration) {
is FirSimpleFunction -> represent(declaration)
is FirRegularClass -> represent(declaration)
is FirTypeAlias -> represent(declaration)
is FirProperty -> represent(declaration)
else -> null
}
private fun FirRegularClass.onConstructors(action: (ctor: FirConstructor) -> Unit) {
class ClassConstructorVisitor : FirVisitorVoid() {
override fun visitElement(element: FirElement) {}
override fun visitConstructor(constructor: FirConstructor) {
action(constructor)
}
override fun visitDeclarationStatus(declarationStatus: FirDeclarationStatus) {}
override fun visitRegularClass(regularClass: FirRegularClass) {}
override fun visitProperty(property: FirProperty) {}
override fun visitSimpleFunction(simpleFunction: FirSimpleFunction) {}
}
if (classKind != ClassKind.OBJECT && classKind != ClassKind.ENUM_ENTRY) {
acceptChildren(ClassConstructorVisitor())
}
private fun FirSimpleFunction.representsMainFunctionAllowingConflictingOverloads(): Boolean {
if (name != StandardNames.MAIN || !symbol.callableId.isTopLevel || !hasMainFunctionStatus) return false
if (receiverParameter != null || typeParameters.isNotEmpty()) return false
if (valueParameters.isEmpty()) return true
val paramType = valueParameters.singleOrNull()?.returnTypeRef?.coneType?.fullyExpandedType(session) ?: return false
if (!paramType.isNonPrimitiveArray) return false
val typeArgument = paramType.typeArguments.singleOrNull() as? ConeKotlinTypeProjection ?: return false
// only Array<String> and Array<out String> are accepted
if (typeArgument !is ConeKotlinType && typeArgument !is ConeKotlinTypeProjectionOut) return false
return typeArgument.type.fullyExpandedType(session).isString
}
private fun areCompatibleMainFunctions(
declaration1: FirDeclaration, file1: FirFile, declaration2: FirDeclaration, file2: FirFile?,
) = file1 != file2
&& declaration1 is FirSimpleFunction
&& declaration2 is FirSimpleFunction
&& declaration1.representsMainFunctionAllowingConflictingOverloads()
&& declaration2.representsMainFunctionAllowingConflictingOverloads()
private fun isOverloadable(
declaration: FirDeclaration,
conflicting: FirDeclaration,
): Boolean {
if (isExpectAndActual(declaration, conflicting)) return true
val declarationIsLowPriority = hasLowPriorityAnnotation(declaration.annotations)
val conflictingIsLowPriority = hasLowPriorityAnnotation(conflicting.annotations)
if (declarationIsLowPriority != conflictingIsLowPriority) return true
return declaration is FirCallableDeclaration &&
conflicting is FirCallableDeclaration &&
session.declarationOverloadabilityHelper.isOverloadable(declaration, conflicting)
}
}
fun checkConflictingElements(elements: List<FirElement>, context: CheckerContext, reporter: DiagnosticReporter) {
/** Checks for redeclarations of value and type parameters, and local variables. */
fun checkForLocalRedeclarations(elements: List<FirElement>, context: CheckerContext, reporter: DiagnosticReporter) {
if (elements.size <= 1) return
val multimap = ListMultimap<Name, FirBasedSymbol<*>>()
for (element in elements) {
val name: Name?
val symbol: FirBasedSymbol<*>?
@@ -1,228 +0,0 @@
/*
* Copyright 2010-2023 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.checkers
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.utils.isOperator
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.name.CallableId
import org.jetbrains.kotlin.name.ClassId
/**
* Provides representations for FirElement's.
*/
interface FirDeclarationPresenter {
fun StringBuilder.appendRepresentation(it: FirElement) {
append("NO_REPRESENTATION")
}
fun StringBuilder.appendRepresentation(it: ClassId) {
append(it.packageFqName.asString())
append('/')
append(it.relativeClassName.asString())
}
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)
}
}
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)
}
is ConeKotlinTypeConflictingProjection -> {}
}
}
fun StringBuilder.appendRepresentation(it: ConeKotlinType) {
when (it) {
is ConeDefinitelyNotNullType -> {
appendRepresentation(it.original)
append(it.nullability.suffix)
}
is ConeErrorType -> {
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 ConeIntegerLiteralConstantType -> {
append(it.value)
append(it.nullability.suffix)
}
is ConeIntegerConstantOperatorType -> {
append("IOT")
append(it.nullability.suffix)
}
is ConeFlexibleType,
is ConeIntersectionType,
is ConeStubType -> {
append("ERROR")
}
}
}
fun StringBuilder.appendRepresentation(it: FirTypeRef) {
when (it) {
is FirResolvedTypeRef -> appendRepresentation(it.type)
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: FirVariable) = buildString {
append('[')
it.receiverParameter?.typeRef?.let {
appendRepresentation(it)
}
append(']')
appendRepresentation(it.symbol.callableId)
}
fun StringBuilder.appendOperatorTag(it: FirSimpleFunction) {
if (it.isOperator) {
append("operator ")
}
}
fun StringBuilder.appendRepresentationBeforeCallableId(it: FirSimpleFunction) {
it.contextReceivers.forEach {
appendRepresentation(it)
append(',')
}
append('<')
it.typeParameters.forEach {
appendRepresentation(it)
append(',')
}
append('>')
append('[')
it.receiverParameter?.typeRef?.let {
appendRepresentation(it)
}
append(']')
appendOperatorTag(it)
}
fun StringBuilder.appendRepresentationAfterCallableId(it: FirSimpleFunction) {
append('(')
it.valueParameters.forEach {
appendRepresentation(it)
append(',')
}
append(')')
}
fun represent(it: FirSimpleFunction) = buildString {
appendRepresentationBeforeCallableId(it)
appendRepresentation(it.symbol.callableId)
appendRepresentationAfterCallableId(it)
}
fun represent(it: FirTypeAlias) = buildString {
append('[')
append(']')
appendRepresentation(it.symbol.classId)
}
fun represent(it: FirRegularClass) = buildString {
append('[')
append(']')
appendRepresentation(it.symbol.classId)
}
fun represent(it: FirConstructor, owner: FirRegularClass) = buildString {
it.contextReceivers.forEach {
appendRepresentation(it)
append(',')
}
append('<')
it.typeParameters.forEach {
appendRepresentation(it)
append(',')
}
append('>')
append('[')
append(']')
appendRepresentation(owner.symbol.classId)
append('(')
it.valueParameters.forEach {
appendRepresentation(it)
append(',')
}
append(')')
}
}
@@ -0,0 +1,121 @@
/*
* Copyright 2010-2023 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.checkers
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.utils.isOperator
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.name.CallableId
import org.jetbrains.kotlin.name.ClassId
/**
* Provides representations for FirElements consisting of declaration name and shape of parameters,
* i.e., number of context receivers, receivers, type parameters, and parameters.
*
* Elements that are potential redeclarations have the same representations, e.g., properties without receivers and classes.
*/
internal object FirRedeclarationPresenter {
private fun StringBuilder.appendRepresentation(it: ClassId) {
append(it.packageFqName.asString())
append('/')
append(it.relativeClassName.asString())
}
private fun StringBuilder.appendRepresentation(it: CallableId) {
append(it.packageName.asString())
append('/')
if (it.className != null) {
append(it.className)
append('.')
}
append(it.callableName)
}
private fun StringBuilder.appendRepresentation(it: FirValueParameter) {
if (it.isVararg) {
append("vararg ")
}
}
private fun StringBuilder.appendRepresentationBeforeCallableId(it: FirCallableDeclaration) {
repeat(it.contextReceivers.size) {
append(',')
}
append('<')
repeat(it.typeParameters.size) {
append(',')
}
append('>')
append('[')
it.receiverParameter?.typeRef?.let {
append(',')
}
append(']')
}
private fun StringBuilder.appendValueParameters(it: FirSimpleFunction) {
append('(')
it.valueParameters.forEach {
appendRepresentation(it)
append(',')
}
append(')')
}
fun represent(declaration: FirDeclaration): String? = when (declaration) {
is FirSimpleFunction -> represent(declaration)
is FirRegularClass -> represent(declaration)
is FirTypeAlias -> represent(declaration)
is FirProperty -> represent(declaration)
else -> null
}
fun represent(it: FirSimpleFunction) = buildString {
appendRepresentationBeforeCallableId(it)
if (it.isOperator) {
append("operator ")
}
appendRepresentation(it.symbol.callableId)
appendValueParameters(it)
}
fun represent(it: FirVariable) = buildString {
appendRepresentationBeforeCallableId(it)
appendRepresentation(it.symbol.callableId)
}
fun represent(it: FirTypeAlias) = representClassLike(it)
fun represent(it: FirRegularClass) = representClassLike(it)
private fun representClassLike(it: FirClassLikeDeclaration) = buildString {
append('<')
append('>')
append('[')
append(']')
appendRepresentation(it.symbol.classId)
}
fun represent(it: FirConstructor, owner: FirRegularClass) = buildString {
repeat(it.contextReceivers.size) {
append(',')
}
append('<')
repeat(it.typeParameters.size) {
append(',')
}
append('>')
append('[')
append(']')
appendRepresentation(owner.symbol.classId)
append('(')
it.valueParameters.forEach {
appendRepresentation(it)
append(',')
}
append(')')
}
}
@@ -5,12 +5,13 @@
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
import com.sun.org.apache.bcel.internal.generic.RETURN
import org.jetbrains.kotlin.KtFakeSourceElementKind
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.diagnostics.reportOn
import org.jetbrains.kotlin.fir.FirNameConflictsTrackerComponent
import org.jetbrains.kotlin.fir.analysis.checkers.FirDeclarationInspector
import org.jetbrains.kotlin.fir.analysis.checkers.checkConflictingElements
import org.jetbrains.kotlin.fir.analysis.checkers.checkForLocalRedeclarations
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.declarations.*
@@ -18,57 +19,61 @@ import org.jetbrains.kotlin.fir.packageFqName
import org.jetbrains.kotlin.fir.resolve.getContainingDeclaration
import org.jetbrains.kotlin.fir.scopes.impl.FirPackageMemberScope
import org.jetbrains.kotlin.fir.scopes.impl.PACKAGE_MEMBER
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.utils.SmartSet
object FirConflictsDeclarationChecker : FirBasicDeclarationChecker() {
override fun check(declaration: FirDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
val inspector: FirDeclarationInspector?
when (declaration) {
is FirFile -> {
inspector = FirDeclarationInspector()
val inspector = FirDeclarationInspector(context.sessionHolder.session)
checkFile(declaration, inspector, context)
reportConflicts(reporter, context, inspector.declarationConflictingSymbols)
}
is FirRegularClass -> {
if (declaration.source?.kind !is KtFakeSourceElementKind) {
checkConflictingElements(declaration.typeParameters, context, reporter)
checkForLocalRedeclarations(declaration.typeParameters, context, reporter)
}
inspector = FirDeclarationInspector()
checkRegularClass(declaration, inspector)
val inspector = FirDeclarationInspector(context.sessionHolder.session)
inspector.collectClassMembers(declaration)
reportConflicts(reporter, context, inspector.declarationConflictingSymbols)
}
else -> {
if (declaration.source?.kind !is KtFakeSourceElementKind && declaration is FirTypeParameterRefsOwner) {
if (declaration is FirFunction) {
checkConflictingElements(declaration.valueParameters, context, reporter)
checkForLocalRedeclarations(declaration.valueParameters, context, reporter)
}
checkConflictingElements(declaration.typeParameters, context, reporter)
checkForLocalRedeclarations(declaration.typeParameters, context, reporter)
}
return
}
}
}
inspector.declarationConflictingSymbols.forEach { (conflictingDeclaration, symbols) ->
private fun reportConflicts(
reporter: DiagnosticReporter,
context: CheckerContext,
declarationConflictingSymbols: Map<FirDeclaration, SmartSet<FirBasedSymbol<*>>>,
) {
declarationConflictingSymbols.forEach { (conflictingDeclaration, symbols) ->
val source = conflictingDeclaration.source
if (symbols.isNotEmpty()) {
when (conflictingDeclaration) {
is FirSimpleFunction,
is FirConstructor -> {
reporter.reportOn(source, FirErrors.CONFLICTING_OVERLOADS, symbols, context)
}
else -> {
val factory = if (conflictingDeclaration is FirClassLikeDeclaration &&
conflictingDeclaration.getContainingDeclaration(context.session) == null &&
symbols.any { it is FirClassLikeSymbol<*> }
) {
FirErrors.PACKAGE_OR_CLASSIFIER_REDECLARATION
} else {
FirErrors.REDECLARATION
}
reporter.reportOn(source, factory, symbols, context)
}
if (symbols.isEmpty()) return@forEach
val factory =
if (conflictingDeclaration is FirSimpleFunction || conflictingDeclaration is FirConstructor) {
FirErrors.CONFLICTING_OVERLOADS
} else if (conflictingDeclaration is FirClassLikeDeclaration &&
conflictingDeclaration.getContainingDeclaration(context.session) == null &&
symbols.any { it is FirClassLikeSymbol<*> }
) {
FirErrors.PACKAGE_OR_CLASSIFIER_REDECLARATION
} else {
FirErrors.REDECLARATION
}
}
reporter.reportOn(source, factory, symbols, context)
}
}
@@ -76,15 +81,10 @@ object FirConflictsDeclarationChecker : FirBasicDeclarationChecker() {
val packageMemberScope: FirPackageMemberScope = context.sessionHolder.scopeSession.getOrBuild(file.packageFqName, PACKAGE_MEMBER) {
FirPackageMemberScope(file.packageFqName, context.sessionHolder.session)
}
inspector.collectTopLevel(file, packageMemberScope)
for (topLevelDeclaration in file.declarations) {
if (topLevelDeclaration is FirErrorProperty || topLevelDeclaration is FirErrorFunction) continue
inspector.collectWithExternalConflicts(topLevelDeclaration, file, context.session, packageMemberScope)
}
}
private fun checkRegularClass(declaration: FirRegularClass, inspector: FirDeclarationInspector) {
for (it in declaration.declarations) {
inspector.collect(it)
}
}
}
@@ -93,7 +93,7 @@ class FirNameConflictsTracker : FirNameConflictsTrackerComponent() {
data class ClassifierWithFile(
val classifier: FirClassLikeSymbol<*>,
val file: FirFile?
val file: FirFile?,
)
val redeclaredClassifiers = HashMap<ClassId, Set<ClassifierWithFile>>()
@@ -101,7 +101,7 @@ class FirNameConflictsTracker : FirNameConflictsTrackerComponent() {
override fun registerClassifierRedeclaration(
classId: ClassId,
newSymbol: FirClassLikeSymbol<*>, newSymbolFile: FirFile,
prevSymbol: FirClassLikeSymbol<*>, prevSymbolFile: FirFile?
prevSymbol: FirClassLikeSymbol<*>, prevSymbolFile: FirFile?,
) {
redeclaredClassifiers.merge(
classId, linkedSetOf(ClassifierWithFile(newSymbol, newSymbolFile), ClassifierWithFile(prevSymbol, prevSymbolFile))
@@ -8,7 +8,6 @@ package org.jetbrains.kotlin.fir.analysis.checkers.declaration
import org.jetbrains.kotlin.builtins.StandardNames.HASHCODE_NAME
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.diagnostics.reportOn
import org.jetbrains.kotlin.fir.analysis.checkers.FirDeclarationPresenter
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
@@ -17,20 +16,9 @@ import org.jetbrains.kotlin.fir.declarations.isEquals
import org.jetbrains.kotlin.fir.declarations.utils.hasBody
import org.jetbrains.kotlin.fir.declarations.utils.isInterface
import org.jetbrains.kotlin.fir.declarations.utils.isOverride
import org.jetbrains.kotlin.name.CallableId
import org.jetbrains.kotlin.util.OperatorNameConventions.TO_STRING
object FirMethodOfAnyImplementedInInterfaceChecker : FirRegularClassChecker(), FirDeclarationPresenter {
// We need representations that look like JVM signatures. Thus, just function names, not fully qualified ones.
override fun StringBuilder.appendRepresentation(it: CallableId) {
append(it.callableName)
}
// We need representations that look like JVM signatures. Hence, no need to represent operator.
override fun StringBuilder.appendOperatorTag(it: FirSimpleFunction) {
// Intentionally empty
}
object FirMethodOfAnyImplementedInInterfaceChecker : FirRegularClassChecker() {
override fun check(declaration: FirRegularClass, context: CheckerContext, reporter: DiagnosticReporter) {
if (!declaration.isInterface) {
return
@@ -6,12 +6,12 @@
package org.jetbrains.kotlin.fir.analysis.checkers.expression
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.checkers.checkConflictingElements
import org.jetbrains.kotlin.fir.analysis.checkers.checkForLocalRedeclarations
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.expressions.FirBlock
object FirConflictsExpressionChecker : FirBlockChecker() {
override fun check(expression: FirBlock, context: CheckerContext, reporter: DiagnosticReporter) {
checkConflictingElements(expression.statements, context, reporter)
checkForLocalRedeclarations(expression.statements, context, reporter)
}
}
}
@@ -17,6 +17,8 @@ import org.jetbrains.kotlin.fir.analysis.jvm.FirJvmOverridesBackwardCompatibilit
import org.jetbrains.kotlin.fir.analysis.jvm.checkers.FirJvmInlineCheckerComponent
import org.jetbrains.kotlin.fir.caches.FirCachesFactory
import org.jetbrains.kotlin.fir.caches.FirThreadUnsafeCachesFactory
import org.jetbrains.kotlin.fir.declarations.FirDeclarationOverloadabilityHelper
import org.jetbrains.kotlin.fir.declarations.FirTypeSpecificityComparatorProvider
import org.jetbrains.kotlin.fir.declarations.SealedClassInheritorsProvider
import org.jetbrains.kotlin.fir.declarations.SealedClassInheritorsProviderImpl
import org.jetbrains.kotlin.fir.deserialization.DeserializedClassConfigurator
@@ -32,6 +34,7 @@ import org.jetbrains.kotlin.fir.java.enhancement.JavaCompilerRequiredAnnotationE
import org.jetbrains.kotlin.fir.java.scopes.JavaOverridabilityRules
import org.jetbrains.kotlin.fir.resolve.*
import org.jetbrains.kotlin.fir.resolve.calls.ConeCallConflictResolverFactory
import org.jetbrains.kotlin.fir.resolve.calls.FirDeclarationOverloadabilityHelperImpl
import org.jetbrains.kotlin.fir.resolve.calls.FirSyntheticNamesProvider
import org.jetbrains.kotlin.fir.resolve.calls.jvm.JvmCallConflictResolverFactory
import org.jetbrains.kotlin.fir.resolve.inference.InferenceComponents
@@ -48,12 +51,10 @@ import org.jetbrains.kotlin.fir.scopes.PlatformSpecificOverridabilityRules
import org.jetbrains.kotlin.fir.scopes.impl.*
import org.jetbrains.kotlin.fir.serialization.FirProvidedDeclarationsForMetadataService
import org.jetbrains.kotlin.fir.symbols.FirLazyDeclarationResolver
import org.jetbrains.kotlin.fir.types.FirCorrespondingSupertypesCache
import org.jetbrains.kotlin.fir.types.FirFunctionTypeKindService
import org.jetbrains.kotlin.fir.types.FirFunctionTypeKindServiceImpl
import org.jetbrains.kotlin.fir.types.TypeComponents
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.incremental.components.EnumWhenTracker
import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.resolve.jvm.JvmTypeSpecificityComparator
import org.jetbrains.kotlin.resolve.jvm.modules.JavaModuleResolver
// -------------------------- Required components --------------------------
@@ -79,6 +80,7 @@ fun FirSession.registerCommonComponents(languageVersionSettings: LanguageVersion
register(FirDynamicMembersStorage::class, FirDynamicMembersStorage(this))
register(FirEnumEntriesSupport::class, FirEnumEntriesSupport(this))
register(FirOverrideChecker::class, FirStandardOverrideChecker(this))
register(FirDeclarationOverloadabilityHelper::class, FirDeclarationOverloadabilityHelperImpl(this))
}
@OptIn(SessionConfiguration::class)
@@ -153,6 +155,10 @@ fun FirSession.registerResolveComponents(lookupTracker: LookupTracker? = null, e
fun FirSession.registerJavaSpecificResolveComponents() {
register(FirVisibilityChecker::class, FirJavaVisibilityChecker)
register(ConeCallConflictResolverFactory::class, JvmCallConflictResolverFactory)
register(
FirTypeSpecificityComparatorProvider::class,
FirTypeSpecificityComparatorProvider(JvmTypeSpecificityComparator(typeContext))
)
register(FirPlatformClassMapper::class, FirJavaClassMapper(this))
register(FirSyntheticNamesProvider::class, FirJavaSyntheticNamesProvider)
register(FirOverridesBackwardCompatibilityHelper::class, FirJvmOverridesBackwardCompatibilityHelper)
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.fir.analysis.checkers.FirPlatformDiagnosticSuppresso
import org.jetbrains.kotlin.fir.analysis.js.checkers.FirJsModuleKind
import org.jetbrains.kotlin.fir.analysis.js.checkers.FirJsPlatformDiagnosticSuppressor
import org.jetbrains.kotlin.fir.checkers.registerJsCheckers
import org.jetbrains.kotlin.fir.declarations.FirTypeSpecificityComparatorProvider
import org.jetbrains.kotlin.fir.deserialization.ModuleDataProvider
import org.jetbrains.kotlin.fir.deserialization.SingleModuleDataProvider
import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrar
@@ -25,8 +26,10 @@ import org.jetbrains.kotlin.fir.resolve.calls.ConeCallConflictResolverFactory
import org.jetbrains.kotlin.fir.resolve.providers.impl.FirBuiltinSyntheticFunctionInterfaceProvider
import org.jetbrains.kotlin.fir.scopes.FirKotlinScopeProvider
import org.jetbrains.kotlin.fir.scopes.FirPlatformClassMapper
import org.jetbrains.kotlin.fir.types.typeContext
import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.js.config.JSConfigurationKeys
import org.jetbrains.kotlin.js.resolve.JsTypeSpecificityComparatorWithoutDelegate
import org.jetbrains.kotlin.library.KotlinLibrary
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.serialization.js.ModuleKind
@@ -106,6 +109,10 @@ object FirJsSessionFactory : FirAbstractSessionFactory() {
fun FirSession.registerJsSpecificComponents(compilerConfiguration: CompilerConfiguration) {
register(FirVisibilityChecker::class, FirVisibilityChecker.Default)
register(ConeCallConflictResolverFactory::class, JsCallConflictResolverFactory)
register(
FirTypeSpecificityComparatorProvider::class,
FirTypeSpecificityComparatorProvider(JsTypeSpecificityComparatorWithoutDelegate(typeContext))
)
register(FirPlatformClassMapper::class, FirPlatformClassMapper.Default)
register(FirOverridesBackwardCompatibilityHelper::class, FirEmptyOverridesBackwardCompatibilityHelper)
register(FirPlatformDiagnosticSuppressor::class, FirJsPlatformDiagnosticSuppressor())
@@ -0,0 +1,15 @@
/*
* Copyright 2010-2023 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.declarations
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.FirSessionComponent
interface FirDeclarationOverloadabilityHelper : FirSessionComponent {
fun isOverloadable(a: FirCallableDeclaration, b: FirCallableDeclaration): Boolean
}
val FirSession.declarationOverloadabilityHelper: FirDeclarationOverloadabilityHelper by FirSession.sessionComponentAccessor()
@@ -0,0 +1,14 @@
/*
* Copyright 2010-2023 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.declarations
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.FirSessionComponent
import org.jetbrains.kotlin.resolve.calls.results.TypeSpecificityComparator
class FirTypeSpecificityComparatorProvider(val typeSpecificityComparator: TypeSpecificityComparator) : FirSessionComponent
val FirSession.typeSpecificityComparatorProvider: FirTypeSpecificityComparatorProvider? by FirSession.nullableSessionComponentAccessor()
@@ -0,0 +1,61 @@
/*
* Copyright 2010-2023 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.resolve.calls
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
import org.jetbrains.kotlin.fir.declarations.FirDeclarationOverloadabilityHelper
import org.jetbrains.kotlin.fir.declarations.FirFunction
import org.jetbrains.kotlin.fir.declarations.typeSpecificityComparatorProvider
import org.jetbrains.kotlin.fir.declarations.utils.isExpect
import org.jetbrains.kotlin.fir.declarations.utils.isSynthetic
import org.jetbrains.kotlin.fir.resolve.inference.inferenceComponents
import org.jetbrains.kotlin.fir.types.coneType
import org.jetbrains.kotlin.resolve.calls.results.*
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
class FirDeclarationOverloadabilityHelperImpl(val session: FirSession) : FirDeclarationOverloadabilityHelper {
override fun isOverloadable(a: FirCallableDeclaration, b: FirCallableDeclaration): Boolean {
val sigA = createSignature(a)
val sigB = createSignature(b)
return !(isNotLessSpecific(sigA, sigB) && isNotLessSpecific(sigB, sigA))
}
private fun isNotLessSpecific(
sigA: FlatSignature<FirCallableDeclaration>,
sigB: FlatSignature<FirCallableDeclaration>,
): Boolean = createEmptyConstraintSystem().isSignatureNotLessSpecific(
sigA,
sigB,
OverloadabilitySpecificityCallbacks,
session.typeSpecificityComparatorProvider?.typeSpecificityComparator ?: TypeSpecificityComparator.NONE,
)
private fun createSignature(declaration: FirCallableDeclaration): FlatSignature<FirCallableDeclaration> {
val valueParameters = (declaration as? FirFunction)?.valueParameters.orEmpty()
return FlatSignature(
origin = declaration,
typeParameters = declaration.typeParameters.map { it.symbol.toLookupTag() },
valueParameterTypes = buildList<KotlinTypeMarker> {
declaration.contextReceivers.mapTo(this) { it.typeRef.coneType }
declaration.receiverParameter?.let { add(it.typeRef.coneType) }
valueParameters.mapTo(this) { it.returnTypeRef.coneType }
},
hasExtensionReceiver = declaration.receiverParameter != null,
contextReceiverCount = declaration.contextReceivers.size,
hasVarargs = valueParameters.any { it.isVararg },
numDefaults = 0,
isExpect = declaration.isExpect,
isSyntheticMember = declaration.isSynthetic
)
}
private fun createEmptyConstraintSystem(): SimpleConstraintSystem {
return ConeSimpleConstraintSystemImpl(session.inferenceComponents.createConstraintSystem(), session)
}
}
@@ -25,11 +25,6 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.varargParameterPosition
import org.jetbrains.kotlin.types.error.ErrorUtils
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
object OverloadabilitySpecificityCallbacks : SpecificityComparisonCallbacks {
override fun isNonSubtypeNotLessSpecific(specific: KotlinTypeMarker, general: KotlinTypeMarker): Boolean =
false
}
class OverloadChecker(val specificityComparator: TypeSpecificityComparator) {
/**
* Does not check names.
@@ -12,6 +12,11 @@ interface SpecificityComparisonCallbacks {
fun isNonSubtypeNotLessSpecific(specific: KotlinTypeMarker, general: KotlinTypeMarker): Boolean
}
object OverloadabilitySpecificityCallbacks : SpecificityComparisonCallbacks {
override fun isNonSubtypeNotLessSpecific(specific: KotlinTypeMarker, general: KotlinTypeMarker): Boolean =
false
}
class TypeWithConversion(val resultType: KotlinTypeMarker?, val originalTypeIfWasConverted: KotlinTypeMarker? = null)
class FlatSignature<out T> constructor(
@@ -136,4 +141,3 @@ fun <T> SimpleConstraintSystem.isSignatureNotLessSpecific(
return !hasContradiction()
}
@@ -1,6 +1,4 @@
// IGNORE_BACKEND: JVM, JVM_IR
// IGNORE_BACKEND_K2: JS_IR, NATIVE, WASM
// FIR status: not supported
package foo
@@ -16,4 +14,4 @@ fun box(): String {
return c1.p + c2.p
}
}
@@ -3,11 +3,11 @@
interface A
interface B
<!CONFLICTING_OVERLOADS!>context(A, B)
fun f(): Unit<!> = TODO()
context(A, B)
fun f(): Unit = TODO()
<!CONFLICTING_OVERLOADS!>context(B, A)
fun f(): Unit<!> = TODO()
context(B, A)
fun f(): Unit = TODO()
fun test(a: A, b: B) {
<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER, NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>with<!>(a) {
@@ -1,20 +0,0 @@
// !LANGUAGE: +ContextReceivers
interface A
interface B
interface C
interface D
<!CONFLICTING_OVERLOADS!>context(A, B)
fun f(): Unit<!> = TODO()
<!CONFLICTING_OVERLOADS!>context(C, D)
fun f(): Unit<!> = TODO()
fun test(a: A, b: B) {
with(a) {
with(b) {
f()
}
}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !LANGUAGE: +ContextReceivers
interface A
@@ -4,7 +4,7 @@ class A<T>(val a: T)
class B(val b: Any)
class C(val c: Any)
<!MUST_BE_INITIALIZED!>context(A<String>, B) var <!REDECLARATION!>p<!>: Int<!>
<!MUST_BE_INITIALIZED!>context(A<String>, B) var p: Int<!>
get() {
this@A.a.length
this@B.b
@@ -18,7 +18,7 @@ class C(val c: Any)
field = value
}
<!MUST_BE_INITIALIZED!>context(A<Int>, A<String>, B) var <!REDECLARATION!>p<!>: Int<!>
<!MUST_BE_INITIALIZED!>context(A<Int>, A<String>, B) var p: Int<!>
get() {
this@A.a.<!UNRESOLVED_REFERENCE!>toDouble<!>()
this@A.a.length
@@ -1,8 +1,8 @@
fun <T1> test1(x: List<T1>) = x
fun <T2> test1(x: List<T2>) = x
<!CONFLICTING_OVERLOADS!>fun <T1> test1(x: List<T1>)<!> = x
<!CONFLICTING_OVERLOADS!>fun <T2> test1(x: List<T2>)<!> = x
fun <T1> List<T1>.test1a() {}
fun <T2> List<T2>.test1a() {}
<!CONFLICTING_OVERLOADS!>fun <T1> List<T1>.test1a()<!> {}
<!CONFLICTING_OVERLOADS!>fun <T2> List<T2>.test1a()<!> {}
fun <T> test2(x: List<T>) = x
fun test2(x: List<String>) = x
@@ -24,11 +24,11 @@ fun <K, V> Map<K, V>.test4a() {}
class Inv<T>
fun <T> test5(x: Inv<T>) = x
fun <T> test5(x: Inv<out T>) = x
<!CONFLICTING_OVERLOADS!>fun <T> test5(x: Inv<T>)<!> = x
<!CONFLICTING_OVERLOADS!>fun <T> test5(x: Inv<out T>)<!> = x
fun <T> test6(x: Array<T>) = x
fun test6(x: Array<String>) = x
fun <T> test7(x: Inv<T>) = x
fun <T> Inv<T>.test7() {}
fun <T> Inv<T>.test7() {}
@@ -1,5 +1,107 @@
// !LANGUAGE: +ContextReceivers
// FIR_IDENTICAL
package foo
val Int.<!REDECLARATION!>foo<!>: Int get() = 2
val Int.<!REDECLARATION!>foo<!>: Int get() = 3
val Int.<!REDECLARATION!>simple<!>: Int get() = 0
val Int.<!REDECLARATION!>simple<!>: Int get() = 0
val Int.differentTypes: Int get() = 0
val String.differentTypes: Int get() = 0
val <T> T.<!REDECLARATION!>sameNamedGenerics<!>: Int get() = 0
val <T> T.<!REDECLARATION!>sameNamedGenerics<!>: Int get() = 0
val <T> T.<!REDECLARATION!>differentlyNamedGenerics<!>: Int get() = 0
val <R> R.<!REDECLARATION!>differentlyNamedGenerics<!>: Int get() = 0
val <T> T.sameNamedGenericsDifferentBounds: Int get() = 0
val <T : Any> T.sameNamedGenericsDifferentBounds: String get() = ""
val <T> T.differentlyNamedGenericsDifferentBounds: Int get() = 0
val <R : Any> R.differentlyNamedGenericsDifferentBounds: String get() = ""
val <T> List<T>.sameNamedGenericsListDifferentBounds: Int get() = 0
val <T : Any> List<T>.sameNamedGenericsListDifferentBounds: String get() = ""
val <T> List<T>.differentlyNamedGenericsListDifferentBounds: Int get() = 0
val <R : Any> List<R>.differentlyNamedGenericsListDifferentBounds: String get() = ""
context(Int) val <!REDECLARATION!>simpleContextReceivers<!>: Int get() = 0
context(Int) val <!REDECLARATION!>simpleContextReceivers<!>: Int get() = 0
context(Int) val differentTypesContextReceivers: Int get() = 0
context(String) val differentTypesContextReceivers: Int get() = 0
context(T) val <T> <!REDECLARATION!>sameNamedGenericsContextReceivers<!>: Int get() = 0
context(T) val <T> <!REDECLARATION!>sameNamedGenericsContextReceivers<!>: Int get() = 0
context(T) val <T> <!REDECLARATION!>differentlyNamedGenericsContextReceivers<!>: Int get() = 0
context(R) val <R> <!REDECLARATION!>differentlyNamedGenericsContextReceivers<!>: Int get() = 0
context(T) val <T> sameNamedGenericsDifferentBoundsContextReceivers: Int get() = 0
context(T) val <T : Any> sameNamedGenericsDifferentBoundsContextReceivers: String get() = ""
context(T) val <T> differentlyNamedGenericsDifferentBoundsContextReceivers: Int get() = 0
context(R) val <R : Any> differentlyNamedGenericsDifferentBoundsContextReceivers: String get() = ""
context(List<T>) val <T> sameNamedGenericsListDifferentBoundsContextReceivers: Int get() = 0
context(List<T>) val <T : Any> sameNamedGenericsListDifferentBoundsContextReceivers: String get() = ""
context(List<T>) val <T> differentlyNamedGenericsListDifferentBoundsContextReceivers: Int get() = 0
context(List<R>) val <R : Any> differentlyNamedGenericsListDifferentBoundsContextReceivers: String get() = ""
val Int.extensionVsContextReceiver: Int get() = 0
context(Int) val extensionVsContextReceiver: String get() = ""
class C {
val Int.<!REDECLARATION!>simple<!>: Int get() = 0
val Int.<!REDECLARATION!>simple<!>: Int get() = 0
val Int.differentTypes: Int get() = 0
val String.differentTypes: Int get() = 0
val <T> T.<!REDECLARATION!>sameNamedGenerics<!>: Int get() = 0
val <T> T.<!REDECLARATION!>sameNamedGenerics<!>: Int get() = 0
val <T> T.<!REDECLARATION!>differentlyNamedGenerics<!>: Int get() = 0
val <R> R.<!REDECLARATION!>differentlyNamedGenerics<!>: Int get() = 0
val <T> T.sameNamedGenericsDifferentBounds: Int get() = 0
val <T : Any> T.sameNamedGenericsDifferentBounds: String get() = ""
val <T> T.differentlyNamedGenericsDifferentBounds: Int get() = 0
val <R : Any> R.differentlyNamedGenericsDifferentBounds: String get() = ""
val <T> List<T>.sameNamedGenericsListDifferentBounds: Int get() = 0
val <T : Any> List<T>.sameNamedGenericsListDifferentBounds: String get() = ""
val <T> List<T>.differentlyNamedGenericsListDifferentBounds: Int get() = 0
val <R : Any> List<R>.differentlyNamedGenericsListDifferentBounds: String get() = ""
context(Int) val <!REDECLARATION!>simpleContextReceivers<!>: Int get() = 0
context(Int) val <!REDECLARATION!>simpleContextReceivers<!>: Int get() = 0
context(Int) val differentTypesContextReceivers: Int get() = 0
context(String) val differentTypesContextReceivers: Int get() = 0
context(T) val <T> <!REDECLARATION!>sameNamedGenericsContextReceivers<!>: Int get() = 0
context(T) val <T> <!REDECLARATION!>sameNamedGenericsContextReceivers<!>: Int get() = 0
context(T) val <T> <!REDECLARATION!>differentlyNamedGenericsContextReceivers<!>: Int get() = 0
context(R) val <R> <!REDECLARATION!>differentlyNamedGenericsContextReceivers<!>: Int get() = 0
context(T) val <T> sameNamedGenericsDifferentBoundsContextReceivers: Int get() = 0
context(T) val <T : Any> sameNamedGenericsDifferentBoundsContextReceivers: String get() = ""
context(T) val <T> differentlyNamedGenericsDifferentBoundsContextReceivers: Int get() = 0
context(R) val <R : Any> differentlyNamedGenericsDifferentBoundsContextReceivers: String get() = ""
context(List<T>) val <T> sameNamedGenericsListDifferentBoundsContextReceivers: Int get() = 0
context(List<T>) val <T : Any> sameNamedGenericsListDifferentBoundsContextReceivers: String get() = ""
context(List<T>) val <T> differentlyNamedGenericsListDifferentBoundsContextReceivers: Int get() = 0
context(List<R>) val <R : Any> differentlyNamedGenericsListDifferentBoundsContextReceivers: String get() = ""
val Int.extensionVsContextReceiver: Int get() = 0
context(Int) val extensionVsContextReceiver: String get() = ""
}
@@ -1,6 +0,0 @@
package
package foo {
public val kotlin.Int.foo: kotlin.Int
public val kotlin.Int.foo: kotlin.Int
}
@@ -1,6 +0,0 @@
// FIR_IDENTICAL
// FILE: a.kt
fun main() {}
// FILE: b.kt
fun main() {}
@@ -1,4 +0,0 @@
package
public fun main(): kotlin.Unit
public fun main(): kotlin.Unit
@@ -0,0 +1,112 @@
// FIR_IDENTICAL
// ### INVALID
// FILE: invalid_noargs.kt
package invalid1
<!CONFLICTING_OVERLOADS!>fun main()<!> {}
<!CONFLICTING_OVERLOADS!>fun main()<!> {}
// FILE: invalid_array.kt
package invalid2
<!CONFLICTING_OVERLOADS!>fun main(args: Array<String>)<!> {}
<!CONFLICTING_OVERLOADS!>fun main(args: Array<String>)<!> {}
// FILE: invalid_vararg.kt
package invalid3
<!CONFLICTING_OVERLOADS!>fun main(vararg args: String)<!> {}
<!CONFLICTING_OVERLOADS!>fun main(vararg args: String)<!> {}
// FILE: invalid_array_typealias.kt
package invalid4
typealias S = String
<!CONFLICTING_OVERLOADS!>fun main(args: Array<String>)<!> {}
<!CONFLICTING_OVERLOADS!>fun main(args: Array<S>)<!> {}
// FILE: invalid_noargs_suspend.kt
package invalid5
<!CONFLICTING_OVERLOADS!>suspend fun main()<!> {}
<!CONFLICTING_OVERLOADS!>suspend fun main()<!> {}
// FILE: invalid_array_suspend.kt
package invalid6
<!CONFLICTING_OVERLOADS!>suspend fun main(args: Array<String>)<!> {}
<!CONFLICTING_OVERLOADS!>suspend fun main(args: Array<String>)<!> {}
// FILE: invalid_vararg_suspend.kt
package invalid7
<!CONFLICTING_OVERLOADS!>suspend fun main(vararg args: String)<!> {}
<!CONFLICTING_OVERLOADS!>suspend fun main(vararg args: String)<!> {}
// FILE: invalid_array_typealias_suspend.kt
package invalid8
typealias S = String
<!CONFLICTING_OVERLOADS!>suspend fun main(args: Array<String>)<!> {}
<!CONFLICTING_OVERLOADS!>suspend fun main(args: Array<S>)<!> {}
// ### VALID
// FILE: valid_noargs.kt
package valid1
fun main() {}
// FILE: valid_noargs2.kt
package valid1
fun main() {}
// FILE: valid_array.kt
package valid2
fun main(args: Array<String>) {}
// FILE: valid_array2.kt
package valid2
fun main(args: Array<String>) {}
// FILE: valid_vararg.kt
package valid3
fun main(vararg args: String) {}
// FILE: valid_vararg2.kt
package valid3
fun main(vararg args: String) {}
// FILE: valid_array_typealias.kt
package valid4
fun main(args: Array<String>) {}
// FILE: valid_array_typealias2.kt
package valid4
typealias S = String
fun main(args: Array<S>) {}
// FILE: valid_noargs_suspend.kt
package valid5
suspend fun main() {}
// FILE: valid_noargs_suspend2.kt
package valid5
suspend fun main() {}
// FILE: valid_array_suspend.kt
package valid6
suspend fun main(args: Array<String>) {}
// FILE: valid_array_suspend2.kt
package valid6
suspend fun main(args: Array<String>) {}
// FILE: valid_vararg_suspend.kt
package valid7
suspend fun main(vararg args: String) {}
// FILE: valid_vararg_suspend2.kt
package valid7
suspend fun main(vararg args: String) {}
// FILE: valid_array_typealias_suspend.kt
package valid8
suspend fun main(args: Array<String>) {}
// FILE: valid_array_typealias_suspend2.kt
package valid8
typealias S = String
suspend fun main(args: Array<S>) {}
@@ -0,0 +1,113 @@
// !LANGUAGE: -ExtendedMainConvention
// ### INVALID
// FILE: invalid_noargs.kt
package invalid1
<!CONFLICTING_OVERLOADS!>fun main()<!> {}
<!CONFLICTING_OVERLOADS!>fun main()<!> {}
// FILE: invalid_array.kt
package invalid2
<!CONFLICTING_OVERLOADS!>fun main(args: Array<String>)<!> {}
<!CONFLICTING_OVERLOADS!>fun main(args: Array<String>)<!> {}
// FILE: invalid_vararg.kt
package invalid3
<!CONFLICTING_OVERLOADS!>fun main(vararg args: String)<!> {}
<!CONFLICTING_OVERLOADS!>fun main(vararg args: String)<!> {}
// FILE: invalid_array_typealias.kt
package invalid4
typealias S = String
<!CONFLICTING_OVERLOADS!>fun main(args: Array<String>)<!> {}
<!CONFLICTING_OVERLOADS!>fun main(args: Array<S>)<!> {}
// FILE: invalid_noargs_suspend.kt
package invalid5
<!CONFLICTING_OVERLOADS!>suspend fun main()<!> {}
<!CONFLICTING_OVERLOADS!>suspend fun main()<!> {}
// FILE: invalid_array_suspend.kt
package invalid6
<!CONFLICTING_OVERLOADS!>suspend fun main(args: Array<String>)<!> {}
<!CONFLICTING_OVERLOADS!>suspend fun main(args: Array<String>)<!> {}
// FILE: invalid_vararg_suspend.kt
package invalid7
<!CONFLICTING_OVERLOADS!>suspend fun main(vararg args: String)<!> {}
<!CONFLICTING_OVERLOADS!>suspend fun main(vararg args: String)<!> {}
// FILE: invalid_array_typealias_suspend.kt
package invalid8
typealias S = String
<!CONFLICTING_OVERLOADS!>suspend fun main(args: Array<String>)<!> {}
<!CONFLICTING_OVERLOADS!>suspend fun main(args: Array<S>)<!> {}
// ### VALID
// FILE: valid_noargs.kt
package valid1
fun main() {}
// FILE: valid_noargs2.kt
package valid1
fun main() {}
// FILE: valid_array.kt
package valid2
fun main(args: Array<String>) {}
// FILE: valid_array2.kt
package valid2
fun main(args: Array<String>) {}
// FILE: valid_vararg.kt
package valid3
fun main(vararg args: String) {}
// FILE: valid_vararg2.kt
package valid3
fun main(vararg args: String) {}
// FILE: valid_array_typealias.kt
package valid4
fun main(args: Array<String>) {}
// FILE: valid_array_typealias2.kt
package valid4
typealias S = String
fun main(args: Array<S>) {}
// FILE: valid_noargs_suspend.kt
package valid5
suspend fun main() {}
// FILE: valid_noargs_suspend2.kt
package valid5
suspend fun main() {}
// FILE: valid_array_suspend.kt
package valid6
suspend fun main(args: Array<String>) {}
// FILE: valid_array_suspend2.kt
package valid6
suspend fun main(args: Array<String>) {}
// FILE: valid_vararg_suspend.kt
package valid7
suspend fun main(vararg args: String) {}
// FILE: valid_vararg_suspend2.kt
package valid7
suspend fun main(vararg args: String) {}
// FILE: valid_array_typealias_suspend.kt
package valid8
suspend fun main(args: Array<String>) {}
// FILE: valid_array_typealias_suspend2.kt
package valid8
typealias S = String
suspend fun main(args: Array<S>) {}
@@ -0,0 +1,113 @@
// !LANGUAGE: -ExtendedMainConvention
// ### INVALID
// FILE: invalid_noargs.kt
package invalid1
<!CONFLICTING_OVERLOADS!>fun main()<!> {}
<!CONFLICTING_OVERLOADS!>fun main()<!> {}
// FILE: invalid_array.kt
package invalid2
<!CONFLICTING_OVERLOADS!>fun main(args: Array<String>)<!> {}
<!CONFLICTING_OVERLOADS!>fun main(args: Array<String>)<!> {}
// FILE: invalid_vararg.kt
package invalid3
<!CONFLICTING_OVERLOADS!>fun main(vararg args: String)<!> {}
<!CONFLICTING_OVERLOADS!>fun main(vararg args: String)<!> {}
// FILE: invalid_array_typealias.kt
package invalid4
typealias S = String
<!CONFLICTING_OVERLOADS!>fun main(args: Array<String>)<!> {}
<!CONFLICTING_OVERLOADS!>fun main(args: Array<S>)<!> {}
// FILE: invalid_noargs_suspend.kt
package invalid5
<!CONFLICTING_OVERLOADS!>suspend fun main()<!> {}
<!CONFLICTING_OVERLOADS!>suspend fun main()<!> {}
// FILE: invalid_array_suspend.kt
package invalid6
<!CONFLICTING_OVERLOADS!>suspend fun main(args: Array<String>)<!> {}
<!CONFLICTING_OVERLOADS!>suspend fun main(args: Array<String>)<!> {}
// FILE: invalid_vararg_suspend.kt
package invalid7
<!CONFLICTING_OVERLOADS!>suspend fun main(vararg args: String)<!> {}
<!CONFLICTING_OVERLOADS!>suspend fun main(vararg args: String)<!> {}
// FILE: invalid_array_typealias_suspend.kt
package invalid8
typealias S = String
<!CONFLICTING_OVERLOADS!>suspend fun main(args: Array<String>)<!> {}
<!CONFLICTING_OVERLOADS!>suspend fun main(args: Array<S>)<!> {}
// ### VALID
// FILE: valid_noargs.kt
package valid1
<!CONFLICTING_OVERLOADS!>fun main()<!> {}
// FILE: valid_noargs2.kt
package valid1
<!CONFLICTING_OVERLOADS!>fun main()<!> {}
// FILE: valid_array.kt
package valid2
fun main(args: Array<String>) {}
// FILE: valid_array2.kt
package valid2
fun main(args: Array<String>) {}
// FILE: valid_vararg.kt
package valid3
fun main(vararg args: String) {}
// FILE: valid_vararg2.kt
package valid3
fun main(vararg args: String) {}
// FILE: valid_array_typealias.kt
package valid4
fun main(args: Array<String>) {}
// FILE: valid_array_typealias2.kt
package valid4
typealias S = String
fun main(args: Array<S>) {}
// FILE: valid_noargs_suspend.kt
package valid5
<!CONFLICTING_OVERLOADS!>suspend fun main()<!> {}
// FILE: valid_noargs_suspend2.kt
package valid5
<!CONFLICTING_OVERLOADS!>suspend fun main()<!> {}
// FILE: valid_array_suspend.kt
package valid6
<!CONFLICTING_OVERLOADS!>suspend fun main(args: Array<String>)<!> {}
// FILE: valid_array_suspend2.kt
package valid6
<!CONFLICTING_OVERLOADS!>suspend fun main(args: Array<String>)<!> {}
// FILE: valid_vararg_suspend.kt
package valid7
<!CONFLICTING_OVERLOADS!>suspend fun main(vararg args: String)<!> {}
// FILE: valid_vararg_suspend2.kt
package valid7
<!CONFLICTING_OVERLOADS!>suspend fun main(vararg args: String)<!> {}
// FILE: valid_array_typealias_suspend.kt
package valid8
<!CONFLICTING_OVERLOADS!>suspend fun main(args: Array<String>)<!> {}
// FILE: valid_array_typealias_suspend2.kt
package valid8
typealias S = String
<!CONFLICTING_OVERLOADS!>suspend fun main(args: Array<S>)<!> {}
@@ -1,6 +0,0 @@
// FIR_IDENTICAL
// FILE: a.kt
fun main() {}
// FILE: b.kt
fun main() {}
@@ -1,4 +0,0 @@
package
public fun main(): kotlin.Unit
public fun main(): kotlin.Unit
@@ -1,8 +0,0 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
// FILE: a.kt
fun main() {}
suspend fun main(args: Array<String>) {}
// FILE: b.kt
fun main() {}
@@ -1,8 +0,0 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
// FILE: a.kt
<!CONFLICTING_OVERLOADS!>fun main()<!> {}
suspend fun main(args: Array<String>) {}
// FILE: b.kt
<!CONFLICTING_OVERLOADS!>fun main()<!> {}
@@ -1,5 +0,0 @@
package
public fun main(): kotlin.Unit
public fun main(): kotlin.Unit
public suspend fun main(/*0*/ args: kotlin.Array<kotlin.String>): kotlin.Unit
@@ -1,7 +0,0 @@
// !LANGUAGE: -ExtendedMainConvention
// FILE: a.kt
fun main() {}
// FILE: b.kt
fun main() {}
@@ -1,7 +0,0 @@
// !LANGUAGE: -ExtendedMainConvention
// FILE: a.kt
<!CONFLICTING_OVERLOADS!>fun main()<!> {}
// FILE: b.kt
<!CONFLICTING_OVERLOADS!>fun main()<!> {}
@@ -1,4 +0,0 @@
package
public fun main(): kotlin.Unit
public fun main(): kotlin.Unit
@@ -1,6 +0,0 @@
// FIR_IDENTICAL
// FILE: a.kt
suspend fun main() {}
// FILE: b.kt
suspend fun main() {}
@@ -1,4 +0,0 @@
package
public suspend fun main(): kotlin.Unit
public suspend fun main(): kotlin.Unit
@@ -1,7 +0,0 @@
// !LANGUAGE: -ExtendedMainConvention
// FILE: a.kt
suspend fun main(args: Array<String>) {}
// FILE: b.kt
suspend fun main(args: Array<String>) {}
@@ -1,7 +0,0 @@
// !LANGUAGE: -ExtendedMainConvention
// FILE: a.kt
<!CONFLICTING_OVERLOADS!>suspend fun main(args: Array<String>)<!> {}
// FILE: b.kt
<!CONFLICTING_OVERLOADS!>suspend fun main(args: Array<String>)<!> {}
@@ -1,4 +0,0 @@
package
public suspend fun main(/*0*/ args: kotlin.Array<kotlin.String>): kotlin.Unit
public suspend fun main(/*0*/ args: kotlin.Array<kotlin.String>): kotlin.Unit
@@ -1,3 +1,5 @@
// FILE: a.kt
val <!REDECLARATION!>Test1<!> = null
class <!REDECLARATION!>Test1<!>
@@ -10,4 +12,12 @@ object <!REDECLARATION!>Test3<!>
val <!REDECLARATION!>Test4<!> = null
class <!PACKAGE_OR_CLASSIFIER_REDECLARATION!>Test4<!>
interface <!PACKAGE_OR_CLASSIFIER_REDECLARATION!>Test4<!>
object <!PACKAGE_OR_CLASSIFIER_REDECLARATION!>Test4<!>
object <!PACKAGE_OR_CLASSIFIER_REDECLARATION!>Test4<!>
val <!REDECLARATION!>Test5<!> = null
class <!REDECLARATION!>Test6<!>
// FILE: b.kt
class <!REDECLARATION!>Test5<!>
val <!REDECLARATION!>Test6<!> = null
@@ -1,3 +1,5 @@
// FILE: a.kt
val <!REDECLARATION!>Test1<!> = null
class <!REDECLARATION!>Test1<!>
@@ -10,4 +12,12 @@ object <!REDECLARATION!>Test3<!>
val <!PACKAGE_OR_CLASSIFIER_REDECLARATION, REDECLARATION!>Test4<!> = null
class <!PACKAGE_OR_CLASSIFIER_REDECLARATION, REDECLARATION!>Test4<!>
interface <!PACKAGE_OR_CLASSIFIER_REDECLARATION!>Test4<!>
object <!PACKAGE_OR_CLASSIFIER_REDECLARATION!>Test4<!>
object <!PACKAGE_OR_CLASSIFIER_REDECLARATION!>Test4<!>
val <!REDECLARATION!>Test5<!> = null
class <!REDECLARATION!>Test6<!>
// FILE: b.kt
class <!REDECLARATION!>Test5<!>
val <!REDECLARATION!>Test6<!> = null
@@ -4,6 +4,8 @@ public val Test1: kotlin.Nothing? = null
public val Test2: kotlin.Nothing? = null
public val Test3: kotlin.Nothing? = null
public val Test4: kotlin.Nothing? = null
public val Test5: kotlin.Nothing? = null
public val Test6: kotlin.Nothing? = null
public final class Test1 {
public constructor Test1()
@@ -44,3 +46,18 @@ public object Test4 {
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public final class Test5 {
public constructor Test5()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public final class Test6 {
public constructor Test6()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -1,16 +0,0 @@
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER -TOPLEVEL_TYPEALIASES_ONLY
// FILE: file1.kt
typealias <!REDECLARATION!>Test<!> = String
val <!REDECLARATION!>Test<!> = 42
class Outer {
typealias <!REDECLARATION!>Test<!> = String
val <!REDECLARATION!>Test<!> = 42
}
typealias Test2 = String
// FILE: file2.kt
val Test2 = 42
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER -TOPLEVEL_TYPEALIASES_ONLY
// FILE: file1.kt
typealias <!REDECLARATION!>Test<!> = String
@@ -1,9 +0,0 @@
object X1
object X2
class A<T>
fun <T1> A<T1>.foo() = X1
fun <T2> A<out T2>.foo() = X2
fun <T> A<out T>.test() = <!OVERLOAD_RESOLUTION_AMBIGUITY!>foo<!>() // TODO fix constraint system
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
object X1
object X2
@@ -1,12 +1,12 @@
//!DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_VARIABLE
<!CONFLICTING_OVERLOADS!>@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
@kotlin.jvm.JvmName("containsAny")
@kotlin.internal.LowPriorityInOverloadResolution
public fun <T> Iterable<T>.contains1(element: T): Int<!> = null!!
public fun <T> Iterable<T>.contains1(element: T): Int = null!!
<!CONFLICTING_OVERLOADS!>@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
public fun <T> Iterable<T>.contains1(element: @kotlin.internal.NoInfer T): Boolean<!> = null!!
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
public fun <T> Iterable<T>.contains1(element: @kotlin.internal.NoInfer T): Boolean = null!!
fun test() {
@@ -1,12 +1,12 @@
//!DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_VARIABLE
<!CONFLICTING_OVERLOADS!>@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
@kotlin.jvm.JvmName("containsAny")
@kotlin.internal.LowPriorityInOverloadResolution
public fun <T> Iterable<T>.contains1(element: T): Int<!> = null!!
public fun <T> Iterable<T>.contains1(element: T): Int = null!!
<!CONFLICTING_OVERLOADS!>@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
public fun <@kotlin.internal.OnlyInputTypes T> Iterable<T>.contains1(element: T): Boolean<!> = null!!
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
public fun <@kotlin.internal.OnlyInputTypes T> Iterable<T>.contains1(element: T): Boolean = null!!
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
@JvmName("getAny")
@@ -26977,39 +26977,15 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
}
@Test
@TestMetadata("RedeclarationMainInMultiFile.kt")
public void testRedeclarationMainInMultiFile() throws Exception {
runTest("compiler/testData/diagnostics/tests/redeclarations/RedeclarationMainInMultiFile.kt");
@TestMetadata("RedeclarationOfMain.kt")
public void testRedeclarationOfMain() throws Exception {
runTest("compiler/testData/diagnostics/tests/redeclarations/RedeclarationOfMain.kt");
}
@Test
@TestMetadata("RedeclarationParameterlessMain.kt")
public void testRedeclarationParameterlessMain() throws Exception {
runTest("compiler/testData/diagnostics/tests/redeclarations/RedeclarationParameterlessMain.kt");
}
@Test
@TestMetadata("RedeclarationParameterlessMainInvalid.kt")
public void testRedeclarationParameterlessMainInvalid() throws Exception {
runTest("compiler/testData/diagnostics/tests/redeclarations/RedeclarationParameterlessMainInvalid.kt");
}
@Test
@TestMetadata("RedeclarationParameterlessMain_before.kt")
public void testRedeclarationParameterlessMain_before() throws Exception {
runTest("compiler/testData/diagnostics/tests/redeclarations/RedeclarationParameterlessMain_before.kt");
}
@Test
@TestMetadata("RedeclarationSuspendMainInMultiFile.kt")
public void testRedeclarationSuspendMainInMultiFile() throws Exception {
runTest("compiler/testData/diagnostics/tests/redeclarations/RedeclarationSuspendMainInMultiFile.kt");
}
@Test
@TestMetadata("RedeclarationSuspendMainInMultiFile_before.kt")
public void testRedeclarationSuspendMainInMultiFile_before() throws Exception {
runTest("compiler/testData/diagnostics/tests/redeclarations/RedeclarationSuspendMainInMultiFile_before.kt");
@TestMetadata("RedeclarationOfMain_before.kt")
public void testRedeclarationOfMain_before() throws Exception {
runTest("compiler/testData/diagnostics/tests/redeclarations/RedeclarationOfMain_before.kt");
}
@Test