diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/MutableClassDescriptor.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/MutableClassDescriptor.java index 872cb0e9b97..669af46b9ae 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/MutableClassDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/MutableClassDescriptor.java @@ -5,7 +5,9 @@ import com.google.common.collect.Sets; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; -import org.jetbrains.jet.lang.resolve.*; +import org.jetbrains.jet.lang.resolve.AbstractScopeAdapter; +import org.jetbrains.jet.lang.resolve.BindingTrace; +import org.jetbrains.jet.lang.resolve.TraceBasedRedeclarationHandler; import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.resolve.scopes.SubstitutingScope; import org.jetbrains.jet.lang.resolve.scopes.WritableScope; @@ -43,10 +45,6 @@ public class MutableClassDescriptor extends MutableDeclarationDescriptor impleme private JetType superclassType; private ClassReceiver implicitReceiver; -// public MutableClassDescriptor(@NotNull BindingTrace trace, @NotNull DeclarationDescriptor containingDeclaration, @NotNull JetScope outerScope) { -// this(trace, containingDeclaration, outerScope, ClassKind.CLASS); -// } - public MutableClassDescriptor(@NotNull BindingTrace trace, @NotNull DeclarationDescriptor containingDeclaration, @NotNull JetScope outerScope, ClassKind kind) { super(containingDeclaration); TraceBasedRedeclarationHandler redeclarationHandler = new TraceBasedRedeclarationHandler(trace); @@ -66,6 +64,23 @@ public class MutableClassDescriptor extends MutableDeclarationDescriptor impleme } assert classObjectDescriptor.getKind() == ClassKind.OBJECT; this.classObjectDescriptor = classObjectDescriptor; + + // Members of the class object are accessible from the class + // The scope must be lazy, because classObjectDescriptor may not by fully built yet + scopeForMemberResolution.importScope(new AbstractScopeAdapter() { + @NotNull + @Override + protected JetScope getWorkerScope() { + return MutableClassDescriptor.this.classObjectDescriptor.getDefaultType().getMemberScope(); + } + + @NotNull + @Override + public ReceiverDescriptor getImplicitReceiver() { + return MutableClassDescriptor.this.classObjectDescriptor.getImplicitReceiver(); + } + } + ); return ClassObjectStatus.OK; } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/TaskPrioritizer.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/TaskPrioritizer.java index 2edca62eb75..872781fb28b 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/TaskPrioritizer.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/TaskPrioritizer.java @@ -98,8 +98,16 @@ import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor } doComputeTasks(scope, explicitReceiver, call, name, result, AutoCastService.NO_AUTO_CASTS); - ReceiverDescriptor receiverToCast = explicitReceiver.exists() ? explicitReceiver : scope.getImplicitReceiver(); - if (receiverToCast.exists()) { + List receivers; + if (explicitReceiver.exists()) { + receivers = Collections.singletonList(explicitReceiver); + } + else { + receivers = Lists.newArrayList(); + scope.getImplicitReceiversHierarchy(receivers); + } + for (ReceiverDescriptor receiverToCast : receivers) { + assert receiverToCast.exists(); doComputeTasks(scope, receiverToCast, call, name, result, new AutoCastServiceImpl(dataFlowInfo, bindingContext)); } return result; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/WritableScopeImpl.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/WritableScopeImpl.java index 81ee15a1873..37de89a17ca 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/WritableScopeImpl.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/WritableScopeImpl.java @@ -232,15 +232,6 @@ public class WritableScopeImpl extends WritableScopeWithImports { return super.getClassifier(name); } - @NotNull - @Override - public ReceiverDescriptor getImplicitReceiver() { - if (implicitReceiver == null) { - return super.getImplicitReceiver(); - } - return implicitReceiver; - } - @Override public void addNamespace(@NotNull NamespaceDescriptor namespaceDescriptor) { Map variableClassOrNamespaceDescriptors = getVariableClassOrNamespaceDescriptors(); @@ -272,6 +263,15 @@ public class WritableScopeImpl extends WritableScopeWithImports { return super.getNamespace(name); } + @NotNull + @Override + public ReceiverDescriptor getImplicitReceiver() { + if (implicitReceiver == null) { + return super.getImplicitReceiver(); + } + return implicitReceiver; + } + @Override public void setImplicitReceiver(@NotNull ReceiverDescriptor implicitReceiver) { if (this.implicitReceiver != null) { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/WritableScopeWithImports.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/WritableScopeWithImports.java index ba957519c14..97cdb1df602 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/WritableScopeWithImports.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/WritableScopeWithImports.java @@ -7,6 +7,7 @@ import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor; import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor; import org.jetbrains.jet.lang.descriptors.VariableDescriptor; +import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import java.util.ArrayList; import java.util.Collections; @@ -50,6 +51,20 @@ public abstract class WritableScopeWithImports extends JetScopeAdapter implement currentIndividualImportScope = null; } + @Override + public void getImplicitReceiversHierarchy(@NotNull List result) { + super.getImplicitReceiversHierarchy(result); + // Imported scopes come with their receivers + // Example: class member resolution scope imports a scope of it's class object + // members of the class object must be able to find it as an implicit receiver + for (JetScope scope : getImports()) { + ReceiverDescriptor definedReceiver = scope.getImplicitReceiver(); + if (definedReceiver.exists()) { + result.add(0, definedReceiver); + } + } + } + @Override public VariableDescriptor getVariable(@NotNull String name) { // Meaningful lookup goes here diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ClosureExpressionsTypingVisitor.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ClosureExpressionsTypingVisitor.java index 41f0705f6aa..8add070d296 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ClosureExpressionsTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ClosureExpressionsTypingVisitor.java @@ -111,13 +111,6 @@ public class ClosureExpressionsTypingVisitor extends ExpressionTypingVisitor { private FunctionDescriptorImpl createFunctionDescriptor(JetFunctionLiteralExpression expression, ExpressionTypingContext context, boolean functionTypeExpected) { JetFunctionLiteral functionLiteral = expression.getFunctionLiteral(); JetTypeReference receiverTypeRef = functionLiteral.getReceiverTypeRef(); - final JetType receiverType; - if (receiverTypeRef != null) { - receiverType = context.getTypeResolver().resolveType(context.scope, receiverTypeRef); - } else { - ReceiverDescriptor implicitReceiver = context.scope.getImplicitReceiver(); - receiverType = implicitReceiver.exists() ? implicitReceiver.getType() : null; - } FunctionDescriptorImpl functionDescriptor = new FunctionDescriptorImpl( context.scope.getContainingDeclaration(), Collections.emptyList(), ""); @@ -133,7 +126,7 @@ public class ClosureExpressionsTypingVisitor extends ExpressionTypingVisitor { } } else { - effectiveReceiverType = receiverType; + effectiveReceiverType = context.getTypeResolver().resolveType(context.scope, receiverTypeRef); } functionDescriptor.initialize(effectiveReceiverType, NO_RECEIVER, Collections.emptyList(), valueParameterDescriptors, null, Modality.FINAL, Visibility.LOCAL); context.trace.record(BindingContext.FUNCTION, expression, functionDescriptor); diff --git a/compiler/testData/checkerWithErrorTypes/quick/regressions/kt394.jet b/compiler/testData/checkerWithErrorTypes/quick/regressions/kt394.jet new file mode 100644 index 00000000000..8e58588f4b0 --- /dev/null +++ b/compiler/testData/checkerWithErrorTypes/quick/regressions/kt394.jet @@ -0,0 +1,11 @@ +// KT-394 Make class object members visible inside the owning class + +class X() { +// class Y {} + + class object{ + class Y() {} + } + + val y : Y = Y() +} \ No newline at end of file diff --git a/compiler/testData/checkerWithErrorTypes/quick/regressions/kt588.jet b/compiler/testData/checkerWithErrorTypes/quick/regressions/kt588.jet new file mode 100644 index 00000000000..2b4b4d86ff4 --- /dev/null +++ b/compiler/testData/checkerWithErrorTypes/quick/regressions/kt588.jet @@ -0,0 +1,12 @@ +// KT-588 Unresolved static method +class Test() : Thread("Test") { + class object { + fun init2() { + + } + } + override fun run() { + init2() // unresolved + Test.init2() // ok + } +} \ No newline at end of file