Skip to content

Commit 3ae82c9

Browse files
authored
Case insensitive module resolution (#12007)
1 parent 8d3cceb commit 3ae82c9

File tree

6 files changed

+44
-7
lines changed

6 files changed

+44
-7
lines changed

lib/elixir/lib/code.ex

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1706,8 +1706,8 @@ defmodule Code do
17061706
def fetch_docs(module_or_path)
17071707

17081708
def fetch_docs(module) when is_atom(module) do
1709-
case :code.get_object_code(module) do
1710-
{_module, bin, beam_path} ->
1709+
case get_beam_and_path(module) do
1710+
{bin, beam_path} ->
17111711
case fetch_docs_from_beam(bin) do
17121712
{:error, :chunk_not_found} ->
17131713
app_root = Path.expand(Path.join(["..", ".."]), beam_path)
@@ -1742,6 +1742,15 @@ defmodule Code do
17421742
fetch_docs_from_beam(String.to_charlist(path))
17431743
end
17441744

1745+
defp get_beam_and_path(module) do
1746+
with {^module, beam, filename} <- :code.get_object_code(module),
1747+
{:ok, ^module} <- beam |> :beam_lib.info() |> Keyword.fetch(:module) do
1748+
{beam, filename}
1749+
else
1750+
_ -> :error
1751+
end
1752+
end
1753+
17451754
@docs_chunk 'Docs'
17461755

17471756
defp fetch_docs_from_beam(bin_or_path) do

lib/elixir/lib/code/typespec.ex

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -174,9 +174,11 @@ defmodule Code.Typespec do
174174
end
175175

176176
defp get_module_and_beam(module) when is_atom(module) do
177-
case :code.get_object_code(module) do
178-
{^module, beam, _filename} -> {module, beam}
179-
:error -> :error
177+
with {^module, beam, _filename} <- :code.get_object_code(module),
178+
{:ok, ^module} <- beam |> :beam_lib.info() |> Keyword.fetch(:module) do
179+
{module, beam}
180+
else
181+
_ -> :error
180182
end
181183
end
182184

lib/elixir/lib/module/parallel_checker.ex

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,7 @@ defmodule Module.ParallelChecker do
317317

318318
defp cache_from_chunk(ets, module) do
319319
with {^module, binary, _filename} <- :code.get_object_code(module),
320+
{:ok, ^module} <- binary |> :beam_lib.info() |> Keyword.fetch(:module),
320321
{:ok, {_, [{'ExCk', chunk}]}} <- :beam_lib.chunks(binary, ['ExCk']),
321322
{:elixir_checker_v1, contents} <- :erlang.binary_to_term(chunk) do
322323
cache_chunk(ets, module, contents.exports)

lib/elixir/test/elixir/code_test.exs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,17 @@ defmodule CodeTest do
311311
Code.put_compiler_option(:debug_info, :not_a_boolean)
312312
end
313313
end
314+
315+
describe "fetch_docs/1" do
316+
test "is case sensitive" do
317+
assert {:docs_v1, _, :elixir, _, %{"en" => module_doc}, _, _} = Code.fetch_docs(IO)
318+
319+
assert "Functions handling input/output (IO)." =
320+
module_doc |> String.split("\n") |> Enum.at(0)
321+
322+
assert Code.fetch_docs(Io) == {:error, :module_not_found}
323+
end
324+
end
314325
end
315326

316327
defmodule Code.SyncTest do

lib/elixir/test/elixir/module/types/integration_test.exs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,8 @@ defmodule Module.Types.IntegrationTest do
201201
202202
@file "external_source.ex"
203203
def c, do: E.no_module()
204+
205+
def i, do: Io.puts "hello"
204206
end
205207
"""
206208
}
@@ -212,6 +214,9 @@ defmodule Module.Types.IntegrationTest do
212214
warning: E.no_module/0 is undefined (module E is not available or is yet to be defined)
213215
external_source.ex:5: A.c/0
214216
217+
warning: Io.puts/1 is undefined (module Io is not available or is yet to be defined)
218+
a.ex:7: A.i/0
219+
215220
"""
216221

217222
assert_warnings(files, warning)

lib/iex/lib/iex/helpers.ex

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1371,8 +1371,8 @@ defmodule IEx.Helpers do
13711371
13721372
"""
13731373
def nl(nodes \\ Node.list(), module) when is_list(nodes) and is_atom(module) do
1374-
case :code.get_object_code(module) do
1375-
{^module, bin, beam_path} ->
1374+
case get_beam_and_path(module) do
1375+
{bin, beam_path} ->
13761376
results =
13771377
for node <- nodes do
13781378
case :rpc.call(node, :code, :load_binary, [module, beam_path, bin]) do
@@ -1389,4 +1389,13 @@ defmodule IEx.Helpers do
13891389
{:error, :nofile}
13901390
end
13911391
end
1392+
1393+
defp get_beam_and_path(module) do
1394+
with {^module, beam, filename} <- :code.get_object_code(module),
1395+
{:ok, ^module} <- beam |> :beam_lib.info() |> Keyword.fetch(:module) do
1396+
{beam, filename}
1397+
else
1398+
_ -> :error
1399+
end
1400+
end
13921401
end

0 commit comments

Comments
 (0)