diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/callableReferences/CallableReferencesResolutionUtils.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/callableReferences/CallableReferencesResolutionUtils.kt index a02236cfebd..49337e3ba5f 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/callableReferences/CallableReferencesResolutionUtils.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/callableReferences/CallableReferencesResolutionUtils.kt @@ -22,6 +22,7 @@ import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.diagnostics.Errors.CALLABLE_REFERENCE_LHS_NOT_A_CLASS import org.jetbrains.kotlin.psi.KtCallableReferenceExpression import org.jetbrains.kotlin.psi.KtSimpleNameExpression +import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.calls.CallResolver import org.jetbrains.kotlin.resolve.calls.callResolverUtil.ResolveArgumentsMode import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext @@ -30,19 +31,14 @@ import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext import org.jetbrains.kotlin.resolve.calls.context.TemporaryTraceAndCache import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults import org.jetbrains.kotlin.resolve.calls.util.CallMaker -import org.jetbrains.kotlin.resolve.scopes.BaseLexicalScope -import org.jetbrains.kotlin.resolve.scopes.LexicalScopeKind -import org.jetbrains.kotlin.resolve.scopes.MemberScope -import org.jetbrains.kotlin.resolve.scopes.ScopeUtils +import org.jetbrains.kotlin.resolve.scopes.receivers.ClassQualifier import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver -import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue +import org.jetbrains.kotlin.resolve.scopes.receivers.Receiver import org.jetbrains.kotlin.resolve.scopes.receivers.TransientReceiver -import org.jetbrains.kotlin.resolve.scopes.utils.memberScopeAsImportingScope import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.TypeUtils import org.jetbrains.kotlin.types.expressions.DoubleColonLHS import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils -import org.jetbrains.kotlin.utils.Printer private fun ResolveArgumentsMode.acceptResolution(results: OverloadResolutionResults, trace: TemporaryTraceAndCache) { when (this) { @@ -55,7 +51,7 @@ private fun ResolveArgumentsMode.acceptResolution(resul private fun resolvePossiblyAmbiguousCallableReference( reference: KtSimpleNameExpression, - receiver: ReceiverValue?, + receiver: Receiver?, context: ResolutionContext<*>, resolutionMode: ResolveArgumentsMode, callResolver: CallResolver @@ -84,32 +80,7 @@ fun resolvePossiblyAmbiguousCallableReference( ): OverloadResolutionResults? { val reference = callableReferenceExpression.callableReference - fun resolveInScope(traceTitle: String, classifier: ClassifierDescriptor, staticScope: MemberScope): OverloadResolutionResults { - - // todo: drop this class when new resolve will be finished - class StaticScopeAsLexicalScope(val staticScope: MemberScope) : BaseLexicalScope(staticScope.memberScopeAsImportingScope(), classifier) { - override val kind: LexicalScopeKind - get() = LexicalScopeKind.CALLABLE_REFERENCE - - override fun printStructure(p: Printer) { - p.println(toString()) - } - - override fun toString(): String = "${javaClass.canonicalName} for $staticScope" - - // this method is needed for correct rewrite LEXICAL_SCOPE in trace - override fun equals(other: Any?) = other is StaticScopeAsLexicalScope && other.staticScope == staticScope - override fun hashCode() = staticScope.hashCode() - } - - val temporaryTraceAndCache = TemporaryTraceAndCache.create(context, traceTitle, reference) - val newContext = context.replaceTraceAndCache(temporaryTraceAndCache).replaceScope(StaticScopeAsLexicalScope(staticScope)) - val results = resolvePossiblyAmbiguousCallableReference(reference, null, newContext, resolutionMode, callResolver) - resolutionMode.acceptResolution(results, temporaryTraceAndCache) - return results - } - - fun resolveWithReceiver(traceTitle: String, receiver: ReceiverValue): OverloadResolutionResults { + fun resolveWithReceiver(traceTitle: String, receiver: Receiver?): OverloadResolutionResults { val temporaryTraceAndCache = TemporaryTraceAndCache.create(context, traceTitle, reference) val newContext = context.replaceTraceAndCache(temporaryTraceAndCache) val results = resolvePossiblyAmbiguousCallableReference(reference, receiver, newContext, resolutionMode, callResolver) @@ -127,14 +98,11 @@ fun resolvePossiblyAmbiguousCallableReference( return null } - val possibleStatic = resolveInScope("resolve unbound callable reference in static scope", classifier, classifier.staticScope) - if (possibleStatic.isSomething()) return possibleStatic - - val possibleNested = resolveInScope( - "resolve unbound callable reference in static nested classes scope", classifier, - ScopeUtils.getStaticNestedClassesScope(classifier) - ) - if (possibleNested.isSomething()) return possibleNested + val qualifier = context.trace.get(BindingContext.QUALIFIER, callableReferenceExpression.receiverExpression!!) + if (qualifier is ClassQualifier) { + val possibleStatic = resolveWithReceiver("resolve unbound callable reference in static scope", qualifier) + if (possibleStatic.isSomething()) return possibleStatic + } val possibleWithReceiver = resolveWithReceiver("resolve unbound callable reference with receiver", TransientReceiver(lhsType)) if (possibleWithReceiver.isSomething()) return possibleWithReceiver diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewResolutionOldInference.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewResolutionOldInference.kt index 0495a52ed9b..69d685d2486 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewResolutionOldInference.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewResolutionOldInference.kt @@ -95,8 +95,8 @@ class NewResolutionOldInference( val simpleContextF = outer.SimpleContext(scopeTower, name, context, tracing) val simpleContextV = outer.SimpleContext(scopeTower, name, context, tracing) return CompositeScopeTowerProcessor( - createFunctionProcessor(simpleContextF, explicitReceiver), - createVariableProcessor(simpleContextV, explicitReceiver) + createFunctionProcessor(simpleContextF, explicitReceiver, classValueReceiver = false), + createVariableProcessor(simpleContextV, explicitReceiver, classValueReceiver = false) ) } } diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/ScopeTowerProcessors.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/ScopeTowerProcessors.kt index 0eb6937188c..5cf3c669fcb 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/ScopeTowerProcessors.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/ScopeTowerProcessors.kt @@ -129,6 +129,7 @@ private class NoExplicitReceiverScopeTowerProcessor> createSimpleProcessor( context: TowerContext, explicitReceiver: Receiver?, + classValueReceiver: Boolean, collectCandidates: ScopeTowerLevel.(name: Name, extensionReceiver: ReceiverValue?) -> Collection> ) : ScopeTowerProcessor { if (explicitReceiver is ReceiverValue) { @@ -136,6 +137,7 @@ private fun > createSimpleProcessor( } else if (explicitReceiver is QualifierReceiver) { val qualifierProcessor = QualifierScopeTowerProcessor(context, explicitReceiver, collectCandidates) + if (!classValueReceiver) return qualifierProcessor // todo enum entry, object. val classValue = explicitReceiver.classValueReceiver ?: return qualifierProcessor @@ -152,14 +154,17 @@ private fun > createSimpleProcessor( } } -fun > createVariableProcessor(context: TowerContext, explicitReceiver: Receiver?) - = createSimpleProcessor(context, explicitReceiver, ScopeTowerLevel::getVariables) +fun > createVariableProcessor( + context: TowerContext, explicitReceiver: Receiver?, classValueReceiver: Boolean = true +) = createSimpleProcessor(context, explicitReceiver, classValueReceiver, ScopeTowerLevel::getVariables) -fun > createVariableAndObjectProcessor(context: TowerContext, explicitReceiver: Receiver?) = - CompositeScopeTowerProcessor( - createVariableProcessor(context, explicitReceiver), - createSimpleProcessor(context, explicitReceiver, ScopeTowerLevel::getObjects) - ) +fun > createVariableAndObjectProcessor( + context: TowerContext, explicitReceiver: Receiver?, classValueReceiver: Boolean = true +) = CompositeScopeTowerProcessor( + createVariableProcessor(context, explicitReceiver), + createSimpleProcessor(context, explicitReceiver, classValueReceiver, ScopeTowerLevel::getObjects) +) -fun > createFunctionProcessor(context: TowerContext, explicitReceiver: Receiver?) - = createSimpleProcessor(context, explicitReceiver, ScopeTowerLevel::getFunctions) +fun > createFunctionProcessor( + context: TowerContext, explicitReceiver: Receiver?, classValueReceiver: Boolean = true +) = createSimpleProcessor(context, explicitReceiver, classValueReceiver, ScopeTowerLevel::getFunctions) diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/scopes/FilteringScope.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/scopes/FilteringScope.kt deleted file mode 100644 index 61a432d8923..00000000000 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/scopes/FilteringScope.kt +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2010-2016 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.resolve.scopes - -import org.jetbrains.kotlin.descriptors.DeclarationDescriptor -import org.jetbrains.kotlin.incremental.components.LookupLocation -import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.utils.Printer - -class FilteringScope(private val workerScope: MemberScope, private val predicate: (DeclarationDescriptor) -> Boolean) : MemberScope { - - override fun getContributedFunctions(name: Name, location: LookupLocation) = workerScope.getContributedFunctions(name, location).filter(predicate) - - private fun filterDescriptor(descriptor: D?): D? - = if (descriptor != null && predicate(descriptor)) descriptor else null - - override fun getContributedClassifier(name: Name, location: LookupLocation) = filterDescriptor(workerScope.getContributedClassifier(name, location)) - - override fun getContributedVariables(name: Name, location: LookupLocation) = workerScope.getContributedVariables(name, location).filter(predicate) - - override fun getContributedDescriptors(kindFilter: DescriptorKindFilter, - nameFilter: (Name) -> Boolean) = workerScope.getContributedDescriptors(kindFilter, nameFilter).filter(predicate) - - override fun printScopeStructure(p: Printer) { - p.println(javaClass.simpleName, " {") - p.pushIndent() - - p.print("workerScope = ") - workerScope.printScopeStructure(p.withholdIndentOnce()) - - p.popIndent() - p.println("}") - } -} diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/scopes/ScopeUtils.java b/compiler/resolution/src/org/jetbrains/kotlin/resolve/scopes/ScopeUtils.java index fec11df4d66..60d66b47eb4 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/scopes/ScopeUtils.java +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/scopes/ScopeUtils.java @@ -20,23 +20,14 @@ import kotlin.Unit; import kotlin.jvm.functions.Function1; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.kotlin.descriptors.*; +import org.jetbrains.kotlin.descriptors.PropertyDescriptor; +import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor; +import org.jetbrains.kotlin.descriptors.VariableDescriptorWithAccessors; import org.jetbrains.kotlin.utils.Printer; public final class ScopeUtils { private ScopeUtils() {} - @NotNull - public static MemberScope getStaticNestedClassesScope(@NotNull ClassDescriptor descriptor) { - MemberScope innerClassesScope = descriptor.getUnsubstitutedInnerClassesScope(); - return new FilteringScope(innerClassesScope, new Function1() { - @Override - public Boolean invoke(DeclarationDescriptor descriptor) { - return descriptor instanceof ClassDescriptor && !((ClassDescriptor) descriptor).isInner(); - } - }); - } - public static LexicalScope makeScopeForPropertyHeader( @NotNull LexicalScope parent, @NotNull final PropertyDescriptor propertyDescriptor diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/scopes/Scopes.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/scopes/Scopes.kt index 771674cb889..606693d9d9f 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/scopes/Scopes.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/scopes/Scopes.kt @@ -39,17 +39,30 @@ interface LexicalScope: HierarchicalScope { val kind: LexicalScopeKind - companion object { - fun empty(parent: HierarchicalScope, ownerDescriptor: DeclarationDescriptor): BaseLexicalScope { - return object : BaseLexicalScope(parent, ownerDescriptor) { - override val kind: LexicalScopeKind get() = LexicalScopeKind.EMPTY + class Empty( + parent: HierarchicalScope, + override val ownerDescriptor: DeclarationDescriptor + ) : BaseHierarchicalScope(parent), LexicalScope { + override val parent: HierarchicalScope + get() = super.parent!! - override fun printStructure(p: Printer) { - p.println("Empty lexical scope with owner = $ownerDescriptor and parent = ${parent}.") - } - } + override val isOwnerDescriptorAccessibleByLabel: Boolean + get() = false + + override val implicitReceiver: ReceiverParameterDescriptor? + get() = null + + override val kind: LexicalScopeKind + get() = LexicalScopeKind.EMPTY + + override fun printStructure(p: Printer) { + p.println("Empty lexical scope with owner = $ownerDescriptor and parent = $parent") } } + + companion object { + fun empty(parent: HierarchicalScope, ownerDescriptor: DeclarationDescriptor): LexicalScope = Empty(parent, ownerDescriptor) + } } enum class LexicalScopeKind(val withLocalDescriptors: Boolean) { @@ -116,20 +129,6 @@ abstract class BaseHierarchicalScope(override val parent: HierarchicalScope?) : override fun getContributedFunctions(name: Name, location: LookupLocation): Collection = emptyList() } -abstract class BaseLexicalScope( - parent: HierarchicalScope, - override val ownerDescriptor: DeclarationDescriptor -): BaseHierarchicalScope(parent), LexicalScope { - override val parent: HierarchicalScope - get() = super.parent!! - - override val isOwnerDescriptorAccessibleByLabel: Boolean - get() = false - - override val implicitReceiver: ReceiverParameterDescriptor? - get() = null -} - abstract class BaseImportingScope(parent: ImportingScope?) : BaseHierarchicalScope(parent), ImportingScope { override val parent: ImportingScope? get() = super.parent as ImportingScope? diff --git a/compiler/testData/diagnostics/tests/callableReference/resolve/kt8596.kt b/compiler/testData/diagnostics/tests/callableReference/resolve/kt8596.kt new file mode 100644 index 00000000000..393f4b28250 --- /dev/null +++ b/compiler/testData/diagnostics/tests/callableReference/resolve/kt8596.kt @@ -0,0 +1,25 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_VARIABLE + +// KT-8596 Rewrite at slice LEXICAL_SCOPE for nested class constructor reference in an argument position + +class K { + class Nested +} + +fun foo(f: Any) {} + +fun test1() { + foo(K::Nested) +} + +// KT-10567 Error: Rewrite at slice LEXICAL_SCOPE key: REFERENCE_EXPRESSION + +class Foo(val a: String, val b: String) + +fun test2() { + val prop : Foo.() -> String = if (true) { + Foo::a + } else { + Foo::b + } +} diff --git a/compiler/testData/diagnostics/tests/callableReference/resolve/kt8596.txt b/compiler/testData/diagnostics/tests/callableReference/resolve/kt8596.txt new file mode 100644 index 00000000000..20a112cd183 --- /dev/null +++ b/compiler/testData/diagnostics/tests/callableReference/resolve/kt8596.txt @@ -0,0 +1,28 @@ +package + +public fun foo(/*0*/ f: kotlin.Any): kotlin.Unit +public fun test1(): kotlin.Unit +public fun test2(): kotlin.Unit + +public final class Foo { + public constructor Foo(/*0*/ a: kotlin.String, /*1*/ b: kotlin.String) + public final val a: kotlin.String + public final val b: kotlin.String + 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 +} + +public final class K { + public constructor K() + 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 + + public final class Nested { + public constructor Nested() + 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/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index c945bb57e74..c9655d22ebc 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -2285,6 +2285,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { doTest(fileName); } + @TestMetadata("kt8596.kt") + public void testKt8596() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/callableReference/resolve/kt8596.kt"); + doTest(fileName); + } + @TestMetadata("kt9601.kt") public void testKt9601() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/callableReference/resolve/kt9601.kt");