Redeclaration errors for type aliases: type alias vs function.

This commit is contained in:
Dmitry Petrov
2016-06-09 15:21:53 +03:00
parent 5ad4c8b9c7
commit 12710bec2f
8 changed files with 121 additions and 37 deletions
@@ -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");
@@ -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
} }
} }
} }