REPL overload resolution ambiguity

Fix overload resolution ambiguity in REPL. Note, resolution for
functions declared in script is very different from regular programs:
in scripts function declared later wins. See
functionOverloadResolutionAnyBeatsString for example.

#KT-2272 Fixed
This commit is contained in:
Stepan Koltsov
2012-06-14 14:06:17 +04:00
parent 441e975323
commit 1d0ef01eea
7 changed files with 53 additions and 2 deletions
@@ -43,6 +43,7 @@ import org.jetbrains.jet.lang.resolve.AnalyzerScriptParameter;
import org.jetbrains.jet.lang.resolve.AnalyzingUtils;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.BindingTraceContext;
import org.jetbrains.jet.lang.resolve.ScriptHeaderResolver;
import org.jetbrains.jet.lang.resolve.TopDownAnalysisParameters;
import org.jetbrains.jet.lang.resolve.TraceBasedRedeclarationHandler;
import org.jetbrains.jet.lang.resolve.java.CompilerDependencies;
@@ -150,6 +151,8 @@ public class ReplInterpreter {
injector.getTopDownAnalyzer().prepareForTheNextReplLine();
psiFile.getScript().putUserData(ScriptHeaderResolver.PRIORITY_KEY, lineNumber);
ScriptDescriptor scriptDescriptor = doAnalyze(psiFile);
Progress backendProgress = new Progress() {
@@ -34,14 +34,17 @@ import java.util.List;
public class ScriptDescriptor extends DeclarationDescriptorImpl {
private static final Name NAME = Name.special("<script>");
private final int priority;
private JetType returnType;
private List<ValueParameterDescriptor> valueParameters;
private final ScriptCodeDescriptor scriptCodeDescriptor = new ScriptCodeDescriptor(this);
private final ReceiverDescriptor implicitReceiver = new ScriptReceiver(this);
public ScriptDescriptor(@Nullable DeclarationDescriptor containingDeclaration) {
public ScriptDescriptor(@Nullable DeclarationDescriptor containingDeclaration, int priority) {
super(containingDeclaration, Collections.<AnnotationDescriptor>emptyList(), NAME);
this.priority = priority;
}
public void initialize(@NotNull JetType returnType) {
@@ -49,6 +52,10 @@ public class ScriptDescriptor extends DeclarationDescriptorImpl {
scriptCodeDescriptor.initialize(implicitReceiver, valueParameters, returnType);
}
public int getPriority() {
return priority;
}
@NotNull
public JetType getReturnType() {
return returnType;
@@ -17,6 +17,7 @@
package org.jetbrains.jet.lang.resolve;
import com.google.common.collect.Lists;
import com.intellij.openapi.util.Key;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
@@ -50,6 +51,8 @@ import static org.jetbrains.jet.lang.types.TypeUtils.NO_EXPECTED_TYPE;
*/
public class ScriptHeaderResolver {
public static final Key<Integer> PRIORITY_KEY = Key.create(JetScript.class.getName() + ".priority");
@NotNull
private NamespaceFactory namespaceFactory;
@NotNull
@@ -118,7 +121,13 @@ public class ScriptHeaderResolver {
public void processScriptHierarchy(@NotNull JetScript script, @NotNull JetScope outerScope) {
NamespaceDescriptorImpl ns = namespaceFactory.createNamespaceDescriptorPathIfNeeded(FqName.ROOT);
ScriptDescriptor scriptDescriptor = new ScriptDescriptor(ns);
Integer priority = script.getUserData(PRIORITY_KEY);
if (priority == null) {
priority = 0;
}
ScriptDescriptor scriptDescriptor = new ScriptDescriptor(ns, priority);
//WriteThroughScope scriptScope = new WriteThroughScope(
// outerScope, ns.getMemberScope(), new TraceBasedRedeclarationHandler(trace));
WritableScopeImpl scriptScope = new WritableScopeImpl(outerScope, scriptDescriptor, RedeclarationHandler.DO_NOTHING, "script");
@@ -21,6 +21,7 @@ import gnu.trove.TObjectHashingStrategy;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
import org.jetbrains.jet.lang.descriptors.ScriptDescriptor;
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.OverridingUtil;
@@ -80,6 +81,15 @@ public class OverloadingConflictResolver {
* Int < Short < Byte
*/
private <Descriptor extends CallableDescriptor> boolean moreSpecific(Descriptor f, Descriptor g, boolean discriminateGenericDescriptors) {
if (f.getContainingDeclaration() instanceof ScriptDescriptor && g.getContainingDeclaration() instanceof ScriptDescriptor) {
ScriptDescriptor fs = (ScriptDescriptor) f.getContainingDeclaration();
ScriptDescriptor gs = (ScriptDescriptor) g.getContainingDeclaration();
if (fs.getPriority() != gs.getPriority()) {
return fs.getPriority() > gs.getPriority();
}
}
if (discriminateGenericDescriptors && !isGeneric(f) && isGeneric(g)) return true;
if (OverridingUtil.overrides(f, g)) return true;
if (OverridingUtil.overrides(g, f)) return false;
@@ -0,0 +1,6 @@
>>> fun foo() = 10
null
>>> fun foo() = 11
null
>>> foo()
11
@@ -0,0 +1,6 @@
>>> fun foo(s: String) = "string"
null
>>> fun foo(a: Any) = "any"
null
>>> foo("a")
any
@@ -92,6 +92,16 @@ public class ReplInterpreterTest {
testFile("twoClosures.repl");
}
@Test
public void functionOverloadResolutionAnyBeatsString() {
testFile("functionOverloadResolutionAnyBeatsString.repl");
}
@Test
public void functionOverloadResolution() {
testFile("functionOverloadResolution.repl");
}
@Test
public void empty() {
testFile("empty.repl");