[FIR] Throw REDECLARATION for duplicated type parameters in declarations

This commit is contained in:
Ivan Kochurkin
2021-08-05 23:38:53 +03:00
committed by Space
parent c19598c2fc
commit 2ca3adbcb2
6 changed files with 63 additions and 26 deletions
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.impl.FirOuterClassTypeParameterRef
import org.jetbrains.kotlin.fir.resolve.firProvider
import org.jetbrains.kotlin.fir.resolve.getOuterClass
import org.jetbrains.kotlin.fir.scopes.PACKAGE_MEMBER
@@ -26,7 +27,6 @@ import org.jetbrains.kotlin.fir.util.ListMultimap
import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.SpecialNames.UNDERSCORE_FOR_UNUSED_VAR
import org.jetbrains.kotlin.utils.SmartSet
object FirConflictsChecker : FirBasicDeclarationChecker() {
@@ -217,11 +217,8 @@ object FirConflictsChecker : FirBasicDeclarationChecker() {
when (declaration) {
is FirFile -> checkFile(declaration, inspector, context)
is FirRegularClass -> checkRegularClass(declaration, inspector)
is FirFunction -> {
checkConflictingValueParameters(declaration, context, reporter)
return
else -> {
}
else -> return
}
inspector.declarationConflictingSymbols.forEach { (conflictingDeclaration, symbols) ->
@@ -246,24 +243,61 @@ object FirConflictsChecker : FirBasicDeclarationChecker() {
}
}
}
if (declaration.source?.kind !is FirFakeSourceElementKind) {
when (declaration) {
is FirMemberDeclaration -> {
if (declaration is FirFunction) {
checkConflictingParameters(declaration.valueParameters, context, reporter)
}
checkConflictingParameters(declaration.typeParameters, context, reporter)
}
is FirTypeParametersOwner -> {
checkConflictingParameters(declaration.typeParameters, context, reporter)
}
else -> {
}
}
}
}
private fun checkConflictingValueParameters(function: FirFunction, context: CheckerContext, reporter: DiagnosticReporter) {
val multimap = ListMultimap<Name, FirValueParameter>()
for (parameter in function.valueParameters) {
if (!parameter.name.isSpecial) {
multimap.put(parameter.name, parameter)
private fun checkConflictingParameters(parameters: List<FirElement>, context: CheckerContext, reporter: DiagnosticReporter) {
if (parameters.size <= 1) return
val multimap = ListMultimap<Name, FirBasedSymbol<*>>()
for (parameter in parameters) {
val name: Name
val symbol: FirBasedSymbol<*>
when (parameter) {
is FirValueParameter -> {
symbol = parameter.symbol
name = parameter.name
}
is FirOuterClassTypeParameterRef -> {
continue
}
is FirTypeParameterRef -> {
symbol = parameter.symbol
name = symbol.name
}
is FirTypeParameter -> {
symbol = parameter.symbol
name = parameter.name
}
else -> throw AssertionError("Invalid parameter type")
}
if (!name.isSpecial) {
multimap.put(name, symbol)
}
}
for (key in multimap.keys) {
val parameters = multimap[key]
if (parameters.size > 1) {
val symbols = parameters.map { it.symbol }
for (parameter in parameters) {
val conflictingParameters = multimap[key]
if (conflictingParameters.size > 1) {
for (parameter in conflictingParameters) {
reporter.reportOn(
parameter.source,
FirErrors.REDECLARATION,
symbols,
conflictingParameters,
context
)
}
@@ -0,0 +1,9 @@
data class A1(val <!REDECLARATION, REDECLARATION!>x<!>: Int, val y: String, val <!REDECLARATION, REDECLARATION!>x<!>: Int) {
val z = ""
}
data class A2(val <!REDECLARATION!>x<!>: Int, val y: String) {
val <!REDECLARATION!>x<!> = ""
}
data class A3(<!REDECLARATION!>val<!SYNTAX!><!> :Int<!>, <!REDECLARATION!>val<!SYNTAX!><!> : Int<!>)
@@ -1,4 +1,3 @@
// FIR_IDENTICAL
data class A1(val <!REDECLARATION, REDECLARATION, REDECLARATION!>x<!>: Int, val y: String, val <!REDECLARATION, REDECLARATION, REDECLARATION!>x<!>: Int) {
val z = ""
}
@@ -1,6 +1,6 @@
fun <T, T> Pair() {}
fun <<!REDECLARATION!>T<!>, <!REDECLARATION!>T<!>> Pair() {}
class P<T, T> {}
class P<<!REDECLARATION!>T<!>, <!REDECLARATION!>T<!>> {}
val <T, T> T.foo : Int
get() = 1
val <<!REDECLARATION!>T<!>, <!REDECLARATION!>T<!>> T.foo : Int
get() = 1
@@ -1,6 +0,0 @@
interface Test1<T, T>
interface Test2<X, Y, X>
class Outer<T> {
interface TestNested<T>
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
interface Test1<<!REDECLARATION!>T<!>, <!REDECLARATION!>T<!>>
interface Test2<<!REDECLARATION!>X<!>, Y, <!REDECLARATION!>X<!>>