Property vs classifier conflict.
TODO get rid of duplicate diagnostics (looks like OverloadResolver and DeclarationResolver are partially redundant; refactor them).
This commit is contained in:
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.resolve.jvm
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptorNonRoot
|
||||
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
|
||||
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil
|
||||
import org.jetbrains.kotlin.fileClasses.NoResolveFileClassesProvider
|
||||
@@ -30,8 +31,8 @@ import java.util.*
|
||||
|
||||
|
||||
object JvmOverloadFilter : OverloadFilter {
|
||||
override fun filterPackageMemberOverloads(overloads: Collection<CallableMemberDescriptor>): Collection<CallableMemberDescriptor> {
|
||||
val result = ArrayList<CallableMemberDescriptor>()
|
||||
override fun filterPackageMemberOverloads(overloads: Collection<DeclarationDescriptorNonRoot>): Collection<DeclarationDescriptorNonRoot> {
|
||||
val result = ArrayList<DeclarationDescriptorNonRoot>()
|
||||
|
||||
val sourceClassesFQNs = HashSet<FqName>()
|
||||
for (overload in overloads) {
|
||||
|
||||
@@ -187,7 +187,7 @@ class LazyTopDownAnalyzer(
|
||||
|
||||
declarationResolver.resolveAnnotationsOnFiles(c, fileScopeProvider)
|
||||
|
||||
overloadResolver.process(c)
|
||||
overloadResolver.checkOverloads(c)
|
||||
|
||||
bodyResolver.resolveBodies(c)
|
||||
|
||||
|
||||
@@ -16,14 +16,14 @@
|
||||
|
||||
package org.jetbrains.kotlin.resolve
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptorNonRoot
|
||||
|
||||
|
||||
interface OverloadFilter {
|
||||
fun filterPackageMemberOverloads(overloads: Collection<CallableMemberDescriptor>): Collection<CallableMemberDescriptor>
|
||||
fun filterPackageMemberOverloads(overloads: Collection<DeclarationDescriptorNonRoot>): Collection<DeclarationDescriptorNonRoot>
|
||||
|
||||
object DEFAULT : OverloadFilter {
|
||||
override fun filterPackageMemberOverloads(overloads: Collection<CallableMemberDescriptor>): Collection<CallableMemberDescriptor> =
|
||||
override fun filterPackageMemberOverloads(overloads: Collection<DeclarationDescriptorNonRoot>): Collection<DeclarationDescriptorNonRoot> =
|
||||
overloads
|
||||
}
|
||||
}
|
||||
@@ -28,11 +28,7 @@ class OverloadResolver(
|
||||
private val trace: BindingTrace,
|
||||
private val overloadFilter: OverloadFilter) {
|
||||
|
||||
fun process(c: BodiesResolveContext) {
|
||||
checkOverloads(c)
|
||||
}
|
||||
|
||||
private fun checkOverloads(c: BodiesResolveContext) {
|
||||
fun checkOverloads(c: BodiesResolveContext) {
|
||||
val inClasses = findConstructorsInNestedClasses(c)
|
||||
|
||||
for (entry in c.declaredClasses.entries) {
|
||||
@@ -93,7 +89,7 @@ class OverloadResolver(
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkOverloadsInPackage(members: Collection<CallableMemberDescriptor>) {
|
||||
private fun checkOverloadsInPackage(members: Collection<DeclarationDescriptorNonRoot>) {
|
||||
if (members.size == 1) return
|
||||
for (redeclarationGroup in OverloadUtil.getPossibleRedeclarationGroups(members)) {
|
||||
reportRedeclarations(findRedeclarations(redeclarationGroup))
|
||||
@@ -105,10 +101,13 @@ class OverloadResolver(
|
||||
reportRedeclarations(findRedeclarations(members))
|
||||
}
|
||||
|
||||
private fun findRedeclarations(members: Collection<CallableMemberDescriptor>): Set<Pair<KtDeclaration?, CallableMemberDescriptor>> {
|
||||
val redeclarations = linkedSetOf<Pair<KtDeclaration?, CallableMemberDescriptor>>()
|
||||
private fun DeclarationDescriptor.isSynthesized() =
|
||||
this is CallableMemberDescriptor && kind == CallableMemberDescriptor.Kind.SYNTHESIZED
|
||||
|
||||
private fun findRedeclarations(members: Collection<DeclarationDescriptorNonRoot>): Set<Pair<KtDeclaration?, DeclarationDescriptorNonRoot>> {
|
||||
val redeclarations = linkedSetOf<Pair<KtDeclaration?, DeclarationDescriptorNonRoot>>()
|
||||
for (member1 in members) {
|
||||
if (member1.kind == CallableMemberDescriptor.Kind.SYNTHESIZED) continue
|
||||
if (member1.isSynthesized()) continue
|
||||
|
||||
for (member2 in members) {
|
||||
if (member1 == member2) continue
|
||||
@@ -124,7 +123,7 @@ class OverloadResolver(
|
||||
return redeclarations
|
||||
}
|
||||
|
||||
private fun isConstructorsOfDifferentRedeclaredClasses(member1: CallableMemberDescriptor, member2: CallableMemberDescriptor): Boolean {
|
||||
private fun isConstructorsOfDifferentRedeclaredClasses(member1: DeclarationDescriptor, member2: DeclarationDescriptor): Boolean {
|
||||
if (member1 !is ConstructorDescriptor || member2 !is ConstructorDescriptor) return false
|
||||
// ignore conflicting overloads for constructors of different classes because their redeclarations will be reported
|
||||
// but don't ignore if there's possibility that classes redeclarations will not be reported
|
||||
@@ -134,7 +133,7 @@ class OverloadResolver(
|
||||
return parent1 !== parent2 && parent1.containingDeclaration == parent2.containingDeclaration
|
||||
}
|
||||
|
||||
private fun isTopLevelMainInDifferentFiles(member1: CallableMemberDescriptor, member2: CallableMemberDescriptor): Boolean {
|
||||
private fun isTopLevelMainInDifferentFiles(member1: DeclarationDescriptor, member2: DeclarationDescriptor): Boolean {
|
||||
if (!MainFunctionDetector.isMain(member1) || !MainFunctionDetector.isMain(member2)) {
|
||||
return false
|
||||
}
|
||||
@@ -144,7 +143,7 @@ class OverloadResolver(
|
||||
return file1 == null || file2 == null || file1 !== file2
|
||||
}
|
||||
|
||||
private fun reportRedeclarations(redeclarations: Set<Pair<KtDeclaration?, CallableMemberDescriptor>>) {
|
||||
private fun reportRedeclarations(redeclarations: Set<Pair<KtDeclaration?, DeclarationDescriptorNonRoot>>) {
|
||||
if (redeclarations.isEmpty()) return
|
||||
|
||||
val redeclarationsIterator = redeclarations.iterator()
|
||||
@@ -154,20 +153,23 @@ class OverloadResolver(
|
||||
for ((ktDeclaration, memberDescriptor) in redeclarations) {
|
||||
if (ktDeclaration == null) continue
|
||||
|
||||
if (memberDescriptor is PropertyDescriptor) {
|
||||
trace.report(Errors.REDECLARATION.on(ktDeclaration, memberDescriptor.getName().asString()))
|
||||
}
|
||||
else {
|
||||
val redeclarationDescriptor =
|
||||
if (otherRedeclarationDescriptor == null)
|
||||
firstRedeclarationDescriptor
|
||||
else if (memberDescriptor == firstRedeclarationDescriptor)
|
||||
otherRedeclarationDescriptor
|
||||
else
|
||||
firstRedeclarationDescriptor
|
||||
when (memberDescriptor) {
|
||||
is PropertyDescriptor,
|
||||
is ClassifierDescriptor -> {
|
||||
trace.report(Errors.REDECLARATION.on(ktDeclaration, memberDescriptor.name.asString()))
|
||||
}
|
||||
is FunctionDescriptor -> {
|
||||
val redeclarationDescriptor =
|
||||
if (otherRedeclarationDescriptor == null)
|
||||
firstRedeclarationDescriptor
|
||||
else if (memberDescriptor == firstRedeclarationDescriptor)
|
||||
otherRedeclarationDescriptor
|
||||
else
|
||||
firstRedeclarationDescriptor
|
||||
|
||||
trace.report(Errors.CONFLICTING_OVERLOADS.on(ktDeclaration, memberDescriptor,
|
||||
redeclarationDescriptor.containingDeclaration))
|
||||
trace.report(Errors.CONFLICTING_OVERLOADS.on(ktDeclaration, memberDescriptor,
|
||||
redeclarationDescriptor.containingDeclaration))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,24 +27,21 @@ import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeIntersector
|
||||
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
||||
import org.jetbrains.kotlin.types.oneMoreSpecificThanAnother
|
||||
import org.jetbrains.kotlin.utils.singletonOrEmptyList
|
||||
|
||||
object OverloadUtil {
|
||||
|
||||
/**
|
||||
* Does not check names.
|
||||
*/
|
||||
@JvmStatic fun isOverloadable(a: CallableDescriptor, b: CallableDescriptor): Boolean {
|
||||
val abc = braceCount(a)
|
||||
val bbc = braceCount(b)
|
||||
@JvmStatic fun isOverloadable(a: DeclarationDescriptor, b: DeclarationDescriptor): Boolean {
|
||||
val aCategory = getDeclarationCategory(a)
|
||||
val bCategory = getDeclarationCategory(b)
|
||||
|
||||
if (abc != bbc) {
|
||||
return true
|
||||
}
|
||||
if (aCategory != bCategory) return true
|
||||
if (a !is CallableDescriptor || b !is CallableDescriptor) return false
|
||||
|
||||
val receiverAndParameterResult = OverridingUtil.checkReceiverAndParameterCount(a, b)
|
||||
if (receiverAndParameterResult != null) {
|
||||
return receiverAndParameterResult.result == INCOMPATIBLE
|
||||
}
|
||||
OverridingUtil.checkReceiverAndParameterCount(a, b)?.let { return it.result == INCOMPATIBLE }
|
||||
|
||||
val aValueParameters = OverridingUtil.compiledValueParameters(a)
|
||||
val bValueParameters = OverridingUtil.compiledValueParameters(b)
|
||||
@@ -62,12 +59,30 @@ object OverloadUtil {
|
||||
return false
|
||||
}
|
||||
|
||||
private fun braceCount(a: CallableDescriptor): Int =
|
||||
private enum class DeclarationCategory {
|
||||
TYPE_OR_VALUE,
|
||||
FUNCTION,
|
||||
EXTENSION_PROPERTY
|
||||
}
|
||||
|
||||
private fun DeclarationDescriptor.isExtensionProperty() =
|
||||
this is PropertyDescriptor &&
|
||||
extensionReceiverParameter != null
|
||||
|
||||
private fun getDeclarationCategory(a: DeclarationDescriptor): DeclarationCategory =
|
||||
when (a) {
|
||||
is PropertyDescriptor -> 0
|
||||
is SimpleFunctionDescriptor -> 1
|
||||
is ConstructorDescriptor -> 1
|
||||
else -> throw IllegalStateException()
|
||||
is PropertyDescriptor ->
|
||||
if (a.isExtensionProperty())
|
||||
DeclarationCategory.EXTENSION_PROPERTY
|
||||
else
|
||||
DeclarationCategory.TYPE_OR_VALUE
|
||||
is ConstructorDescriptor,
|
||||
is SimpleFunctionDescriptor ->
|
||||
DeclarationCategory.FUNCTION
|
||||
is ClassifierDescriptor ->
|
||||
DeclarationCategory.TYPE_OR_VALUE
|
||||
else ->
|
||||
error("Unexpected declaration kind: $a")
|
||||
}
|
||||
|
||||
private val KotlinType.upperBound: KotlinType
|
||||
@@ -83,8 +98,8 @@ object OverloadUtil {
|
||||
@JvmStatic fun groupModulePackageMembersByFqName(
|
||||
c: BodiesResolveContext,
|
||||
overloadFilter: OverloadFilter
|
||||
): MultiMap<FqNameUnsafe, CallableMemberDescriptor> {
|
||||
val packageMembersByName = MultiMap<FqNameUnsafe, CallableMemberDescriptor>()
|
||||
): MultiMap<FqNameUnsafe, DeclarationDescriptorNonRoot> {
|
||||
val packageMembersByName = MultiMap<FqNameUnsafe, DeclarationDescriptorNonRoot>()
|
||||
|
||||
collectModulePackageMembersWithSameName(packageMembersByName, c.functions.values + c.declaredClasses.values, overloadFilter) {
|
||||
scope, name ->
|
||||
@@ -98,17 +113,19 @@ object OverloadUtil {
|
||||
|
||||
collectModulePackageMembersWithSameName(packageMembersByName, c.properties.values, overloadFilter) {
|
||||
scope, name ->
|
||||
scope.getContributedVariables(name, NoLookupLocation.WHEN_CHECK_REDECLARATIONS).filterIsInstance<CallableMemberDescriptor>()
|
||||
val variables = scope.getContributedVariables(name, NoLookupLocation.WHEN_CHECK_REDECLARATIONS)
|
||||
val classifier = scope.getContributedClassifier(name, NoLookupLocation.WHEN_CHECK_REDECLARATIONS)
|
||||
variables + classifier.singletonOrEmptyList()
|
||||
}
|
||||
|
||||
return packageMembersByName
|
||||
}
|
||||
|
||||
private inline fun collectModulePackageMembersWithSameName(
|
||||
packageMembersByName: MultiMap<FqNameUnsafe, CallableMemberDescriptor>,
|
||||
packageMembersByName: MultiMap<FqNameUnsafe, DeclarationDescriptorNonRoot>,
|
||||
interestingDescriptors: Collection<DeclarationDescriptor>,
|
||||
overloadFilter: OverloadFilter,
|
||||
getMembersByName: (MemberScope, Name) -> Collection<CallableMemberDescriptor>
|
||||
getMembersByName: (MemberScope, Name) -> Collection<DeclarationDescriptorNonRoot>
|
||||
) {
|
||||
val observedFQNs = hashSetOf<FqNameUnsafe>()
|
||||
for (descriptor in interestingDescriptors) {
|
||||
@@ -126,8 +143,8 @@ object OverloadUtil {
|
||||
private inline fun getModulePackageMembersWithSameName(
|
||||
descriptor: DeclarationDescriptor,
|
||||
overloadFilter: OverloadFilter,
|
||||
getMembersByName: (MemberScope, Name) -> Collection<CallableMemberDescriptor>
|
||||
): Collection<CallableMemberDescriptor> {
|
||||
getMembersByName: (MemberScope, Name) -> Collection<DeclarationDescriptorNonRoot>
|
||||
): Collection<DeclarationDescriptorNonRoot> {
|
||||
val containingPackage = descriptor.containingDeclaration
|
||||
if (containingPackage !is PackageFragmentDescriptor) {
|
||||
throw AssertionError("$descriptor is not a top-level package member")
|
||||
@@ -150,17 +167,21 @@ object OverloadUtil {
|
||||
return overloadFilter.filterPackageMemberOverloads(possibleOverloads)
|
||||
}
|
||||
|
||||
private fun MemberDescriptor.isPrivate() = Visibilities.isPrivate(this.visibility)
|
||||
private fun DeclarationDescriptor.isPrivate() =
|
||||
this is DeclarationDescriptorWithVisibility &&
|
||||
Visibilities.isPrivate(this.visibility)
|
||||
|
||||
@JvmStatic fun getPossibleRedeclarationGroups(members: Collection<CallableMemberDescriptor>): Collection<Collection<CallableMemberDescriptor>> {
|
||||
val result = arrayListOf<Collection<CallableMemberDescriptor>>()
|
||||
@JvmStatic fun getPossibleRedeclarationGroups(
|
||||
members: Collection<DeclarationDescriptorNonRoot>
|
||||
): Collection<Collection<DeclarationDescriptorNonRoot>> {
|
||||
val result = arrayListOf<Collection<DeclarationDescriptorNonRoot>>()
|
||||
|
||||
val nonPrivates = members.filter { !it.isPrivate() }
|
||||
if (nonPrivates.size > 1) {
|
||||
result.add(nonPrivates)
|
||||
}
|
||||
|
||||
val bySourceFile = MultiMap.createSmart<SourceFile, CallableMemberDescriptor>()
|
||||
val bySourceFile = MultiMap.createSmart<SourceFile, DeclarationDescriptorNonRoot>()
|
||||
for (member in members) {
|
||||
val sourceFile = DescriptorUtils.getContainingSourceFile(member)
|
||||
if (sourceFile != SourceFile.NO_SOURCE_FILE) {
|
||||
|
||||
@@ -7,11 +7,11 @@
|
||||
|
||||
}
|
||||
|
||||
val<!SYNTAX!><!> : Int = 1
|
||||
<!REDECLARATION!>val<!SYNTAX!><!> : Int = 1<!>
|
||||
|
||||
class<!SYNTAX!><!> {
|
||||
<!REDECLARATION!>class<!SYNTAX!><!> {
|
||||
|
||||
}
|
||||
}<!>
|
||||
|
||||
object<!SYNTAX!><!> {
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// FILE: f.kt
|
||||
package redeclarations
|
||||
object <!REDECLARATION!>A<!> {
|
||||
object <!REDECLARATION, REDECLARATION!>A<!> {
|
||||
val x : Int = 0
|
||||
|
||||
val A = 1
|
||||
@@ -8,7 +8,7 @@ package redeclarations
|
||||
|
||||
class <!REDECLARATION!>A<!> {}
|
||||
|
||||
val <!REDECLARATION!>A<!> = 1
|
||||
val <!REDECLARATION, REDECLARATION!>A<!> = 1
|
||||
|
||||
// FILE: f.kt
|
||||
package redeclarations.<!REDECLARATION!>A<!>
|
||||
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
val <!REDECLARATION!>Test1<!> = null
|
||||
class <!REDECLARATION!>Test1<!>
|
||||
|
||||
val <!REDECLARATION!>Test2<!> = null
|
||||
interface <!REDECLARATION!>Test2<!>
|
||||
|
||||
val <!REDECLARATION!>Test3<!> = null
|
||||
object <!REDECLARATION!>Test3<!>
|
||||
|
||||
val <!REDECLARATION, REDECLARATION!>Test4<!> = null
|
||||
class <!REDECLARATION, REDECLARATION!>Test4<!>
|
||||
interface <!REDECLARATION!>Test4<!>
|
||||
object <!REDECLARATION!>Test4<!>
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
package
|
||||
|
||||
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 final class Test1 {
|
||||
public constructor Test1()
|
||||
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 interface Test2 {
|
||||
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 object Test3 {
|
||||
private constructor Test3()
|
||||
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 Test4 {
|
||||
public constructor Test4()
|
||||
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 interface Test4 {
|
||||
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 object Test4 {
|
||||
private constructor Test4()
|
||||
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
|
||||
}
|
||||
@@ -13275,6 +13275,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("TopLevelPropertyVsClassifier.kt")
|
||||
public void testTopLevelPropertyVsClassifier() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/redeclarations/TopLevelPropertyVsClassifier.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("typeParameterWithTwoBounds.kt")
|
||||
public void testTypeParameterWithTwoBounds() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/redeclarations/typeParameterWithTwoBounds.kt");
|
||||
|
||||
@@ -4,12 +4,12 @@ package<EOLError></EOLError>
|
||||
|
||||
}
|
||||
|
||||
val<error> </error>: Int = 1
|
||||
<error>val<error> </error>: Int = 1</error>
|
||||
|
||||
|
||||
class<error> </error>{
|
||||
<error>class<error> </error>{
|
||||
|
||||
}
|
||||
}</error>
|
||||
|
||||
interface<error> </error>{
|
||||
|
||||
|
||||
Reference in New Issue
Block a user