diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/meta/EqualsComplexNode.java b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/meta/EqualsComplexNode.java index d8bccb0a2114..20840f678770 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/meta/EqualsComplexNode.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/meta/EqualsComplexNode.java @@ -27,6 +27,8 @@ import org.enso.interpreter.runtime.data.EnsoFile; import org.enso.interpreter.runtime.data.Type; import org.enso.interpreter.runtime.data.atom.Atom; +import org.enso.interpreter.runtime.data.hash.EnsoHashMap; +import org.enso.interpreter.runtime.data.hash.HashMapInsertAllNode; import org.enso.interpreter.runtime.library.dispatch.TypesLibrary; import org.enso.interpreter.runtime.scope.ModuleScope; import org.enso.interpreter.runtime.warning.WarningsLibrary; @@ -112,17 +114,28 @@ EqualsAndInfo equalsWithWarnings( Object otherWithWarnings, @CachedLibrary("selfWithWarnings") WarningsLibrary selfWarnLib, @CachedLibrary("otherWithWarnings") WarningsLibrary otherWarnLib, - @Shared("equalsNode") @Cached EqualsSimpleNode equalsNode) { + @Shared("equalsNode") @Cached EqualsSimpleNode equalsNode, + @Cached HashMapInsertAllNode insertAllNode) { try { - Object self = - selfWarnLib.hasWarnings(selfWithWarnings) - ? selfWarnLib.removeWarnings(selfWithWarnings) - : selfWithWarnings; - Object other = - otherWarnLib.hasWarnings(otherWithWarnings) - ? otherWarnLib.removeWarnings(otherWithWarnings) - : otherWithWarnings; - return equalsNode.execute(frame, self, other); + var all = EnsoHashMap.empty(); + var max = EnsoContext.get(this).getWarningsLimit(); + Object self = selfWithWarnings; + Object other = otherWithWarnings; + if (selfWarnLib.hasWarnings(selfWithWarnings)) { + self = selfWarnLib.removeWarnings(selfWithWarnings); + var toAdd = selfWarnLib.getWarnings(selfWithWarnings, false); + all = insertAllNode.executeInsertAll(frame, all, toAdd, max); + } + if (otherWarnLib.hasWarnings(otherWithWarnings)) { + other = otherWarnLib.removeWarnings(otherWithWarnings); + var toAdd = otherWarnLib.getWarnings(otherWithWarnings, false); + all = insertAllNode.executeInsertAll(frame, all, toAdd, max); + } + var res = equalsNode.execute(frame, self, other); + if (res.warnings() != null) { + all = insertAllNode.executeInsertAll(frame, all, res.warnings(), max); + } + return new EqualsAndInfo(res.equals(), all); } catch (UnsupportedMessageException e) { throw EnsoContext.get(this).raiseAssertionPanic(this, null, e); } diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/meta/EqualsNode.java b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/meta/EqualsNode.java index cdbd05b9d8cb..3b33c104a12e 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/meta/EqualsNode.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/meta/EqualsNode.java @@ -126,7 +126,7 @@ static WithConversionNode create() { * @return {code false} if the conversion makes no sense or result of equality check after doing * the conversion */ - abstract boolean executeWithConversion(VirtualFrame frame, Object self, Object that); + abstract Object executeWithConversion(VirtualFrame frame, Object self, Object that); static Type findType(TypeOfNode typeOfNode, Object obj) { var rawType = typeOfNode.execute(obj); @@ -212,7 +212,7 @@ private static boolean findConversionImpl( "selfType == findType(typeOfNode, self)", "thatType == findType(typeOfNode, that)" }) - final boolean doConversionCached( + final Object doConversionCached( VirtualFrame frame, Object self, Object that, @@ -223,45 +223,48 @@ final boolean doConversionCached( Type thatType, @Cached("findConversions(selfType, thatType, self, that)") Boolean convert, @Shared("convert") @Cached InteropConversionCallNode convertNode, - @Shared("invoke") @Cached(allowUncached = true) EqualsSimpleNode equalityNode) { + @Shared("invoke") @Cached(allowUncached = true) EqualsSimpleNode equalityNode, + @Shared("warn") @Cached(allowUncached = true) AppendWarningNode warningsNode) { if (convert == null) { return false; } if (convert) { - return doDispatch(frame, that, self, thatType, convertNode, equalityNode); + return doDispatch(frame, that, self, thatType, convertNode, equalityNode, warningsNode); } else { - return doDispatch(frame, self, that, selfType, convertNode, equalityNode); + return doDispatch(frame, self, that, selfType, convertNode, equalityNode, warningsNode); } } @Specialization(replaces = "doConversionCached") - final boolean doConversionUncached( + final Object doConversionUncached( VirtualFrame frame, Object self, Object that, @Shared("typeOf") @Cached TypeOfNode typeOfNode, @Shared("convert") @Cached InteropConversionCallNode convertNode, - @Shared("invoke") @Cached(allowUncached = true) EqualsSimpleNode equalityNode) { + @Shared("invoke") @Cached(allowUncached = true) EqualsSimpleNode equalityNode, + @Shared("warn") @Cached(allowUncached = true) AppendWarningNode warningsNode) { var selfType = findType(typeOfNode, self); var thatType = findType(typeOfNode, that); var conv = findConversions(selfType, thatType, self, that); if (conv != null) { var result = conv - ? doDispatch(frame, that, self, thatType, convertNode, equalityNode) - : doDispatch(frame, self, that, selfType, convertNode, equalityNode); + ? doDispatch(frame, that, self, thatType, convertNode, equalityNode, warningsNode) + : doDispatch(frame, self, that, selfType, convertNode, equalityNode, warningsNode); return result; } return false; } - private boolean doDispatch( + private Object doDispatch( VirtualFrame frame, Object self, Object that, Type selfType, InteropConversionCallNode convertNode, - EqualsSimpleNode equalityNode) + EqualsSimpleNode equalityNode, + AppendWarningNode warnings) throws PanicException { var convert = UnresolvedConversion.build(selfType.getDefinitionScope()); @@ -269,9 +272,14 @@ private boolean doDispatch( var state = State.create(ctx); try { var thatAsSelf = convertNode.execute(convert, state, new Object[] {selfType, that}); - var result = equalityNode.execute(frame, self, thatAsSelf).equals(); + var withInfo = equalityNode.execute(frame, self, thatAsSelf); + var result = withInfo.equals(); assert !result || assertHashCodeIsTheSame(that, thatAsSelf); - return result; + if (withInfo.warnings() != null) { + return warnings.executeAppend(frame, result, withInfo.warnings()); + } else { + return result; + } } catch (ArityException ex) { var assertsOn = false; assert assertsOn = true;