From c6be69a48331a4af264927e93f9f289a3fdda79f Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Fri, 27 Nov 2015 18:23:47 +0300 Subject: [PATCH] No more reified types for catch parameter #KT-9742 Fixed --- .../jetbrains/kotlin/diagnostics/Errors.java | 2 ++ .../rendering/DefaultErrorMessages.java | 2 ++ .../ControlStructureTypingVisitor.java | 12 +++++---- .../tests/controlStructures/catchGenerics.kt | 25 +++++++++++++++++++ .../tests/controlStructures/catchGenerics.txt | 16 ++++++++++++ .../checkers/DiagnosticsTestGenerated.java | 6 +++++ .../org/jetbrains/kotlin/types/TypeUtils.java | 5 ++++ 7 files changed, 63 insertions(+), 5 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/controlStructures/catchGenerics.kt create mode 100644 compiler/testData/diagnostics/tests/controlStructures/catchGenerics.txt diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java index 669525a38ba..abfa420c94b 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java @@ -106,6 +106,8 @@ public interface Errors { DiagnosticFactory0 TYPE_ARGUMENTS_FOR_OUTER_CLASS_WHEN_NESTED_REFERENCED = DiagnosticFactory0.create(ERROR); + DiagnosticFactory0 REIFIED_TYPE_IN_CATCH_CLAUSE = DiagnosticFactory0.create(ERROR); + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Errors in declarations diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java index a8d4140efd7..eb8a35ce1da 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java @@ -516,6 +516,8 @@ public class DefaultErrorMessages { MAP.put(TYPE_ARGUMENTS_FOR_OUTER_CLASS_WHEN_NESTED_REFERENCED, "Type arguments for outer class are redundant when nested class is referenced"); + MAP.put(REIFIED_TYPE_IN_CATCH_CLAUSE, "Reified type is forbidden for catch parameter"); + MAP.put(TYPE_MISMATCH_IN_FOR_LOOP, "The loop iterates over values of type {0} but the parameter is declared to be {1}", RENDER_TYPE, RENDER_TYPE); MAP.put(TYPE_MISMATCH_IN_CONDITION, "Condition must be of type kotlin.Boolean, but is of type {0}", RENDER_TYPE); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ControlStructureTypingVisitor.java b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ControlStructureTypingVisitor.java index c267a8fc590..59fcbfdc470 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ControlStructureTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ControlStructureTypingVisitor.java @@ -39,10 +39,7 @@ import org.jetbrains.kotlin.resolve.scopes.LexicalScopeKind; import org.jetbrains.kotlin.resolve.scopes.LexicalWritableScope; import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver; import org.jetbrains.kotlin.resolve.scopes.receivers.TransientReceiver; -import org.jetbrains.kotlin.types.CommonSupertypes; -import org.jetbrains.kotlin.types.ErrorUtils; -import org.jetbrains.kotlin.types.KotlinType; -import org.jetbrains.kotlin.types.TypeUtils; +import org.jetbrains.kotlin.types.*; import org.jetbrains.kotlin.types.checker.KotlinTypeChecker; import org.jetbrains.kotlin.types.expressions.ControlStructureTypingUtils.ResolveConstruct; import org.jetbrains.kotlin.types.expressions.typeInfoFactory.TypeInfoFactoryKt; @@ -478,8 +475,13 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor { VariableDescriptor variableDescriptor = components.descriptorResolver.resolveLocalVariableDescriptor( context.scope, catchParameter, context.trace); + KotlinType catchParameterType = variableDescriptor.getType(); + if (TypeUtils.isReifiedTypeParameter(catchParameterType)) { + context.trace.report(REIFIED_TYPE_IN_CATCH_CLAUSE.on(catchParameter)); + } + KotlinType throwableType = components.builtIns.getThrowable().getDefaultType(); - components.dataFlowAnalyzer.checkType(variableDescriptor.getType(), catchParameter, context.replaceExpectedType(throwableType)); + components.dataFlowAnalyzer.checkType(catchParameterType, catchParameter, context.replaceExpectedType(throwableType)); if (catchBody != null) { LexicalWritableScope catchScope = newWritableScopeImpl(context, LexicalScopeKind.CATCH); catchScope.addVariableDescriptor(variableDescriptor); diff --git a/compiler/testData/diagnostics/tests/controlStructures/catchGenerics.kt b/compiler/testData/diagnostics/tests/controlStructures/catchGenerics.kt new file mode 100644 index 00000000000..8ff699f12f2 --- /dev/null +++ b/compiler/testData/diagnostics/tests/controlStructures/catchGenerics.kt @@ -0,0 +1,25 @@ +// See KT-9816, KT-9742 + +// Not allowed in Java +open class ZException(val p: T) : Exception() + +fun foo(): String { + try { + throw ZException(11) + } catch (e: ZException) { + return e.p + } +} + +fun bar() { + try { + throw ZException(11) + } catch (e: ZException<*>) {} +} + +inline fun tryCatch(lazy: () -> R, failure: (E) -> R): R = + try { + lazy() + } catch (e: E) { + failure(e) + } diff --git a/compiler/testData/diagnostics/tests/controlStructures/catchGenerics.txt b/compiler/testData/diagnostics/tests/controlStructures/catchGenerics.txt new file mode 100644 index 00000000000..fa5e2c403df --- /dev/null +++ b/compiler/testData/diagnostics/tests/controlStructures/catchGenerics.txt @@ -0,0 +1,16 @@ +package + +public fun bar(): kotlin.Unit +public fun foo(): kotlin.String +public inline fun tryCatch(/*0*/ lazy: () -> R, /*1*/ failure: (E) -> R): R + +public open class ZException : java.lang.Exception { + public constructor ZException(/*0*/ p: T) + public final override /*1*/ /*fake_override*/ val cause: kotlin.Throwable? + public final override /*1*/ /*fake_override*/ val message: kotlin.String? + public final val p: T + 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 override /*1*/ /*fake_override*/ fun printStackTrace(): kotlin.Unit + 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 850c5a8639f..afffbb7277c 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -3240,6 +3240,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/tests/controlStructures"), Pattern.compile("^(.+)\\.kt$"), true); } + @TestMetadata("catchGenerics.kt") + public void testCatchGenerics() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/controlStructures/catchGenerics.kt"); + doTest(fileName); + } + @TestMetadata("commonSupertypeOfT.kt") public void testCommonSupertypeOfT() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/controlStructures/commonSupertypeOfT.kt"); diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/TypeUtils.java b/core/descriptors/src/org/jetbrains/kotlin/types/TypeUtils.java index f16b05831d9..147c2954614 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/TypeUtils.java +++ b/core/descriptors/src/org/jetbrains/kotlin/types/TypeUtils.java @@ -497,6 +497,11 @@ public class TypeUtils { return typeParameterDescriptor != null && !typeParameterDescriptor.isReified(); } + public static boolean isReifiedTypeParameter(@NotNull KotlinType type) { + TypeParameterDescriptor typeParameterDescriptor = getTypeParameterDescriptorOrNull(type); + return typeParameterDescriptor != null && typeParameterDescriptor.isReified(); + } + @Nullable public static TypeParameterDescriptor getTypeParameterDescriptorOrNull(@NotNull KotlinType type) { if (type.getConstructor().getDeclarationDescriptor() instanceof TypeParameterDescriptor) {