angelikatyborska
Why does Code.compile_string report deprecation warnings only sometimes?
I’m having trouble understanding why function deprecation warnings don’t always show up when I compile code that uses deprecated functions.
Let me explain with an example: HashDict.new/0 is a deprecated function. Let’s say I have a file called deprecated_test.ex. The file contains a module and a function definition that uses the deprecated function:
# deprecated_test.ex
defmodule Foo do
def foo, do: HashDict.new()
end
If I compile the file with elixirc, I get a nice deprecation warning:
angelika in ~/Documents
$ elixirc deprecated_test.ex
warning: HashDict.new/0 is deprecated. Use maps and the Map module instead
deprecated_test.ex:2: Foo.foo/0
However, if I start iex, load the same file and compile it with Code.compile_string/1, I don’t get the warning:
iex(2)> code = File.read!("./deprecated_test.ex")
"defmodule Foo do\n def foo, do: HashDict.new()\nend\n"
iex(3)> Code.compile_string(code)
[
{Foo,
<<70, 79, 82, 49, 0, 0, 4, 208, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 0,
153, 0, 0, 0, 16, 10, 69, 108, 105, 120, 105, 114, 46, 70, 111, 111, 8, 95,
95, 105, 110, 102, 111, 95, 95, 10, 97, 116, ...>>}
]
I thought this means that Code.compile_string/1 won’t give me deprecation warnings at all, but that’s not true.
I get a deprecation warning about HashDict.new/0 if I try different code snippets:
iex(4)> Code.compile_string("fn -> HashDict.new() end")
warning: HashDict.new/0 is deprecated. Use maps and the Map module instead
nofile:1
[]
or
iex(15)> Code.compile_string("ref = &HashDict.new/0")
warning: HashDict.new/0 is deprecated. Use maps and the Map module instead
nofile:1
warning: variable "ref" is unused (if the variable is not meant to be used, prefix it with an underscore)
nofile:1
[]
Why is this happening? Can I somehow ensure that I will always get exactly the same deprecation warnings when compiling code with Code.compile_string/1 and/or Code.compile_quoted/1 as I would get with elixirc?
Marked As Solved
josevalim
Both :elixir_compiler and Module.ParallelChecker are private, so please don’t use them.
Please open up an issue and we will make sure to also check for deprecations from compile_string. ![]()
Also Liked
moogle19
It seems that compile_file/2 call the private function verify_loaded/1 in Code which verifies some things (e.g. deprecations) (see code.ex#L1503).
compile_string/2 doens’t (see code.ex#L1466).
Not sure why only the compile_file/2 checks this. Maybe performance reasons?
angelikatyborska
Thanks a lot! Based on your hints, I was able to get the deprecation checks working fully.
The only purpose of my code is to get all the compilation warnings. Here’s what I had before:
warnings =
capture_io(:stderr, fn ->
Code.compile_quoted(code_ast, Path.basename(code_path))
|> Enum.each(fn {module, _binary} ->
:code.delete(module)
:code.purge(module)
end)
end)
And here’s what I have now:
warnings =
capture_io(:stderr, fn ->
:elixir_compiler.quoted(code_ast, code_path, fn _, _ -> :ok end)
|> Enum.each(fn {module, map, binary} ->
Module.ParallelChecker.verify([{map, binary}], [])
:code.delete(module)
:code.purge(module)
end)
end)
I’m just not sure if it’s a great idea to use a private module (Module.ParallelChecker) like this.
Popular in Questions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #javascript
- #code-sync
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #advent-of-code
- #elixirconf-us
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #performance








