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.Name
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.scopes.MemberScope
import org.jetbrains.kotlin.types.ErrorUtils
@@ -99,14 +100,25 @@ class OverloadChecker(val specificityComparator: TypeSpecificityComparator) {
): 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 ->
val functions = scope.getContributedFunctions(name, NoLookupLocation.WHEN_CHECK_REDECLARATIONS)
val classifier = scope.getContributedClassifier(name, NoLookupLocation.WHEN_CHECK_REDECLARATIONS)
if (classifier is ClassDescriptor && !classifier.kind.isSingleton)
functions + classifier.constructors
else
functions
when (classifier) {
is ClassDescriptor ->
if (!classifier.kind.isSingleton)
functions + classifier.constructors
else
functions
is TypeAliasDescriptor ->
functions + classifier.getTypeAliasConstructors()
else ->
functions
}
}
collectModulePackageMembersWithSameName(packageMembersByName, c.properties.values, overloadFilter) {
@@ -18,10 +18,12 @@ package org.jetbrains.kotlin.resolve
import com.intellij.util.containers.MultiMap
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor
import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.idea.MainFunctionDetector
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.resolve.calls.tower.getTypeAliasConstructors
import org.jetbrains.kotlin.utils.addToStdlib.check
class OverloadResolver(
@@ -31,7 +33,7 @@ class OverloadResolver(
) {
fun checkOverloads(c: BodiesResolveContext) {
val inClasses = findConstructorsInNestedClasses(c)
val inClasses = findConstructorsInNestedClassesAndTypeAliases(c)
for (entry in c.declaredClasses.entries) {
checkOverloadsInClass(entry.value, inClasses.get(entry.value))
@@ -39,8 +41,8 @@ class OverloadResolver(
checkOverloadsInPackages(c)
}
private fun findConstructorsInNestedClasses(c: BodiesResolveContext): MultiMap<ClassDescriptor, ConstructorDescriptor> {
val constructorsInNestedClasses = MultiMap.create<ClassDescriptor, ConstructorDescriptor>()
private fun findConstructorsInNestedClassesAndTypeAliases(c: BodiesResolveContext): MultiMap<ClassDescriptor, ConstructorDescriptor> {
val constructorsByOuterClass = MultiMap.create<ClassDescriptor, ConstructorDescriptor>()
for (klass in c.declaredClasses.values) {
if (klass.kind.isSingleton || klass.name.isSpecial) {
@@ -52,7 +54,7 @@ class OverloadResolver(
// TODO: check overload conflicts of functions with constructors in scripts
}
else if (containingDeclaration is ClassDescriptor) {
constructorsInNestedClasses.putValues(containingDeclaration, klass.constructors)
constructorsByOuterClass.putValues(containingDeclaration, klass.constructors)
}
else if (!(containingDeclaration is FunctionDescriptor ||
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) {
@@ -82,8 +91,14 @@ class OverloadResolver(
functionsByName.putValue(function.name, function)
}
for (nestedClassConstructor in nestedClassConstructors) {
functionsByName.putValue(nestedClassConstructor.containingDeclaration.name, nestedClassConstructor)
for (nestedConstructor in nestedClassConstructors) {
val name =
if (nestedConstructor is TypeAliasConstructorDescriptor)
nestedConstructor.typeAliasDescriptor.name
else
nestedConstructor.containingDeclaration.name
functionsByName.putValue(name, nestedConstructor)
}
for (e in functionsByName.entrySet()) {
@@ -244,7 +244,7 @@ private fun ResolutionScope.getContributedFunctionsAndConstructors(name: Name, l
val classifier = getContributedClassifier(name, location)
return getContributedFunctions(name, location) +
(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> {
@@ -274,7 +274,7 @@ private fun getClassWithConstructors(classifier: ClassifierDescriptor?): ClassDe
private val ClassDescriptor.canHaveCallableConstructors: Boolean
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()
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")
return classDescriptor.constructors.filter {
if (inner) it.dispatchReceiverParameter != null else it.dispatchReceiverParameter == null
}.mapNotNull {
TypeAliasConstructorDescriptorImpl.create(this, it, substitutor)
return classDescriptor.constructors.mapNotNull {
if (it.dispatchReceiverParameter == null)
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
class Outer {
class <!REDECLARATION!>Nested<!>
class <!REDECLARATION, CONFLICTING_OVERLOADS!>Nested<!>
typealias <!REDECLARATION!>Nested<!> = Any
typealias <!REDECLARATION!>Nested<!> = Any
typealias <!REDECLARATION!>Nested<!> = Any
<!CONFLICTING_OVERLOADS!>typealias <!REDECLARATION!>Nested<!> = Any<!>
<!CONFLICTING_OVERLOADS!>typealias <!REDECLARATION!>Nested<!> = Any<!>
<!CONFLICTING_OVERLOADS!>typealias <!REDECLARATION!>Nested<!> = Any<!>
}
// FILE: file2.kt
@@ -13902,6 +13902,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
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")
public void testTypeAliasVsClass() throws Exception {
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.annotations.Annotations
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeSubstitutor
import org.jetbrains.kotlin.types.Variance
interface TypeAliasConstructorDescriptor : ConstructorDescriptor {
val typeAliasDescriptor: TypeAliasDescriptor
val underlyingConstructorDescriptor: ConstructorDescriptor
}
class TypeAliasConstructorDescriptorImpl private constructor(
override val typeAliasDescriptor: TypeAliasDescriptor,
override val underlyingConstructorDescriptor: ConstructorDescriptor,
containingDeclaration: ClassDescriptor,
original: ConstructorDescriptor,
original: TypeAliasConstructorDescriptor?,
annotations: Annotations,
primary: Boolean,
kind: Kind,
source: SourceElement
) : 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 =
super.substitute(substitutor) as TypeAliasConstructorDescriptor
@@ -70,28 +75,31 @@ class TypeAliasConstructorDescriptorImpl private constructor(
}
assert(newName == null) { "Renaming type alias constructor: $this" }
return TypeAliasConstructorDescriptorImpl(
typeAliasDescriptor,
typeAliasDescriptor, underlyingConstructorDescriptor,
newOwner as ClassDescriptor,
this, annotations, isPrimary, Kind.DECLARATION,
source)
this,
annotations, isPrimary, Kind.DECLARATION, source)
}
companion object {
fun create(
typeAliasDescriptor: TypeAliasDescriptor,
original: ConstructorDescriptor,
underlyingConstructor: ConstructorDescriptor,
substitutor: TypeSubstitutor
): TypeAliasConstructorDescriptor? {
val descriptor = TypeAliasConstructorDescriptorImpl(typeAliasDescriptor, original.containingDeclaration, original,
original.annotations, original.isPrimary, original.kind, original.source)
val valueParameters = FunctionDescriptorImpl.getSubstitutedValueParameters(descriptor, original.valueParameters, substitutor, false)
?: return null
): TypeAliasConstructorDescriptor? = with(underlyingConstructor) {
val typeAliasConstructor =
TypeAliasConstructorDescriptorImpl(typeAliasDescriptor, underlyingConstructor, containingDeclaration, null,
annotations, isPrimary, kind, typeAliasDescriptor.source)
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
}
}
}