otp icon indicating copy to clipboard operation
otp copied to clipboard

Dialyzer ignores guard and reports an error with `-Wmissing_return`

Open sabiwara opened this issue 2 years ago • 1 comments

Describe the bug When using a guard such as when X =:= nil or when X =:= nil orelse orelse X =:= false, dialyzer is not able to eliminate the nil type from the integer() | nil return type and incorrectly complains about a missingnil type when turning on the -Wmissing_return flag.

To Reproduce

-spec foo(string()) -> integer().
foo(Text) ->
  case one(Text) of
    X when X =:= nil orelse X =:= false -> two(Text);
    X -> X
  end.

one("1") -> 1;
one(_) -> nil.

two("2") -> 2;
two(_) -> 0.

fails with

$ dialyzer -Wmissing_return foo.erl
foo.erl:4:2: The success typing for foo:foo/1 implies that the function might also return
          'nil' but the specification return is
          integer()

Expected behavior No error being raised.

Affected versions 26.2.1

Additional context This bug is affecting truthiness checks in Elixir such as one(text) || two(text) (see https://github.com/elixir-lang/elixir/issues/13269).

sabiwara avatar Jan 21 '24 00:01 sabiwara

Thanks for your report! We do not consider this a bug, when you ask dialyzer to go beyond its capabilities (e.g. by specifying -Wmissing_return or similar options), it may report things that cannot happen for reasons it's unable to infer.

You're essentially changing its mode from "only report things you know for certain" to "report things you think might be wrong," and warnings like these naturally arise from the latter.

That said, we may be able to fix this particular case. We'll look into it. :)

jhogberg avatar Jan 22 '24 11:01 jhogberg