Don't convert type to the same type (#11122)

This commit is contained in:
Jaroslav Tulach 2024-09-18 18:15:58 +02:00 committed by GitHub
parent 859b572242
commit 37688033c8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 83 additions and 3 deletions

View File

@ -0,0 +1,71 @@
package org.enso.interpreter.test;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.core.AllOf.allOf;
import static org.junit.Assert.fail;
import org.enso.common.MethodNames;
import org.enso.test.utils.ContextUtils;
import org.graalvm.polyglot.Context;
import org.graalvm.polyglot.PolyglotException;
import org.graalvm.polyglot.Source;
import org.graalvm.polyglot.Value;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
public class BinarySelfDispatchTest {
private static Context ctx;
private static Value module;
@BeforeClass
public static void initCtx() throws Exception {
ctx = ContextUtils.createDefaultContext();
var prelude =
Source.newBuilder(
"enso",
"""
from Standard.Base import all
type Delay
private Days n
type Datum
private On at delta
+ self (delta : Delay) -> Datum = Datum.On self.n delta.n
today_plus n =
delta = Delay.Days n
now = Datum.On 0 delta
now + now
""",
"error.enso")
.build();
module = ctx.eval(prelude);
}
@AfterClass
public static void closeCtx() {
module = null;
ctx.close();
ctx = null;
}
@Test
public void avoidSelfConversion() {
try {
var error = module.invokeMember(MethodNames.Module.EVAL_EXPRESSION, "today_plus 3");
fail("The code should yield a panic: " + error);
} catch (PolyglotException ex) {
assertThat(
"The error message is correct",
ex.getMessage(),
allOf(
containsString("expected `delta`"),
containsString("to be Delay"),
containsString("but got Datum")));
}
}
}

View File

@ -138,7 +138,7 @@ final class BinaryOperatorNode extends ExpressionNode {
@Shared("convert") @Cached InteropConversionCallNode convertNode, @Shared("convert") @Cached InteropConversionCallNode convertNode,
@Shared("invoke") @Cached(allowUncached = true, value = "buildWithArity(2)") @Shared("invoke") @Cached(allowUncached = true, value = "buildWithArity(2)")
InvokeFunctionNode invokeNode) { InvokeFunctionNode invokeNode) {
return doDispatch(frame, self, that, thatType, symbolFn, convertNode, invokeNode); return doDispatch(frame, self, that, selfType, thatType, symbolFn, convertNode, invokeNode);
} }
@Specialization(replaces = "doThatConversionCached") @Specialization(replaces = "doThatConversionCached")
@ -151,12 +151,15 @@ final class BinaryOperatorNode extends ExpressionNode {
@Shared("convert") @Cached InteropConversionCallNode convertNode, @Shared("convert") @Cached InteropConversionCallNode convertNode,
@Shared("invoke") @Cached(allowUncached = true, value = "buildWithArity(2)") @Shared("invoke") @Cached(allowUncached = true, value = "buildWithArity(2)")
InvokeFunctionNode invokeNode) { InvokeFunctionNode invokeNode) {
var selfType = findType(typeOfNode, self);
if (that instanceof EnsoMultiValue multi) { if (that instanceof EnsoMultiValue multi) {
for (var thatType : multi.allTypes()) { for (var thatType : multi.allTypes()) {
var fn = findSymbol(symbol, thatType); var fn = findSymbol(symbol, thatType);
if (fn != null) { if (fn != null) {
var thatCasted = EnsoMultiValue.CastToNode.getUncached().executeCast(thatType, multi); var thatCasted = EnsoMultiValue.CastToNode.getUncached().executeCast(thatType, multi);
var result = doDispatch(frame, self, thatCasted, thatType, fn, convertNode, invokeNode); var result =
doDispatch(
frame, self, thatCasted, selfType, thatType, fn, convertNode, invokeNode);
if (result != null) { if (result != null) {
return result; return result;
} }
@ -167,7 +170,8 @@ final class BinaryOperatorNode extends ExpressionNode {
if (thatType != null) { if (thatType != null) {
var fn = findSymbol(symbol, thatType); var fn = findSymbol(symbol, thatType);
if (fn != null) { if (fn != null) {
var result = doDispatch(frame, self, that, thatType, fn, convertNode, invokeNode); var result =
doDispatch(frame, self, that, selfType, thatType, fn, convertNode, invokeNode);
if (result != null) { if (result != null) {
return result; return result;
} }
@ -181,11 +185,16 @@ final class BinaryOperatorNode extends ExpressionNode {
VirtualFrame frame, VirtualFrame frame,
Object self, Object self,
Object that, Object that,
Type selfType,
Type thatType, Type thatType,
Function symbolFn, Function symbolFn,
InteropConversionCallNode convertNode, InteropConversionCallNode convertNode,
InvokeFunctionNode invokeNode) InvokeFunctionNode invokeNode)
throws PanicException { throws PanicException {
if (selfType == thatType) {
// conversions won't help
return null;
}
var convert = UnresolvedConversion.build(thatType.getDefinitionScope()); var convert = UnresolvedConversion.build(thatType.getDefinitionScope());
var ctx = EnsoContext.get(this); var ctx = EnsoContext.get(this);