Skip to content

Type error reported for block which cannot be evaluated #13701

Closed
@devonestes

Description

@devonestes

Elixir and Erlang/OTP versions

Erlang/OTP 26 [erts-14.2.5] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1]

Elixir 1.17.1 (compiled with Erlang/OTP 26)

Operating system

MacOS

Current behavior

Given the code below:

defmodule Test do
  def tester do
    list = [:a]
    
    if is_list(list) do
      hd(list)
    else
      list.()
    end
  end
end

I get the following type warning even though the block that would trigger it cannot be hit given the if clause:

    warning: incompatible types in expression:

        list

    expected type:

        fun()

    but got type:

        non_empty_list()

    where "list" was given the type:

        # type: non_empty_list()
        # from: lib/assertions.ex:7
        list = [:a]

    typing violation found at:
    │
 11 │       list.()
    │       ~
    │
    └─ lib/assertions.ex:11:7: Assertions.tester/0

I know the probable solution to this simple reproduction is "don't do that" since in this simple case there's no need for the check and it's functionally warning about an unused branch of logic, but this reproduction stems from the type errors I'm getting with Elixir 1.17.1 in my assertions library where I use a similar check to see which of the two supported APIs is being used.

This seems like a pretty narrow issue due only to the fact that this is a macro expansion, and so the "unused" branch of the if/else condition is being inlined and the type checker sees this as "unused" in each test in which the macro is being used and raising the type warning.

Is there a way to make the type checker happy here? I can assume that I would need to check the type of the argument passed to the macro before returning the quoted AST so I can return only the correct AST for the given type, but I also don't think that is possible now, is it?

Expected behavior

No warning is given from "unreachable" code paths for a given data type.

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