From 5ccfbcbe22572414127808da7adcaa7a18a0e831 Mon Sep 17 00:00:00 2001 From: Dmitry Petrov Date: Tue, 28 Mar 2017 15:59:33 +0300 Subject: [PATCH] KT-4960 Redeclaration is not reported for type parameters of interfaces When resolving a class body for a class without a primary constructor (e.g., an interface), no checks were performed for redeclarations in the corresponding class header. Creating & initializing a lexical scope of an appropriate kind will do it. Note that since class has no primary constructor, only type parameters could be redeclared (and that's KT-4960). --- .../kotlin/resolve/BodyResolver.java | 22 ++++++++++++++++ .../redeclarations/interfaceTypeParameters.kt | 6 +++++ .../interfaceTypeParameters.txt | 26 +++++++++++++++++++ .../checkers/DiagnosticsTestGenerated.java | 6 +++++ .../typeArgumentsRedundantInSuperQualifier.kt | 2 +- ...rgumentsRedundantInSuperQualifier.kt.after | 2 +- 6 files changed, 62 insertions(+), 2 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/redeclarations/interfaceTypeParameters.kt create mode 100644 compiler/testData/diagnostics/tests/redeclarations/interfaceTypeParameters.txt diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/BodyResolver.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/BodyResolver.java index d0819f21703..11bd8cb1d21 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/BodyResolver.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/BodyResolver.java @@ -268,6 +268,9 @@ public class BodyResolver { primaryConstructor == null ? null : FunctionDescriptorUtil.getFunctionInnerScope(scopeForConstructorResolution, primaryConstructor, trace, overloadChecker); + if (primaryConstructor == null) { + checkRedeclarationsInClassHeaderWithoutPrimaryConstructor(descriptor, scopeForConstructorResolution); + } ExpressionTypingServices typeInferrer = expressionTypingServices; // TODO : flow Map supertypes = Maps.newLinkedHashMap(); @@ -396,6 +399,25 @@ public class BodyResolver { checkSupertypeList(descriptor, supertypes, ktClass); } + private void checkRedeclarationsInClassHeaderWithoutPrimaryConstructor( + @NotNull final ClassDescriptor descriptor, @NotNull LexicalScope scopeForConstructorResolution + ) { + // Initializing a scope will report errors if any. + new LexicalScopeImpl( + scopeForConstructorResolution, descriptor, true, null, LexicalScopeKind.CLASS_HEADER, + new TraceBasedLocalRedeclarationChecker(trace, overloadChecker), + new Function1() { + @Override + public Unit invoke(LexicalScopeImpl.InitializeHandler handler) { + // If a class has no primary constructor, it still can have type parameters declared in header. + for (TypeParameterDescriptor typeParameter : descriptor.getDeclaredTypeParameters()) { + handler.addClassifierDescriptor(typeParameter); + } + return Unit.INSTANCE; + } + }); + } + private void resolveConstructorCallForEnumEntryWithoutInitializer( @NotNull KtEnumEntry ktEnumEntry, @NotNull ClassDescriptor enumEntryDescriptor, diff --git a/compiler/testData/diagnostics/tests/redeclarations/interfaceTypeParameters.kt b/compiler/testData/diagnostics/tests/redeclarations/interfaceTypeParameters.kt new file mode 100644 index 00000000000..25c3a42c108 --- /dev/null +++ b/compiler/testData/diagnostics/tests/redeclarations/interfaceTypeParameters.kt @@ -0,0 +1,6 @@ +interface Test1<T, T> +interface Test2<X, Y, X> + +class Outer { + interface TestNested +} diff --git a/compiler/testData/diagnostics/tests/redeclarations/interfaceTypeParameters.txt b/compiler/testData/diagnostics/tests/redeclarations/interfaceTypeParameters.txt new file mode 100644 index 00000000000..5016cb1638b --- /dev/null +++ b/compiler/testData/diagnostics/tests/redeclarations/interfaceTypeParameters.txt @@ -0,0 +1,26 @@ +package + +public final class Outer { + public constructor Outer() + 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 TestNested { + 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 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 +} diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index 35ff0b97726..146fd9485a7 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -15949,6 +15949,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { doTest(fileName); } + @TestMetadata("interfaceTypeParameters.kt") + public void testInterfaceTypeParameters() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/redeclarations/interfaceTypeParameters.kt"); + doTest(fileName); + } + @TestMetadata("kt2418.kt") public void testKt2418() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/redeclarations/kt2418.kt"); diff --git a/idea/testData/quickfix/supercalls/typeArgumentsRedundantInSuperQualifier.kt b/idea/testData/quickfix/supercalls/typeArgumentsRedundantInSuperQualifier.kt index fed170d2b6b..ae92bc29714 100644 --- a/idea/testData/quickfix/supercalls/typeArgumentsRedundantInSuperQualifier.kt +++ b/idea/testData/quickfix/supercalls/typeArgumentsRedundantInSuperQualifier.kt @@ -1,5 +1,5 @@ // "Remove type arguments" "true" -interface Foo { +interface Foo { fun f() {} } diff --git a/idea/testData/quickfix/supercalls/typeArgumentsRedundantInSuperQualifier.kt.after b/idea/testData/quickfix/supercalls/typeArgumentsRedundantInSuperQualifier.kt.after index d8b9089f890..b764bacf0f9 100644 --- a/idea/testData/quickfix/supercalls/typeArgumentsRedundantInSuperQualifier.kt.after +++ b/idea/testData/quickfix/supercalls/typeArgumentsRedundantInSuperQualifier.kt.after @@ -1,5 +1,5 @@ // "Remove type arguments" "true" -interface Foo { +interface Foo { fun f() {} }