From 6ede1a342f01a39cc7f4cc38f70c714e2ec00c33 Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Tue, 20 Sep 2011 06:35:09 -0500 Subject: [PATCH] Receivers introduced to descriptors --- .../jetbrains/jet/codegen/ClassContext.java | 9 +- .../jetbrains/jet/codegen/ClosureCodegen.java | 13 +- .../jetbrains/jet/codegen/JetTypeMapper.java | 7 +- .../resolve/java/JavaClassDescriptor.java | 12 ++ .../lang/descriptors/CallableDescriptor.java | 7 +- .../jet/lang/descriptors/ClassDescriptor.java | 4 + .../lang/descriptors/ClassDescriptorImpl.java | 12 ++ .../descriptors/FunctionDescriptorImpl.java | 18 +- .../descriptors/FunctionDescriptorUtil.java | 11 +- .../LazySubstitutingClassDescriptor.java | 7 + .../descriptors/MutableClassDescriptor.java | 11 ++ .../PropertyAccessorDescriptor.java | 7 + .../lang/descriptors/PropertyDescriptor.java | 15 +- .../descriptors/PropertyGetterDescriptor.java | 6 +- .../descriptors/PropertySetterDescriptor.java | 6 +- .../descriptors/VariableDescriptorImpl.java | 6 +- .../jet/lang/resolve/AnnotationResolver.java | 3 +- .../jet/lang/resolve/BindingContext.java | 3 + .../jet/lang/resolve/BodyResolver.java | 13 +- .../jet/lang/resolve/DescriptorUtils.java | 4 +- .../jet/lang/resolve/calls/CallResolver.java | 158 +++++++----------- .../calls/OverloadingConflictResolver.java | 9 +- .../lang/resolve/calls/ResolutionTask.java | 18 +- .../lang/resolve/calls/TaskPrioritizer.java | 44 +++-- .../lang/resolve/calls/TracingStrategy.java | 10 +- .../lang/resolve/scopes/WritableScope.java | 4 +- .../resolve/scopes/WritableScopeImpl.java | 7 +- .../resolve/scopes/WriteThroughScope.java | 3 +- .../receivers/AbstractReceiverDescriptor.java | 26 +++ .../scopes/receivers/ExplicitReceiver.java | 22 --- .../scopes/receivers/ExpressionReceiver.java | 23 +++ .../receivers/ExtensionCallableReceiver.java | 13 -- .../scopes/receivers/ExtensionReceiver.java | 15 ++ .../receivers/ImplicitReceiverDescriptor.java | 13 +- .../scopes/receivers/ReceiverDescriptor.java | 14 +- .../scopes/receivers/TransientReceiver.java | 16 ++ .../jet/lang/types/JetTypeInferrer.java | 154 +++++++++-------- .../jet/resolve/DescriptorRenderer.java | 20 ++- .../quick/AutoCreatedIt.jet | 2 +- .../jetbrains/jet/resolve/JetResolveTest.java | 4 +- .../jet/types/JetTypeCheckerTest.java | 6 +- 41 files changed, 431 insertions(+), 324 deletions(-) create mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/receivers/AbstractReceiverDescriptor.java delete mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/receivers/ExplicitReceiver.java create mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/receivers/ExpressionReceiver.java delete mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/receivers/ExtensionCallableReceiver.java create mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/receivers/ExtensionReceiver.java create mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/receivers/TransientReceiver.java diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ClassContext.java b/compiler/backend/src/org/jetbrains/jet/codegen/ClassContext.java index 837c899c41a..81d06bf4ea8 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ClassContext.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ClassContext.java @@ -7,6 +7,7 @@ import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor; +import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import org.jetbrains.jet.lang.types.JetType; import org.objectweb.asm.Type; import org.objectweb.asm.commons.InstructionAdapter; @@ -72,7 +73,7 @@ public class ClassContext { thisIdx++; } - final boolean hasReceiver = descriptor.getReceiverType() != null; + final boolean hasReceiver = descriptor.getReceiver().exists(); if (hasReceiver) { thisIdx++; } @@ -102,12 +103,12 @@ public class ClassContext { return frameMap; } - private JetType receiverType() { - return contextType instanceof FunctionDescriptor ? ((FunctionDescriptor) contextType).getReceiverType() : null; + private ReceiverDescriptor receiver() { + return contextType instanceof FunctionDescriptor ? ((FunctionDescriptor) contextType).getReceiver() : ReceiverDescriptor.NO_RECEIVER; } private boolean hasReceiver() { - return receiverType() != null; + return receiver().exists(); } public ClassContext getParentContext() { diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java index 4de5e2ff34a..864111bee96 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java @@ -11,6 +11,7 @@ import org.jetbrains.jet.lang.descriptors.VariableDescriptor; import org.jetbrains.jet.lang.psi.JetFunctionLiteral; import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression; import org.jetbrains.jet.lang.resolve.BindingContext; +import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import org.jetbrains.jet.lang.types.JetType; import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.MethodVisitor; @@ -41,7 +42,7 @@ public class ClosureCodegen { } public static Method erasedInvokeSignature(FunctionDescriptor fd) { - boolean isExtensionFunction = fd.getReceiverType() != null; + boolean isExtensionFunction = fd.getReceiver().exists(); int paramCount = fd.getValueParameters().size(); if (isExtensionFunction) { paramCount++; @@ -150,11 +151,11 @@ public class ClosureCodegen { iv.load(0, Type.getObjectType(className)); - final JetType receiverType = funDescriptor.getReceiverType(); + final ReceiverDescriptor receiver = funDescriptor.getReceiver(); int count = 1; - if (receiverType != null) { + if (receiver.exists()) { StackValue.local(count, JetTypeMapper.TYPE_OBJECT).put(JetTypeMapper.TYPE_OBJECT, iv); - StackValue.onStack(JetTypeMapper.TYPE_OBJECT).upcast(state.getTypeMapper().mapType(receiverType), iv); + StackValue.onStack(JetTypeMapper.TYPE_OBJECT).upcast(state.getTypeMapper().mapType(receiver.getType()), iv); count++; } @@ -228,7 +229,7 @@ public class ClosureCodegen { public static String getInternalClassName(FunctionDescriptor descriptor) { final int paramCount = descriptor.getValueParameters().size(); - if (descriptor.getReceiverType() != null) { + if (descriptor.getReceiver().exists()) { return "jet/ExtensionFunction" + paramCount; } else { @@ -249,7 +250,7 @@ public class ClosureCodegen { Method descriptor = erasedInvokeSignature(fd); String owner = getInternalClassName(fd); final CallableMethod result = new CallableMethod(owner, descriptor, Opcodes.INVOKEVIRTUAL, Arrays.asList(descriptor.getArgumentTypes())); - if (fd.getReceiverType() != null) { + if (fd.getReceiver().exists()) { result.setNeedsReceiver(null); } result.requestGenerateCallee(Type.getObjectType(getInternalClassName(fd))); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java b/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java index e014f057e38..c44f54556af 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java @@ -9,6 +9,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.BindingContext; +import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import org.jetbrains.jet.lang.types.*; import org.jetbrains.jet.lexer.JetTokens; import org.jetbrains.jet.resolve.DescriptorRenderer; @@ -514,11 +515,11 @@ public class JetTypeMapper { } public Method mapSignature(String name, FunctionDescriptor f) { - final JetType receiverType = f.getReceiverType(); + final ReceiverDescriptor receiver = f.getReceiver(); final List parameters = f.getValueParameters(); List parameterTypes = new ArrayList(); - if (receiverType != null) { - parameterTypes.add(mapType(receiverType)); + if (receiver.exists()) { + parameterTypes.add(mapType(receiver.getType())); } for (ValueParameterDescriptor parameter : parameters) { parameterTypes.add(mapType(parameter.getOutType())); diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaClassDescriptor.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaClassDescriptor.java index 680d984b1e7..cad5c8890bb 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaClassDescriptor.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaClassDescriptor.java @@ -5,6 +5,8 @@ import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.resolve.scopes.SubstitutingScope; +import org.jetbrains.jet.lang.resolve.scopes.receivers.ClassReceiver; +import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import org.jetbrains.jet.lang.types.*; import java.util.Collections; @@ -23,6 +25,7 @@ public class JavaClassDescriptor extends MutableDeclarationDescriptor implements private Modality modality; private JetType superclassType; private final ClassKind kind; + private ClassReceiver implicitReceiver; public JavaClassDescriptor(DeclarationDescriptor containingDeclaration, @NotNull ClassKind kind) { @@ -155,4 +158,13 @@ public class JavaClassDescriptor extends MutableDeclarationDescriptor implements public String toString() { return "java class " + typeConstructor; } + + @NotNull + @Override + public ReceiverDescriptor getImplicitReceiver() { + if (implicitReceiver == null) { + implicitReceiver = new ClassReceiver(this); + } + return implicitReceiver; + } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/CallableDescriptor.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/CallableDescriptor.java index d263169649a..47eac9f2bee 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/CallableDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/CallableDescriptor.java @@ -1,7 +1,8 @@ package org.jetbrains.jet.lang.descriptors; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.resolve.scopes.receivers.ImplicitReceiverDescriptor; +import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.TypeSubstitutor; @@ -12,8 +13,8 @@ import java.util.Set; * @author abreslav */ public interface CallableDescriptor extends DeclarationDescriptor { - @Nullable - JetType getReceiverType(); + @NotNull + ReceiverDescriptor getReceiver(); @NotNull List getTypeParameters(); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/ClassDescriptor.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/ClassDescriptor.java index efb8efb0995..5d0f349f42c 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/ClassDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/ClassDescriptor.java @@ -3,6 +3,7 @@ package org.jetbrains.jet.lang.descriptors; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.resolve.scopes.JetScope; +import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.TypeProjection; import org.jetbrains.jet.lang.types.TypeSubstitutor; @@ -53,4 +54,7 @@ public interface ClassDescriptor extends ClassifierDescriptor { @NotNull Modality getModality(); + + @NotNull + ReceiverDescriptor getImplicitReceiver(); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/ClassDescriptorImpl.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/ClassDescriptorImpl.java index 484382ba987..77fe77579ac 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/ClassDescriptorImpl.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/ClassDescriptorImpl.java @@ -5,6 +5,8 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.resolve.scopes.SubstitutingScope; +import org.jetbrains.jet.lang.resolve.scopes.receivers.ClassReceiver; +import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import org.jetbrains.jet.lang.types.*; import java.util.Collection; @@ -21,6 +23,7 @@ public class ClassDescriptorImpl extends DeclarationDescriptorImpl implements Cl private FunctionGroup constructors; private ConstructorDescriptor primaryConstructor; private JetType superclassType; + private ReceiverDescriptor implicitReceiver; public ClassDescriptorImpl( @NotNull DeclarationDescriptor containingDeclaration, @@ -151,4 +154,13 @@ public class ClassDescriptorImpl extends DeclarationDescriptorImpl implements Cl public Modality getModality() { return Modality.FINAL; } + + @NotNull + @Override + public ReceiverDescriptor getImplicitReceiver() { + if (implicitReceiver == null) { + implicitReceiver = new ClassReceiver(this); + } + return implicitReceiver; + } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/FunctionDescriptorImpl.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/FunctionDescriptorImpl.java index b7d7d353d2b..ff2fc69b585 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/FunctionDescriptorImpl.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/FunctionDescriptorImpl.java @@ -5,6 +5,8 @@ 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.scopes.receivers.ExtensionReceiver; +import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import org.jetbrains.jet.lang.types.DescriptorSubstitutor; import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.TypeSubstitutor; @@ -13,6 +15,8 @@ import org.jetbrains.jet.lang.types.Variance; import java.util.List; import java.util.Set; +import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor.NO_RECEIVER; + /** * @author abreslav */ @@ -21,7 +25,7 @@ public class FunctionDescriptorImpl extends DeclarationDescriptorImpl implements private List typeParameters; private List unsubstitutedValueParameters; private JetType unsubstitutedReturnType; - private JetType receiverType; + private ReceiverDescriptor receiver; private Modality modality; private final Set overriddenFunctions = Sets.newLinkedHashSet(); @@ -49,11 +53,11 @@ public class FunctionDescriptorImpl extends DeclarationDescriptorImpl implements @NotNull List unsubstitutedValueParameters, @Nullable JetType unsubstitutedReturnType, @Nullable Modality modality) { - this.receiverType = receiverType; this.typeParameters = typeParameters; this.unsubstitutedValueParameters = unsubstitutedValueParameters; this.unsubstitutedReturnType = unsubstitutedReturnType; this.modality = modality; + this.receiver = receiverType == null ? NO_RECEIVER : new ExtensionReceiver(this, receiverType); return this; } @@ -61,9 +65,10 @@ public class FunctionDescriptorImpl extends DeclarationDescriptorImpl implements this.unsubstitutedReturnType = unsubstitutedReturnType; } + @NotNull @Override - public JetType getReceiverType() { - return receiverType; + public ReceiverDescriptor getReceiver() { + return receiver; } @NotNull @@ -116,10 +121,9 @@ public class FunctionDescriptorImpl extends DeclarationDescriptorImpl implements List substitutedTypeParameters = Lists.newArrayList(); TypeSubstitutor substitutor = DescriptorSubstitutor.substituteTypeParameters(getTypeParameters(), originalSubstitutor, substitutedDescriptor, substitutedTypeParameters); - JetType receiverType = getReceiverType(); JetType substitutedReceiverType = null; - if (receiverType != null) { - substitutedReceiverType = substitutor.substitute(receiverType, Variance.IN_VARIANCE); + if (receiver != NO_RECEIVER) { + substitutedReceiverType = substitutor.substitute(getReceiver().getType(), Variance.IN_VARIANCE); if (substitutedReceiverType == null) { return null; } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/FunctionDescriptorUtil.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/FunctionDescriptorUtil.java index 00dc4d2f7a3..04bd0dcd6ca 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/FunctionDescriptorUtil.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/FunctionDescriptorUtil.java @@ -5,11 +5,12 @@ import com.google.common.collect.HashBiMap; import com.google.common.collect.Maps; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.jet.lang.resolve.*; +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.WritableScope; import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl; -import org.jetbrains.jet.lang.resolve.scopes.receivers.ExtensionCallableReceiver; +import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import org.jetbrains.jet.lang.types.*; import java.util.*; @@ -97,9 +98,9 @@ public class FunctionDescriptorUtil { @NotNull public static JetScope getFunctionInnerScope(@NotNull JetScope outerScope, @NotNull FunctionDescriptor descriptor, @NotNull BindingTrace trace) { WritableScope parameterScope = new WritableScopeImpl(outerScope, descriptor, new TraceBasedRedeclarationHandler(trace)).setDebugName("Function inner scope"); - JetType receiverType = descriptor.getReceiverType(); - if (receiverType != null) { - parameterScope.setImplicitReceiver(new ExtensionCallableReceiver(descriptor)); + ReceiverDescriptor receiver = descriptor.getReceiver(); + if (receiver.exists()) { + parameterScope.setImplicitReceiver(receiver); } for (TypeParameterDescriptor typeParameter : descriptor.getTypeParameters()) { parameterScope.addTypeParameterDescriptor(typeParameter); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/LazySubstitutingClassDescriptor.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/LazySubstitutingClassDescriptor.java index 86b70a0dcf5..2c1f3e8bca4 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/LazySubstitutingClassDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/LazySubstitutingClassDescriptor.java @@ -5,6 +5,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.resolve.scopes.SubstitutingScope; +import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import org.jetbrains.jet.lang.types.*; import java.util.Collection; @@ -94,6 +95,12 @@ public class LazySubstitutingClassDescriptor implements ClassDescriptor { throw new UnsupportedOperationException(); // TODO } + @NotNull + @Override + public ReceiverDescriptor getImplicitReceiver() { + throw new UnsupportedOperationException(); // TODO + } + @NotNull @Override public FunctionGroup getConstructors() { 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 5768910bd25..cf2103f43bf 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/MutableClassDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/MutableClassDescriptor.java @@ -11,6 +11,7 @@ import org.jetbrains.jet.lang.resolve.scopes.SubstitutingScope; import org.jetbrains.jet.lang.resolve.scopes.WritableScope; import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl; import org.jetbrains.jet.lang.resolve.scopes.receivers.ClassReceiver; +import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import org.jetbrains.jet.lang.types.*; import org.jetbrains.jet.resolve.DescriptorRenderer; @@ -38,6 +39,7 @@ public class MutableClassDescriptor extends MutableDeclarationDescriptor impleme private JetType defaultType; private final ClassKind kind; private JetType superclassType; + private ClassReceiver implicitReceiver; // public MutableClassDescriptor(@NotNull BindingTrace trace, @NotNull DeclarationDescriptor containingDeclaration, @NotNull JetScope outerScope) { // this(trace, containingDeclaration, outerScope, ClassKind.CLASS); @@ -293,4 +295,13 @@ public class MutableClassDescriptor extends MutableDeclarationDescriptor impleme public Collection getSupertypes() { return supertypes; } + + @NotNull + @Override + public ReceiverDescriptor getImplicitReceiver() { + if (implicitReceiver == null) { + implicitReceiver = new ClassReceiver(this); + } + return implicitReceiver; + } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/PropertyAccessorDescriptor.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/PropertyAccessorDescriptor.java index 8ed128622d4..7d477fe72b7 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/PropertyAccessorDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/PropertyAccessorDescriptor.java @@ -15,6 +15,7 @@ public abstract class PropertyAccessorDescriptor extends DeclarationDescriptorIm private final boolean hasBody; private final boolean isDefault; private final Modality modality; + private final PropertyDescriptor correspondingProperty; protected PropertyAccessorDescriptor( @NotNull Modality modality, @@ -24,6 +25,7 @@ public abstract class PropertyAccessorDescriptor extends DeclarationDescriptorIm boolean hasBody, boolean isDefault) { super(correspondingProperty.getContainingDeclaration(), annotations, name); + this.correspondingProperty = correspondingProperty; this.modality = modality; this.hasBody = hasBody; this.isDefault = isDefault; @@ -60,4 +62,9 @@ public abstract class PropertyAccessorDescriptor extends DeclarationDescriptorIm public Modality getModality() { return modality; } + + @NotNull + public PropertyDescriptor getCorrespondingProperty() { + return correspondingProperty; + } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/PropertyDescriptor.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/PropertyDescriptor.java index a8b134f1032..b303150e166 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/PropertyDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/PropertyDescriptor.java @@ -4,6 +4,8 @@ import com.google.common.collect.Lists; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; +import org.jetbrains.jet.lang.resolve.scopes.receivers.ExtensionReceiver; +import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.TypeSubstitutor; import org.jetbrains.jet.lang.types.Variance; @@ -17,7 +19,7 @@ public class PropertyDescriptor extends VariableDescriptorImpl implements Member private final Modality modality; private final boolean isVar; - private final JetType receiverType; + private final ReceiverDescriptor receiver; private final List typeParemeters = Lists.newArrayListWithCapacity(0); private final PropertyDescriptor original; private PropertyGetterDescriptor getter; @@ -38,7 +40,7 @@ public class PropertyDescriptor extends VariableDescriptorImpl implements Member // assert outType != null; this.isVar = isVar; this.modality = modality; - this.receiverType = receiverType; + this.receiver = receiverType == null ? ReceiverDescriptor.NO_RECEIVER : new ExtensionReceiver(this, receiverType); this.original = original == null ? this : original.getOriginal(); } @@ -83,9 +85,9 @@ public class PropertyDescriptor extends VariableDescriptorImpl implements Member return typeParemeters; } - @Nullable - public JetType getReceiverType() { - return receiverType; + @NotNull + public ReceiverDescriptor getReceiver() { + return receiver; } @NotNull @@ -125,10 +127,9 @@ public class PropertyDescriptor extends VariableDescriptorImpl implements Member if (inType == null && outType == null) { return null; // TODO : tell the user that the property was projected out } - JetType receiverType = getReceiverType(); return new PropertyDescriptor( this, - receiverType == null ? null : substitutor.substitute(receiverType, Variance.IN_VARIANCE), + receiver.exists() ? substitutor.substitute(receiver.getType(), Variance.IN_VARIANCE) : null, inType, outType ); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/PropertyGetterDescriptor.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/PropertyGetterDescriptor.java index 7034626fe50..2e54e868dac 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/PropertyGetterDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/PropertyGetterDescriptor.java @@ -4,6 +4,7 @@ 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.scopes.receivers.ReceiverDescriptor; import org.jetbrains.jet.lang.types.JetType; import java.util.Collections; @@ -32,9 +33,10 @@ public class PropertyGetterDescriptor extends PropertyAccessorDescriptor { overriddenGetters.add(overriddenGetter); } + @NotNull @Override - public JetType getReceiverType() { - return null; // TODO + public ReceiverDescriptor getReceiver() { + return getCorrespondingProperty().getReceiver(); } @NotNull diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/PropertySetterDescriptor.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/PropertySetterDescriptor.java index 94a3774ff74..ae28522affb 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/PropertySetterDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/PropertySetterDescriptor.java @@ -3,6 +3,7 @@ package org.jetbrains.jet.lang.descriptors; import com.google.common.collect.Sets; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; +import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import org.jetbrains.jet.lang.types.JetStandardClasses; import org.jetbrains.jet.lang.types.JetType; @@ -41,9 +42,10 @@ public class PropertySetterDescriptor extends PropertyAccessorDescriptor { overriddenSetters.add(overriddenSetter); } + @NotNull @Override - public JetType getReceiverType() { - return null; // TODO + public ReceiverDescriptor getReceiver() { + return getCorrespondingProperty().getReceiver(); } @NotNull diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/VariableDescriptorImpl.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/VariableDescriptorImpl.java index 3807447cddc..c941fae9605 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/VariableDescriptorImpl.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/VariableDescriptorImpl.java @@ -3,6 +3,7 @@ package org.jetbrains.jet.lang.descriptors; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; +import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import org.jetbrains.jet.lang.types.JetType; import java.util.Collections; @@ -71,9 +72,10 @@ public abstract class VariableDescriptorImpl extends DeclarationDescriptorImpl i return Collections.emptyList(); } + @NotNull @Override - public JetType getReceiverType() { - return null; + public ReceiverDescriptor getReceiver() { + return ReceiverDescriptor.NO_RECEIVER; } @NotNull diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnnotationResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnnotationResolver.java index ba70a94aee1..813118617a6 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnnotationResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnnotationResolver.java @@ -11,6 +11,7 @@ import org.jetbrains.jet.lang.psi.JetExpression; import org.jetbrains.jet.lang.psi.JetModifierList; import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; import org.jetbrains.jet.lang.resolve.scopes.JetScope; +import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import org.jetbrains.jet.lang.types.ErrorUtils; import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.JetTypeInferrer; @@ -46,7 +47,7 @@ public class AnnotationResolver { } public void resolveAnnotationStub(@NotNull JetScope scope, @NotNull JetAnnotationEntry entryElement, @NotNull AnnotationDescriptor descriptor) { - JetType jetType = typeInferrer.getCallResolver().resolveCall(trace, scope, null, entryElement, NO_EXPECTED_TYPE); + JetType jetType = typeInferrer.getCallResolver().resolveCall(trace, scope, ReceiverDescriptor.NO_RECEIVER, entryElement, NO_EXPECTED_TYPE); descriptor.setAnnotationType(jetType == null ? ErrorUtils.createErrorType("Unresolved annotation type") : jetType); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContext.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContext.java index b9f7086b750..ec82ca8b18a 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContext.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContext.java @@ -8,6 +8,7 @@ import org.jetbrains.jet.lang.diagnostics.Diagnostic; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; import org.jetbrains.jet.lang.resolve.scopes.JetScope; +import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.util.slicedmap.*; @@ -17,6 +18,8 @@ import java.util.Collection; * @author abreslav */ public interface BindingContext { + WritableSlice RECEIVER = Slices.createSimpleSlice("RECEIVER"); + WritableSlice ANNOTATION = Slices.createSimpleSlice("ANNOTATION"); WritableSlice> COMPILE_TIME_VALUE = Slices.createSimpleSlice("COMPILE_TIME_VALUE"); WritableSlice TYPE = Slices.createSimpleSlice("TYPE"); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BodyResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BodyResolver.java index 64ceb724c88..d15e9f5859b 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BodyResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BodyResolver.java @@ -13,8 +13,7 @@ import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.resolve.scopes.WritableScope; import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl; -import org.jetbrains.jet.lang.resolve.scopes.receivers.ClassReceiver; -import org.jetbrains.jet.lang.resolve.scopes.receivers.ExtensionCallableReceiver; +import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import org.jetbrains.jet.lang.types.*; import org.jetbrains.jet.lexer.JetTokens; import org.jetbrains.jet.util.slicedmap.WritableSlice; @@ -276,7 +275,7 @@ public class BodyResolver { JetTypeReference typeReference = call.getTypeReference(); if (typeReference != null) { if (descriptor.getUnsubstitutedPrimaryConstructor() != null) { - JetType supertype = typeInferrer.getCallResolver().resolveCall(context.getTrace(), scopeForConstructor, null, call, NO_EXPECTED_TYPE); + JetType supertype = typeInferrer.getCallResolver().resolveCall(context.getTrace(), scopeForConstructor, ReceiverDescriptor.NO_RECEIVER, call, NO_EXPECTED_TYPE); if (supertype != null) { recordSupertype(typeReference, supertype); ClassDescriptor classDescriptor = TypeUtils.getClassDescriptor(supertype); @@ -461,7 +460,7 @@ public class BodyResolver { typeInferrerForInitializers.getCallResolver().resolveCall(context.getTrace(), functionInnerScope, - null, call, NO_EXPECTED_TYPE); + ReceiverDescriptor.NO_RECEIVER, call, NO_EXPECTED_TYPE); // call.getThisReference(), // classDescriptor, // classDescriptor.getDefaultType(), @@ -576,9 +575,9 @@ public class BodyResolver { for (TypeParameterDescriptor typeParameterDescriptor : propertyDescriptor.getTypeParameters()) { result.addTypeParameterDescriptor(typeParameterDescriptor); } - JetType receiverType = propertyDescriptor.getReceiverType(); - if (receiverType != null) { - result.setImplicitReceiver(new ExtensionCallableReceiver(propertyDescriptor)); + ReceiverDescriptor receiver = propertyDescriptor.getReceiver(); + if (receiver.exists()) { + result.setImplicitReceiver(receiver); } return result; } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java index 1aaeaecf64f..cd8bdea4078 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java @@ -21,7 +21,7 @@ public class DescriptorUtils { @Override public Boolean visitFunctionDescriptor(FunctionDescriptor descriptor, Void data) { - return descriptor.getReceiverType() != null; + return descriptor.getReceiver().exists(); } @Override @@ -31,7 +31,7 @@ public class DescriptorUtils { @Override public Boolean visitPropertyDescriptor(PropertyDescriptor descriptor, Void data) { - return descriptor.getReceiverType() != null; + return descriptor.getReceiver().exists(); } }, null); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java index 5a8af24287b..3746bf6bba7 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java @@ -13,6 +13,7 @@ import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.*; import org.jetbrains.jet.lang.resolve.scopes.JetScope; +import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import org.jetbrains.jet.lang.types.*; import org.jetbrains.jet.lang.types.inference.ConstraintSystem; @@ -20,7 +21,9 @@ import java.util.*; import static org.jetbrains.jet.lang.diagnostics.Errors.*; import static org.jetbrains.jet.lang.resolve.BindingContext.AMBIGUOUS_REFERENCE_TARGET; +import static org.jetbrains.jet.lang.resolve.BindingContext.RECEIVER; import static org.jetbrains.jet.lang.resolve.BindingContext.REFERENCE_TARGET; +import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor.NO_RECEIVER; import static org.jetbrains.jet.lang.types.JetTypeInferrer.NO_EXPECTED_TYPE; /** @@ -42,11 +45,11 @@ public class CallResolver { public VariableDescriptor resolveSimpleProperty( @NotNull BindingTrace trace, @NotNull JetScope scope, - @Nullable JetType receiverType, + @NotNull ReceiverDescriptor receiver, @NotNull final JetSimpleNameExpression nameExpression, @NotNull JetType expectedType) { Call call = CallMaker.makePropertyCall(nameExpression); - List> prioritizedTasks = PROPERTY_TASK_PRIORITIZER.computePrioritizedTasks(scope, receiverType, call, nameExpression.getReferencedName()); + List> prioritizedTasks = PROPERTY_TASK_PRIORITIZER.computePrioritizedTasks(scope, receiver, call, nameExpression.getReferencedName()); return resolveCallToDescriptor(trace, scope, call, nameExpression.getNode(), expectedType, prioritizedTasks, nameExpression); } @@ -55,11 +58,11 @@ public class CallResolver { public JetType resolveCall( @NotNull BindingTrace trace, @NotNull JetScope scope, - @Nullable JetType receiverType, + @NotNull ReceiverDescriptor receiver, @NotNull JetCallElement call, @NotNull JetType expectedType ) { - FunctionDescriptor functionDescriptor = resolveSimpleCallToFunctionDescriptor(trace, scope, receiverType, call, expectedType); + FunctionDescriptor functionDescriptor = resolveSimpleCallToFunctionDescriptor(trace, scope, receiver, call, expectedType); return functionDescriptor == null ? null : functionDescriptor.getReturnType(); } @@ -70,11 +73,11 @@ public class CallResolver { @NotNull final Call call, @NotNull final JetReferenceExpression functionReference, @NotNull String name, - @Nullable JetType receiverType, + @NotNull ReceiverDescriptor receiver, @NotNull JetType expectedType) { // TODO : autocasts // TODO : nullability - List> tasks = FUNCTION_TASK_PRIORITIZER.computePrioritizedTasks(scope, receiverType, call, name); + List> tasks = FUNCTION_TASK_PRIORITIZER.computePrioritizedTasks(scope, receiver, call, name); return resolveCallToDescriptor(trace, scope, call, functionReference.getNode(), expectedType, tasks, functionReference); } @@ -82,7 +85,7 @@ public class CallResolver { public FunctionDescriptor resolveSimpleCallToFunctionDescriptor( @NotNull BindingTrace trace, @NotNull JetScope scope, - @Nullable JetType receiverType, + @NotNull ReceiverDescriptor receiver, @NotNull final JetCallElement call, @NotNull JetType expectedType ) { @@ -97,7 +100,7 @@ public class CallResolver { String name = expression.getReferencedName(); if (name == null) return checkArgumentTypesAndFail(trace, scope, call); - prioritizedTasks = FUNCTION_TASK_PRIORITIZER.computePrioritizedTasks(scope, receiverType, call, name); + prioritizedTasks = FUNCTION_TASK_PRIORITIZER.computePrioritizedTasks(scope, receiver, call, name); ResolutionTask.DescriptorCheckStrategy abstractConstructorCheck = new ResolutionTask.DescriptorCheckStrategy() { @Override public boolean performAdvancedChecks(D descriptor, BindingTrace trace, TracingStrategy tracing) { @@ -120,7 +123,7 @@ public class CallResolver { JetValueArgumentList valueArgumentList = call.getValueArgumentList(); ASTNode reportAbsenceOn = valueArgumentList == null ? call.getNode() : valueArgumentList.getNode(); if (calleeExpression instanceof JetConstructorCalleeExpression) { - assert receiverType == null; + assert receiver == NO_RECEIVER; prioritizedTasks = Lists.newArrayList(); @@ -141,7 +144,7 @@ public class CallResolver { trace.report(NO_CONSTRUCTOR.on(reportAbsenceOn)); return checkArgumentTypesAndFail(trace, scope, call); } - prioritizedTasks.add(new ResolutionTask(constructors, null, call)); + prioritizedTasks.add(new ResolutionTask(constructors, NO_RECEIVER, call)); } else { // trace.getErrorHandler().genericError(calleeExpression.getNode(), "Not a class"); @@ -162,7 +165,7 @@ public class CallResolver { trace.report(NO_CONSTRUCTOR.on(reportAbsenceOn)); return checkArgumentTypesAndFail(trace, scope, call); } - prioritizedTasks = Collections.singletonList(new ResolutionTask(constructors, null, call)); + prioritizedTasks = Collections.singletonList(new ResolutionTask(constructors, NO_RECEIVER, call)); } else { throw new UnsupportedOperationException("Type argument inference not implemented for " + call.getText()); @@ -190,45 +193,11 @@ public class CallResolver { OverloadResolutionResult resultForFirstNonemptyCandidateSet = null; TracingStrategy tracing = new TracingStrategy() { @Override - public void bindReference(@NotNull BindingTrace trace, @NotNull CallableDescriptor descriptor) { + public void bindReference(@NotNull BindingTrace trace, @NotNull ReceiverDescriptor receiver, @NotNull CallableDescriptor descriptor) { trace.record(REFERENCE_TARGET, reference, descriptor); + trace.record(RECEIVER, reference, receiver); } -// public void reportOverallResolutionError(@NotNull BindingTrace trace, @NotNull String message) { -// trace.getErrorHandler().genericError(callNode, message); -// } -// -// public void reportWrongTypeArguments(@NotNull BindingTrace trace, @NotNull String message) { -// JetTypeArgumentList typeArgumentList = call.getTypeArgumentList(); -// if (typeArgumentList != null) { -// trace.getErrorHandler().genericError(typeArgumentList.getNode(), message); -// } -// else { -// reportOverallResolutionError(trace, message); -// } -// } -// -// public void reportWrongValueArguments(@NotNull BindingTrace trace, @NotNull String message) { -// ASTNode node; -// -// JetValueArgumentList valueArgumentList = call.getValueArgumentList(); -// if (valueArgumentList != null) { -// node = valueArgumentList.getNode(); -// } -// else if (!call.getFunctionLiteralArguments().isEmpty()) { -// node = call.getFunctionLiteralArguments().get(0).getNode(); -// } -// else { -// node = callNode; -// } -// -// trace.getErrorHandler().genericError(node, message); -// } -// -// public void reportErrorOnReference(BindingTrace trace, String message) { -// trace.getErrorHandler().genericError(reference.getNode(), message); -// } - @Override public void recordAmbiguity(BindingTrace trace, Collection candidates) { trace.record(AMBIGUOUS_REFERENCE_TARGET, reference, candidates); @@ -257,8 +226,8 @@ public class CallResolver { } @Override - public void missingReceiver(@NotNull BindingTrace trace, @NotNull JetType candidateReceiverType) { - trace.report(MISSING_RECEIVER.on(reference, candidateReceiverType)); + public void missingReceiver(@NotNull BindingTrace trace, @NotNull ReceiverDescriptor expectedReceiver) { + trace.report(MISSING_RECEIVER.on(reference, expectedReceiver.getType())); } @Override @@ -340,7 +309,7 @@ public class CallResolver { traces.put(candidate, temporaryTrace); JetTypeInferrer.Services temporaryServices = typeInferrer.getServices(temporaryTrace); - tracing.bindReference(temporaryTrace, candidate); + tracing.bindReference(temporaryTrace, task.getReceiver(), candidate); if (ErrorUtils.isError(candidate)) { successfulCandidates.put(candidate, candidate); @@ -394,10 +363,10 @@ public class CallResolver { checkReceiverAbsence(task, tracing, candidate, temporaryTrace); // Error is already reported if something is missing - JetType receiverType = task.getReceiverType(); - JetType candidateReceiverType = candidate.getReceiverType(); - if (receiverType != null && candidateReceiverType != null) { - constraintSystem.addSubtypingConstraint(receiverType, candidateReceiverType); + ReceiverDescriptor receiver = task.getReceiver(); + ReceiverDescriptor candidateReceiver = candidate.getReceiver(); + if (receiver != NO_RECEIVER && candidateReceiver != NO_RECEIVER) { + constraintSystem.addSubtypingConstraint(receiver.getType(), candidateReceiver.getType()); } if (expectedType != NO_EXPECTED_TYPE) { @@ -508,28 +477,28 @@ public class CallResolver { private boolean checkReceiver(ResolutionTask task, TracingStrategy tracing, D candidate, TemporaryBindingTrace temporaryTrace) { if (!checkReceiverAbsence(task, tracing, candidate, temporaryTrace)) return false; - JetType receiverType = task.getReceiverType(); - JetType candidateReceiverType = candidate.getReceiverType(); - if (receiverType != null - && candidateReceiverType != null - && !semanticServices.getTypeChecker().isSubtypeOf(receiverType, candidateReceiverType)) { - tracing.missingReceiver(temporaryTrace, candidateReceiverType); + ReceiverDescriptor receiver = task.getReceiver(); + ReceiverDescriptor candidateReceiver = candidate.getReceiver(); + if (receiver != NO_RECEIVER + && candidateReceiver != NO_RECEIVER + && !semanticServices.getTypeChecker().isSubtypeOf(receiver.getType(), candidateReceiver.getType())) { + tracing.missingReceiver(temporaryTrace, candidateReceiver); return false; } return true; } private boolean checkReceiverAbsence(ResolutionTask task, TracingStrategy tracing, D candidate, TemporaryBindingTrace temporaryTrace) { - JetType receiverType = task.getReceiverType(); - JetType candidateReceiverType = candidate.getReceiverType(); - if (receiverType != null) { - if (candidateReceiverType == null) { + ReceiverDescriptor receiver = task.getReceiver(); + ReceiverDescriptor candidateReceiver = candidate.getReceiver(); + if (receiver != NO_RECEIVER) { + if (candidateReceiver == NO_RECEIVER) { tracing.noReceiverAllowed(temporaryTrace); return false; } } - else if (candidateReceiverType != null) { - tracing.missingReceiver(temporaryTrace, candidateReceiverType); + else if (candidateReceiver != NO_RECEIVER) { + tracing.missingReceiver(temporaryTrace, candidateReceiver); return false; } return true; @@ -658,8 +627,8 @@ public class CallResolver { } @NotNull - public OverloadResolutionResult resolveExactSignature(@NotNull JetScope scope, @Nullable JetType receiverType, @NotNull String name, @NotNull List parameterTypes) { - List result = findCandidatesByExactSignature(scope, receiverType, name, parameterTypes); + public OverloadResolutionResult resolveExactSignature(@NotNull JetScope scope, @NotNull ReceiverDescriptor receiver, @NotNull String name, @NotNull List parameterTypes) { + List result = findCandidatesByExactSignature(scope, receiver, name, parameterTypes); BindingTraceContext trace = new BindingTraceContext(); TemporaryBindingTrace temporaryBindingTrace = TemporaryBindingTrace.create(trace); @@ -672,25 +641,25 @@ public class CallResolver { return computeResultAndReportErrors(trace, TracingStrategy.EMPTY, candidates, Collections.emptySet(), Collections.emptySet(), traces); } - private List findCandidatesByExactSignature(JetScope scope, JetType receiverType, String name, List parameterTypes) { + private List findCandidatesByExactSignature(JetScope scope, ReceiverDescriptor receiver, String name, List parameterTypes) { List result = Lists.newArrayList(); - if (receiverType != null) { + if (receiver != NO_RECEIVER) { Set extensionFunctionDescriptors = scope.getFunctionGroup(name).getFunctionDescriptors(); List nonlocal = Lists.newArrayList(); List local = Lists.newArrayList(); TaskPrioritizer.splitLexicallyLocalDescriptors(extensionFunctionDescriptors, scope.getContainingDeclaration(), local, nonlocal); - if (findExtensionFunctions(local, receiverType, parameterTypes, result)) { + if (findExtensionFunctions(local, receiver, parameterTypes, result)) { return result; } - Set functionDescriptors = receiverType.getMemberScope().getFunctionGroup(name).getFunctionDescriptors(); + Set functionDescriptors = receiver.getType().getMemberScope().getFunctionGroup(name).getFunctionDescriptors(); if (lookupExactSignature(functionDescriptors, parameterTypes, result)) { return result; } - findExtensionFunctions(nonlocal, receiverType, parameterTypes, result); + findExtensionFunctions(nonlocal, receiver, parameterTypes, result); return result; } else { @@ -702,7 +671,7 @@ public class CallResolver { private boolean lookupExactSignature(Set candidates, List parameterTypes, List result) { boolean found = false; for (FunctionDescriptor functionDescriptor : candidates) { - if (functionDescriptor.getReceiverType() != null) continue; + if (functionDescriptor.getReceiver() != NO_RECEIVER) continue; if (!functionDescriptor.getTypeParameters().isEmpty()) continue; if (!checkValueParameters(functionDescriptor, parameterTypes)) continue; result.add(functionDescriptor); @@ -711,13 +680,13 @@ public class CallResolver { return found; } - private boolean findExtensionFunctions(Collection candidates, JetType receiverType, List parameterTypes, List result) { + private boolean findExtensionFunctions(Collection candidates, ReceiverDescriptor receiver, List parameterTypes, List result) { boolean found = false; for (FunctionDescriptor functionDescriptor : candidates) { - JetType functionReceiverType = functionDescriptor.getReceiverType(); - if (functionReceiverType == null) continue; + ReceiverDescriptor functionReceiver = functionDescriptor.getReceiver(); + if (functionReceiver == NO_RECEIVER) continue; if (!functionDescriptor.getTypeParameters().isEmpty()) continue; - if (!semanticServices.getTypeChecker().isSubtypeOf(receiverType, functionReceiverType)) continue; + if (!semanticServices.getTypeChecker().isSubtypeOf(receiver.getType(), functionReceiver.getType())) continue; if (!checkValueParameters(functionDescriptor, parameterTypes))continue; result.add(functionDescriptor); found = true; @@ -744,7 +713,7 @@ public class CallResolver { Set functions = Sets.newLinkedHashSet(scope.getFunctionGroup(name).getFunctionDescriptors()); for (Iterator iterator = functions.iterator(); iterator.hasNext(); ) { FunctionDescriptor functionDescriptor = iterator.next(); - if (functionDescriptor.getReceiverType() != null) { + if (functionDescriptor.getReceiver() != NO_RECEIVER) { iterator.remove(); } } @@ -756,10 +725,11 @@ public class CallResolver { @NotNull @Override - protected Collection getMembersByName(@NotNull JetType receiverType, String name) { - Set members = Sets.newHashSet(receiverType.getMemberScope().getFunctionGroup(name).getFunctionDescriptors()); - addConstructors(receiverType.getMemberScope(), name, members); - addVariableAsFunction(receiverType.getMemberScope(), name, members, false); + protected Collection getMembersByName(@NotNull ReceiverDescriptor receiver, String name) { + JetScope receiverScope = receiver.getType().getMemberScope(); + Set members = Sets.newHashSet(receiverScope.getFunctionGroup(name).getFunctionDescriptors()); + addConstructors(receiverScope, name, members); + addVariableAsFunction(receiverScope, name, members, false); return members; } @@ -769,7 +739,7 @@ public class CallResolver { Set extensionFunctions = Sets.newHashSet(scope.getFunctionGroup(name).getFunctionDescriptors()); for (Iterator iterator = extensionFunctions.iterator(); iterator.hasNext(); ) { FunctionDescriptor descriptor = iterator.next(); - if (descriptor.getReceiverType() == null) { + if (descriptor.getReceiver() == NO_RECEIVER) { iterator.remove(); } } @@ -779,8 +749,8 @@ public class CallResolver { @NotNull @Override - protected ResolutionTask createTask(JetType receiverType, Call call, Collection candidates) { - return new ResolutionTask(candidates, receiverType, call); + protected ResolutionTask createTask(@NotNull ReceiverDescriptor receiver, Call call, Collection candidates) { + return new ResolutionTask(candidates, receiver, call); } private void addConstructors(JetScope scope, String name, Collection functions) { @@ -793,11 +763,11 @@ public class CallResolver { private void addVariableAsFunction(JetScope scope, String name, Set functions, boolean receiverNeeded) { VariableDescriptor variable = scope.getVariable(name); - if (variable != null && variable.getReceiverType() == null) { + if (variable != null && variable.getReceiver() == NO_RECEIVER) { JetType outType = variable.getOutType(); if (outType != null && JetStandardClasses.isFunctionType(outType)) { VariableAsFunctionDescriptor functionDescriptor = VariableAsFunctionDescriptor.create(variable); - if ((functionDescriptor.getReceiverType() != null) == receiverNeeded) { + if ((functionDescriptor.getReceiver() != NO_RECEIVER) == receiverNeeded) { functions.add(functionDescriptor); } } @@ -811,7 +781,7 @@ public class CallResolver { @Override protected Collection getNonExtensionsByName(JetScope scope, String name) { VariableDescriptor variable = scope.getVariable(name); - if (variable != null && variable.getReceiverType() == null) { + if (variable != null && variable.getReceiver() == NO_RECEIVER) { return Collections.singleton(variable); } return Collections.emptyList(); @@ -819,8 +789,8 @@ public class CallResolver { @NotNull @Override - protected Collection getMembersByName(@NotNull JetType receiverType, String name) { - VariableDescriptor variable = receiverType.getMemberScope().getVariable(name); + protected Collection getMembersByName(@NotNull ReceiverDescriptor receiver, String name) { + VariableDescriptor variable = receiver.getType().getMemberScope().getVariable(name); if (variable != null) { return Collections.singleton(variable); } @@ -831,7 +801,7 @@ public class CallResolver { @Override protected Collection getExtensionsByName(JetScope scope, String name) { VariableDescriptor variable = scope.getVariable(name); - if (variable != null && variable.getReceiverType() != null) { + if (variable != null && variable.getReceiver() != NO_RECEIVER) { return Collections.singleton(variable); } return Collections.emptyList(); @@ -839,8 +809,8 @@ public class CallResolver { @NotNull @Override - protected ResolutionTask createTask(JetType receiverType, Call call, Collection candidates) { - return new ResolutionTask(candidates, receiverType, call); + protected ResolutionTask createTask(@NotNull ReceiverDescriptor receiver, Call call, Collection candidates) { + return new ResolutionTask(candidates, receiver, call); } }; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/OverloadingConflictResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/OverloadingConflictResolver.java index c25f75451b0..ca78d53b398 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/OverloadingConflictResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/OverloadingConflictResolver.java @@ -9,6 +9,7 @@ import org.jetbrains.jet.lang.descriptors.CallableDescriptor; import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor; import org.jetbrains.jet.lang.resolve.DescriptorUtils; import org.jetbrains.jet.lang.resolve.TemporaryBindingTrace; +import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import org.jetbrains.jet.lang.types.JetStandardLibrary; import org.jetbrains.jet.lang.types.JetType; @@ -59,10 +60,10 @@ import java.util.Set; if (overrides(f, g)) return true; if (overrides(g, f)) return false; - JetType receiverTypeOfF = f.getReceiverType(); - JetType receiverTypeOfG = g.getReceiverType(); - if (receiverTypeOfF != null && receiverTypeOfG != null) { - if (!typeMoreSpecific(receiverTypeOfF, receiverTypeOfG)) return false; + ReceiverDescriptor receiverOfF = f.getReceiver(); + ReceiverDescriptor receiverOfG = g.getReceiver(); + if (f.getReceiver().exists() && g.getReceiver().exists()) { + if (!typeMoreSpecific(receiverOfF.getType(), receiverOfG.getType())) return false; } List fParams = f.getValueParameters(); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ResolutionTask.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ResolutionTask.java index 410f7f00080..c369d8aa730 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ResolutionTask.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ResolutionTask.java @@ -8,9 +8,9 @@ import org.jetbrains.jet.lang.psi.JetExpression; import org.jetbrains.jet.lang.psi.JetTypeProjection; import org.jetbrains.jet.lang.psi.ValueArgument; import org.jetbrains.jet.lang.resolve.BindingTrace; +import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import org.jetbrains.jet.lang.types.JetType; -import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -19,7 +19,7 @@ import java.util.List; */ /*package*/ class ResolutionTask { private final Collection candidates; - private final JetType receiverType; + private final ReceiverDescriptor receiver; private final List typeArguments; private final List valueArguments; private final List functionLiteralArguments; @@ -27,12 +27,12 @@ import java.util.List; public ResolutionTask( @NotNull Collection candidates, - @Nullable JetType receiverType, + @NotNull ReceiverDescriptor receiver, @NotNull List typeArguments, @NotNull List valueArguments, @NotNull List functionLiteralArguments) { this.candidates = candidates; - this.receiverType = receiverType; + this.receiver = receiver; this.typeArguments = typeArguments; this.valueArguments = valueArguments; this.functionLiteralArguments = functionLiteralArguments; @@ -40,10 +40,10 @@ import java.util.List; public ResolutionTask( @NotNull Collection candidates, - @Nullable JetType receiverType, + @NotNull ReceiverDescriptor receiver, @NotNull Call call ) { - this(candidates, receiverType, call.getTypeArguments(), call.getValueArguments(), call.getFunctionLiteralArguments()); + this(candidates, receiver, call.getTypeArguments(), call.getValueArguments(), call.getFunctionLiteralArguments()); } @NotNull @@ -51,9 +51,9 @@ import java.util.List; return candidates; } - @Nullable - public JetType getReceiverType() { - return receiverType; + @NotNull + public ReceiverDescriptor getReceiver() { + return receiver; } @NotNull 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 96a668739de..c14a3c00e9e 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 @@ -2,7 +2,6 @@ package org.jetbrains.jet.lang.resolve.calls; import com.google.common.collect.Lists; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.descriptors.CallableDescriptor; import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; @@ -10,7 +9,6 @@ import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor; import org.jetbrains.jet.lang.psi.Call; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import org.jetbrains.jet.lang.resolve.scopes.JetScope; -import org.jetbrains.jet.lang.types.JetType; import java.util.Collection; import java.util.List; @@ -64,33 +62,33 @@ import java.util.List; return false; } - public List> computePrioritizedTasks(@NotNull JetScope scope, @Nullable JetType receiverType, @NotNull Call call, @NotNull String name) { + public List> computePrioritizedTasks(@NotNull JetScope scope, @NotNull ReceiverDescriptor receiver, @NotNull Call call, @NotNull String name) { List> result = Lists.newArrayList(); - doComputeTasks(scope, receiverType, call, name, result); + doComputeTasks(scope, receiver, call, name, result); return result; } - private void doComputeTasks(JetScope scope, JetType receiverType, Call call, String name, List> result) { - List receivers = Lists.newArrayList(); - scope.getImplicitReceiversHierarchy(receivers); - if (receiverType != null) { + private void doComputeTasks(JetScope scope, ReceiverDescriptor receiver, Call call, String name, List> result) { + List implicitReceivers = Lists.newArrayList(); + scope.getImplicitReceiversHierarchy(implicitReceivers); + if (receiver != ReceiverDescriptor.NO_RECEIVER) { Collection extensionFunctions = getExtensionsByName(scope, name); List nonlocals = Lists.newArrayList(); List locals = Lists.newArrayList(); //noinspection unchecked,RedundantTypeArguments TaskPrioritizer.splitLexicallyLocalDescriptors(extensionFunctions, scope.getContainingDeclaration(), locals, nonlocals); - Collection members = getMembersByName(receiverType, name); + Collection members = getMembersByName(receiver, name); - addTask(result, receiverType, call, locals); - addTask(result, null, call, members); + addTask(result, receiver, call, locals); + addTask(result, ReceiverDescriptor.NO_RECEIVER, call, members); - for (ReceiverDescriptor receiver : receivers) { - Collection memberExtensions = getExtensionsByName(receiver.getReceiverType().getMemberScope(), name); - addTask(result, receiverType, call, memberExtensions); + for (ReceiverDescriptor implicitReceiver : implicitReceivers) { + Collection memberExtensions = getExtensionsByName(implicitReceiver.getType().getMemberScope(), name); + addTask(result, receiver, call, memberExtensions); } - addTask(result, receiverType, call, nonlocals); + addTask(result, receiver, call, nonlocals); } else { Collection functions = getNonExtensionsByName(scope, name); @@ -100,13 +98,13 @@ import java.util.List; //noinspection unchecked,RedundantTypeArguments TaskPrioritizer.splitLexicallyLocalDescriptors(functions, scope.getContainingDeclaration(), locals, nonlocals); - addTask(result, receiverType, call, locals); + addTask(result, receiver, call, locals); - for (ReceiverDescriptor receiver : receivers) { - doComputeTasks(scope, receiver.getReceiverType(), call, name, result); + for (ReceiverDescriptor implicitReceiver : implicitReceivers) { + doComputeTasks(scope, implicitReceiver, call, name, result); } - addTask(result, receiverType, call, nonlocals); + addTask(result, receiver, call, nonlocals); } } @@ -114,17 +112,17 @@ import java.util.List; protected abstract Collection getNonExtensionsByName(JetScope scope, String name); @NotNull - protected abstract Collection getMembersByName(@NotNull JetType receiverType, String name); + protected abstract Collection getMembersByName(@NotNull ReceiverDescriptor receiver, String name); @NotNull protected abstract Collection getExtensionsByName(JetScope scope, String name); - private void addTask(@NotNull List> result, @Nullable JetType receiverType, @NotNull Call call, @NotNull Collection candidates) { + private void addTask(@NotNull List> result, @NotNull ReceiverDescriptor receiver, @NotNull Call call, @NotNull Collection candidates) { if (candidates.isEmpty()) return; - result.add(createTask(receiverType, call, candidates)); + result.add(createTask(receiver, call, candidates)); } @NotNull - protected abstract ResolutionTask createTask(JetType receiverType, Call call, Collection candidates); + protected abstract ResolutionTask createTask(ReceiverDescriptor receiver, Call call, Collection candidates); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/TracingStrategy.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/TracingStrategy.java index 117df0b9a8c..2429496de86 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/TracingStrategy.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/TracingStrategy.java @@ -4,7 +4,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.descriptors.CallableDescriptor; import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor; import org.jetbrains.jet.lang.resolve.BindingTrace; -import org.jetbrains.jet.lang.types.JetType; +import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import java.util.Collection; import java.util.Set; @@ -15,7 +15,7 @@ import java.util.Set; /*package*/ interface TracingStrategy { TracingStrategy EMPTY = new TracingStrategy() { @Override - public void bindReference(@NotNull BindingTrace trace, @NotNull CallableDescriptor descriptor) {} + public void bindReference(@NotNull BindingTrace trace, @NotNull ReceiverDescriptor receiver, @NotNull CallableDescriptor descriptor) {} @Override public void unresolvedReference(@NotNull BindingTrace trace) {} @@ -24,7 +24,7 @@ import java.util.Set; public void recordAmbiguity(BindingTrace trace, Collection candidates) {} @Override - public void missingReceiver(@NotNull BindingTrace trace, @NotNull JetType candidateReceiverType) {} + public void missingReceiver(@NotNull BindingTrace trace, @NotNull ReceiverDescriptor expectedReceiver) {} @Override public void noReceiverAllowed(@NotNull BindingTrace trace) {} @@ -48,13 +48,13 @@ import java.util.Set; public void typeInferenceFailed(@NotNull BindingTrace trace) {} }; - void bindReference(@NotNull BindingTrace trace, @NotNull CallableDescriptor descriptor); + void bindReference(@NotNull BindingTrace trace, @NotNull ReceiverDescriptor receiver, @NotNull CallableDescriptor descriptor); void unresolvedReference(@NotNull BindingTrace trace); void recordAmbiguity(BindingTrace trace, Collection candidates); - void missingReceiver(@NotNull BindingTrace trace, @NotNull JetType candidateReceiverType); + void missingReceiver(@NotNull BindingTrace trace, @NotNull ReceiverDescriptor expectedReceiver); void noReceiverAllowed(@NotNull BindingTrace trace); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/WritableScope.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/WritableScope.java index c052fb4a23e..f37b8ae6b16 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/WritableScope.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/WritableScope.java @@ -3,7 +3,7 @@ package org.jetbrains.jet.lang.resolve.scopes; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.*; -import org.jetbrains.jet.lang.resolve.scopes.receivers.ImplicitReceiverDescriptor; +import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; /** * @author abreslav @@ -30,5 +30,5 @@ public interface WritableScope extends JetScope { void importScope(@NotNull JetScope imported); - void setImplicitReceiver(@NotNull ImplicitReceiverDescriptor implicitReceiver); + void setImplicitReceiver(@NotNull ReceiverDescriptor implicitReceiver); } 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 dbb5f057c23..9fa55238319 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 @@ -7,7 +7,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.resolve.DescriptorUtils; -import org.jetbrains.jet.lang.resolve.scopes.receivers.ImplicitReceiverDescriptor; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import java.util.*; @@ -36,7 +35,7 @@ public class WritableScopeImpl extends WritableScopeWithImports { private Map> labelsToDescriptors; @Nullable - private ImplicitReceiverDescriptor implicitReceiver; + private ReceiverDescriptor implicitReceiver; public WritableScopeImpl(@NotNull JetScope scope, @NotNull DeclarationDescriptor owner, @NotNull RedeclarationHandler redeclarationHandler) { super(scope, redeclarationHandler); @@ -275,7 +274,7 @@ public class WritableScopeImpl extends WritableScopeWithImports { } @Override - public void setImplicitReceiver(@NotNull ImplicitReceiverDescriptor implicitReceiver) { + public void setImplicitReceiver(@NotNull ReceiverDescriptor implicitReceiver) { if (this.implicitReceiver != null) { throw new UnsupportedOperationException("Receiver redeclared"); } @@ -284,7 +283,7 @@ public class WritableScopeImpl extends WritableScopeWithImports { @Override public void getImplicitReceiversHierarchy(@NotNull List result) { - if (implicitReceiver != null && implicitReceiver != ReceiverDescriptor.NO_RECEIVER) { + if (implicitReceiver != null && implicitReceiver.exists()) { result.add(implicitReceiver); } super.getImplicitReceiversHierarchy(result); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/WriteThroughScope.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/WriteThroughScope.java index 4c36fd0949e..e3082888951 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/WriteThroughScope.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/WriteThroughScope.java @@ -4,7 +4,6 @@ import com.google.common.collect.Lists; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.*; -import org.jetbrains.jet.lang.resolve.scopes.receivers.ImplicitReceiverDescriptor; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import java.util.Collection; @@ -147,7 +146,7 @@ public class WriteThroughScope extends WritableScopeWithImports { } @Override - public void setImplicitReceiver(@NotNull ImplicitReceiverDescriptor implicitReceiver) { + public void setImplicitReceiver(@NotNull ReceiverDescriptor implicitReceiver) { writableWorker.setImplicitReceiver(implicitReceiver); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/receivers/AbstractReceiverDescriptor.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/receivers/AbstractReceiverDescriptor.java new file mode 100644 index 00000000000..19c8657fb32 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/receivers/AbstractReceiverDescriptor.java @@ -0,0 +1,26 @@ +package org.jetbrains.jet.lang.resolve.scopes.receivers; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.types.JetType; + +/** + * @author abreslav + */ +public class AbstractReceiverDescriptor implements ReceiverDescriptor { + protected final JetType receiverType; + + public AbstractReceiverDescriptor(@NotNull JetType receiverType) { + this.receiverType = receiverType; + } + + @Override + @NotNull + public JetType getType() { + return receiverType; + } + + @Override + public boolean exists() { + return true; + } +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/receivers/ExplicitReceiver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/receivers/ExplicitReceiver.java deleted file mode 100644 index 2b58bf569c8..00000000000 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/receivers/ExplicitReceiver.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.jetbrains.jet.lang.resolve.scopes.receivers; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.jet.lang.types.JetType; - -/** - * @author abreslav - */ -public class ExplicitReceiver implements ReceiverDescriptor { - - private final JetType type; - - public ExplicitReceiver(@NotNull JetType type) { - this.type = type; - } - - @NotNull - @Override - public JetType getReceiverType() { - return type; - } -} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/receivers/ExpressionReceiver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/receivers/ExpressionReceiver.java new file mode 100644 index 00000000000..e66cd98226f --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/receivers/ExpressionReceiver.java @@ -0,0 +1,23 @@ +package org.jetbrains.jet.lang.resolve.scopes.receivers; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.psi.JetExpression; +import org.jetbrains.jet.lang.types.JetType; + +/** + * @author abreslav + */ +public class ExpressionReceiver extends AbstractReceiverDescriptor implements ReceiverDescriptor { + + private final JetExpression expression; + + public ExpressionReceiver(@NotNull JetExpression expression, @NotNull JetType type) { + super(type); + this.expression = expression; + } + + @NotNull + public JetExpression getExpression() { + return expression; + } +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/receivers/ExtensionCallableReceiver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/receivers/ExtensionCallableReceiver.java deleted file mode 100644 index 2828c2c39b8..00000000000 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/receivers/ExtensionCallableReceiver.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.jetbrains.jet.lang.resolve.scopes.receivers; - -import org.jetbrains.jet.lang.descriptors.CallableDescriptor; - -/** - * @author abreslav - */ -public class ExtensionCallableReceiver extends ImplicitReceiverDescriptor { - - public ExtensionCallableReceiver(CallableDescriptor callableDescriptor) { - super(callableDescriptor, callableDescriptor.getReceiverType()); - } -} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/receivers/ExtensionReceiver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/receivers/ExtensionReceiver.java new file mode 100644 index 00000000000..6a54c7ac18d --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/receivers/ExtensionReceiver.java @@ -0,0 +1,15 @@ +package org.jetbrains.jet.lang.resolve.scopes.receivers; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.descriptors.CallableDescriptor; +import org.jetbrains.jet.lang.types.JetType; + +/** + * @author abreslav + */ +public class ExtensionReceiver extends ImplicitReceiverDescriptor { + + public ExtensionReceiver(@NotNull CallableDescriptor callableDescriptor, @NotNull JetType receiverType) { + super(callableDescriptor, receiverType); + } +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/receivers/ImplicitReceiverDescriptor.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/receivers/ImplicitReceiverDescriptor.java index 8910ce1810a..4c566658f83 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/receivers/ImplicitReceiverDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/receivers/ImplicitReceiverDescriptor.java @@ -9,21 +9,14 @@ import org.jetbrains.jet.lang.types.JetType; * * @author abreslav */ -public abstract class ImplicitReceiverDescriptor implements ReceiverDescriptor { - private final JetType receiverType; +public abstract class ImplicitReceiverDescriptor extends AbstractReceiverDescriptor { private final DeclarationDescriptor declarationDescriptor; - protected ImplicitReceiverDescriptor(DeclarationDescriptor declarationDescriptor, JetType receiverType) { - this.receiverType = receiverType; + protected ImplicitReceiverDescriptor(@NotNull DeclarationDescriptor declarationDescriptor, @NotNull JetType receiverType) { + super(receiverType); this.declarationDescriptor = declarationDescriptor; } - @Override - @NotNull - public JetType getReceiverType() { - return receiverType; - } - @NotNull public DeclarationDescriptor getDeclarationDescriptor() { return declarationDescriptor; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/receivers/ReceiverDescriptor.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/receivers/ReceiverDescriptor.java index c909cd5125a..9b9bd0df20c 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/receivers/ReceiverDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/receivers/ReceiverDescriptor.java @@ -1,7 +1,6 @@ package org.jetbrains.jet.lang.resolve.scopes.receivers; import org.jetbrains.annotations.NotNull; -import org.jetbrains.jet.lang.types.JetStandardClasses; import org.jetbrains.jet.lang.types.JetType; /** @@ -12,8 +11,13 @@ public interface ReceiverDescriptor { ReceiverDescriptor NO_RECEIVER = new ReceiverDescriptor() { @NotNull @Override - public JetType getReceiverType() { - return JetStandardClasses.getNothingType(); + public JetType getType() { + throw new UnsupportedOperationException("NO_RECEIVER.getType()"); + } + + @Override + public boolean exists() { + return false; } @Override @@ -23,5 +27,7 @@ public interface ReceiverDescriptor { }; @NotNull - JetType getReceiverType(); + JetType getType(); + + boolean exists(); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/receivers/TransientReceiver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/receivers/TransientReceiver.java new file mode 100644 index 00000000000..7364960e682 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/receivers/TransientReceiver.java @@ -0,0 +1,16 @@ +package org.jetbrains.jet.lang.resolve.scopes.receivers; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.types.JetType; + +/** + * This represents the receiver of hasNext and next() in for-loops + * Cannot be an expression receiver because there is no expression for the iterator() call + * + * @author abreslav + */ +public class TransientReceiver extends AbstractReceiverDescriptor { + public TransientReceiver(@NotNull JetType type) { + super(type); + } +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java index 440a0451e62..cb4de3e4c5f 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java @@ -26,6 +26,9 @@ import org.jetbrains.jet.lang.resolve.constants.StringValue; import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.resolve.scopes.WritableScope; import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl; +import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver; +import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; +import org.jetbrains.jet.lang.resolve.scopes.receivers.TransientReceiver; import org.jetbrains.jet.lexer.JetTokens; import org.jetbrains.jet.util.slicedmap.WritableSlice; @@ -196,7 +199,7 @@ public class JetTypeInferrer { } @NotNull - public JetType safeGetType(@NotNull final JetScope scope, @NotNull JetExpression expression, @NotNull JetType expectedType) { + public JetType safeGetType(@NotNull JetScope scope, @NotNull JetExpression expression, @NotNull JetType expectedType) { JetType type = getType(scope, expression, expectedType); if (type != null) { return type; @@ -220,9 +223,9 @@ public class JetTypeInferrer { private void checkNullSafety(@Nullable JetType receiverType, @NotNull ASTNode operationTokenNode, @Nullable FunctionDescriptor callee) { if (receiverType != null && callee != null) { boolean namespaceType = receiverType instanceof NamespaceType; - JetType calleeReceiverType = callee.getReceiverType(); boolean nullableReceiver = !namespaceType && receiverType.isNullable(); - boolean calleeForbidsNullableReceiver = calleeReceiverType == null || !calleeReceiverType.isNullable(); + ReceiverDescriptor calleeReceiver = callee.getReceiver(); + boolean calleeForbidsNullableReceiver = !calleeReceiver.exists() || !calleeReceiver.getType().isNullable(); IElementType operationSign = operationTokenNode.getElementType(); if (nullableReceiver && calleeForbidsNullableReceiver && operationSign == JetTokens.DOT) { @@ -681,6 +684,20 @@ public class JetTypeInferrer { } return ErrorUtils.createErrorType("Type for " + expression.getText()); } + + @Nullable + public final ExpressionReceiver getExpressionReceiver(@NotNull JetExpression expression, TypeInferenceContext context) { + JetType type = getType(expression, context); + if (type == null) { + return null; + } + return new ExpressionReceiver(expression, type); + } + + @NotNull + public final ExpressionReceiver safeGetExpressionReceiver(@NotNull JetExpression expression, TypeInferenceContext context) { + return new ExpressionReceiver(expression, safeGetType(expression, context)); + } @Nullable public final JetType getType(@NotNull JetExpression expression, TypeInferenceContext context) { @@ -761,7 +778,7 @@ public class JetTypeInferrer { } } else { - return getSelectorReturnType(null, expression, context); // TODO : Extensions to this + return getSelectorReturnType(ReceiverDescriptor.NO_RECEIVER, expression, context); // TODO : Extensions to this // assert JetTokens.IDENTIFIER == expression.getReferencedNameElementType(); // if (referencedName != null) { // VariableDescriptor variable = context.scope.getVariable(referencedName); @@ -894,7 +911,8 @@ public class JetTypeInferrer { if (receiverTypeRef != null) { receiverType = context.typeResolver.resolveType(context.scope, receiverTypeRef); } else { - receiverType = context.scope.getImplicitReceiver().getReceiverType(); + ReceiverDescriptor implicitReceiver = context.scope.getImplicitReceiver(); + receiverType = implicitReceiver.exists() ? implicitReceiver.getType() : null; } FunctionDescriptorImpl functionDescriptor = new FunctionDescriptorImpl( @@ -1216,7 +1234,7 @@ public class JetTypeInferrer { @Override public JetType visitThisExpression(JetThisExpression expression, TypeInferenceContext context) { JetType result = null; - JetType thisType = null; + ReceiverDescriptor thisReceiver = null; String labelName = expression.getLabelName(); if (labelName != null) { Collection declarationsByLabel = context.scope.getDeclarationsByLabel(labelName); @@ -1227,11 +1245,11 @@ public class JetTypeInferrer { DeclarationDescriptor declarationDescriptor = declarationsByLabel.iterator().next(); if (declarationDescriptor instanceof ClassDescriptor) { ClassDescriptor classDescriptor = (ClassDescriptor) declarationDescriptor; - thisType = classDescriptor.getDefaultType(); + thisReceiver = classDescriptor.getImplicitReceiver(); } else if (declarationDescriptor instanceof FunctionDescriptor) { FunctionDescriptor functionDescriptor = (FunctionDescriptor) declarationDescriptor; - thisType = functionDescriptor.getReceiverType(); + thisReceiver = functionDescriptor.getReceiver(); } else { throw new UnsupportedOperationException(); // TODO @@ -1245,11 +1263,8 @@ public class JetTypeInferrer { if (psiElement instanceof JetFunctionLiteralExpression) { DeclarationDescriptor declarationDescriptor = context.trace.getBindingContext().get(BindingContext.DECLARATION_TO_DESCRIPTOR, psiElement); if (declarationDescriptor instanceof FunctionDescriptor) { - thisType = ((FunctionDescriptor) declarationDescriptor).getReceiverType(); - if (thisType == null) { - thisType = JetStandardClasses.getNothingType(); - } - else { + thisReceiver = ((FunctionDescriptor) declarationDescriptor).getReceiver(); + if (thisReceiver.exists()) { context.trace.record(REFERENCE_TARGET, targetLabel, declarationDescriptor); context.trace.record(REFERENCE_TARGET, expression.getThisReference(), declarationDescriptor); } @@ -1268,7 +1283,7 @@ public class JetTypeInferrer { } } else { - thisType = context.scope.getImplicitReceiver().getReceiverType(); + thisReceiver = context.scope.getImplicitReceiver(); DeclarationDescriptor declarationDescriptorForUnqualifiedThis = context.scope.getDeclarationDescriptorForUnqualifiedThis(); if (declarationDescriptorForUnqualifiedThis != null) { @@ -1276,8 +1291,8 @@ public class JetTypeInferrer { } } - if (thisType != null) { - if (JetStandardClasses.isNothing(thisType)) { + if (thisReceiver != null) { + if (!thisReceiver.exists()) { // context.trace.getErrorHandler().genericError(expression.getNode(), "'this' is not defined in this context"); context.trace.report(NO_THIS.on(expression)); } @@ -1293,6 +1308,7 @@ public class JetTypeInferrer { if (classifierCandidate instanceof ClassDescriptor) { ClassDescriptor superclass = (ClassDescriptor) classifierCandidate; + JetType thisType = thisReceiver.getType(); Collection supertypes = thisType.getConstructor().getSupertypes(); TypeSubstitutor substitutor = TypeSubstitutor.create(thisType); for (JetType declaredSupertype : supertypes) { @@ -1307,8 +1323,9 @@ public class JetTypeInferrer { } } } - } else { - result = thisType; + } + else { + result = thisReceiver.getType(); } if (result != null) { context.trace.record(BindingContext.EXPRESSION_TYPE, expression.getThisReference(), result); @@ -1395,7 +1412,8 @@ public class JetTypeInferrer { // JetScope compositeScope = new ScopeWithReceiver(context.scope, subjectType, semanticServices.getTypeChecker()); if (callSuffixExpression != null) { // JetType selectorReturnType = getType(compositeScope, callSuffixExpression, false, context); - JetType selectorReturnType = getSelectorReturnType(subjectType, callSuffixExpression, context);//getType(compositeScope, callSuffixExpression, false, context); + assert subjectExpression != null; + JetType selectorReturnType = getSelectorReturnType(new ExpressionReceiver(subjectExpression, subjectType), callSuffixExpression, context);//getType(compositeScope, callSuffixExpression, false, context); ensureBooleanResultWithCustomSubject(callSuffixExpression, selectorReturnType, "This expression", context); context.services.checkNullSafety(subjectType, condition.getOperationTokenNode(), getCalleeFunctionDescriptor(callSuffixExpression, context)); } @@ -1473,7 +1491,8 @@ public class JetTypeInferrer { public void visitDecomposerPattern(JetDecomposerPattern pattern) { JetExpression decomposerExpression = pattern.getDecomposerExpression(); if (decomposerExpression != null) { - JetType selectorReturnType = getSelectorReturnType(subjectType, decomposerExpression, context); + ReceiverDescriptor receiver = new TransientReceiver(subjectType); + JetType selectorReturnType = getSelectorReturnType(receiver, decomposerExpression, context); result[0] = checkPatternType(pattern.getArgumentList(), selectorReturnType == null ? ErrorUtils.createErrorType("No type") : selectorReturnType, scopeToExtend, context); } @@ -1839,13 +1858,12 @@ public class JetTypeInferrer { TypeInferenceContext context = contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE); JetParameter loopParameter = expression.getLoopParameter(); JetExpression loopRange = expression.getLoopRange(); - JetType loopRangeType = null; - if (loopRange != null) { - loopRangeType = getType(loopRange, context.replaceScope(context.scope)); - } JetType expectedParameterType = null; - if (loopRangeType != null) { - expectedParameterType = checkIterableConvention(loopRangeType, loopRange, context); + if (loopRange != null) { + ExpressionReceiver loopRangeReceiver = getExpressionReceiver(loopRange, context.replaceScope(context.scope)); + if (loopRangeReceiver != null) { + expectedParameterType = checkIterableConvention(loopRangeReceiver, context); + } } WritableScope loopScope = newWritableScopeImpl(context.scope, context.trace).setDebugName("Scope with for-loop index"); @@ -1881,42 +1899,42 @@ public class JetTypeInferrer { } @Nullable - private JetType checkIterableConvention(@NotNull JetType type, @NotNull JetExpression loopRange, TypeInferenceContext context) { - ASTNode reportErrorsOn = loopRange.getNode(); - OverloadResolutionResult iteratorResolutionResult = callResolver.resolveExactSignature(context.scope, type, "iterator", Collections.emptyList()); + private JetType checkIterableConvention(@NotNull ExpressionReceiver loopRange, TypeInferenceContext context) { + JetExpression loopRangeExpression = loopRange.getExpression(); + OverloadResolutionResult iteratorResolutionResult = callResolver.resolveExactSignature(context.scope, loopRange, "iterator", Collections.emptyList()); if (iteratorResolutionResult.isSuccess()) { FunctionDescriptor iteratorFunction = iteratorResolutionResult.getDescriptor(); - context.trace.record(LOOP_RANGE_ITERATOR, loopRange, iteratorFunction); + context.trace.record(LOOP_RANGE_ITERATOR, loopRangeExpression, iteratorFunction); JetType iteratorType = iteratorFunction.getReturnType(); - FunctionDescriptor hasNextFunction = checkHasNextFunctionSupport(loopRange, iteratorType, context); + FunctionDescriptor hasNextFunction = checkHasNextFunctionSupport(loopRangeExpression, iteratorType, context); boolean hasNextFunctionSupported = hasNextFunction != null; - VariableDescriptor hasNextProperty = checkHasNextPropertySupport(loopRange, iteratorType, context); + VariableDescriptor hasNextProperty = checkHasNextPropertySupport(loopRangeExpression, iteratorType, context); boolean hasNextPropertySupported = hasNextProperty != null; if (hasNextFunctionSupported && hasNextPropertySupported && !ErrorUtils.isErrorType(iteratorType)) { // TODO : overload resolution rules impose priorities here??? // context.trace.getErrorHandler().genericError(reportErrorsOn, "An ambiguity between 'iterator().hasNext()' function and 'iterator().hasNext' property"); - context.trace.report(HAS_NEXT_PROPERTY_AND_FUNCTION_AMBIGUITY.on(reportErrorsOn)); + context.trace.report(HAS_NEXT_PROPERTY_AND_FUNCTION_AMBIGUITY.on(loopRangeExpression)); } else if (!hasNextFunctionSupported && !hasNextPropertySupported) { // context.trace.getErrorHandler().genericError(reportErrorsOn, "Loop range must have an 'iterator().hasNext()' function or an 'iterator().hasNext' property"); - context.trace.report(HAS_NEXT_MISSING.on(reportErrorsOn)); + context.trace.report(HAS_NEXT_MISSING.on(loopRangeExpression)); } else { - context.trace.record(LOOP_RANGE_HAS_NEXT, loopRange, hasNextFunctionSupported ? hasNextFunction : hasNextProperty); + context.trace.record(LOOP_RANGE_HAS_NEXT, loopRange.getExpression(), hasNextFunctionSupported ? hasNextFunction : hasNextProperty); } - OverloadResolutionResult nextResolutionResult = callResolver.resolveExactSignature(context.scope, iteratorType, "next", Collections.emptyList()); + OverloadResolutionResult nextResolutionResult = callResolver.resolveExactSignature(context.scope, new TransientReceiver(iteratorType), "next", Collections.emptyList()); if (nextResolutionResult.isAmbiguity()) { // context.trace.getErrorHandler().genericError(reportErrorsOn, "Method 'iterator().next()' is ambiguous for this expression"); - context.trace.report(NEXT_AMBIGUITY.on(reportErrorsOn)); + context.trace.report(NEXT_AMBIGUITY.on(loopRangeExpression)); } else if (nextResolutionResult.isNothing()) { // context.trace.getErrorHandler().genericError(reportErrorsOn, "Loop range must have an 'iterator().next()' method"); - context.trace.report(NEXT_MISSING.on(reportErrorsOn)); + context.trace.report(NEXT_MISSING.on(loopRangeExpression)); } else { FunctionDescriptor nextFunction = nextResolutionResult.getDescriptor(); - context.trace.record(LOOP_RANGE_NEXT, loopRange, nextFunction); + context.trace.record(LOOP_RANGE_NEXT, loopRange.getExpression(), nextFunction); return nextFunction.getReturnType(); } } @@ -1927,11 +1945,11 @@ public class JetTypeInferrer { // stringBuffer.append(DescriptorRenderer.TEXT.render(functionDescriptor)).append(" "); // } // errorMessage = stringBuffer.toString(); - context.trace.report(ITERATOR_AMBIGUITY.on(reportErrorsOn, iteratorResolutionResult.getDescriptors())); + context.trace.report(ITERATOR_AMBIGUITY.on(loopRangeExpression, iteratorResolutionResult.getDescriptors())); } else { // context.trace.getErrorHandler().genericError(reportErrorsOn, errorMessage); - context.trace.report(ITERATOR_MISSING.on(reportErrorsOn)); + context.trace.report(ITERATOR_MISSING.on(loopRangeExpression)); } } return null; @@ -1939,7 +1957,7 @@ public class JetTypeInferrer { @Nullable private FunctionDescriptor checkHasNextFunctionSupport(@NotNull JetExpression loopRange, @NotNull JetType iteratorType, TypeInferenceContext context) { - OverloadResolutionResult hasNextResolutionResult = callResolver.resolveExactSignature(context.scope, iteratorType, "hasNext", Collections.emptyList()); + OverloadResolutionResult hasNextResolutionResult = callResolver.resolveExactSignature(context.scope, new TransientReceiver(iteratorType), "hasNext", Collections.emptyList()); if (hasNextResolutionResult.isAmbiguity()) { // context.trace.getErrorHandler().genericError(loopRange.getNode(), "Method 'iterator().hasNext()' is ambiguous for this expression"); context.trace.report(HAS_NEXT_FUNCTION_AMBIGUITY.on(loopRange)); @@ -2001,7 +2019,7 @@ public class JetTypeInferrer { // Clean resolution: no autocasts TemporaryBindingTrace cleanResolutionTrace = TemporaryBindingTrace.create(context.trace); TypeInferenceContext cleanResolutionContext = context.replaceBindingTrace(cleanResolutionTrace); - JetType selectorReturnType = getSelectorReturnType(receiverType, selectorExpression, cleanResolutionContext); + JetType selectorReturnType = getSelectorReturnType(new ExpressionReceiver(receiverExpression, receiverType), selectorExpression, cleanResolutionContext); //TODO move further if (expression.getOperationSign() == JetTokens.SAFE_ACCESS) { @@ -2022,7 +2040,7 @@ public class JetTypeInferrer { TemporaryBindingTrace autocastResolutionTrace = TemporaryBindingTrace.create(context.trace); TypeInferenceContext autocastResolutionContext = context.replaceBindingTrace(autocastResolutionTrace); for (JetType possibleType : possibleTypes) { - selectorReturnType = getSelectorReturnType(possibleType, selectorExpression, autocastResolutionContext); + selectorReturnType = getSelectorReturnType(new ExpressionReceiver(receiverExpression, possibleType), selectorExpression, autocastResolutionContext); if (selectorReturnType != null) { context.services.checkAutoCast(receiverExpression, possibleType, variableDescriptor, autocastResolutionTrace); autocastResolutionTrace.commit(); @@ -2145,20 +2163,20 @@ public class JetTypeInferrer { } @Nullable - private JetType getSelectorReturnType(@Nullable JetType receiverType, @NotNull JetExpression selectorExpression, @NotNull TypeInferenceContext context) { + private JetType getSelectorReturnType(@NotNull ReceiverDescriptor receiver, @NotNull JetExpression selectorExpression, @NotNull TypeInferenceContext context) { if (selectorExpression instanceof JetCallExpression) { - return callResolver.resolveCall(context.trace, context.scope, receiverType, (JetCallExpression) selectorExpression, context.expectedType); + return callResolver.resolveCall(context.trace, context.scope, receiver, (JetCallExpression) selectorExpression, context.expectedType); } else if (selectorExpression instanceof JetSimpleNameExpression) { JetSimpleNameExpression nameExpression = (JetSimpleNameExpression) selectorExpression; TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create(context.trace); - VariableDescriptor variableDescriptor = callResolver.resolveSimpleProperty(temporaryTrace, context.scope, receiverType, nameExpression, context.expectedType); + VariableDescriptor variableDescriptor = callResolver.resolveSimpleProperty(temporaryTrace, context.scope, receiver, nameExpression, context.expectedType); if (variableDescriptor != null) { temporaryTrace.commit(); return context.services.checkEnrichedType(variableDescriptor.getOutType(), nameExpression, context); } - TypeInferenceContext newContext = receiverType == null ? context : context.replaceScope(receiverType.getMemberScope()); + TypeInferenceContext newContext = receiver.exists() ? context.replaceScope(receiver.getType().getMemberScope()) : context; JetType jetType = lookupNamespaceOrClassObject(nameExpression, nameExpression.getReferencedName(), newContext); if (jetType == null) { context.trace.report(UNRESOLVED_REFERENCE.on(nameExpression)); @@ -2169,10 +2187,11 @@ public class JetTypeInferrer { } else if (selectorExpression instanceof JetQualifiedExpression) { JetQualifiedExpression qualifiedExpression = (JetQualifiedExpression) selectorExpression; - JetType newReceiverType = getSelectorReturnType(receiverType, qualifiedExpression.getReceiverExpression(), context.replaceExpectedType(NO_EXPECTED_TYPE)); + JetExpression newReceiverExpression = qualifiedExpression.getReceiverExpression(); + JetType newReceiverType = getSelectorReturnType(receiver, newReceiverExpression, context.replaceExpectedType(NO_EXPECTED_TYPE)); JetExpression newSelectorExpression = qualifiedExpression.getSelectorExpression(); if (newReceiverType != null && newSelectorExpression != null) { - return getSelectorReturnType(newReceiverType, newSelectorExpression, context); + return getSelectorReturnType(new ExpressionReceiver(newReceiverExpression, newReceiverType), newSelectorExpression, context); } } else { @@ -2185,7 +2204,7 @@ public class JetTypeInferrer { @Override public JetType visitCallExpression(JetCallExpression expression, TypeInferenceContext context) { - JetType expressionType = callResolver.resolveCall(context.trace, context.scope, null, expression, context.expectedType); + JetType expressionType = callResolver.resolveCall(context.trace, context.scope, ReceiverDescriptor.NO_RECEIVER, expression, context.expectedType); return context.services.checkType(expressionType, expression, context); } @@ -2219,8 +2238,8 @@ public class JetTypeInferrer { context.trace.report(UNSUPPORTED.on(operationSign, "visitUnaryExpression")); return null; } - JetType receiverType = getType(baseExpression, context.replaceExpectedType(NO_EXPECTED_TYPE).replaceScope(context.scope)); - if (receiverType == null) return null; + ExpressionReceiver receiver = getExpressionReceiver(baseExpression, context.replaceExpectedType(NO_EXPECTED_TYPE).replaceScope(context.scope)); + if (receiver == null) return null; FunctionDescriptor functionDescriptor = callResolver.resolveCallWithGivenName( context.trace, @@ -2228,7 +2247,7 @@ public class JetTypeInferrer { CallMaker.makeCall(expression), expression.getOperationSign(), name, - receiverType, + receiver, context.expectedType); if (functionDescriptor == null) return null; @@ -2239,6 +2258,7 @@ public class JetTypeInferrer { result = JetStandardClasses.getUnitType(); } else { + JetType receiverType = receiver.getType(); if (!semanticServices.getTypeChecker().isSubtypeOf(returnType, receiverType)) { // context.trace.getErrorHandler().genericError(operationSign.getNode(), name + " must return " + receiverType + " but returns " + returnType); context.trace.report(RESULT_TYPE_MISMATCH.on(operationSign, name, receiverType, returnType)); @@ -2298,9 +2318,9 @@ public class JetTypeInferrer { else if (equalsOperations.contains(operationType)) { String name = "equals"; if (right != null) { - JetType leftType = safeGetType(left, context.replaceScope(context.scope)); + ExpressionReceiver receiver = safeGetExpressionReceiver(left, context.replaceScope(context.scope)); OverloadResolutionResult resolutionResult = callResolver.resolveExactSignature( - context.scope, leftType, "equals", + context.scope, receiver, "equals", Collections.singletonList(JetStandardClasses.getNullableAnyType())); if (resolutionResult.isSuccess()) { FunctionDescriptor equals = resolutionResult.getDescriptor(); @@ -2379,13 +2399,13 @@ public class JetTypeInferrer { private void checkInExpression(JetSimpleNameExpression operationSign, JetExpression left, JetExpression right, TypeInferenceContext context) { String name = "contains"; - JetType receiverType = context.services.safeGetType(context.scope, right, NO_EXPECTED_TYPE); + ExpressionReceiver receiver = safeGetExpressionReceiver(right, context.replaceExpectedType(NO_EXPECTED_TYPE)); FunctionDescriptor functionDescriptor = callResolver.resolveCallWithGivenName( context.trace, context.scope, CallMaker.makeCall(operationSign, Collections.singletonList(left)), operationSign, - name, receiverType, context.expectedType); + name, receiver, context.expectedType); JetType containsType = functionDescriptor != null ? functionDescriptor.getReturnType() : null; ensureBooleanResult(operationSign, name, containsType, context); } @@ -2448,16 +2468,16 @@ public class JetTypeInferrer { public JetType visitArrayAccessExpression(JetArrayAccessExpression expression, TypeInferenceContext contextWithExpectedType) { TypeInferenceContext context = contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE); JetExpression arrayExpression = expression.getArrayExpression(); - JetType receiverType = getType(arrayExpression, context.replaceScope(context.scope)); + ExpressionReceiver receiver = getExpressionReceiver(arrayExpression, context.replaceScope(context.scope)); - if (receiverType != null) { + if (receiver != null) { FunctionDescriptor functionDescriptor = callResolver.resolveCallWithGivenName( context.trace, context.scope, CallMaker.makeCall(expression, expression.getIndexExpressions()), expression, "get", - receiverType, + receiver, context.expectedType); if (functionDescriptor != null) { return context.services.checkType(functionDescriptor.getReturnType(), expression, contextWithExpectedType); @@ -2468,17 +2488,17 @@ public class JetTypeInferrer { @Nullable protected JetType getTypeForBinaryCall(JetScope scope, String name, TypeInferenceContext context, JetBinaryExpression binaryExpression) { - JetType leftType = getType(binaryExpression.getLeft(), context.replaceScope(scope)); + ExpressionReceiver receiver = safeGetExpressionReceiver(binaryExpression.getLeft(), context.replaceScope(scope)); FunctionDescriptor functionDescriptor = callResolver.resolveCallWithGivenName( context.trace, scope, CallMaker.makeCall(binaryExpression), binaryExpression.getOperationReference(), name, - leftType, + receiver, context.expectedType); if (functionDescriptor != null) { - if (leftType != null && leftType.isNullable()) { + if (receiver.getType().isNullable()) { // TODO : better error message for '1 + nullableVar' case JetExpression right = binaryExpression.getRight(); String rightText = right == null ? "" : right.getText(); @@ -2718,8 +2738,8 @@ public class JetTypeInferrer { } private JetType resolveArrayAccessToLValue(JetArrayAccessExpression arrayAccessExpression, JetExpression rightHandSide, JetSimpleNameExpression operationSign, TypeInferenceContext context) { - JetType receiverType = getType(arrayAccessExpression.getArrayExpression(), context.replaceScope(scope)); - if (receiverType == null) return null; + ExpressionReceiver receiver = getExpressionReceiver(arrayAccessExpression.getArrayExpression(), context.replaceScope(scope)); + if (receiver == null) return null; // Call call = CallMaker.makeCall(arrayAccessExpression, rightHandSide); // // TODO : nasty hack: effort is duplicated @@ -2733,7 +2753,7 @@ public class JetTypeInferrer { scope, call, arrayAccessExpression, - "set", receiverType, NO_EXPECTED_TYPE); + "set", receiver, NO_EXPECTED_TYPE); if (functionDescriptor == null) return null; context.trace.record(REFERENCE_TARGET, operationSign, functionDescriptor); return context.services.checkType(functionDescriptor.getReturnType(), arrayAccessExpression, context); diff --git a/compiler/frontend/src/org/jetbrains/jet/resolve/DescriptorRenderer.java b/compiler/frontend/src/org/jetbrains/jet/resolve/DescriptorRenderer.java index 31653945c8a..32dcfce68ab 100644 --- a/compiler/frontend/src/org/jetbrains/jet/resolve/DescriptorRenderer.java +++ b/compiler/frontend/src/org/jetbrains/jet/resolve/DescriptorRenderer.java @@ -3,7 +3,9 @@ package org.jetbrains.jet.resolve; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.*; -import org.jetbrains.jet.lang.types.*; +import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; +import org.jetbrains.jet.lang.types.JetStandardClasses; +import org.jetbrains.jet.lang.types.JetType; import java.util.Collection; import java.util.Collections; @@ -128,7 +130,7 @@ public class DescriptorRenderer { @Override public Void visitVariableDescriptor(VariableDescriptor descriptor, StringBuilder builder) { - String typeString = renderPropertyPrefixAndComputeTypeString(builder, Collections.emptyList(), null, descriptor.getOutType(), descriptor.getInType()); + String typeString = renderPropertyPrefixAndComputeTypeString(builder, Collections.emptyList(), ReceiverDescriptor.NO_RECEIVER, descriptor.getOutType(), descriptor.getInType()); renderName(descriptor, builder); builder.append(" : ").append(escape(typeString)); return super.visitVariableDescriptor(descriptor, builder); @@ -137,7 +139,7 @@ public class DescriptorRenderer { private String renderPropertyPrefixAndComputeTypeString( @NotNull StringBuilder builder, @NotNull List typeParameters, - @Nullable JetType receiverType, + @NotNull ReceiverDescriptor receiver, @Nullable JetType outType, @Nullable JetType inType) { String typeString = lt() + "no type>"; @@ -161,8 +163,8 @@ public class DescriptorRenderer { renderTypeParameters(typeParameters, builder); - if (receiverType != null) { - builder.append(escape(renderType(receiverType))).append("."); + if (receiver.exists()) { + builder.append(escape(renderType(receiver.getType()))).append("."); } return typeString; @@ -172,7 +174,7 @@ public class DescriptorRenderer { public Void visitPropertyDescriptor(PropertyDescriptor descriptor, StringBuilder builder) { String typeString = renderPropertyPrefixAndComputeTypeString( builder, descriptor.getTypeParameters(), - descriptor.getReceiverType(), + descriptor.getReceiver(), descriptor.getOutType(), descriptor.getInType()); renderName(descriptor, builder); @@ -185,9 +187,9 @@ public class DescriptorRenderer { builder.append(renderKeyword("fun")).append(" "); renderTypeParameters(descriptor.getTypeParameters(), builder); - JetType receiverType = descriptor.getReceiverType(); - if (receiverType != null) { - builder.append(escape(renderType(receiverType))).append("."); + ReceiverDescriptor receiver = descriptor.getReceiver(); + if (receiver.exists()) { + builder.append(escape(renderType(receiver.getType()))).append("."); } renderName(descriptor, builder); diff --git a/idea/testData/checkerWithErrorTypes/quick/AutoCreatedIt.jet b/idea/testData/checkerWithErrorTypes/quick/AutoCreatedIt.jet index 66c9e1f9543..ef474b07d54 100644 --- a/idea/testData/checkerWithErrorTypes/quick/AutoCreatedIt.jet +++ b/idea/testData/checkerWithErrorTypes/quick/AutoCreatedIt.jet @@ -3,7 +3,7 @@ fun text() { "direct:a" on {it.body == ""} to "mock:a" "direct:a" on {it => it.body == ""} to "mock:a" bar {1} - bar {it + 1} + bar {it + 1} bar {it, it1 => it} bar1 {1} diff --git a/idea/tests/org/jetbrains/jet/resolve/JetResolveTest.java b/idea/tests/org/jetbrains/jet/resolve/JetResolveTest.java index d3678955b79..309b9e984bd 100644 --- a/idea/tests/org/jetbrains/jet/resolve/JetResolveTest.java +++ b/idea/tests/org/jetbrains/jet/resolve/JetResolveTest.java @@ -16,6 +16,7 @@ import org.jetbrains.jet.lang.cfg.JetFlowInformationProvider; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.resolve.BindingTraceContext; import org.jetbrains.jet.lang.resolve.calls.OverloadResolutionResult; +import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import org.jetbrains.jet.lang.types.*; import org.jetbrains.jet.parsing.JetParsingTest; @@ -106,7 +107,8 @@ public class JetResolveTest extends ExtensibleResolveTestCase { List parameterTypeList = Arrays.asList(parameterType); JetTypeInferrer.Services typeInferrerServices = JetSemanticServices.createSemanticServices(getProject()).getTypeInferrerServices(new BindingTraceContext(), JetFlowInformationProvider.NONE); - OverloadResolutionResult functions = typeInferrerServices.getCallResolver().resolveExactSignature(classDescriptor.getMemberScope(typeArguments), null, name, parameterTypeList); + OverloadResolutionResult functions = typeInferrerServices.getCallResolver().resolveExactSignature( + classDescriptor.getMemberScope(typeArguments), ReceiverDescriptor.NO_RECEIVER, name, parameterTypeList); for (FunctionDescriptor function : functions.getDescriptors()) { List unsubstitutedValueParameters = function.getValueParameters(); for (int i = 0, unsubstitutedValueParametersSize = unsubstitutedValueParameters.size(); i < unsubstitutedValueParametersSize; i++) { diff --git a/idea/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java b/idea/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java index 078051a6a6f..c5eee12fc5d 100644 --- a/idea/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java +++ b/idea/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java @@ -18,7 +18,7 @@ import org.jetbrains.jet.lang.resolve.*; import org.jetbrains.jet.lang.resolve.java.JavaPackageScope; import org.jetbrains.jet.lang.resolve.java.JavaSemanticServices; import org.jetbrains.jet.lang.resolve.scopes.*; -import org.jetbrains.jet.lang.resolve.scopes.receivers.ExplicitReceiver; +import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import org.jetbrains.jet.lang.types.*; import org.jetbrains.jet.lexer.JetTokens; @@ -504,13 +504,13 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase { assertTrue("Error type expected but " + type + " returned", ErrorUtils.isErrorType(type)); } - private void assertType(String contextType, String expression, String expectedType) { + private void assertType(String contextType, final String expression, String expectedType) { final JetType thisType = makeType(contextType); JetScope scope = new JetScopeAdapter(classDefinitions.BASIC_SCOPE) { @NotNull @Override public ReceiverDescriptor getImplicitReceiver() { - return new ExplicitReceiver(thisType); + return new ExpressionReceiver(JetPsiFactory.createExpression(getProject(), expression), thisType); } }; assertType(scope, expression, expectedType);