Skip to content

ExDoc crashes on the following @spec (macro-spec with when) #1191

@Qqwy

Description

@Qqwy

Elixir/Erlang version:

Erlang/OTP 23 [erts-11.0] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [hipe]

Elixir 1.10.3 (compiled with Erlang/OTP 21)

When running mix docs on the following code:

This version works:

defmodule Example do
  @type do_block :: any
  @type else_block :: any
  @spec by(binary(), binary() | nil, [] | [do: do_block] | [do: do_block, else: do_block]) :: do_block | else_block
  defmacro by(issue_reference, reason \\ nil, code_blocks \\ [])
  defmacro by(_, _, _), do: 42
end

This version crashes:

defmodule Example do
  @spec by(binary(), binary() | nil, [] | [do: do_block] | [do: do_block, else: do_block]) :: (do_block | else_block) when do_block: any, else_block: any
  defmacro by(issue_reference, reason \\ nil, code_blocks \\ [])
  defmacro by(_, _, _), do: 42
end

with a stractrace akin

$ mix docs
Compiling 1 file (.ex)
Generating docs...
** (FunctionClauseError) no function clause matching in ExDoc.Retriever.remove_first_macro_arg/1    
    
    The following arguments were given to ExDoc.Retriever.remove_first_macro_arg/1:
    
        # 1
        {:when, [line: 98], [{:"::", [line: 98], [{:by, [line: 98], [{:term, [line: 98], []}, {:binary, [line: 98], []}, {:|, [line: 98], [{:binary, [line: 98], []}, nil]}, {:|, [line: 98], [[], {:|, [line: 98], [[{:{}, [line: 0], [:do, {:do_block, [line: 98], nil}]}], [do: {:do_block, [line: 98], nil}, else: {:do_block, [line: 98], nil}]]}]}]}, {:|, [line: 98], [{:do_block, [line: 98], nil}, {:else_block, [line: 98], nil}]}]}, [do_block: {:any, [line: 98], []}, else_block: {:any, [line: 98], []}]]}
    
    Attempted function clauses (showing 1 out of 1):
    
        defp remove_first_macro_arg({:"::", info, [{name, info2, [_term_arg | rest_args]}, return]})
    
    (ex_doc 0.22.1) lib/ex_doc/retriever.ex:533: ExDoc.Retriever.remove_first_macro_arg/1
    (elixir 1.10.3) lib/enum.ex:1396: Enum."-map/2-lists^map/1-0-"/2
    (ex_doc 0.22.1) lib/ex_doc/retriever.ex:288: ExDoc.Retriever.get_function/4
    (ex_doc 0.22.1) lib/ex_doc/retriever.ex:238: anonymous fn/6 in ExDoc.Retriever.get_docs/3
    (elixir 1.10.3) lib/enum.ex:2111: Enum."-reduce/3-lists^foldl/2-0-"/3
    (ex_doc 0.22.1) lib/ex_doc/retriever.ex:237: ExDoc.Retriever.get_docs/3
    (ex_doc 0.22.1) lib/ex_doc/retriever.ex:136: ExDoc.Retriever.do_generate_node/3
    (ex_doc 0.22.1) lib/ex_doc/retriever.ex:124: ExDoc.Retriever.generate_node/3

To reproduce this quickly, feel free to look at the broken_spec branch of the new library "blocked" I am building, where I encountered this in the wild.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions