diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java b/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java index f45d9c48e98..1d3269aabaf 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java @@ -842,6 +842,8 @@ public class JetTypeMapper { knowTypes.put(standardLibrary.getNullableStringType(),JL_STRING_TYPE); knowTypes.put(standardLibrary.getCharSequenceType(),JL_CHAR_SEQUENCE_TYPE); knowTypes.put(standardLibrary.getNullableCharSequenceType(),JL_CHAR_SEQUENCE_TYPE); + knowTypes.put(standardLibrary.getThrowableType(), TYPE_THROWABLE); + knowTypes.put(standardLibrary.getNullableThrowableType(), TYPE_THROWABLE); for (JvmPrimitiveType jvmPrimitiveType : JvmPrimitiveType.values()) { PrimitiveType primitiveType = jvmPrimitiveType.getPrimitiveType(); diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaTypeTransformer.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaTypeTransformer.java index 6a9af4a80e1..43646012db9 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaTypeTransformer.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaTypeTransformer.java @@ -204,10 +204,11 @@ public class JavaTypeTransformer { classTypesMap.put("java.lang.Object", JetStandardClasses.getNullableAnyType()); classTypesMap.put("java.lang.String", standardLibrary.getNullableStringType()); classTypesMap.put("java.lang.CharSequence", standardLibrary.getNullableCharSequenceType()); + classTypesMap.put("java.lang.Throwable", standardLibrary.getThrowableType()); } return classTypesMap; } - + public Map getPrimitiveWrappersClassDescriptorMap() { if (classDescriptorMap == null) { classDescriptorMap = new HashMap(); @@ -217,6 +218,7 @@ public class JavaTypeTransformer { } classDescriptorMap.put("java.lang.String", standardLibrary.getString()); classDescriptorMap.put("java.lang.CharSequence", standardLibrary.getCharSequence()); + classDescriptorMap.put("java.lang.Throwable", standardLibrary.getThrowable()); } return classDescriptorMap; } diff --git a/compiler/frontend/src/jet/Library.jet b/compiler/frontend/src/jet/Library.jet index 6d15cfc9d09..7bff1e6c775 100644 --- a/compiler/frontend/src/jet/Library.jet +++ b/compiler/frontend/src/jet/Library.jet @@ -59,3 +59,9 @@ class String() : Comparable, CharSequence { fun equals(other : Any?) : Boolean } + +class Throwable(message : String? = null, cause: Throwable? = null) { + fun getMessage() : String? + fun getCause() : Throwable? + fun printStackTrace() : Unit +} \ No newline at end of file diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/JetStandardLibrary.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/JetStandardLibrary.java index 8eff2cc9ecf..f3086e20f22 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/JetStandardLibrary.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/JetStandardLibrary.java @@ -72,14 +72,16 @@ public class JetStandardLibrary { private ClassDescriptor iterableClass; private ClassDescriptor comparableClass; private ClassDescriptor volatileClass; + private ClassDescriptor throwableClass; private JetType stringType; private JetType volatileType; private JetType nullableStringType; private JetType charSequenceType; private JetType nullableCharSequenceType; - private JetType nullableTuple0Type; + private JetType throwableType; + private JetType nullableThrowableType; private JetType tuple0Type; @@ -143,6 +145,7 @@ public class JetStandardLibrary { this.charSequenceClass = (ClassDescriptor) libraryScope.getClassifier("CharSequence"); this.arrayClass = (ClassDescriptor) libraryScope.getClassifier("Array"); this.volatileClass = (ClassDescriptor) libraryScope.getClassifier("volatile"); + this.throwableClass = (ClassDescriptor) libraryScope.getClassifier("Throwable"); this.iterableClass = (ClassDescriptor) libraryScope.getClassifier("Iterable"); this.comparableClass = (ClassDescriptor) libraryScope.getClassifier("Comparable"); @@ -153,6 +156,8 @@ public class JetStandardLibrary { this.nullableCharSequenceType = TypeUtils.makeNullable(charSequenceType); this.nullableStringType = TypeUtils.makeNullable(stringType); this.volatileType = new JetTypeImpl(getVolatile()); + this.throwableType = new JetTypeImpl(getThrowable()); + this.nullableThrowableType = TypeUtils.makeNullable(throwableType); this.tuple0Type = new JetTypeImpl(JetStandardClasses.getTuple(0)); this.nullableTuple0Type = TypeUtils.makeNullable(tuple0Type); @@ -270,6 +275,12 @@ public class JetStandardLibrary { return comparableClass; } + @NotNull + public ClassDescriptor getThrowable() { + initStdClasses(); + return throwableClass; + } + public Set getTypeInfoFunctions() { initStdClasses(); return typeInfoFunction; @@ -393,6 +404,17 @@ public class JetStandardLibrary { initStdClasses(); return nullableCharSequenceType; } + + @NotNull + public JetType getThrowableType() { + initStdClasses(); + return throwableType; + } + + public JetType getNullableThrowableType() { + initStdClasses(); + return nullableThrowableType; + } @NotNull public JetType getNullablePrimitiveJetType(PrimitiveType primitiveType) { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ControlStructureTypingVisitor.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ControlStructureTypingVisitor.java index d34bb5af595..0a2caaa9918 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ControlStructureTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ControlStructureTypingVisitor.java @@ -400,6 +400,8 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor { JetExpression catchBody = catchClause.getCatchBody(); if (catchParameter != null) { VariableDescriptor variableDescriptor = context.getDescriptorResolver().resolveLocalVariableDescriptor(context.scope.getContainingDeclaration(), context.scope, catchParameter); + JetType throwableType = context.semanticServices.getStandardLibrary().getThrowable().getDefaultType(); + DataFlowUtils.checkType(variableDescriptor.getOutType(), catchParameter, context.replaceExpectedType(throwableType)); if (catchBody != null) { WritableScope catchScope = newWritableScopeImpl(context).setDebugName("Catch scope"); catchScope.addVariableDescriptor(variableDescriptor); @@ -433,8 +435,8 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor { public JetType visitThrowExpression(JetThrowExpression expression, ExpressionTypingContext context) { JetExpression thrownExpression = expression.getThrownExpression(); if (thrownExpression != null) { - JetType type = facade.getType(thrownExpression, context.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE).replaceScope(context.scope)); - // TODO : check that it inherits Throwable + JetType throwableType = context.semanticServices.getStandardLibrary().getThrowable().getDefaultType(); + facade.getType(thrownExpression, context.replaceExpectedType(throwableType).replaceScope(context.scope)); } return DataFlowUtils.checkType(JetStandardClasses.getNothingType(), expression, context); } diff --git a/compiler/testData/codegen/regressions/kt1157.kt b/compiler/testData/codegen/regressions/kt1157.kt index 31d6f075c8a..a053a0e54cd 100644 --- a/compiler/testData/codegen/regressions/kt1157.kt +++ b/compiler/testData/codegen/regressions/kt1157.kt @@ -23,6 +23,6 @@ public object SomeClass { public fun box():String { if(SomeClass.bug is Throwable) - throw SomeClass.bug + throw SomeClass.bug as Throwable return "OK" } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/FunctionReturnTypes.jet b/compiler/testData/diagnostics/tests/FunctionReturnTypes.jet index 8cbd5644de8..2fb4c9d914c 100644 --- a/compiler/testData/diagnostics/tests/FunctionReturnTypes.jet +++ b/compiler/testData/diagnostics/tests/FunctionReturnTypes.jet @@ -162,7 +162,7 @@ fun illegalReturnIf(): Char { } fun returnNothing(): Nothing { - throw 1 + throw 1 } fun f(): Int { if (1 < 2) { return 1 } else returnNothing() diff --git a/compiler/testData/diagnostics/tests/UnreachableCode.jet b/compiler/testData/diagnostics/tests/UnreachableCode.jet index 6352778d4c6..df32131cd64 100644 --- a/compiler/testData/diagnostics/tests/UnreachableCode.jet +++ b/compiler/testData/diagnostics/tests/UnreachableCode.jet @@ -109,7 +109,7 @@ fun t7() : Int { return 1 2 } - catch (e : Any) { + catch (e : Any) { 2 } return 1 // this is OK, like in Java @@ -120,7 +120,7 @@ fun t8() : Int { return 1 2 } - catch (e : Any) { + catch (e : Any) { return 1 2 } diff --git a/compiler/testData/diagnostics/tests/regressions/kt701.jet b/compiler/testData/diagnostics/tests/regressions/kt701.jet index cd536d66aa8..3b5659a2008 100644 --- a/compiler/testData/diagnostics/tests/regressions/kt701.jet +++ b/compiler/testData/diagnostics/tests/regressions/kt701.jet @@ -7,7 +7,7 @@ public class Throwables() { public fun propagateIfInstanceOf(throwable : Throwable?, declaredType : Class?) { if (((throwable != null) && declaredType?.isInstance(throwable).sure())) { - throw declaredType?.cast(throwable) + throw declaredType?.cast(throwable).sure() } } public fun propagateIfPossible(throwable : Throwable?) { diff --git a/idea/testData/checker/FunctionReturnTypes.jet b/idea/testData/checker/FunctionReturnTypes.jet index 85ee309f851..014411e2944 100644 --- a/idea/testData/checker/FunctionReturnTypes.jet +++ b/idea/testData/checker/FunctionReturnTypes.jet @@ -157,7 +157,7 @@ fun illegalReturnIf(): Char { } fun returnNothing(): Nothing { - throw 1 + throw 1 } fun f(): Int { if (1 < 2) { return 1 } else returnNothing() diff --git a/idea/testData/checker/UnreachableCode.jet b/idea/testData/checker/UnreachableCode.jet index d6a6eab78ba..08028200ed5 100644 --- a/idea/testData/checker/UnreachableCode.jet +++ b/idea/testData/checker/UnreachableCode.jet @@ -107,7 +107,7 @@ fun t7() : Int { return 1 2 } - catch (e : Any) { + catch (e : Any) { 2 } return 1 // this is OK, like in Java @@ -118,7 +118,7 @@ fun t8() : Int { return 1 2 } - catch (e : Any) { + catch (e : Any) { return 1 2 } diff --git a/testlib/test/Test.kt b/testlib/test/Test.kt index 8915aa542b1..dae55b52080 100644 --- a/testlib/test/Test.kt +++ b/testlib/test/Test.kt @@ -135,7 +135,7 @@ fun failsWith(block: ()-> Any) { } fun todo(block: ()-> Any) { - println("TODO at " + Exception().getStackTrace()?.get(1) + " for " + block) + println("TODO at " + (Exception() as java.lang.Throwable).getStackTrace()?.get(1) + " for " + block) } /*