Binary construction infers to any
-module(test2).
-spec test(binary()) -> binary().
test(Bin) -> <<Bin/binary, "test">>.
With verbose:
Checking module test2
Checking function test/1
4:1: Checking clause :: binary()
4:14: Checking that <<Bin/binary, "test">> :: binary()
4:16: Checking that Bin :: <<_:_*8>>
4:28: Checking that "test" :: string()
4:14: Propagated type of <<Bin/binary, "test">> :: any()
Now this doesn't complain but that seems wrong. I guess because it's inferred as any(), it doesn't complain? I'm trying to find a way to write a test case that fails to confirm I can fix this but can't think of any.
All literals are given the type any() unless you use --infer (which I think should be the default but there have been theoretical reasons against it that I didn't fully understand).
Does this example pass even (without infer) if you change the spec to -spec test(binary()) -> atom(). or something like that, a non-binary return type?
It's not a literal actually, but my guess is that it's handled the same as literals in this case... (not sure)
It does pass, it's just something I saw while debugging some other bugs 🙃
It does pass, it's just something I saw while debugging some other bugs upside_down_face
What does pass? The original example passes, yes, I know and I think I know why. The follow up questions are for checking if I was right. :-) So if you want to check if it passes with the spec changed to a wrong return type also, nice, but if you don't have time, fine!
I guess the example passes also with the wrong return type, but if you add --infer and use the wrong return type, it should fail. That's my guess anyway.