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

Referencing result of earlier segment when pattern matching generates invalid Erlang #4145

Open
richard-viney opened this issue Jan 4, 2025 · 3 comments
Labels
bug Something isn't working help wanted Contributions encouraged priority:high

Comments

@richard-viney
Copy link
Contributor

The following code references the result of the pattern's first segment in its second segment:

pub fn main() {
  let assert <<length, _:size(length)-unit(8)>> = <<3, 1, 2, 3>>
}

Building for Erlang gives:

/bit_array_test/src/bit_array_test.gleam:6:16: variable 'Length' is unbound
error: Shell command failure

Erlang can handle this kind of self-referencing pattern so Gleam probably should too.

The following Erlang works as expected:

test_pattern() ->
    _assert_subject = <<3, 1, 2, 3>>,
    case _assert_subject of
        <<Length, _:Length/unit:8>> -> _assert_subject;
        _assert_fail -> erlang:error()
    end.

Gleam version: 1.6.3 and 1.7.0-rc3.

@richard-viney richard-viney added the bug Something isn't working label Jan 4, 2025
@lpil
Copy link
Member

lpil commented Jan 4, 2025

What Erlang does it compile to today?

@richard-viney
Copy link
Contributor Author

main() ->
    _assert_subject = <<3, 1, 2, 3>>,
    <<Length@1, _:Length@1/unit:8>> = case _assert_subject of
        <<_, _:Length/unit:8>> -> _assert_subject;
        _assert_fail ->
            erlang:error(#{gleam_error => let_assert,
                        message => <<"Pattern match failed, no pattern matched the value."/utf8>>,
                        value => _assert_fail,
                        module => <<"bit_array_test"/utf8>>,
                        function => <<"main"/utf8>>,
                        line => 17})
    end.

If the match inside the case captured the first segment into a Length variable similar to the assignment on the previous line then that would likely fix it.

Is this doing the pattern match twice? Or does Erlang optimise that away?

@lpil
Copy link
Member

lpil commented Jan 8, 2025

Ah, thank you.

I believe it does not get optimised.

@lpil lpil added help wanted Contributions encouraged priority:high labels Jan 8, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working help wanted Contributions encouraged priority:high
Projects
None yet
Development

No branches or pull requests

2 participants