Implicit nothing / intersection types are now checked also for member functions #KT-11666 Fixed
This commit is contained in:
committed by
Mikhail Glukhikh
parent
0ea3b4ade4
commit
4c03aaabd4
@@ -349,6 +349,7 @@ class DeclarationsChecker(
|
|||||||
if (memberDescriptor.kind != CallableMemberDescriptor.Kind.DECLARATION) continue
|
if (memberDescriptor.kind != CallableMemberDescriptor.Kind.DECLARATION) continue
|
||||||
val member = DescriptorToSourceUtils.descriptorToDeclaration(memberDescriptor) as? KtFunction
|
val member = DescriptorToSourceUtils.descriptorToDeclaration(memberDescriptor) as? KtFunction
|
||||||
if (member != null && memberDescriptor is FunctionDescriptor) {
|
if (member != null && memberDescriptor is FunctionDescriptor) {
|
||||||
|
checkImplicitCallableType(member, memberDescriptor)
|
||||||
checkFunctionExposedType(member, memberDescriptor)
|
checkFunctionExposedType(member, memberDescriptor)
|
||||||
checkVarargParameters(trace, memberDescriptor)
|
checkVarargParameters(trace, memberDescriptor)
|
||||||
}
|
}
|
||||||
@@ -689,14 +690,15 @@ class DeclarationsChecker(
|
|||||||
if (!hasBody && !hasAbstractModifier && !hasExternalModifier && !inTrait) {
|
if (!hasBody && !hasAbstractModifier && !hasExternalModifier && !inTrait) {
|
||||||
trace.report(NON_ABSTRACT_FUNCTION_WITH_NO_BODY.on(function, functionDescriptor))
|
trace.report(NON_ABSTRACT_FUNCTION_WITH_NO_BODY.on(function, functionDescriptor))
|
||||||
}
|
}
|
||||||
return
|
|
||||||
}
|
}
|
||||||
if (!function.hasBody() && !hasAbstractModifier && !hasExternalModifier) {
|
else /* top-level only */ {
|
||||||
trace.report(NON_MEMBER_FUNCTION_NO_BODY.on(function, functionDescriptor))
|
if (!function.hasBody() && !hasAbstractModifier && !hasExternalModifier) {
|
||||||
|
trace.report(NON_MEMBER_FUNCTION_NO_BODY.on(function, functionDescriptor))
|
||||||
|
}
|
||||||
|
checkImplicitCallableType(function, functionDescriptor)
|
||||||
|
checkFunctionExposedType(function, functionDescriptor)
|
||||||
|
checkVarargParameters(trace, functionDescriptor)
|
||||||
}
|
}
|
||||||
checkImplicitCallableType(function, functionDescriptor)
|
|
||||||
checkFunctionExposedType(function, functionDescriptor)
|
|
||||||
checkVarargParameters(trace, functionDescriptor)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkImplicitCallableType(declaration: KtCallableDeclaration, descriptor: CallableDescriptor) {
|
private fun checkImplicitCallableType(declaration: KtCallableDeclaration, descriptor: CallableDescriptor) {
|
||||||
|
|||||||
+1
-1
@@ -4,7 +4,7 @@ import kotlin.reflect.KProperty
|
|||||||
|
|
||||||
class NotImplemented<T>(){
|
class NotImplemented<T>(){
|
||||||
operator fun getValue(thisRef: Any?, prop: KProperty<*>): T = notImplemented()
|
operator fun getValue(thisRef: Any?, prop: KProperty<*>): T = notImplemented()
|
||||||
operator fun setValue(thisRef: Any?, prop: KProperty<*>, value: T) = notImplemented()
|
operator fun setValue(thisRef: Any?, prop: KProperty<*>, value: T): Nothing = notImplemented()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun notImplemented() : Nothing = notImplemented()
|
fun notImplemented() : Nothing = notImplemented()
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ class C {
|
|||||||
|
|
||||||
|
|
||||||
object Delegate {
|
object Delegate {
|
||||||
operator fun getValue(x: C, p: KProperty<*>) = throw AssertionError()
|
operator fun getValue(x: C, p: KProperty<*>): Nothing = throw AssertionError()
|
||||||
|
|
||||||
operator fun setValue(x: C, p: KProperty<*>, value: Int) = throw AssertionError()
|
operator fun setValue(x: C, p: KProperty<*>, value: Int): Nothing = throw AssertionError()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ class My(b: B) {
|
|||||||
val <!IMPLICIT_INTERSECTION_TYPE!>x<!> = if (b is A && b is C) b else null
|
val <!IMPLICIT_INTERSECTION_TYPE!>x<!> = if (b is A && b is C) b else null
|
||||||
// Ok: given explicitly
|
// Ok: given explicitly
|
||||||
val y: C? = if (b is A && b is C) <!DEBUG_INFO_SMARTCAST!>b<!> else null
|
val y: C? = if (b is A && b is C) <!DEBUG_INFO_SMARTCAST!>b<!> else null
|
||||||
|
// Error!
|
||||||
|
fun <!IMPLICIT_INTERSECTION_TYPE!>foo<!>(b: B) = if (b is A && b is C) b else null
|
||||||
}
|
}
|
||||||
|
|
||||||
fun bar(b: B): String {
|
fun bar(b: B): String {
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ public final class My {
|
|||||||
public final val x: {C & A & B}?
|
public final val x: {C & A & B}?
|
||||||
public final val y: C?
|
public final val y: C?
|
||||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public final fun foo(/*0*/ b: B): {C & A & B}?
|
||||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,3 +16,21 @@ fun check() {
|
|||||||
// Unreachable / unused, but not implicit Nothing
|
// Unreachable / unused, but not implicit Nothing
|
||||||
<!UNREACHABLE_CODE!>val <!UNUSED_VARIABLE!>x<!> =<!> null!!
|
<!UNREACHABLE_CODE!>val <!UNUSED_VARIABLE!>x<!> =<!> null!!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class Klass {
|
||||||
|
fun <!IMPLICIT_NOTHING_RETURN_TYPE!>bar<!>() = null!!
|
||||||
|
|
||||||
|
val <!IMPLICIT_NOTHING_PROPERTY_TYPE!>y<!> = null!!
|
||||||
|
|
||||||
|
init {
|
||||||
|
fun <!IMPLICIT_NOTHING_RETURN_TYPE!>local<!>() = bar()
|
||||||
|
// Should be unreachable: see KT-5311
|
||||||
|
val z = null!!
|
||||||
|
}
|
||||||
|
|
||||||
|
fun foo() {
|
||||||
|
fun <!IMPLICIT_NOTHING_RETURN_TYPE!>local<!>() = bar()
|
||||||
|
|
||||||
|
<!UNREACHABLE_CODE!>val <!UNUSED_VARIABLE!>x<!> =<!> y
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -7,3 +7,13 @@ public fun baz(): kotlin.Nothing
|
|||||||
public fun check(): kotlin.Unit
|
public fun check(): kotlin.Unit
|
||||||
public fun foo(): kotlin.Nothing
|
public fun foo(): kotlin.Nothing
|
||||||
public fun gav(): kotlin.Any
|
public fun gav(): kotlin.Any
|
||||||
|
|
||||||
|
public final class Klass {
|
||||||
|
public constructor Klass()
|
||||||
|
public final val y: kotlin.Nothing
|
||||||
|
public final fun bar(): kotlin.Nothing
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public final fun foo(): kotlin.Unit
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|||||||
+1
-1
@@ -6,6 +6,6 @@ annotation class Anno
|
|||||||
|
|
||||||
class Class {
|
class Class {
|
||||||
@Anno val x: Int by object {
|
@Anno val x: Int by object {
|
||||||
operator fun getValue(thiz: Class, data: KProperty<*>) = null!!
|
operator fun getValue(thiz: Class, data: KProperty<*>): Nothing = null!!
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -8,5 +8,5 @@ import kotlin.reflect.KProperty
|
|||||||
annotation class Anno
|
annotation class Anno
|
||||||
|
|
||||||
@Anno val x: Int by object {
|
@Anno val x: Int by object {
|
||||||
operator fun getValue(thiz: Any?, data: KProperty<*>) = null!!
|
operator fun getValue(thiz: Any?, data: KProperty<*>): Nothing = null!!
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -213,7 +213,7 @@ private class EnhancedTypeAnnotations(private val fqNameToMatch: FqName) : Annot
|
|||||||
}
|
}
|
||||||
|
|
||||||
private object EnhancedTypeAnnotationDescriptor : AnnotationDescriptor {
|
private object EnhancedTypeAnnotationDescriptor : AnnotationDescriptor {
|
||||||
private fun throwError() = error("No methods should be called on this descriptor. Only its presence matters")
|
private fun throwError(): Nothing = error("No methods should be called on this descriptor. Only its presence matters")
|
||||||
override fun getType() = throwError()
|
override fun getType() = throwError()
|
||||||
override fun getAllValueArguments() = throwError()
|
override fun getAllValueArguments() = throwError()
|
||||||
override fun getSource() = throwError()
|
override fun getSource() = throwError()
|
||||||
|
|||||||
@@ -76,6 +76,6 @@ internal object EmptyContainerForLocal : KDeclarationContainerImpl() {
|
|||||||
|
|
||||||
override fun getFunctions(name: Name): Collection<FunctionDescriptor> = fail()
|
override fun getFunctions(name: Name): Collection<FunctionDescriptor> = fail()
|
||||||
|
|
||||||
private fun fail() = throw KotlinReflectionInternalError("Introspecting local functions, lambdas and anonymous functions " +
|
private fun fail(): Nothing = throw KotlinReflectionInternalError("Introspecting local functions, lambdas and anonymous functions " +
|
||||||
"is not yet fully supported in Kotlin reflection")
|
"is not yet fully supported in Kotlin reflection")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -440,9 +440,9 @@ class KotlinEvaluator(val codeFragment: KtCodeFragment, val sourcePosition: Sour
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun exception(msg: String) = throw EvaluateExceptionUtil.createEvaluateException(msg)
|
private fun exception(msg: String): Nothing = throw EvaluateExceptionUtil.createEvaluateException(msg)
|
||||||
|
|
||||||
private fun exception(e: Throwable) = throw EvaluateExceptionUtil.createEvaluateException(e)
|
private fun exception(e: Throwable): Nothing = throw EvaluateExceptionUtil.createEvaluateException(e)
|
||||||
|
|
||||||
// contextFile must be NotNull when analyzeInlineFunctions = true
|
// contextFile must be NotNull when analyzeInlineFunctions = true
|
||||||
private fun KtFile.checkForErrors(analyzeInlineFunctions: Boolean = false, contextFile: KtFile? = null): ExtendedAnalysisResult {
|
private fun KtFile.checkForErrors(analyzeInlineFunctions: Boolean = false, contextFile: KtFile? = null): ExtendedAnalysisResult {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
// IS_APPLICABLE: false
|
// IS_APPLICABLE: false
|
||||||
class A(val n: Int) {
|
class A(val n: Int) {
|
||||||
fun <caret>foo() = throw Exception("foo")
|
fun <caret>foo(): Nothing = throw Exception("foo")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun test() {
|
fun test() {
|
||||||
|
|||||||
Reference in New Issue
Block a user