elixir-lang / elixir

Elixir is a dynamic, functional language for building scalable and maintainable applications

Home Page:https://elixir-lang.org/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Dialyzer fails on `sigil_r` with unicode (`/u`) modifier in 1.17-rc.0+ (was fine in 1.16.3-)

breunigs opened this issue · comments

Elixir and Erlang/OTP versions

Versions that fail:

  • Erlang/OTP 26 [erts-14.2.1] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [jit:ns]; Elixir 1.18.0-dev (43788c0) (compiled with Erlang/OTP 25)
  • Erlang/OTP 26 [erts-14.2.1] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [jit:ns]; Elixir 1.17.0-rc.0 (a2600ea) (compiled with Erlang/OTP 25)
  • Erlang/OTP 25 [erts-13.2.2.6] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [jit:ns]; 1.17.0-rc.0 (a2600ea) (compiled with Erlang/OTP 25)
  • Erlang/OTP 27 [erts-15.0] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [jit:ns]; Elixir 1.17.0-rc.0 (a2600ea) (compiled with Erlang/OTP 25)

Versions that works:

  • Erlang/OTP 26 [erts-14.2.1] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [jit:ns]; 1.16.3 (compiled with Erlang/OTP 24)
  • likely Elixir 1.16.1, but didn't reproduce with the test case

Operating system

Linux

Current behavior

STR:

  1. mix new debug
  2. put Regex.source(~r/foo/u) into the auto-generated lib/debug.ex, e.g. into hello/0
  3. add {:dialyxir, "~> 1.4", only: [:dev, :test], runtime: false} to mix.exs and mix deps.get etc
  4. mix dialyzer

Expected behavior

In versions that work, Dialyzer (or Dialyxer) doesn't report any issues.
In the newer versions, it is not happy:

Total errors: 1, Skipped: 0, Unnecessary Skips: 0
done in 0m0.96s
lib/debug.ex:15:no_return
Function hello/0 has no local return.
________________________________________________________________________________
done (warnings were emitted)
Halting VM with exit status 2

It seems to be related to sigil_r with unicode modifier being actually processed, i.e. passed to some Regex or String function. Note that the actual regex continues to work, and only Dialyzer is complaining. So if there is an edge case that triggers the error condition that makes Dialyzer complain, I have not found it yet.

Findings so far (works = Dialyzer reports no error):

  • The same issue appears when using e.g. String.replace
  • Unicode in the subject works (e.g. String.match?("josé", ~r/^[[:lower:]]+$/) from the docs continues to work)
  • Unicode in regex without unicode modifier works, e.g. Regex.source(~r/ẞÄẞ®₃©™§/) produces no errors
  • "bare" sigil_r is ok, too: IO.inspect(~r{foo}u)
  • this example Regex.replace(~r/\s/u, "Unicode\u00A0spaces", "-") from the regex docs also fails. At a glance it's part of the doctests, so running Dialyzer on those should've caught the issue. Out of scope for this bug report for sure, but maybe a worthwhile investigation to prevent regressions.

Can you please provide a small project with mix new that reproduces the issue?

Curiously, when I compile Elixir from source (i.e. git clone && make), I can't reproduce the issue. However, installing/compiling it via asdf lead to the issue described above -- at least the main branch was not a precompiled version. So obviously I tested changing versions there, with the result that I now can't reproduce the issue anymore, not even with the original Erlang version I had installed.

I have no good hunch as to what happened here… bit flip, stale cache, updated release-tar-ball compared to the one I downloaded years ago?

Either way, I'll close this issue until I can reproduce it again. Will provide the example project if it occurs the next time around. Sorry for the false alarm!

Can you please provide a small project with mix new that reproduces the issue?

Hi @josevalim! Here it is - https://github.com/etehtsea/the-point-of-no-return

Oh that's probably my PR.
I suspect this is because ~r//u.opts used to be "u" and is now [:unicode, :ucp], and :ucp is not in the options types.
Will send a PR later. Thanks @etehtsea for the repro 🙇 💜