From d7f6b6da0d3c24175bc8c75bd2198114fb683380 Mon Sep 17 00:00:00 2001 From: Jaroslav Tulach Date: Tue, 28 Jan 2025 14:56:27 +0100 Subject: [PATCH 01/12] Making indexStdLibs independent of createEnginePackage --- build.sbt | 62 ++++++++++--------------------- project/DistributionPackage.scala | 14 +------ 2 files changed, 21 insertions(+), 55 deletions(-) diff --git a/build.sbt b/build.sbt index 170ec271e8fb..21de3fd2159b 100644 --- a/build.sbt +++ b/build.sbt @@ -5125,34 +5125,29 @@ launcherDistributionRoot := packageBuilder.localArtifact("launcher") / "enso" projectManagerDistributionRoot := packageBuilder.localArtifact("project-manager") / "enso" -lazy val createEnginePackage = - taskKey[Unit]("Creates the engine distribution package") +lazy val createEngineIndex = + taskKey[Unit]("Creates index files for standard libraries") createEnginePackage := { updateLibraryManifests.value buildEngineDistributionNoIndex.value - val modulesToCopy = componentModulesPaths.value - val root = engineDistributionRoot.value - val log = streams.value.log - val cacheFactory = streams.value.cacheStoreFactory - DistributionPackage.createEnginePackage( - distributionRoot = root, - cacheFactory = cacheFactory, - log = log, - jarModulesToCopy = modulesToCopy, - graalVersion = graalMavenPackagesVersion, - javaVersion = graalVersion, - ensoVersion = ensoVersion, - editionName = currentEdition, - sourceStdlibVersion = stdLibVersion, - targetStdlibVersion = targetStdlibVersion, - targetDir = (`syntax-rust-definition` / rustParserTargetDirectory).value, - generateIndex = true - ) - log.info(s"Engine package created at $root") + val modulesToCopy = componentModulesPaths.value + val distributionRoot = engineDistributionRoot.value + val log = streams.value.log + val cacheFactory = streams.value.cacheStoreFactory + + DistributionPackage.indexStdLibs( + stdLibVersion = targetStdlibVersion, + ensoVersion = ensoVersion, + stdLibRoot = distributionRoot / "lib", + ensoExecutable = distributionRoot / "bin" / "enso", + cacheFactory = cacheFactory.sub("stdlib"), + log = log + ) + log.info(s"Standard library indexes create for $root") } -ThisBuild / createEnginePackage := { - createEnginePackage.result.value +ThisBuild / createEngineIndex := { + createEngineIndex.result.value } lazy val createEnginePackageNoIndex = @@ -5199,25 +5194,7 @@ buildEngineDistributionNoIndex := Def.taskIf { // of other tasks. ThisBuild / buildEngineDistributionNoIndex := { updateLibraryManifests.value - val modulesToCopy = componentModulesPaths.value - val root = engineDistributionRoot.value - val log = streams.value.log - val cacheFactory = streams.value.cacheStoreFactory - DistributionPackage.createEnginePackage( - distributionRoot = root, - cacheFactory = cacheFactory, - log = log, - jarModulesToCopy = modulesToCopy, - graalVersion = graalMavenPackagesVersion, - javaVersion = graalVersion, - ensoVersion = ensoVersion, - editionName = currentEdition, - sourceStdlibVersion = stdLibVersion, - targetStdlibVersion = targetStdlibVersion, - targetDir = (`syntax-rust-definition` / rustParserTargetDirectory).value, - generateIndex = false - ) - log.info(s"Engine package created at $root") + createEnginePackage.value } lazy val shouldBuildNativeImage = taskKey[Boolean]( @@ -5257,6 +5234,7 @@ lazy val buildEngineDistribution = buildEngineDistribution := { buildEngineDistributionNoIndex.value createEnginePackage.value + createEngineIndex.value } // This makes the buildEngineDistributionNoIndex task usable as a dependency diff --git a/project/DistributionPackage.scala b/project/DistributionPackage.scala index 5af65ec471e3..510d489facc8 100644 --- a/project/DistributionPackage.scala +++ b/project/DistributionPackage.scala @@ -137,8 +137,7 @@ object DistributionPackage { editionName: String, sourceStdlibVersion: String, targetStdlibVersion: String, - targetDir: File, - generateIndex: Boolean + targetDir: File ): Unit = { copyDirectoryIncremental( file("distribution/engine/THIRD-PARTY"), @@ -195,17 +194,6 @@ object DistributionPackage { graalVersion = graalVersion, javaVersion = javaVersion ) - - if (generateIndex) { - indexStdLibs( - stdLibVersion = targetStdlibVersion, - ensoVersion = ensoVersion, - stdLibRoot = distributionRoot / "lib", - ensoExecutable = distributionRoot / "bin" / "enso", - cacheFactory = cacheFactory.sub("stdlib"), - log = log - ) - } } def indexStdLibs( From db70cbbc7161536edc0f8245b3dbead6527e805e Mon Sep 17 00:00:00 2001 From: Jaroslav Tulach Date: Tue, 28 Jan 2025 15:31:38 +0100 Subject: [PATCH 02/12] Renaming to +createStdLibsIndexes --- build.sbt | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/build.sbt b/build.sbt index 21de3fd2159b..2b4b6eb99ade 100644 --- a/build.sbt +++ b/build.sbt @@ -5125,9 +5125,9 @@ launcherDistributionRoot := packageBuilder.localArtifact("launcher") / "enso" projectManagerDistributionRoot := packageBuilder.localArtifact("project-manager") / "enso" -lazy val createEngineIndex = +lazy val createStdLibsIndexes = taskKey[Unit]("Creates index files for standard libraries") -createEnginePackage := { +createStdLibsIndexes := { updateLibraryManifests.value buildEngineDistributionNoIndex.value val modulesToCopy = componentModulesPaths.value @@ -5143,11 +5143,11 @@ createEnginePackage := { cacheFactory = cacheFactory.sub("stdlib"), log = log ) - log.info(s"Standard library indexes create for $root") + log.info(s"Standard library indexes create for $distributionRoot") } -ThisBuild / createEngineIndex := { - createEngineIndex.result.value +ThisBuild / createStdLibsIndexes := { + createStdLibsIndexes.result.value } lazy val createEnginePackageNoIndex = @@ -5169,8 +5169,7 @@ createEnginePackageNoIndex := { editionName = currentEdition, sourceStdlibVersion = stdLibVersion, targetStdlibVersion = targetStdlibVersion, - targetDir = (`syntax-rust-definition` / rustParserTargetDirectory).value, - generateIndex = false + targetDir = (`syntax-rust-definition` / rustParserTargetDirectory).value ) log.info(s"Engine package created at $root") } @@ -5194,7 +5193,7 @@ buildEngineDistributionNoIndex := Def.taskIf { // of other tasks. ThisBuild / buildEngineDistributionNoIndex := { updateLibraryManifests.value - createEnginePackage.value + createEnginePackageNoIndex.value } lazy val shouldBuildNativeImage = taskKey[Boolean]( @@ -5233,8 +5232,8 @@ lazy val buildEngineDistribution = taskKey[Unit]("Builds the engine distribution") buildEngineDistribution := { buildEngineDistributionNoIndex.value - createEnginePackage.value - createEngineIndex.value + createEnginePackageNoIndex.value + createStdLibsIndexes.value } // This makes the buildEngineDistributionNoIndex task usable as a dependency From 1eae6e49c5e4fcb07d3c7044f6635c64bde5f4d7 Mon Sep 17 00:00:00 2001 From: Jaroslav Tulach Date: Tue, 28 Jan 2025 16:16:58 +0100 Subject: [PATCH 03/12] Test invoking an identity method on Any to confuse EnsoMultiValue --- test/Base_Tests/src/Semantic/Multi_Value_Spec.enso | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/Base_Tests/src/Semantic/Multi_Value_Spec.enso b/test/Base_Tests/src/Semantic/Multi_Value_Spec.enso index b78a1be127f6..28df4479ea8e 100644 --- a/test/Base_Tests/src/Semantic/Multi_Value_Spec.enso +++ b/test/Base_Tests/src/Semantic/Multi_Value_Spec.enso @@ -34,6 +34,10 @@ add_specs suite_builder = c = Complex.new 1.5 0.0 (c:Complex).re . should_equal 1.5 (c:Float) . should_equal 1.5 + group_builder.specify "Complex & Float remain after instance method invocation" <| + c = Complex.new 1.5 0.0 . confuse_me + (c:Complex).re . should_equal 1.5 + (c:Float) . should_equal 1.5 suite_builder.group "Chain Multi Value" group_builder-> to_b_to_c obj = @@ -173,6 +177,8 @@ add_specs suite_builder = Test.expect_panic Type_Error <| a : C +Any.confuse_me self = self + main filter=Nothing = suite = Test.build suite_builder-> add_specs suite_builder From 9b83c85201cfc36331ce9be72b5cdf606a4f0c37 Mon Sep 17 00:00:00 2001 From: Jaroslav Tulach Date: Tue, 28 Jan 2025 16:20:28 +0100 Subject: [PATCH 04/12] Use first method available on Any, if found --- .../java/org/enso/interpreter/runtime/data/EnsoMultiValue.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoMultiValue.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoMultiValue.java index 06257b80987e..b08aefab41a7 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoMultiValue.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoMultiValue.java @@ -599,6 +599,9 @@ public final Pair resolveSymbol( for (var t : EnsoMultiType.AllTypesWith.getUncached().executeAllTypes(dispatch, null, 0)) { var fnAndType = node.execute(t, symbol); if (fnAndType != null) { + if (fnAndType.getRight() == ctx.getBuiltins().any()) { + return fnAndType; + } if (dispatch.typesLength() == 1 || fnAndType.getRight() != ctx.getBuiltins().any()) { return Pair.create(fnAndType.getLeft(), t); } From 00b6aa65264b8a978d5907c580d443c9c1cd7a09 Mon Sep 17 00:00:00 2001 From: Jaroslav Tulach Date: Tue, 28 Jan 2025 17:15:53 +0100 Subject: [PATCH 05/12] Select first non-Any method. Use Any method only as a fallback --- .../interpreter/runtime/data/EnsoMultiValue.java | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoMultiValue.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoMultiValue.java index b08aefab41a7..861e32d26a6c 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoMultiValue.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/EnsoMultiValue.java @@ -595,19 +595,21 @@ public final Object findTypeOrNull( public final Pair resolveSymbol( MethodResolverNode node, UnresolvedSymbol symbol) { var ctx = EnsoContext.get(node); - Pair foundAnyMethod = null; + Pair fallbackToAnyMethod = null; for (var t : EnsoMultiType.AllTypesWith.getUncached().executeAllTypes(dispatch, null, 0)) { var fnAndType = node.execute(t, symbol); if (fnAndType != null) { - if (fnAndType.getRight() == ctx.getBuiltins().any()) { + if (fnAndType.getRight() != ctx.getBuiltins().any()) { + // if there is a non-Any method available in any of the + // dispach types, then use it! return fnAndType; } - if (dispatch.typesLength() == 1 || fnAndType.getRight() != ctx.getBuiltins().any()) { - return Pair.create(fnAndType.getLeft(), t); + if (fallbackToAnyMethod == null) { + // remember a suitable method on Any + fallbackToAnyMethod = fnAndType; } - foundAnyMethod = fnAndType; } } - return foundAnyMethod; + return fallbackToAnyMethod; } } From 6f3e3f974b82a055252be69bd556fd3dddbe9621 Mon Sep 17 00:00:00 2001 From: Jaroslav Tulach Date: Tue, 28 Jan 2025 17:16:36 +0100 Subject: [PATCH 06/12] Extract first value of EnsoMultiValue and call to_text on it --- .../builtin/text/AnyToTextNode.java | 28 ++++++++++++++----- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/text/AnyToTextNode.java b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/text/AnyToTextNode.java index d398f7fe4456..b5ff158f000d 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/text/AnyToTextNode.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/text/AnyToTextNode.java @@ -1,14 +1,16 @@ package org.enso.interpreter.node.expression.builtin.text; import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.GenerateUncached; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.interop.InteropLibrary; import com.oracle.truffle.api.interop.UnsupportedMessageException; -import com.oracle.truffle.api.library.CachedLibrary; import com.oracle.truffle.api.nodes.Node; import org.enso.interpreter.dsl.BuiltinMethod; +import org.enso.interpreter.runtime.EnsoContext; +import org.enso.interpreter.runtime.data.EnsoMultiValue; import org.enso.interpreter.runtime.data.atom.Atom; import org.enso.interpreter.runtime.data.atom.AtomConstructor; import org.enso.interpreter.runtime.data.atom.StructsLibrary; @@ -33,10 +35,22 @@ Text doAtom(Atom at) { } } + @Specialization + Text doMultiValue( + EnsoMultiValue mv, + @Cached EnsoMultiValue.CastToNode castToNode, + @Cached AnyToTextNode toTextNode) { + var ctx = EnsoContext.get(this); + var any = ctx.getBuiltins().any(); + var first = castToNode.findTypeOrNull(any, mv, false, false); + assert first != null; + return toTextNode.execute(first); + } + @Fallback - Text doOther(Object object, @CachedLibrary(limit = "5") InteropLibrary interop) { + Text doOther(Object object) { try { - return Text.create(showObject(object, interop)); + return Text.create(showObject(object)); } catch (UnsupportedMessageException e) { CompilerDirectives.transferToInterpreter(); return Text.create(object.toString()); @@ -55,14 +69,14 @@ private Text doComplexAtom(Atom atom) { Text res = Text.create("(", consName(atom.getConstructor())); res = Text.create(res, " "); try { - res = Text.create(res, showObject(structs.getField(atom, 0), interop)); + res = Text.create(res, showObject(structs.getField(atom, 0))); } catch (UnsupportedMessageException e) { res = Text.create(res, structs.getField(atom, 0).toString()); } for (int i = 1; i < atom.getConstructor().getArity(); i++) { res = Text.create(res, " "); try { - res = Text.create(res, showObject(structs.getField(atom, i), interop)); + res = Text.create(res, showObject(structs.getField(atom, i))); } catch (UnsupportedMessageException e) { res = Text.create(res, structs.getField(atom, i).toString()); } @@ -72,8 +86,7 @@ private Text doComplexAtom(Atom atom) { } @CompilerDirectives.TruffleBoundary - private String showObject(Object child, InteropLibrary interop) - throws UnsupportedMessageException { + private String showObject(Object child) throws UnsupportedMessageException { if (child == null) { // TODO [RW] This is a temporary workaround to make it possible to display errors related to // https://www.pivotaltracker.com/story/show/181652974 @@ -82,6 +95,7 @@ private String showObject(Object child, InteropLibrary interop) } else if (child instanceof Boolean) { return (boolean) child ? "True" : "False"; } else { + var interop = InteropLibrary.getUncached(); return interop.asString(interop.toDisplayString(child)); } } From 34b6a3d2634062e3eef99ce54c84e26b1d3a216e Mon Sep 17 00:00:00 2001 From: Jaroslav Tulach Date: Tue, 28 Jan 2025 17:34:54 +0100 Subject: [PATCH 07/12] Any.is_a method is called on EnsoMultiValue now --- .../Multi_Value_As_Type_Refinement_Spec.enso | 24 ++++++++++++------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/test/Base_Tests/src/Semantic/Multi_Value_As_Type_Refinement_Spec.enso b/test/Base_Tests/src/Semantic/Multi_Value_As_Type_Refinement_Spec.enso index 37bc78622039..8f97e10864e6 100644 --- a/test/Base_Tests/src/Semantic/Multi_Value_As_Type_Refinement_Spec.enso +++ b/test/Base_Tests/src/Semantic/Multi_Value_As_Type_Refinement_Spec.enso @@ -46,8 +46,9 @@ add_specs suite_builder = group_builder.specify "after passing A&B value to a function expecting A argument, B becomes hidden" <| ab = make_a_and_b a2 = id_a ab + # checks also hidden types a2.is_a A . should_be_true - a2.is_a B . should_be_false + a2.is_a B . should_be_true # Passing a2 to a function expecting B fails because B part was hidden Test.expect_panic Type_Error (id_b a2) @@ -60,8 +61,9 @@ add_specs suite_builder = group_builder.specify "after casting A&B to A, B part is again hidden" <| ab = make_a_and_b a2 = ab:A + # checks also hidden types a2.is_a A . should_be_true - a2.is_a B . should_be_false + a2.is_a B . should_be_true # Passing a2 to a function expecting B fails because B part was hidden Test.expect_panic Type_Error (id_b a2) @@ -74,8 +76,9 @@ add_specs suite_builder = ab = make_a_and_b b2 = id_b ab a2 = b2:A + # checks also hidden types a2.is_a A . should_be_true - a2.is_a B . should_be_false + a2.is_a B . should_be_true a2.a_method.should_equal "A method" Test.expect_panic No_Such_Method (a2.b_method) @@ -84,7 +87,8 @@ add_specs suite_builder = ab = make_a_and_b a2 = id_a ab b2 = a2:B - b2.is_a A . should_be_false + # checks also hidden types + b2.is_a A . should_be_true b2.is_a B . should_be_true Test.expect_panic No_Such_Method (b2.a_method) @@ -98,13 +102,15 @@ add_specs suite_builder = ab_as_a : A -> ab_as_a.a_method . should_equal "A method" ab_as_a.is_a A . should_be_true - ab_as_a.is_a B . should_be_false + # checks also hidden types + ab_as_a.is_a B . should_be_true _ -> Test.fail "Expected ab to go to `: A` branch" case ab of ab_as_b : B -> ab_as_b.b_method . should_equal "B method" - ab_as_b.is_a A . should_be_false + # checks also hidden types + ab_as_b.is_a A . should_be_true ab_as_b.is_a B . should_be_true _ -> Test.fail "Expected ab to go to `: B` branch" @@ -141,8 +147,10 @@ add_specs suite_builder = # We hide A&B parts by casting to C c = abc:C - c.is_a A . should_be_false - c.is_a B . should_be_false + + # is_a checks also hidden types + c.is_a A . should_be_true + c.is_a B . should_be_true c.is_a C . should_be_true Test.expect_panic No_Such_Method (c.a_method) From 4a94a80e8274b01e1ad5995796cdd605a8eb8317 Mon Sep 17 00:00:00 2001 From: Jaroslav Tulach Date: Wed, 29 Jan 2025 10:55:33 +0100 Subject: [PATCH 08/12] Note in changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1142678cc01e..afacd0805975 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -45,6 +45,7 @@ parentheses. [This is now a syntax error.][11856] - [Native libraries of projects can be added to `polyglot/lib` directory][11874] - [Prefer module methods over `Any` instance ones][12048] +- [Keep intersection type's self when dispatching Any instance methods][12170] - [Types without constructors can be public][12052] - Symetric, transitive and reflexive [equality for intersection types][11897] - [IR definitions are generated by an annotation processor][11770] @@ -55,6 +56,7 @@ [11856]: https://github.com/enso-org/enso/pull/11856 [11874]: https://github.com/enso-org/enso/pull/11874 [12048]: https://github.com/enso-org/enso/pull/12048 +[12170]: https://github.com/enso-org/enso/pull/12170 [12052]: https://github.com/enso-org/enso/pull/12052 [11897]: https://github.com/enso-org/enso/pull/11897 [11770]: https://github.com/enso-org/enso/pull/11770 From da06cc0e42882fcfaa941514c75e3b945b1a703c Mon Sep 17 00:00:00 2001 From: Jaroslav Tulach Date: Wed, 29 Jan 2025 11:03:22 +0100 Subject: [PATCH 09/12] calling .catch on an intersection type should not lose even the hidden refinements --- .../src/Semantic/Multi_Value_As_Type_Refinement_Spec.enso | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Base_Tests/src/Semantic/Multi_Value_As_Type_Refinement_Spec.enso b/test/Base_Tests/src/Semantic/Multi_Value_As_Type_Refinement_Spec.enso index 8f97e10864e6..c54c62dee2df 100644 --- a/test/Base_Tests/src/Semantic/Multi_Value_As_Type_Refinement_Spec.enso +++ b/test/Base_Tests/src/Semantic/Multi_Value_As_Type_Refinement_Spec.enso @@ -277,7 +277,7 @@ add_specs suite_builder = r.a_method . should_equal "A method" r.b_method . should_equal "B method" - group_builder.specify "calling `.catch` on an intersection type should not lose even the hidden refinements" pending=dispatch_pending <| + group_builder.specify "calling `.catch` on an intersection type should not lose even the hidden refinements" <| ab = make_a_and_b x = ab:A r = x.catch Any _->"catched" From 9f60eba64bf6a8d5d895c03d9b31a74d68178b5e Mon Sep 17 00:00:00 2001 From: Jaroslav Tulach Date: Wed, 29 Jan 2025 11:04:33 +0100 Subject: [PATCH 10/12] calling .throw_on_warning on an intersection type should not lose even the hidden refinements --- .../src/Semantic/Multi_Value_As_Type_Refinement_Spec.enso | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Base_Tests/src/Semantic/Multi_Value_As_Type_Refinement_Spec.enso b/test/Base_Tests/src/Semantic/Multi_Value_As_Type_Refinement_Spec.enso index c54c62dee2df..c118ae8fac74 100644 --- a/test/Base_Tests/src/Semantic/Multi_Value_As_Type_Refinement_Spec.enso +++ b/test/Base_Tests/src/Semantic/Multi_Value_As_Type_Refinement_Spec.enso @@ -291,7 +291,7 @@ add_specs suite_builder = y.a_method . should_equal "A method" y.b_method . should_equal "B method" - group_builder.specify "calling `.throw_on_warning` on an intersection type should not lose even the hidden refinements" pending=dispatch_pending <| + group_builder.specify "calling `.throw_on_warning` on an intersection type should not lose even the hidden refinements" <| ab = make_a_and_b x = ab:A r = x.throw_on_warning From 123ebfdad3142de9632507f8c921c0d42f884253 Mon Sep 17 00:00:00 2001 From: Jaroslav Tulach Date: Wed, 29 Jan 2025 11:05:52 +0100 Subject: [PATCH 11/12] removing warnings from an intersection type should not lose even the hidden refinements --- .../src/Semantic/Multi_Value_As_Type_Refinement_Spec.enso | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Base_Tests/src/Semantic/Multi_Value_As_Type_Refinement_Spec.enso b/test/Base_Tests/src/Semantic/Multi_Value_As_Type_Refinement_Spec.enso index c118ae8fac74..17f38788a914 100644 --- a/test/Base_Tests/src/Semantic/Multi_Value_As_Type_Refinement_Spec.enso +++ b/test/Base_Tests/src/Semantic/Multi_Value_As_Type_Refinement_Spec.enso @@ -314,7 +314,7 @@ add_specs suite_builder = y.b_method . should_equal "B method" Problems.expect_only_warning Illegal_State y - group_builder.specify "removing warnings from an intersection type should not lose even the hidden refinements" pending=dispatch_pending <| + group_builder.specify "removing warnings from an intersection type should not lose even the hidden refinements" <| ab = make_a_and_b x1 = Warning.attach (Illegal_State.Error "my warning") (ab:A) x2 = (Warning.attach (Illegal_State.Error "my warning") ab):A From bfbcab5aa017630d16721238bb593e6b32052e1d Mon Sep 17 00:00:00 2001 From: Jaroslav Tulach Date: Wed, 29 Jan 2025 18:04:44 +0100 Subject: [PATCH 12/12] Hidden type yields No_Such_Method on its method invocation --- .../Multi_Value_As_Type_Refinement_Spec.enso | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/test/Base_Tests/src/Semantic/Multi_Value_As_Type_Refinement_Spec.enso b/test/Base_Tests/src/Semantic/Multi_Value_As_Type_Refinement_Spec.enso index 17f38788a914..317503d59974 100644 --- a/test/Base_Tests/src/Semantic/Multi_Value_As_Type_Refinement_Spec.enso +++ b/test/Base_Tests/src/Semantic/Multi_Value_As_Type_Refinement_Spec.enso @@ -46,9 +46,10 @@ add_specs suite_builder = group_builder.specify "after passing A&B value to a function expecting A argument, B becomes hidden" <| ab = make_a_and_b a2 = id_a ab - # checks also hidden types a2.is_a A . should_be_true - a2.is_a B . should_be_true + a2.is_a B . should_be_true # B is a hidden type + Test.expect_panic No_Such_Method (a2.b_method) + # Passing a2 to a function expecting B fails because B part was hidden Test.expect_panic Type_Error (id_b a2) @@ -61,9 +62,9 @@ add_specs suite_builder = group_builder.specify "after casting A&B to A, B part is again hidden" <| ab = make_a_and_b a2 = ab:A - # checks also hidden types a2.is_a A . should_be_true - a2.is_a B . should_be_true + a2.is_a B . should_be_true # B is hidden type + Test.expect_panic No_Such_Method (a2.b_method) # Passing a2 to a function expecting B fails because B part was hidden Test.expect_panic Type_Error (id_b a2) @@ -76,9 +77,9 @@ add_specs suite_builder = ab = make_a_and_b b2 = id_b ab a2 = b2:A - # checks also hidden types a2.is_a A . should_be_true - a2.is_a B . should_be_true + a2.is_a B . should_be_true # B is hidden type + Test.expect_panic No_Such_Method (a2.b_method) a2.a_method.should_equal "A method" Test.expect_panic No_Such_Method (a2.b_method) @@ -87,11 +88,11 @@ add_specs suite_builder = ab = make_a_and_b a2 = id_a ab b2 = a2:B - # checks also hidden types - b2.is_a A . should_be_true - b2.is_a B . should_be_true + b2.is_a B . should_be_true + b2.is_a A . should_be_true # A is hidden type Test.expect_panic No_Such_Method (b2.a_method) + b2.b_method.should_equal "B method" # We can still explicitly cast back to A (b2:A).a_method.should_equal "A method" @@ -102,15 +103,15 @@ add_specs suite_builder = ab_as_a : A -> ab_as_a.a_method . should_equal "A method" ab_as_a.is_a A . should_be_true - # checks also hidden types - ab_as_a.is_a B . should_be_true + ab_as_a.is_a B . should_be_true # B is hidden type + Test.expect_panic No_Such_Method (ab_as_a.b_method) _ -> Test.fail "Expected ab to go to `: A` branch" case ab of ab_as_b : B -> ab_as_b.b_method . should_equal "B method" - # checks also hidden types - ab_as_b.is_a A . should_be_true + ab_as_b.is_a A . should_be_true # A is hidden type + Test.expect_panic No_Such_Method (ab_as_b.a_method) ab_as_b.is_a B . should_be_true _ -> Test.fail "Expected ab to go to `: B` branch" @@ -148,13 +149,12 @@ add_specs suite_builder = # We hide A&B parts by casting to C c = abc:C - # is_a checks also hidden types - c.is_a A . should_be_true - c.is_a B . should_be_true - c.is_a C . should_be_true - + c.is_a A . should_be_true # A is a hidden type Test.expect_panic No_Such_Method (c.a_method) + c.is_a B . should_be_true # B is a hidden type Test.expect_panic No_Such_Method (c.b_method) + c.is_a C . should_be_true + c.c_method . should_equal "C method" # But because the structure was not lost, only hidden, we can cast back to A/B