diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/VarianceChecker.kt b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/VarianceChecker.kt index dd0aa8a26a0..e339e9e22d8 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/VarianceChecker.kt +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/VarianceChecker.kt @@ -89,7 +89,7 @@ class VarianceChecker(private val trace: BindingTrace) { class object { platformStatic fun recordPrivateToThisIfNeeded(trace: BindingTrace, descriptor: CallableMemberDescriptor) { - if (descriptor.getVisibility() != Visibilities.PRIVATE) return + if (isIrrelevant(descriptor) || descriptor.getVisibility() != Visibilities.PRIVATE) return val psiElement = descriptor.getSource().getPsi() if (psiElement !is JetCallableDeclaration) return @@ -99,7 +99,14 @@ class VarianceChecker(private val trace: BindingTrace) { } } - private fun recordPrivateToThis(descriptor: CallableDescriptor) { + private fun isIrrelevant(descriptor: CallableDescriptor): Boolean { + val containingClass = descriptor.getContainingDeclaration() + if (containingClass !is ClassDescriptor) return true + + return containingClass.getTypeConstructor().getParameters().all { it.getVariance() == INVARIANT } + } + + private fun recordPrivateToThis(descriptor: CallableMemberDescriptor) { if (descriptor is FunctionDescriptorImpl) { descriptor.setVisibility(Visibilities.PRIVATE_TO_THIS); } @@ -120,7 +127,7 @@ class VarianceChecker(private val trace: BindingTrace) { descriptor: CallableDescriptor, diagnosticSink: DiagnosticSink ): Boolean { - if (descriptor.getContainingDeclaration() !is ClassDescriptor) return true + if (isIrrelevant(descriptor)) return true var noError = true noError = noError and declaration.checkTypeParameters(trace, IN_VARIANCE, diagnosticSink) diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/descriptors/LazyClassMemberScope.kt b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/descriptors/LazyClassMemberScope.kt index 99bb1ffc9b8..11a28ebbf6e 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/descriptors/LazyClassMemberScope.kt +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/descriptors/LazyClassMemberScope.kt @@ -185,7 +185,7 @@ public open class LazyClassMemberScope(resolveSession: ResolveSession, if (descriptor.getKind() != FAKE_OVERRIDE && descriptor.getKind() != DELEGATION) { OverridingUtil.resolveUnknownVisibilityForMember(descriptor, OverrideResolver.createCannotInferVisibilityReporter(trace)) } -// VarianceChecker.recordPrivateToThisIfNeeded(trace, descriptor); todo make visibility lazy and enable + VarianceChecker.recordPrivateToThisIfNeeded(trace, descriptor); } } diff --git a/compiler/testData/diagnostics/tests/RecursiveResolve.kt b/compiler/testData/diagnostics/tests/RecursiveResolve.kt index 119c3075eeb..e8a9c181957 100644 --- a/compiler/testData/diagnostics/tests/RecursiveResolve.kt +++ b/compiler/testData/diagnostics/tests/RecursiveResolve.kt @@ -11,4 +11,65 @@ class Test(foo: Any?, bar: Any?) { fun bar(i: Int) = 2 private fun bar2() = bar2(1) private fun bar2(i: Int) = 2 +} + +// KT-6413 Typechecker recursive problem when class have non-invariant generic parameters +class Test2(foo: Any?, bar: Any?) { + val foo = foo ?: this + private val bar = bar ?: this + private val bas = bas() + val bas2 = bas2() + + private fun bas(): Int = null!! + private fun bas2(): Int = null!! + + fun bar() = bar(1) + fun bar(i: Int) = 2 + private fun bar2() = bar2(1) + private fun bar2(i: Int) = 2 +} + +class Test3(foo: Any?, bar: Any?) { + val foo = foo ?: this + private val bar = bar ?: this + private val bas = bas() + val bas2 = bas2() + + private fun bas(): Int = null!! + private fun bas2(): Int = null!! + + fun bar() = bar(1) + fun bar(i: Int) = 2 + private fun bar2() = bar2(1) + private fun bar2(i: Int) = 2 +} + +class Test4(foo: Any?, bar: Any?) { + val foo = foo ?: this + private val bar = bar ?: this + private val bas = bas() + val bas2 = bas2() + + private fun bas(): Int = null!! + private fun bas2(): Int = null!! + + fun bar() = bar(1) + fun bar(i: Int) = 2 + private fun bar2() = bar2(1) + private fun bar2(i: Int) = 2 +} + +class Test5(foo: Any?, bar: Any?) { + val foo = foo ?: this + private val bar = bar ?: this + private val bas: Int = bas() + val bas2 = bas2() + + private fun bas(): Int = null!! + private fun bas2(): Int = null!! + + fun bar() = bar(1) + fun bar(i: Int) = 2 + private fun bar2(): Int = bar2(1) + private fun bar2(i: Int) = 2 } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/RecursiveResolve.txt b/compiler/testData/diagnostics/tests/RecursiveResolve.txt index 0aba2a88654..5724383da44 100644 --- a/compiler/testData/diagnostics/tests/RecursiveResolve.txt +++ b/compiler/testData/diagnostics/tests/RecursiveResolve.txt @@ -16,3 +16,71 @@ internal final class Test { public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String } + +internal final class Test2 { + public constructor Test2(/*0*/ foo: kotlin.Any?, /*1*/ bar: kotlin.Any?) + private final val bar: kotlin.Any + private final val bas: kotlin.Int + internal final val bas2: kotlin.Int + internal final val foo: kotlin.Any + internal final fun bar(): kotlin.Int + internal final fun bar(/*0*/ i: kotlin.Int): kotlin.Int + private final fun bar2(): kotlin.Int + private final fun bar2(/*0*/ i: kotlin.Int): kotlin.Int + private final fun bas(): kotlin.Int + private final fun bas2(): kotlin.Int + 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 +} + +internal final class Test3 { + public constructor Test3(/*0*/ foo: kotlin.Any?, /*1*/ bar: kotlin.Any?) + private final val bar: kotlin.Any + private final val bas: [ERROR : Type for bas()] + internal final val bas2: kotlin.Int + internal final val foo: kotlin.Any + internal final fun bar(): kotlin.Int + internal final fun bar(/*0*/ i: kotlin.Int): kotlin.Int + private final fun bar2(): [ERROR : Error function type] + private final fun bar2(/*0*/ i: kotlin.Int): kotlin.Int + private final fun bas(): kotlin.Int + private final fun bas2(): kotlin.Int + 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 +} + +internal final class Test4 { + public constructor Test4(/*0*/ foo: kotlin.Any?, /*1*/ bar: kotlin.Any?) + private final val bar: kotlin.Any + private final val bas: [ERROR : Type for bas()] + internal final val bas2: kotlin.Int + internal final val foo: kotlin.Any + internal final fun bar(): kotlin.Int + internal final fun bar(/*0*/ i: kotlin.Int): kotlin.Int + private final fun bar2(): [ERROR : Error function type] + private final fun bar2(/*0*/ i: kotlin.Int): kotlin.Int + private final fun bas(): kotlin.Int + private final fun bas2(): kotlin.Int + 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 +} + +internal final class Test5 { + public constructor Test5(/*0*/ foo: kotlin.Any?, /*1*/ bar: kotlin.Any?) + private final val bar: kotlin.Any + private final val bas: kotlin.Int + internal final val bas2: kotlin.Int + internal final val foo: kotlin.Any + internal final fun bar(): kotlin.Int + internal final fun bar(/*0*/ i: kotlin.Int): kotlin.Int + private final fun bar2(): kotlin.Int + private final fun bar2(/*0*/ i: kotlin.Int): kotlin.Int + private final fun bas(): kotlin.Int + private final fun bas2(): kotlin.Int + 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/testData/diagnostics/tests/regressions/Jet81.kt b/compiler/testData/diagnostics/tests/regressions/Jet81.kt index f57756e51fc..dfb6a09746b 100644 --- a/compiler/testData/diagnostics/tests/regressions/Jet81.kt +++ b/compiler/testData/diagnostics/tests/regressions/Jet81.kt @@ -18,10 +18,10 @@ class Test2 { { b + 1 } - val x = b + val x = b val y = 1 } - val b = a.x + val b = a.x val c = a.y } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/regressions/Jet81.txt b/compiler/testData/diagnostics/tests/regressions/Jet81.txt index 57e6307b95d..246f7d7c101 100644 --- a/compiler/testData/diagnostics/tests/regressions/Jet81.txt +++ b/compiler/testData/diagnostics/tests/regressions/Jet81.txt @@ -28,7 +28,7 @@ internal final class Test { internal final class Test2 { public constructor Test2() private final val a: Test2.. - internal final val b: [ERROR : Type for b] + internal final val b: [ERROR : ] internal final val c: kotlin.Int = 1 public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int