Check local function declarations for overload conflicts.
In PSI unifier tests, disable errors for tests on local functions (as irrelevant).
This commit is contained in:
@@ -296,7 +296,7 @@ public interface Errors {
|
||||
|
||||
// Members
|
||||
|
||||
DiagnosticFactory2<KtDeclaration, CallableMemberDescriptor, DeclarationDescriptor> CONFLICTING_OVERLOADS =
|
||||
DiagnosticFactory2<PsiElement, CallableMemberDescriptor, DeclarationDescriptor> CONFLICTING_OVERLOADS =
|
||||
DiagnosticFactory2.create(ERROR, DECLARATION_SIGNATURE_OR_DEFAULT);
|
||||
|
||||
DiagnosticFactory0<KtNamedDeclaration> NON_FINAL_MEMBER_IN_FINAL_CLASS = DiagnosticFactory0.create(WARNING, modifierSetPosition(
|
||||
|
||||
+21
-3
@@ -18,9 +18,11 @@ package org.jetbrains.kotlin.resolve;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.kotlin.resolve.scopes.RedeclarationHandler;
|
||||
|
||||
import static org.jetbrains.kotlin.diagnostics.Errors.CONFLICTING_OVERLOADS;
|
||||
import static org.jetbrains.kotlin.diagnostics.Errors.REDECLARATION;
|
||||
|
||||
public class TraceBasedRedeclarationHandler implements RedeclarationHandler {
|
||||
@@ -32,11 +34,27 @@ public class TraceBasedRedeclarationHandler implements RedeclarationHandler {
|
||||
|
||||
@Override
|
||||
public void handleRedeclaration(@NotNull DeclarationDescriptor first, @NotNull DeclarationDescriptor second) {
|
||||
report(first);
|
||||
report(second);
|
||||
reportRedeclaration(first);
|
||||
reportRedeclaration(second);
|
||||
}
|
||||
|
||||
private void report(DeclarationDescriptor descriptor) {
|
||||
@Override
|
||||
public void handleConflictingOverloads(@NotNull CallableMemberDescriptor first, @NotNull CallableMemberDescriptor second) {
|
||||
reportConflictingOverloads(first, second.getContainingDeclaration());
|
||||
reportConflictingOverloads(second, first.getContainingDeclaration());
|
||||
}
|
||||
|
||||
private void reportConflictingOverloads(CallableMemberDescriptor conflicting, DeclarationDescriptor withContainedIn) {
|
||||
PsiElement reportElement = DescriptorToSourceUtils.descriptorToDeclaration(conflicting);
|
||||
if (reportElement != null) {
|
||||
trace.report(CONFLICTING_OVERLOADS.on(reportElement, conflicting, withContainedIn));
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException("No declaration found for " + conflicting);
|
||||
}
|
||||
}
|
||||
|
||||
private void reportRedeclaration(DeclarationDescriptor descriptor) {
|
||||
PsiElement firstElement = DescriptorToSourceUtils.descriptorToDeclaration(descriptor);
|
||||
if (firstElement != null) {
|
||||
trace.report(REDECLARATION.on(firstElement, descriptor.getName().asString()));
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.jetbrains.kotlin.resolve.scopes;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||
|
||||
@@ -25,6 +26,10 @@ public interface RedeclarationHandler {
|
||||
@Override
|
||||
public void handleRedeclaration(@NotNull DeclarationDescriptor first, @NotNull DeclarationDescriptor second) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleConflictingOverloads(@NotNull CallableMemberDescriptor first, @NotNull CallableMemberDescriptor second) {
|
||||
}
|
||||
};
|
||||
RedeclarationHandler THROW_EXCEPTION = new RedeclarationHandler() {
|
||||
@Override
|
||||
@@ -34,7 +39,17 @@ public interface RedeclarationHandler {
|
||||
DescriptorUtils.getFqName(second), second)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleConflictingOverloads(@NotNull CallableMemberDescriptor first, @NotNull CallableMemberDescriptor second) {
|
||||
throw new IllegalStateException(
|
||||
String.format("Conflicting overloads: %s (%s) and %s (%s) (no line info available)",
|
||||
DescriptorUtils.getFqName(first), first,
|
||||
DescriptorUtils.getFqName(second), second)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
void handleRedeclaration(@NotNull DeclarationDescriptor first, @NotNull DeclarationDescriptor second);
|
||||
void handleConflictingOverloads(@NotNull CallableMemberDescriptor first, @NotNull CallableMemberDescriptor second);
|
||||
}
|
||||
|
||||
@@ -17,11 +17,9 @@
|
||||
package org.jetbrains.kotlin.resolve.scopes
|
||||
|
||||
import com.intellij.util.SmartList
|
||||
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.VariableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.OverloadUtil
|
||||
import java.util.*
|
||||
|
||||
abstract class WritableScopeStorage(val redeclarationHandler: RedeclarationHandler) {
|
||||
@@ -50,16 +48,34 @@ abstract class WritableScopeStorage(val redeclarationHandler: RedeclarationHandl
|
||||
}
|
||||
|
||||
protected fun addFunctionDescriptorInternal(functionDescriptor: FunctionDescriptor) {
|
||||
val descriptorIndex = addDescriptor(functionDescriptor)
|
||||
checkOverloadConflicts(functionDescriptor)
|
||||
|
||||
val name = functionDescriptor.name
|
||||
val descriptorIndex = addDescriptor(functionDescriptor)
|
||||
if (functionsByName == null) {
|
||||
functionsByName = HashMap(1)
|
||||
}
|
||||
val name = functionDescriptor.name
|
||||
//TODO: could not use += because of KT-8050
|
||||
functionsByName!![name] = functionsByName!![name] + descriptorIndex
|
||||
}
|
||||
|
||||
private fun checkOverloadConflicts(functionDescriptor: FunctionDescriptor) {
|
||||
val name = functionDescriptor.name
|
||||
val originalFunctions = functionsByName(name).orEmpty()
|
||||
val originalVariableOrClass = variableOrClassDescriptorByName(name)
|
||||
val potentiallyConflictingOverloads =
|
||||
if (originalVariableOrClass is ClassDescriptor)
|
||||
originalFunctions + originalVariableOrClass.constructors
|
||||
else
|
||||
originalFunctions
|
||||
for (overloadedDescriptor in potentiallyConflictingOverloads) {
|
||||
if (!OverloadUtil.isOverloadable(overloadedDescriptor, functionDescriptor)) {
|
||||
redeclarationHandler.handleConflictingOverloads(functionDescriptor, overloadedDescriptor)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected fun variableOrClassDescriptorByName(name: Name, descriptorLimit: Int = addedDescriptors.size): DeclarationDescriptor? {
|
||||
if (descriptorLimit == 0) return null
|
||||
|
||||
|
||||
+2
-2
@@ -18,9 +18,9 @@ class Outer {
|
||||
}
|
||||
|
||||
fun outerFun() {
|
||||
<!FUNCTION_DECLARATION_WITH_NO_NAME!>fun ()<!> {}
|
||||
<!FUNCTION_DECLARATION_WITH_NO_NAME, CONFLICTING_OVERLOADS!>fun ()<!> {}
|
||||
<!FUNCTION_DECLARATION_WITH_NO_NAME!>fun B.()<!> {}
|
||||
|
||||
<!FUNCTION_DECLARATION_WITH_NO_NAME!>@a fun ()<!> {}
|
||||
<!FUNCTION_DECLARATION_WITH_NO_NAME, CONFLICTING_OVERLOADS!>@a fun ()<!> {}
|
||||
<!FUNCTION_DECLARATION_WITH_NO_NAME!>fun @a A.()<!> {}
|
||||
}
|
||||
@@ -58,10 +58,10 @@ class Outer {
|
||||
}
|
||||
|
||||
fun outerFun() {
|
||||
<!FUNCTION_DECLARATION_WITH_NO_NAME!>fun ()<!> {
|
||||
<!FUNCTION_DECLARATION_WITH_NO_NAME, CONFLICTING_OVERLOADS!>fun ()<!> {
|
||||
|
||||
}
|
||||
<!FUNCTION_DECLARATION_WITH_NO_NAME!>fun ()<!> {
|
||||
<!FUNCTION_DECLARATION_WITH_NO_NAME, CONFLICTING_OVERLOADS!>fun ()<!> {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,213 @@
|
||||
fun test() {
|
||||
<!CONFLICTING_OVERLOADS!>fun test1()<!> {}
|
||||
<!CONFLICTING_OVERLOADS!>fun test1()<!> {}
|
||||
|
||||
fun Any.test2() {}
|
||||
fun test2(x: Any) = x
|
||||
|
||||
<!CONFLICTING_OVERLOADS!>fun Any.test3()<!> {}
|
||||
<!CONFLICTING_OVERLOADS!>fun Any.test3()<!> {}
|
||||
|
||||
<!CONFLICTING_OVERLOADS!>fun test4(): Int<!> = 0
|
||||
<!CONFLICTING_OVERLOADS!>fun test4(): String<!> = ""
|
||||
|
||||
class Test5<!CONFLICTING_OVERLOADS!>(val x: Int)<!> {
|
||||
<!CONFLICTING_OVERLOADS!>constructor()<!>: this(0)
|
||||
}
|
||||
<!CONFLICTING_OVERLOADS!>fun Test5()<!> {}
|
||||
<!CONFLICTING_OVERLOADS!>fun Test5(x: Int)<!> = x
|
||||
|
||||
fun local() {
|
||||
<!CONFLICTING_OVERLOADS!>fun test1()<!> {}
|
||||
<!CONFLICTING_OVERLOADS!>fun test1()<!> {}
|
||||
|
||||
fun Any.test2() {}
|
||||
fun test2(x: Any) = x
|
||||
|
||||
<!CONFLICTING_OVERLOADS!>fun Any.test3()<!> {}
|
||||
<!CONFLICTING_OVERLOADS!>fun Any.test3()<!> {}
|
||||
|
||||
<!CONFLICTING_OVERLOADS!>fun test4(): Int<!> = 0
|
||||
<!CONFLICTING_OVERLOADS!>fun test4(): String<!> = ""
|
||||
|
||||
class Test5<!CONFLICTING_OVERLOADS!>(val x: Int)<!> {
|
||||
<!CONFLICTING_OVERLOADS!>constructor()<!>: this(0)
|
||||
}
|
||||
<!CONFLICTING_OVERLOADS!>fun Test5()<!> {}
|
||||
<!CONFLICTING_OVERLOADS!>fun Test5(x: Int)<!> = x
|
||||
}
|
||||
}
|
||||
|
||||
class Test {
|
||||
init {
|
||||
<!CONFLICTING_OVERLOADS!>fun test1()<!> {}
|
||||
<!CONFLICTING_OVERLOADS!>fun test1()<!> {}
|
||||
|
||||
fun Any.test2() {}
|
||||
fun test2(x: Any) = x
|
||||
|
||||
<!CONFLICTING_OVERLOADS!>fun Any.test3()<!> {}
|
||||
<!CONFLICTING_OVERLOADS!>fun Any.test3()<!> {}
|
||||
|
||||
<!CONFLICTING_OVERLOADS!>fun test4(): Int<!> = 0
|
||||
<!CONFLICTING_OVERLOADS!>fun test4(): String<!> = ""
|
||||
|
||||
class Test5<!CONFLICTING_OVERLOADS!>(val x: Int)<!> {
|
||||
<!CONFLICTING_OVERLOADS!>constructor()<!>: this(0)
|
||||
}
|
||||
<!CONFLICTING_OVERLOADS!>fun Test5()<!> {}
|
||||
<!CONFLICTING_OVERLOADS!>fun Test5(x: Int)<!> = x
|
||||
}
|
||||
|
||||
fun test() {
|
||||
<!CONFLICTING_OVERLOADS!>fun test1()<!> {}
|
||||
<!CONFLICTING_OVERLOADS!>fun test1()<!> {}
|
||||
|
||||
fun Any.test2() {}
|
||||
fun test2(x: Any) = x
|
||||
|
||||
<!CONFLICTING_OVERLOADS!>fun Any.test3()<!> {}
|
||||
<!CONFLICTING_OVERLOADS!>fun Any.test3()<!> {}
|
||||
|
||||
<!CONFLICTING_OVERLOADS!>fun test4(): Int<!> = 0
|
||||
<!CONFLICTING_OVERLOADS!>fun test4(): String<!> = ""
|
||||
|
||||
class Test5<!CONFLICTING_OVERLOADS!>(val x: Int)<!> {
|
||||
<!CONFLICTING_OVERLOADS!>constructor()<!>: this(0)
|
||||
}
|
||||
<!CONFLICTING_OVERLOADS!>fun Test5()<!> {}
|
||||
<!CONFLICTING_OVERLOADS!>fun Test5(x: Int)<!> = x
|
||||
}
|
||||
|
||||
val property: Any get() {
|
||||
<!CONFLICTING_OVERLOADS!>fun test1()<!> {}
|
||||
<!CONFLICTING_OVERLOADS!>fun test1()<!> {}
|
||||
|
||||
fun Any.test2() {}
|
||||
fun test2(x: Any) = x
|
||||
|
||||
<!CONFLICTING_OVERLOADS!>fun Any.test3()<!> {}
|
||||
<!CONFLICTING_OVERLOADS!>fun Any.test3()<!> {}
|
||||
|
||||
<!CONFLICTING_OVERLOADS!>fun test4(): Int<!> = 0
|
||||
<!CONFLICTING_OVERLOADS!>fun test4(): String<!> = ""
|
||||
|
||||
class Test5<!CONFLICTING_OVERLOADS!>(val x: Int)<!> {
|
||||
<!CONFLICTING_OVERLOADS!>constructor()<!>: this(0)
|
||||
}
|
||||
<!CONFLICTING_OVERLOADS!>fun Test5()<!> {}
|
||||
<!CONFLICTING_OVERLOADS!>fun Test5(x: Int)<!> = x
|
||||
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
val property: Any get() {
|
||||
<!CONFLICTING_OVERLOADS!>fun test1()<!> {}
|
||||
<!CONFLICTING_OVERLOADS!>fun test1()<!> {}
|
||||
|
||||
fun Any.test2() {}
|
||||
fun test2(x: Any) = x
|
||||
|
||||
<!CONFLICTING_OVERLOADS!>fun Any.test3()<!> {}
|
||||
<!CONFLICTING_OVERLOADS!>fun Any.test3()<!> {}
|
||||
|
||||
<!CONFLICTING_OVERLOADS!>fun test4(): Int<!> = 0
|
||||
<!CONFLICTING_OVERLOADS!>fun test4(): String<!> = ""
|
||||
|
||||
class Test5<!CONFLICTING_OVERLOADS!>(val x: Int)<!> {
|
||||
<!CONFLICTING_OVERLOADS!>constructor()<!>: this(0)
|
||||
}
|
||||
<!CONFLICTING_OVERLOADS!>fun Test5()<!> {}
|
||||
<!CONFLICTING_OVERLOADS!>fun Test5(x: Int)<!> = x
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
object Object {
|
||||
fun test() {
|
||||
<!CONFLICTING_OVERLOADS!>fun test1()<!> {}
|
||||
<!CONFLICTING_OVERLOADS!>fun test1()<!> {}
|
||||
|
||||
fun Any.test2() {}
|
||||
fun test2(x: Any) = x
|
||||
|
||||
<!CONFLICTING_OVERLOADS!>fun Any.test3()<!> {}
|
||||
<!CONFLICTING_OVERLOADS!>fun Any.test3()<!> {}
|
||||
|
||||
<!CONFLICTING_OVERLOADS!>fun test4(): Int<!> = 0
|
||||
<!CONFLICTING_OVERLOADS!>fun test4(): String<!> = ""
|
||||
|
||||
class Test5<!CONFLICTING_OVERLOADS!>(val x: Int)<!> {
|
||||
<!CONFLICTING_OVERLOADS!>constructor()<!>: this(0)
|
||||
}
|
||||
<!CONFLICTING_OVERLOADS!>fun Test5()<!> {}
|
||||
<!CONFLICTING_OVERLOADS!>fun Test5(x: Int)<!> = x
|
||||
}
|
||||
|
||||
val property: Any get() {
|
||||
<!CONFLICTING_OVERLOADS!>fun test1()<!> {}
|
||||
<!CONFLICTING_OVERLOADS!>fun test1()<!> {}
|
||||
|
||||
fun Any.test2() {}
|
||||
fun test2(x: Any) = x
|
||||
|
||||
<!CONFLICTING_OVERLOADS!>fun Any.test3()<!> {}
|
||||
<!CONFLICTING_OVERLOADS!>fun Any.test3()<!> {}
|
||||
|
||||
<!CONFLICTING_OVERLOADS!>fun test4(): Int<!> = 0
|
||||
<!CONFLICTING_OVERLOADS!>fun test4(): String<!> = ""
|
||||
|
||||
class Test5<!CONFLICTING_OVERLOADS!>(val x: Int)<!> {
|
||||
<!CONFLICTING_OVERLOADS!>constructor()<!>: this(0)
|
||||
}
|
||||
<!CONFLICTING_OVERLOADS!>fun Test5()<!> {}
|
||||
<!CONFLICTING_OVERLOADS!>fun Test5(x: Int)<!> = x
|
||||
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
val obj = object {
|
||||
fun test() {
|
||||
<!CONFLICTING_OVERLOADS!>fun test1()<!> {}
|
||||
<!CONFLICTING_OVERLOADS!>fun test1()<!> {}
|
||||
|
||||
fun Any.test2() {}
|
||||
fun test2(x: Any) = x
|
||||
|
||||
<!CONFLICTING_OVERLOADS!>fun Any.test3()<!> {}
|
||||
<!CONFLICTING_OVERLOADS!>fun Any.test3()<!> {}
|
||||
|
||||
<!CONFLICTING_OVERLOADS!>fun test4(): Int<!> = 0
|
||||
<!CONFLICTING_OVERLOADS!>fun test4(): String<!> = ""
|
||||
|
||||
class Test5<!CONFLICTING_OVERLOADS!>(val x: Int)<!> {
|
||||
<!CONFLICTING_OVERLOADS!>constructor()<!>: this(0)
|
||||
}
|
||||
<!CONFLICTING_OVERLOADS!>fun Test5()<!> {}
|
||||
<!CONFLICTING_OVERLOADS!>fun Test5(x: Int)<!> = x
|
||||
}
|
||||
|
||||
val property: Any get() {
|
||||
<!CONFLICTING_OVERLOADS!>fun test1()<!> {}
|
||||
<!CONFLICTING_OVERLOADS!>fun test1()<!> {}
|
||||
|
||||
fun Any.test2() {}
|
||||
fun test2(x: Any) = x
|
||||
|
||||
<!CONFLICTING_OVERLOADS!>fun Any.test3()<!> {}
|
||||
<!CONFLICTING_OVERLOADS!>fun Any.test3()<!> {}
|
||||
|
||||
<!CONFLICTING_OVERLOADS!>fun test4(): Int<!> = 0
|
||||
<!CONFLICTING_OVERLOADS!>fun test4(): String<!> = ""
|
||||
|
||||
class Test5<!CONFLICTING_OVERLOADS!>(val x: Int)<!> {
|
||||
<!CONFLICTING_OVERLOADS!>constructor()<!>: this(0)
|
||||
}
|
||||
<!CONFLICTING_OVERLOADS!>fun Test5()<!> {}
|
||||
<!CONFLICTING_OVERLOADS!>fun Test5(x: Int)<!> = x
|
||||
|
||||
return 0
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package
|
||||
|
||||
public val obj: kotlin.Any
|
||||
public val property: kotlin.Any
|
||||
public fun test(): kotlin.Unit
|
||||
|
||||
public object Object {
|
||||
private constructor Object()
|
||||
public final val property: kotlin.Any
|
||||
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 final fun test(): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public final class Test {
|
||||
public constructor Test()
|
||||
public final val property: kotlin.Any
|
||||
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 final fun test(): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
@@ -11781,6 +11781,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("LocalFunctions.kt")
|
||||
public void testLocalFunctions() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/overload/LocalFunctions.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("OverloadFunRegularAndExt.kt")
|
||||
public void testOverloadFunRegularAndExt() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/overload/OverloadFunRegularAndExt.kt");
|
||||
|
||||
+1
@@ -1,3 +1,4 @@
|
||||
// DISABLE-ERRORS
|
||||
class A(val n: Int)
|
||||
|
||||
fun test() {
|
||||
|
||||
+1
@@ -1,3 +1,4 @@
|
||||
// DISABLE-ERRORS
|
||||
class A(val n: Int)
|
||||
|
||||
fun test() {
|
||||
|
||||
Reference in New Issue
Block a user