Skip to content

Mark type-check macro expansions as generated - #15888

Merged
josevalim merged 5 commits into
elixir-lang:mainfrom
shoutoutuoadi325:fix-struct-guard-macro-warnings
Sep 13, 2026
Merged

josevalim merged 5 commits into
elixir-lang:mainfrom
shoutoutuoadi325:fix-struct-guard-macro-warnings

Conversation

@shoutoutuoadi325

Copy link
Copy Markdown
Contributor

Since %_{} patterns became precise (#15635), the type-check macros leak warnings from their own expansion whenever the argument type is statically known. Calling is_struct/1 on a struct:

defmodule Foo do
  def uri?(%URI{} = uri), do: is_struct(uri)
end
$ elixirc foo.ex
warning: the following clause cannot match because the previous clauses already matched all possible values:

    _ ->

it attempts to match on the result of:

    uri

which has the already matched type:

    %URI{...}

The _ -> false clause belongs to the macro expansion, so the warning points at code the caller never wrote. The same happens with is_exception/1 and is_non_struct_map/1, and in rescue clauses (rescue x -> ... is_exception(x)); compiling the test suite on main emits this warning for the doctest of try/rescue x -> ... in Kernel.SpecialForms. It also fires in the other direction: x = %{}; is_struct(x) warns that the %_{} clause will never match, and e = %ArgumentError{}; is_exception(e, ArgumentError) hits is_exception/2 through the pinned name.

is_struct/2 already wraps its whole expression expansion in quote generated: true, which is why it never triggers these warnings. This does the same for the remaining macros. Guards and match contexts are untouched.

Since %_{} patterns became precise (#15635), is_struct/1, is_exception/1,
is_exception/2 and is_non_struct_map/1 emit "clause cannot match" and
"clause will never match" warnings when the type of the argument is
statically known, pointing at clauses that belong to the macro expansion.
Mark the whole expression expansion as generated, as is_struct/2 already
does.
Copilot AI lite review requested due to automatic review settings September 13, 2026 03:28

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟢 Approval recommended

No unresolved issues were identified, and regression coverage is included.

Pull request overview

Marks type-check macro expansions as generated to suppress warnings from macro-internal clauses.

Changes:

  • Updates is_struct/1, is_non_struct_map/1, and is_exception.
  • Adds regression coverage for known types, maps, exceptions, and rescue clauses.
File summaries
File Description
lib/elixir/test/elixir/module/types/integration_test.exs Adds compiler integration regression coverage.
lib/elixir/test/elixir/module/types/expr_test.exs Tests warning suppression across type-check macros.
lib/elixir/lib/kernel.ex Marks affected macro expansions as generated.
Review details
  • Files reviewed: 3/3 changed files
  • Comments generated: 0
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@josevalim

Copy link
Copy Markdown
Member

Thank you. I'd say in this case it is correct to warn, it will always return true, but we need to improve the warning itself. Unless you can see cases where the warning is a false positive? What was the original case that led to this report?

@josevalim

Copy link
Copy Markdown
Member

After double checking, none of the other guards warn on this, they let the upper condition warn instead, so this is good to go. I just cleaned up the tests a bit!

@josevalim
josevalim merged commit 44f9ec2 into elixir-lang:main Sep 13, 2026
15 checks passed
@josevalim

Copy link
Copy Markdown
Member

💚 💙 💜 💛 ❤️

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.

3 participants