Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Calling a method that returns 'itself' on a multi-value should not lose multi-value structure? #12143

Closed
radeusgd opened this issue Jan 24, 2025 · 7 comments · Fixed by #12170
Assignees

Comments

@radeusgd
Copy link
Member

radeusgd commented Jan 24, 2025

I think that indeed it is undesirable to lose the multi value structure in methods such as:

type My_Type
    method self = if self.some_property then self else 0

This is demonstrated in ffe1172.

FYI:

@radeusgd
Copy link
Member Author

The relevant tests are

group_builder.specify "calling a method on one of the types should not lose the intersection type" <|
    ab = make_a_and_b

    ab.a_id_unchecked . is_a A . should_be_true
    ab.a_id_unchecked . is_a B . should_be_true
    ab.a_id_unchecked.a_method . should_equal "A method"
    ab.a_id_unchecked.b_method . should_equal "B method"

    # Checked variant can hide the B part
    ab.a_id . is_a A . should_be_true
    ab.a_id . is_a B . should_be_false
    # But it can be uncovered via explicit cast
    b = (ab.a_id):B
    b.is_a A . should_be_false
    b.is_a B . should_be_true

    new_ab = (ab.a_id):A&B
    new_ab.is_a A . should_be_true
    new_ab.is_a B . should_be_true
    new_ab.a_method . should_equal "A method"
    new_ab.b_method . should_equal "B method"

    # The same should apply to the B part
    ab.b_id_unchecked . is_a A . should_be_true
    ab.b_id_unchecked . is_a B . should_be_true
    ab.b_id_unchecked.a_method . should_equal "A method"
    ab.b_id_unchecked.b_method . should_equal "B method"

    ab.b_id . is_a A . should_be_false
    ab.b_id . is_a B . should_be_true
    new_ab_2 = (ab.b_id):A&B
    new_ab_2.is_a A . should_be_true
    new_ab_2.is_a B . should_be_true

group_builder.specify "calling `.catch` on an intersection type should not lose the refinements" <|
    ab = make_a_and_b
    r = ab.catch Any _->"catched"
    r.is_a A . should_be_true
    r.is_a B . should_be_true
    r.a_method . should_equal "A method"
    r.b_method . should_equal "B method"

group_builder.specify "calling `.throw_on_warning` on an intersection type should not lose the refinements" <|
    ab = make_a_and_b
    r = ab.throw_on_warning
    r.is_a A . should_be_true
    r.is_a B . should_be_true
    r.a_method . should_equal "A method"
    r.b_method . should_equal "B method"

group_builder.specify "attaching warnings to an intersection type should not lose the refinements" <|
    ab = make_a_and_b
    ab_with_warning = Warning.attach (Illegal_State.Error "my warning") ab
    ab_with_warning.is_a A . should_be_true
    ab_with_warning.is_a B . should_be_true
    ab_with_warning.a_method . should_equal "A method"
    ab_with_warning.b_method . should_equal "B method"
    Problems.expect_only_warning Illegal_State ab_with_warning

group_builder.specify "removing warnings from an intersection type should not lose the refinements" <|
    ab = make_a_and_b
    ab_with_warning = Warning.attach (Illegal_State.Error "my warning") ab

    ab_without_warning = ab_with_warning.remove_warnings
    Problems.assume_no_problems ab_without_warning
    ab_without_warning.is_a A . should_be_true
    ab_without_warning.is_a B . should_be_true
    ab_without_warning.a_method . should_equal "A method"
    ab_without_warning.b_method . should_equal "B method"

    ab2 = ab.remove_warnings
    ab2.is_a A . should_be_true
    ab2.is_a B . should_be_true
    ab2.a_method . should_equal "A method"
    ab2.b_method . should_equal "B method"

To be honest, based on @JaroslavTulach's workaround 9bb73ae led me to believe that all of these tests will fail. Somehow, in my tests I see:

    - [FAILED] calling a method on one of the types should not lose the intersection type [46ms]
        Reason: Expected False to be True (at Base_Tests\src\Semantic\Multi_Value_As_Type_Refinement_Spec.enso:189:13-55).

    - calling `.catch` on an intersection type should not lose the refinements [15ms]
    - calling `.throw_on_warning` on an intersection type should not lose the refinements [37ms]
    - attaching warnings to an intersection type should not lose the refinements [75ms]
    - removing warnings from an intersection type should not lose the refinements [52ms]

So only the first one fails but others pass already. That suggests to me that these tests are inexhaustive, because the workaround that @JaroslavTulach added was for throw_on_warning. For now I was not yet able to find a good repro.

@radeusgd
Copy link
Member Author

Eureka!

In b8407da I was able to add tests that are failing. When on a walk, I've realized what was the difference between my test cases and the -> Column example. The difference was that the 'refinement' part was hidden.

Apparently, the hidden part of the type gets cut off at dispatch of e.g. remove_warnings or catch.

I think it should not disappear as that will be very confusing to our users. catch or remove_warnings are relatively common user-facing operations.

@radeusgd
Copy link
Member Author

Additionally, the tests from b8407da uncover a related assertion failure:

Execution finished with an error: java.lang.AssertionError: Dispatch (MultiType{types=[A, A]} and extra MultiType{types=[]} should be disjoin!
        at <java> org.enso.runtime/org.enso.interpreter.runtime.data.EnsoMultiValue$NewNode.newValue(EnsoMultiValue.java:98)
        at <java> org.enso.runtime/org.enso.interpreter.node.typecheck.AllOfTypesCheckNode.executeCheckOrConversion(AllOfTypesCheckNode.java:84)
        at <java> org.enso.runtime/org.enso.interpreter.node.typecheck.TypeCheckValueNode.handleCheckOrConversion(TypeCheckValueNode.java:56)
        at <java> org.enso.runtime/org.enso.interpreter.node.typecheck.TypeCheckExpressionNode.executeGeneric(TypeCheckExpressionNode.java:23)
        at <java> org.enso.runtime/org.enso.interpreter.node.callable.thunk.ForceNodeGen.executeGeneric(ForceNodeGen.java:46)
        at <java> org.enso.runtime/org.enso.interpreter.node.scope.AssignmentNodeGen.executeGeneric(AssignmentNodeGen.java:51)
        at <java> org.enso.runtime/org.enso.interpreter.node.callable.function.BlockNode.executeGeneric(BlockNode.java:70)
        at <java> org.enso.runtime/org.enso.interpreter.node.ClosureRootNode.execute(ClosureRootNode.java:85)
        at <enso> Multi_Value_As_Type_Refinement_Spec.add_specs.Multi_Value_As_Type_Refinement_Spec.add_specs<arg-1>(Internal)
        at <enso> case_branch.case <internal-216>(Group.enso:30:61-64)
        at <enso> Helpers.execute_spec_code<arg-1>(Helpers.enso:57:18-34)
        at <enso> Panic.catch(Internal)
        at <enso> Panic.type.recover(Panic.enso:189-194)
        at <enso> Helpers.execute_spec_code(Helpers.enso:56-60)
        at <enso> case_branch<arg-3>(Helpers.enso:48:37-63)
        at <enso> case_branch<arg-1>(Helpers.enso:48:13-64)
        at <enso> Runtime.no_inline(Internal)
        at <enso> Duration.type.time_execution(Duration.enso:131:18-43)
        at <enso> case_branch(Helpers.enso:47-48)
        at <enso> Helpers.run_spec(Helpers.enso:46-49)
        at <enso> case_branch.test_results(Helpers.enso:27:24-36)
        at <enso> Array_Like_Helpers.map.Array_Like_Helpers.map(Array_Like_Helpers.enso:232:56-77)
        at <enso> Array_Like_Helpers.vector_from_function(Internal)
        at <enso> case_branch(Helpers.enso:24-30)
        at <enso> Helpers.run_specs_from_group(Helpers.enso:21-36)
        at <enso> case_branch(Suite.enso:97:35-92)
        at <enso> Suite.run_with_filter.junit_sb_builder(Suite.enso:95-101)
        at <enso> Array_Like_Helpers.each.Array_Like_Helpers.each(Array_Like_Helpers.enso:272:9-24)
        at <enso> Range.each.go<arg-1>(Range.enso:263:36-51)
        at <enso> Range.each.go<arg-2>(Range.enso:263:21-52)
        at <enso> Range.each.go(Range.enso:262-264)
        at <enso> Range.each<arg-2>(Range.enso:265:13-25)
        at <enso> Range.each(Range.enso:259-265)
        at <enso> Array_Like_Helpers.each(Array_Like_Helpers.enso:271-272)
        at <enso> Vector.each(Vector.enso:817:9-38)
        at <enso> Suite.run_with_filter<arg-1>(Suite.enso:92-101)
        at <enso> Test_Reporter.wrap_junit_testsuites(Test_Reporter.enso:29:14-19)
        at <enso> Suite.run_with_filter(Suite.enso:91-101)
        at <enso> Multi_Value_As_Type_Refinement_Spec.main(Multi_Value_As_Type_Refinement_Spec.enso:336:5-32)

@JaroslavTulach JaroslavTulach changed the title Calling a method that returns 'itself' on a multi-value should not lose multi-value strucutre? Calling a method that returns 'itself' on a multi-value should not lose multi-value structure? Jan 27, 2025
radeusgd added a commit that referenced this issue Jan 28, 2025
radeusgd added a commit that referenced this issue Jan 28, 2025
@JaroslavTulach JaroslavTulach self-assigned this Jan 28, 2025
@JaroslavTulach JaroslavTulach moved this from ❓New to 📤 Backlog in Issues Board Jan 28, 2025
@JaroslavTulach JaroslavTulach moved this from 📤 Backlog to 🔧 Implementation in Issues Board Jan 28, 2025
@enso-bot
Copy link

enso-bot bot commented Jan 28, 2025

Jaroslav Tulach reports a new STANDUP for today (2025-01-28):

Progress: .

GitHub
Enso Analytics is a self-service data prep and analysis platform designed for data teams. - Progress API · af2ec78

@mergify mergify bot closed this as completed in caec1e6 Jan 29, 2025
@mergify mergify bot closed this as completed in #12170 Jan 29, 2025
@github-project-automation github-project-automation bot moved this from 🔧 Implementation to 🟢 Accepted in Issues Board Jan 29, 2025
@enso-bot
Copy link

enso-bot bot commented Jan 30, 2025

Jaroslav Tulach reports a new STANDUP for yesterday (2025-01-29):

Progress: .

@enso-bot
Copy link

enso-bot bot commented Jan 31, 2025

Jaroslav Tulach reports a new STANDUP for yesterday (2025-01-30):

Progress: .

Discord
Discord is great for playing games and chilling with friends, or even building a worldwide community. Customize your own space to talk, play, and hang out.

@enso-bot
Copy link

enso-bot bot commented Jan 31, 2025

Jaroslav Tulach reports a new STANDUP for today (2025-01-31):

Progress: .

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: 🟢 Accepted
Development

Successfully merging a pull request may close this issue.

2 participants