From 99a32b93fb9cb1cc4396e355ff2b625bae490632 Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Wed, 23 Dec 2015 11:35:25 +0300 Subject: [PATCH] Implemented missed checks for local functions #KT-10449 Fixed Relevant code/test fixes --- .../kotlin/resolve/DeclarationsChecker.kt | 36 ++++++++++++------- .../ExpressionTypingComponents.java | 6 ++++ .../ExpressionTypingVisitorDispatcher.java | 6 ++-- .../expressions/FunctionsTypingVisitor.kt | 5 +-- .../exceptionInMonitorExpression.kt | 2 +- .../deadCode/deadCallInInvokeCall.kt | 2 +- .../TypeParametersInTypeParameterBounds.kt | 5 ++- .../diagnostics/tests/implicitIntersection.kt | 2 ++ .../diagnostics/tests/implicitNothing.kt | 2 +- .../tests/typeParameters/deprecatedSyntax.kt | 1 + .../typeParameters/misplacedConstraints.kt | 1 + .../typeParameters/boundsAndConstraints.kt | 16 +++++---- .../boundsAndConstraints.kt.match | 10 ++---- .../stdlib/test/collections/ArraysTest.kt | 2 +- 14 files changed, 58 insertions(+), 38 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DeclarationsChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DeclarationsChecker.kt index dc4fda7d906..445c8bdd33e 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DeclarationsChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DeclarationsChecker.kt @@ -67,12 +67,23 @@ fun KtTypeReference.checkNotEnumEntry(trace: BindingTrace): Boolean { return result } +internal class DeclarationsCheckerBuilder( + private val descriptorResolver: DescriptorResolver, + private val originalModifiersChecker: ModifiersChecker, + private val annotationChecker: AnnotationChecker, + private val identifierChecker: IdentifierChecker +) { + fun withTrace(trace: BindingTrace) = + DeclarationsChecker(descriptorResolver, originalModifiersChecker, annotationChecker, identifierChecker, trace) +} + class DeclarationsChecker( private val descriptorResolver: DescriptorResolver, modifiersChecker: ModifiersChecker, private val annotationChecker: AnnotationChecker, private val identifierChecker: IdentifierChecker, - private val trace: BindingTrace) { + private val trace: BindingTrace +) { private val modifiersChecker = modifiersChecker.withTrace(trace) @@ -612,7 +623,7 @@ class DeclarationsChecker( checkMemberReceiverExposedType(property.receiverTypeReference, propertyDescriptor) } - private fun checkFunction(function: KtNamedFunction, functionDescriptor: SimpleFunctionDescriptor) { + fun checkFunction(function: KtNamedFunction, functionDescriptor: SimpleFunctionDescriptor) { val typeParameterList = function.typeParameterList val nameIdentifier = function.nameIdentifier if (typeParameterList != null && nameIdentifier != null && @@ -754,20 +765,21 @@ class DeclarationsChecker( } } - companion object { - internal fun checkVarargParameters(trace: BindingTrace, callableDescriptor: CallableDescriptor) { - val numberOfVarargParameters = callableDescriptor.valueParameters.count { it.varargElementType != null } - if (numberOfVarargParameters > 1) { - for (parameter in callableDescriptor.valueParameters) { - if (parameter.varargElementType != null) { - val parameterDeclaration = DescriptorToSourceUtils.descriptorToDeclaration(parameter) - if (parameterDeclaration is KtParameter) { - trace.report(MULTIPLE_VARARG_PARAMETERS.on(parameterDeclaration)) - } + private fun checkVarargParameters(trace: BindingTrace, callableDescriptor: CallableDescriptor) { + val numberOfVarargParameters = callableDescriptor.valueParameters.count { it.varargElementType != null } + if (numberOfVarargParameters > 1) { + for (parameter in callableDescriptor.valueParameters) { + if (parameter.varargElementType != null) { + val parameterDeclaration = DescriptorToSourceUtils.descriptorToDeclaration(parameter) + if (parameterDeclaration is KtParameter) { + trace.report(MULTIPLE_VARARG_PARAMETERS.on(parameterDeclaration)) } } } } + } + + companion object { private fun removeDuplicateTypes(conflictingTypes: MutableSet) { val iterator = conflictingTypes.iterator() diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingComponents.java b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingComponents.java index 884ce7827ac..5fb6932a565 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingComponents.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingComponents.java @@ -55,6 +55,7 @@ public class ExpressionTypingComponents { /*package*/ DataFlowAnalyzer dataFlowAnalyzer; /*package*/ Iterable callCheckers; /*package*/ IdentifierChecker identifierChecker; + /*package*/ DeclarationsCheckerBuilder declarationsCheckerBuilder; @Inject public void setGlobalContext(@NotNull GlobalContext globalContext) { @@ -175,4 +176,9 @@ public class ExpressionTypingComponents { public void setCallCheckers(@NotNull Iterable callCheckers) { this.callCheckers = callCheckers; } + + @Inject + public void setDeclarationsCheckerBuilder(@NotNull DeclarationsCheckerBuilder declarationsCheckerBuilder) { + this.declarationsCheckerBuilder = declarationsCheckerBuilder; + } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingVisitorDispatcher.java b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingVisitorDispatcher.java index 4e91eecd7ac..0b6709d5da7 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingVisitorDispatcher.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingVisitorDispatcher.java @@ -24,9 +24,7 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.diagnostics.DiagnosticUtils; import org.jetbrains.kotlin.diagnostics.Errors; import org.jetbrains.kotlin.psi.*; -import org.jetbrains.kotlin.resolve.AnnotationChecker; -import org.jetbrains.kotlin.resolve.BindingContext; -import org.jetbrains.kotlin.resolve.BindingContextUtils; +import org.jetbrains.kotlin.resolve.*; import org.jetbrains.kotlin.resolve.bindingContextUtil.BindingContextUtilsKt; import org.jetbrains.kotlin.resolve.scopes.LexicalScopeKind; import org.jetbrains.kotlin.resolve.scopes.LexicalWritableScope; @@ -87,6 +85,7 @@ public abstract class ExpressionTypingVisitorDispatcher extends KtVisitor() } diff --git a/compiler/testData/diagnostics/tests/generics/TypeParametersInTypeParameterBounds.kt b/compiler/testData/diagnostics/tests/generics/TypeParametersInTypeParameterBounds.kt index 64c747bb07d..32eafa745cf 100644 --- a/compiler/testData/diagnostics/tests/generics/TypeParametersInTypeParameterBounds.kt +++ b/compiler/testData/diagnostics/tests/generics/TypeParametersInTypeParameterBounds.kt @@ -8,5 +8,8 @@ interface A3V> where V interface A4<K, V> where K : I1, K : I2, K : C, K : V, V : I2, V : I1 fun f1() where V : K, V : K {} -fun f2() where W : K, W : V {} +fun f2() where W : K, W : V { + fun f3() where T : K, T : V {} + fun f4() where T : K, T : K {} +} fun W> f3() where W : K, W : V, W : Any {} diff --git a/compiler/testData/diagnostics/tests/implicitIntersection.kt b/compiler/testData/diagnostics/tests/implicitIntersection.kt index e636b3f199b..e3103ae5553 100644 --- a/compiler/testData/diagnostics/tests/implicitIntersection.kt +++ b/compiler/testData/diagnostics/tests/implicitIntersection.kt @@ -19,5 +19,7 @@ class My(b: B) { fun bar(b: B): String { // Ok: local variable val tmp = if (b is A && b is C) b else null + // Error: local function + fun foo(b: B) = if (b is A && b is C) b else null return tmp.toString() } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/implicitNothing.kt b/compiler/testData/diagnostics/tests/implicitNothing.kt index f0fdce761a3..68c27bb6e63 100644 --- a/compiler/testData/diagnostics/tests/implicitNothing.kt +++ b/compiler/testData/diagnostics/tests/implicitNothing.kt @@ -12,7 +12,7 @@ val y: Nothing = throw Exception() fun check() { // Error: KT-10449 - fun local() = bar() + fun local() = bar() // Unreachable / unused, but not implicit Nothing val x = null!! } diff --git a/compiler/testData/diagnostics/tests/typeParameters/deprecatedSyntax.kt b/compiler/testData/diagnostics/tests/typeParameters/deprecatedSyntax.kt index fc02f6c51d8..d1dba42ad9c 100644 --- a/compiler/testData/diagnostics/tests/typeParameters/deprecatedSyntax.kt +++ b/compiler/testData/diagnostics/tests/typeParameters/deprecatedSyntax.kt @@ -1,2 +1,3 @@ fun foo() { + fun bar() {} } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/typeParameters/misplacedConstraints.kt b/compiler/testData/diagnostics/tests/typeParameters/misplacedConstraints.kt index 512f8361b87..01347eb583a 100644 --- a/compiler/testData/diagnostics/tests/typeParameters/misplacedConstraints.kt +++ b/compiler/testData/diagnostics/tests/typeParameters/misplacedConstraints.kt @@ -1,5 +1,6 @@ class Foo<T : Cloneable> where T : Comparable { fun <U : Cloneable> foo(u: U): U where U: Comparable { + fun <T: Any> bar() where T: U {} return u } diff --git a/idea/testData/unifier/equivalence/declarations/typeParameters/boundsAndConstraints.kt b/idea/testData/unifier/equivalence/declarations/typeParameters/boundsAndConstraints.kt index 846413e3526..cc91ad7e0ec 100644 --- a/idea/testData/unifier/equivalence/declarations/typeParameters/boundsAndConstraints.kt +++ b/idea/testData/unifier/equivalence/declarations/typeParameters/boundsAndConstraints.kt @@ -1,17 +1,19 @@ +interface I + fun foo() { abstract class T - fun bar1(a: A, b: B, c: C): A where B: A, C: B, C: T = c + fun bar1(a: A, b: B, c: C): I where B: A, C: I, C: T = c - fun bar2(x: X, y: Y, z: Z): X where Z: Y, Z: T = z + fun bar2(x: X, y: Y, z: Z): I where Z: I, Z: T = z - fun bar3(x: X, y: Y, z: Z): X where Y: X, Z: T = z + fun bar3(x: X, y: Y, z: Z): T where Y: X, Z: T = z - fun bar4(x: X, y: Y, z: Z): X where Z: T = z + fun bar4(x: X, y: Y, z: Z): T where Z: T = z - fun bar5(x: X, y: Y, z: Z): X where Z: Y = z + fun bar5(x: X, y: Y, z: Z): I where Z: I = z - fun bar6(x: X, y: Y, z: Z): X where Y: X, Z: T = z + fun bar6(x: X, y: Y, z: Z): I where Y: X, Z: T = z - fun bar7(x: X, y: Y, z: Z): X where Y: X, Z: Y, Z: T = z + fun bar7(x: X, y: Y, z: Z): T where Y: I, Z: I, Z: T = z } \ No newline at end of file diff --git a/idea/testData/unifier/equivalence/declarations/typeParameters/boundsAndConstraints.kt.match b/idea/testData/unifier/equivalence/declarations/typeParameters/boundsAndConstraints.kt.match index bd7abf56b1c..001bd218617 100644 --- a/idea/testData/unifier/equivalence/declarations/typeParameters/boundsAndConstraints.kt.match +++ b/idea/testData/unifier/equivalence/declarations/typeParameters/boundsAndConstraints.kt.match @@ -1,9 +1,5 @@ -fun bar1(a: A, b: B, c: C): A where B: A, C: B, C: T = c +fun bar1(a: A, b: B, c: C): I where B: A, C: I, C: T = c -fun bar2(x: X, y: Y, z: Z): X where Z: Y, Z: T = z +fun bar2(x: X, y: Y, z: Z): I where Z: I, Z: T = z -fun bar3(x: X, y: Y, z: Z): X where Y: X, Z: T = z - -fun bar4(x: X, y: Y, z: Z): X where Z: T = z - -fun bar5(x: X, y: Y, z: Z): X where Z: Y = z +fun bar5(x: X, y: Y, z: Z): I where Z: I = z \ No newline at end of file diff --git a/libraries/stdlib/test/collections/ArraysTest.kt b/libraries/stdlib/test/collections/ArraysTest.kt index 4df225ab7da..184602195e4 100644 --- a/libraries/stdlib/test/collections/ArraysTest.kt +++ b/libraries/stdlib/test/collections/ArraysTest.kt @@ -968,7 +968,7 @@ class ArraysTest { assertTrue(arrayOf().sorted().none()) assertEquals(listOf(1), arrayOf(1).sorted()) - fun arrayData>(vararg values: T, toArray: Array.() -> A) = ArraySortedChecker(values.toArray(), naturalOrder()) + fun > arrayData(vararg values: T, toArray: Array.() -> A) = ArraySortedChecker(values.toArray(), naturalOrder()) with (arrayData("ac", "aD", "aba") { toList().toTypedArray() }) { checkSorted>({ sorted() }, { sortedDescending() }, { iterator() })