Redeclaration errors for type aliases: type alias vs function.
This commit is contained in:
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
|||||||
import org.jetbrains.kotlin.name.FqNameUnsafe
|
import org.jetbrains.kotlin.name.FqNameUnsafe
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.resolve.calls.results.*
|
import org.jetbrains.kotlin.resolve.calls.results.*
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.tower.getTypeAliasConstructors
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.hasLowPriorityInOverloadResolution
|
import org.jetbrains.kotlin.resolve.descriptorUtil.hasLowPriorityInOverloadResolution
|
||||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||||
import org.jetbrains.kotlin.types.ErrorUtils
|
import org.jetbrains.kotlin.types.ErrorUtils
|
||||||
@@ -99,14 +100,25 @@ class OverloadChecker(val specificityComparator: TypeSpecificityComparator) {
|
|||||||
): MultiMap<FqNameUnsafe, DeclarationDescriptorNonRoot> {
|
): MultiMap<FqNameUnsafe, DeclarationDescriptorNonRoot> {
|
||||||
val packageMembersByName = MultiMap<FqNameUnsafe, DeclarationDescriptorNonRoot>()
|
val packageMembersByName = MultiMap<FqNameUnsafe, DeclarationDescriptorNonRoot>()
|
||||||
|
|
||||||
collectModulePackageMembersWithSameName(packageMembersByName, c.functions.values + c.declaredClasses.values, overloadFilter) {
|
collectModulePackageMembersWithSameName(
|
||||||
|
packageMembersByName,
|
||||||
|
c.functions.values + c.declaredClasses.values + c.typeAliases.values,
|
||||||
|
overloadFilter
|
||||||
|
) {
|
||||||
scope, name ->
|
scope, name ->
|
||||||
val functions = scope.getContributedFunctions(name, NoLookupLocation.WHEN_CHECK_REDECLARATIONS)
|
val functions = scope.getContributedFunctions(name, NoLookupLocation.WHEN_CHECK_REDECLARATIONS)
|
||||||
val classifier = scope.getContributedClassifier(name, NoLookupLocation.WHEN_CHECK_REDECLARATIONS)
|
val classifier = scope.getContributedClassifier(name, NoLookupLocation.WHEN_CHECK_REDECLARATIONS)
|
||||||
if (classifier is ClassDescriptor && !classifier.kind.isSingleton)
|
when (classifier) {
|
||||||
functions + classifier.constructors
|
is ClassDescriptor ->
|
||||||
else
|
if (!classifier.kind.isSingleton)
|
||||||
functions
|
functions + classifier.constructors
|
||||||
|
else
|
||||||
|
functions
|
||||||
|
is TypeAliasDescriptor ->
|
||||||
|
functions + classifier.getTypeAliasConstructors()
|
||||||
|
else ->
|
||||||
|
functions
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
collectModulePackageMembersWithSameName(packageMembersByName, c.properties.values, overloadFilter) {
|
collectModulePackageMembersWithSameName(packageMembersByName, c.properties.values, overloadFilter) {
|
||||||
|
|||||||
@@ -18,10 +18,12 @@ package org.jetbrains.kotlin.resolve
|
|||||||
|
|
||||||
import com.intellij.util.containers.MultiMap
|
import com.intellij.util.containers.MultiMap
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
|
import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor
|
||||||
import org.jetbrains.kotlin.diagnostics.Errors
|
import org.jetbrains.kotlin.diagnostics.Errors
|
||||||
import org.jetbrains.kotlin.idea.MainFunctionDetector
|
import org.jetbrains.kotlin.idea.MainFunctionDetector
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.tower.getTypeAliasConstructors
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.check
|
import org.jetbrains.kotlin.utils.addToStdlib.check
|
||||||
|
|
||||||
class OverloadResolver(
|
class OverloadResolver(
|
||||||
@@ -31,7 +33,7 @@ class OverloadResolver(
|
|||||||
) {
|
) {
|
||||||
|
|
||||||
fun checkOverloads(c: BodiesResolveContext) {
|
fun checkOverloads(c: BodiesResolveContext) {
|
||||||
val inClasses = findConstructorsInNestedClasses(c)
|
val inClasses = findConstructorsInNestedClassesAndTypeAliases(c)
|
||||||
|
|
||||||
for (entry in c.declaredClasses.entries) {
|
for (entry in c.declaredClasses.entries) {
|
||||||
checkOverloadsInClass(entry.value, inClasses.get(entry.value))
|
checkOverloadsInClass(entry.value, inClasses.get(entry.value))
|
||||||
@@ -39,8 +41,8 @@ class OverloadResolver(
|
|||||||
checkOverloadsInPackages(c)
|
checkOverloadsInPackages(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun findConstructorsInNestedClasses(c: BodiesResolveContext): MultiMap<ClassDescriptor, ConstructorDescriptor> {
|
private fun findConstructorsInNestedClassesAndTypeAliases(c: BodiesResolveContext): MultiMap<ClassDescriptor, ConstructorDescriptor> {
|
||||||
val constructorsInNestedClasses = MultiMap.create<ClassDescriptor, ConstructorDescriptor>()
|
val constructorsByOuterClass = MultiMap.create<ClassDescriptor, ConstructorDescriptor>()
|
||||||
|
|
||||||
for (klass in c.declaredClasses.values) {
|
for (klass in c.declaredClasses.values) {
|
||||||
if (klass.kind.isSingleton || klass.name.isSpecial) {
|
if (klass.kind.isSingleton || klass.name.isSpecial) {
|
||||||
@@ -52,7 +54,7 @@ class OverloadResolver(
|
|||||||
// TODO: check overload conflicts of functions with constructors in scripts
|
// TODO: check overload conflicts of functions with constructors in scripts
|
||||||
}
|
}
|
||||||
else if (containingDeclaration is ClassDescriptor) {
|
else if (containingDeclaration is ClassDescriptor) {
|
||||||
constructorsInNestedClasses.putValues(containingDeclaration, klass.constructors)
|
constructorsByOuterClass.putValues(containingDeclaration, klass.constructors)
|
||||||
}
|
}
|
||||||
else if (!(containingDeclaration is FunctionDescriptor ||
|
else if (!(containingDeclaration is FunctionDescriptor ||
|
||||||
containingDeclaration is PropertyDescriptor ||
|
containingDeclaration is PropertyDescriptor ||
|
||||||
@@ -61,7 +63,14 @@ class OverloadResolver(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return constructorsInNestedClasses
|
for (typeAlias in c.typeAliases.values) {
|
||||||
|
val containingDeclaration = typeAlias.containingDeclaration
|
||||||
|
if (containingDeclaration is ClassDescriptor) {
|
||||||
|
constructorsByOuterClass.putValues(containingDeclaration, typeAlias.getTypeAliasConstructors())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return constructorsByOuterClass
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkOverloadsInPackages(c: BodiesResolveContext) {
|
private fun checkOverloadsInPackages(c: BodiesResolveContext) {
|
||||||
@@ -82,8 +91,14 @@ class OverloadResolver(
|
|||||||
functionsByName.putValue(function.name, function)
|
functionsByName.putValue(function.name, function)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (nestedClassConstructor in nestedClassConstructors) {
|
for (nestedConstructor in nestedClassConstructors) {
|
||||||
functionsByName.putValue(nestedClassConstructor.containingDeclaration.name, nestedClassConstructor)
|
val name =
|
||||||
|
if (nestedConstructor is TypeAliasConstructorDescriptor)
|
||||||
|
nestedConstructor.typeAliasDescriptor.name
|
||||||
|
else
|
||||||
|
nestedConstructor.containingDeclaration.name
|
||||||
|
|
||||||
|
functionsByName.putValue(name, nestedConstructor)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (e in functionsByName.entrySet()) {
|
for (e in functionsByName.entrySet()) {
|
||||||
|
|||||||
@@ -244,7 +244,7 @@ private fun ResolutionScope.getContributedFunctionsAndConstructors(name: Name, l
|
|||||||
val classifier = getContributedClassifier(name, location)
|
val classifier = getContributedClassifier(name, location)
|
||||||
return getContributedFunctions(name, location) +
|
return getContributedFunctions(name, location) +
|
||||||
(getClassWithConstructors(classifier)?.constructors?.filter { it.dispatchReceiverParameter == null } ?: emptyList()) +
|
(getClassWithConstructors(classifier)?.constructors?.filter { it.dispatchReceiverParameter == null } ?: emptyList()) +
|
||||||
(classifier?.getTypeAliasConstructors(false) ?: emptyList())
|
(classifier?.getTypeAliasConstructors() ?: emptyList())
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun ResolutionScope.getContributedVariablesAndObjects(name: Name, location: LookupLocation): Collection<VariableDescriptor> {
|
private fun ResolutionScope.getContributedVariablesAndObjects(name: Name, location: LookupLocation): Collection<VariableDescriptor> {
|
||||||
@@ -274,7 +274,7 @@ private fun getClassWithConstructors(classifier: ClassifierDescriptor?): ClassDe
|
|||||||
private val ClassDescriptor.canHaveCallableConstructors: Boolean
|
private val ClassDescriptor.canHaveCallableConstructors: Boolean
|
||||||
get() = !ErrorUtils.isError(this) && !kind.isSingleton
|
get() = !ErrorUtils.isError(this) && !kind.isSingleton
|
||||||
|
|
||||||
private fun ClassifierDescriptor.getTypeAliasConstructors(inner: Boolean): Collection<ConstructorDescriptor> {
|
fun ClassifierDescriptor.getTypeAliasConstructors(): Collection<ConstructorDescriptor> {
|
||||||
if (this !is TypeAliasDescriptor) return emptyList()
|
if (this !is TypeAliasDescriptor) return emptyList()
|
||||||
|
|
||||||
val classDescriptor = this.classDescriptor ?: return emptyList()
|
val classDescriptor = this.classDescriptor ?: return emptyList()
|
||||||
@@ -282,10 +282,11 @@ private fun ClassifierDescriptor.getTypeAliasConstructors(inner: Boolean): Colle
|
|||||||
|
|
||||||
val substitutor = this.getTypeSubstitutorForUnderlyingClass() ?: throw AssertionError("classDescriptor should be non-null for $this")
|
val substitutor = this.getTypeSubstitutorForUnderlyingClass() ?: throw AssertionError("classDescriptor should be non-null for $this")
|
||||||
|
|
||||||
return classDescriptor.constructors.filter {
|
return classDescriptor.constructors.mapNotNull {
|
||||||
if (inner) it.dispatchReceiverParameter != null else it.dispatchReceiverParameter == null
|
if (it.dispatchReceiverParameter == null)
|
||||||
}.mapNotNull {
|
TypeAliasConstructorDescriptorImpl.create(this, it, substitutor)
|
||||||
TypeAliasConstructorDescriptorImpl.create(this, it, substitutor)
|
else
|
||||||
|
null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
class C(val x: Int)
|
||||||
|
|
||||||
|
<!CONFLICTING_OVERLOADS!>typealias CC = C<!>
|
||||||
|
|
||||||
|
<!CONFLICTING_OVERLOADS!>fun CC(x: Int)<!> = x
|
||||||
|
|
||||||
|
class Outer {
|
||||||
|
class C(val x: Int)
|
||||||
|
|
||||||
|
<!CONFLICTING_OVERLOADS!>typealias CC = C<!>
|
||||||
|
|
||||||
|
<!CONFLICTING_OVERLOADS!>fun CC(x: Int)<!> = x
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public typealias CC = C
|
||||||
|
public fun CC(/*0*/ x: kotlin.Int): kotlin.Int
|
||||||
|
|
||||||
|
public final class C {
|
||||||
|
public constructor C(/*0*/ x: kotlin.Int)
|
||||||
|
public final val x: kotlin.Int
|
||||||
|
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 Outer {
|
||||||
|
public typealias CC = Outer.C
|
||||||
|
public constructor Outer()
|
||||||
|
public final fun CC(/*0*/ x: kotlin.Int): kotlin.Int
|
||||||
|
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 C {
|
||||||
|
public constructor C(/*0*/ x: kotlin.Int)
|
||||||
|
public final val x: kotlin.Int
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,11 +6,11 @@ typealias <!REDECLARATION!>SomeClass<!> = Any
|
|||||||
typealias <!REDECLARATION!>SomeClass<!> = Any
|
typealias <!REDECLARATION!>SomeClass<!> = Any
|
||||||
|
|
||||||
class Outer {
|
class Outer {
|
||||||
class <!REDECLARATION!>Nested<!>
|
class <!REDECLARATION, CONFLICTING_OVERLOADS!>Nested<!>
|
||||||
|
|
||||||
typealias <!REDECLARATION!>Nested<!> = Any
|
<!CONFLICTING_OVERLOADS!>typealias <!REDECLARATION!>Nested<!> = Any<!>
|
||||||
typealias <!REDECLARATION!>Nested<!> = Any
|
<!CONFLICTING_OVERLOADS!>typealias <!REDECLARATION!>Nested<!> = Any<!>
|
||||||
typealias <!REDECLARATION!>Nested<!> = Any
|
<!CONFLICTING_OVERLOADS!>typealias <!REDECLARATION!>Nested<!> = Any<!>
|
||||||
}
|
}
|
||||||
|
|
||||||
// FILE: file2.kt
|
// FILE: file2.kt
|
||||||
|
|||||||
@@ -13902,6 +13902,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("TypeAliasCtorVsFun.kt")
|
||||||
|
public void testTypeAliasCtorVsFun() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/redeclarations/TypeAliasCtorVsFun.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("TypeAliasVsClass.kt")
|
@TestMetadata("TypeAliasVsClass.kt")
|
||||||
public void testTypeAliasVsClass() throws Exception {
|
public void testTypeAliasVsClass() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/redeclarations/TypeAliasVsClass.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/redeclarations/TypeAliasVsClass.kt");
|
||||||
|
|||||||
+23
-15
@@ -20,25 +20,30 @@ import org.jetbrains.kotlin.descriptors.*
|
|||||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind
|
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
|
||||||
import org.jetbrains.kotlin.types.TypeSubstitutor
|
import org.jetbrains.kotlin.types.TypeSubstitutor
|
||||||
import org.jetbrains.kotlin.types.Variance
|
import org.jetbrains.kotlin.types.Variance
|
||||||
|
|
||||||
interface TypeAliasConstructorDescriptor : ConstructorDescriptor {
|
interface TypeAliasConstructorDescriptor : ConstructorDescriptor {
|
||||||
val typeAliasDescriptor: TypeAliasDescriptor
|
val typeAliasDescriptor: TypeAliasDescriptor
|
||||||
|
val underlyingConstructorDescriptor: ConstructorDescriptor
|
||||||
}
|
}
|
||||||
|
|
||||||
class TypeAliasConstructorDescriptorImpl private constructor(
|
class TypeAliasConstructorDescriptorImpl private constructor(
|
||||||
override val typeAliasDescriptor: TypeAliasDescriptor,
|
override val typeAliasDescriptor: TypeAliasDescriptor,
|
||||||
|
override val underlyingConstructorDescriptor: ConstructorDescriptor,
|
||||||
containingDeclaration: ClassDescriptor,
|
containingDeclaration: ClassDescriptor,
|
||||||
original: ConstructorDescriptor,
|
original: TypeAliasConstructorDescriptor?,
|
||||||
annotations: Annotations,
|
annotations: Annotations,
|
||||||
primary: Boolean,
|
primary: Boolean,
|
||||||
kind: Kind,
|
kind: Kind,
|
||||||
source: SourceElement
|
source: SourceElement
|
||||||
) : TypeAliasConstructorDescriptor,
|
) : TypeAliasConstructorDescriptor,
|
||||||
ConstructorDescriptorImpl(containingDeclaration, original, annotations, primary, kind, source)
|
ConstructorDescriptorImpl(containingDeclaration, original, annotations,
|
||||||
|
primary, kind, source)
|
||||||
{
|
{
|
||||||
|
override fun getOriginal(): TypeAliasConstructorDescriptor =
|
||||||
|
super.getOriginal() as TypeAliasConstructorDescriptor
|
||||||
|
|
||||||
override fun substitute(substitutor: TypeSubstitutor): TypeAliasConstructorDescriptor =
|
override fun substitute(substitutor: TypeSubstitutor): TypeAliasConstructorDescriptor =
|
||||||
super.substitute(substitutor) as TypeAliasConstructorDescriptor
|
super.substitute(substitutor) as TypeAliasConstructorDescriptor
|
||||||
|
|
||||||
@@ -70,28 +75,31 @@ class TypeAliasConstructorDescriptorImpl private constructor(
|
|||||||
}
|
}
|
||||||
assert(newName == null) { "Renaming type alias constructor: $this" }
|
assert(newName == null) { "Renaming type alias constructor: $this" }
|
||||||
return TypeAliasConstructorDescriptorImpl(
|
return TypeAliasConstructorDescriptorImpl(
|
||||||
typeAliasDescriptor,
|
typeAliasDescriptor, underlyingConstructorDescriptor,
|
||||||
newOwner as ClassDescriptor,
|
newOwner as ClassDescriptor,
|
||||||
this, annotations, isPrimary, Kind.DECLARATION,
|
this,
|
||||||
source)
|
annotations, isPrimary, Kind.DECLARATION, source)
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun create(
|
fun create(
|
||||||
typeAliasDescriptor: TypeAliasDescriptor,
|
typeAliasDescriptor: TypeAliasDescriptor,
|
||||||
original: ConstructorDescriptor,
|
underlyingConstructor: ConstructorDescriptor,
|
||||||
substitutor: TypeSubstitutor
|
substitutor: TypeSubstitutor
|
||||||
): TypeAliasConstructorDescriptor? {
|
): TypeAliasConstructorDescriptor? = with(underlyingConstructor) {
|
||||||
val descriptor = TypeAliasConstructorDescriptorImpl(typeAliasDescriptor, original.containingDeclaration, original,
|
val typeAliasConstructor =
|
||||||
original.annotations, original.isPrimary, original.kind, original.source)
|
TypeAliasConstructorDescriptorImpl(typeAliasDescriptor, underlyingConstructor, containingDeclaration, null,
|
||||||
val valueParameters = FunctionDescriptorImpl.getSubstitutedValueParameters(descriptor, original.valueParameters, substitutor, false)
|
annotations, isPrimary, kind, typeAliasDescriptor.source)
|
||||||
?: return null
|
|
||||||
|
|
||||||
descriptor.initialize(valueParameters, original.visibility, typeAliasDescriptor.typeConstructor.parameters)
|
val valueParameters =
|
||||||
|
FunctionDescriptorImpl.getSubstitutedValueParameters(typeAliasConstructor, valueParameters, substitutor, false)
|
||||||
|
?: return null
|
||||||
|
|
||||||
descriptor.returnType = substitutor.substitute(original.returnType, Variance.OUT_VARIANCE) ?: return null
|
typeAliasConstructor.initialize(valueParameters, visibility, typeAliasDescriptor.typeConstructor.parameters)
|
||||||
|
|
||||||
return descriptor
|
typeAliasConstructor.returnType = substitutor.substitute(returnType, Variance.OUT_VARIANCE) ?: return null
|
||||||
|
|
||||||
|
typeAliasConstructor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user