Skip to content

Conversation

sabiwara
Copy link
Contributor

Attempt at fixing #13895, but I'm a bit stuck, sharing for discussion.

{form, meta, args}

Keyword.has_key?(meta, :do) or match?([{{:__block__, _, [:do]}, _} | _], last) ->
Keyword.has_key?(meta, :do) ->
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was initially trying to add some check, like

Suggested change
Keyword.has_key?(meta, :do) ->
Keyword.has_key?(meta, :do) or (match?([{{:__block__, _, [:do]}, _} | _], last) and keyword?(last)) ->

but I couldn't find a case where this would actually work:

  • keyword? would return false because the blocks don't have the :format metadata
  • even if I force it, normalize_kw_blocks is useless at fixing the second test case I added

The full test suite otherwise passes without that match? clause.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the correct fix would be something like:

Keyword.has_key?(meta, :do) or (match?([{{:__block__, _, [:do]}, _} | _], last) and keyword_wrapped_in_block?(last)) ->

But perhaps, it is best to not use Keyword.has_key? or keyword? and instead have your own function called keyword_ast_key? (which checks both for :do and the wrapped one) and keyword_ast? which checks if all keys are wrapped in blocks or a regular atoms.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @josevalim for checking this 🙇

I think the correct fix would be something like:

Keyword.has_key?(meta, :do) or (match?([{{:__block__, _, [:do]}, _} | _], last) and keyword_wrapped_in_block?(last)) ->

I tried but even if we make sure we get through this clause, it doesn't fix the test added here, which let me think I misunderstood something.

But perhaps, it is best to not use Keyword.has_key? or keyword? and instead have your own function called keyword_ast_key? (which checks both for :do and the wrapped one) and keyword_ast? which checks if all keys are wrapped in blocks or a regular atoms.

I tried something like this too, like the first clause being just checking the meta: Keyword.has_key?(meta, :do) and the second clause checking if it's a :do kw ast, disregarding if it's wrapped or not. But this would trigger some other test to fail:

Screenshot 2024-10-22 at 21 29 27

Maybe the test I tried to add shouldn't be passing in the first place, and I'm overthinking this, but I just couldn't find a test that the existing or match?([{{:__block__, _, [:do]}, _} | _], last) would otherwise make pass.


ast =
Code.string_to_quoted!(input,
literal_encoder: &{:ok, {:__block__, &2, [&1]}}
Copy link
Contributor Author

@sabiwara sabiwara Oct 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • with token_metadata: true, this passes without needing the match? clause
  • without token_metadata: true, this fails with or without the match? clause

assert quoted_to_string(ast) == expected
end

test "keyword arg edge case: literal encoder" do
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test is a reverse engineering attempt to understand how the match? clause works, but it doesn't seem to

@sabiwara sabiwara closed this Oct 22, 2024
@sabiwara sabiwara deleted the normalizer-kw branch October 22, 2024 14:28
josevalim added a commit that referenced this pull request Oct 22, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants