Skip to content

Commit 86f4e3b

Browse files
author
José Valim
committed
Do not lose source compile info on protocol consolidation, closes #6270
1 parent 50aba8f commit 86f4e3b

File tree

3 files changed

+26
-13
lines changed

3 files changed

+26
-13
lines changed

lib/elixir/lib/protocol.ex

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -254,21 +254,22 @@ defmodule Protocol do
254254
{:error, :not_a_protocol} |
255255
{:error, :no_beam_info}
256256
def consolidate(protocol, types) when is_atom(protocol) do
257-
with {:ok, info} <- beam_protocol(protocol),
258-
{:ok, code, docs} <- change_debug_info(info, types),
259-
do: compile(code, docs)
257+
with {:ok, ast_info, chunks_info} <- beam_protocol(protocol),
258+
{:ok, code} <- change_debug_info(ast_info, types),
259+
do: compile(protocol, code, chunks_info)
260260
end
261261

262262
defp beam_protocol(protocol) do
263-
chunk_ids = [:abstract_code, :attributes, 'ExDc']
263+
chunk_ids = [:abstract_code, :attributes, :compile_info, 'ExDc']
264264
opts = [:allow_missing_chunks]
265265
case :beam_lib.chunks(beam_file(protocol), chunk_ids, opts) do
266266
{:ok, {^protocol, [{:abstract_code, {_raw, abstract_code}},
267267
{:attributes, attributes},
268+
{:compile_info, compile_info},
268269
{'ExDc', docs}]}} ->
269270
case attributes[:protocol] do
270271
[fallback_to_any: any] ->
271-
{:ok, {protocol, any, abstract_code, docs}}
272+
{:ok, {protocol, any, abstract_code}, {compile_info, docs}}
272273
_ ->
273274
{:error, :not_a_protocol}
274275
end
@@ -286,12 +287,12 @@ defmodule Protocol do
286287

287288
# Change the debug information to the optimized
288289
# impl_for/1 dispatch version.
289-
defp change_debug_info({protocol, any, code, docs}, types) do
290+
defp change_debug_info({protocol, any, code}, types) do
290291
types = if any, do: types, else: List.delete(types, Any)
291292
all = [Any] ++ for {_guard, mod} <- __builtin__(), do: mod
292293
structs = types -- all
293294
case change_impl_for(code, protocol, types, structs, false, []) do
294-
{:ok, ret} -> {:ok, ret, docs}
295+
{:ok, ret} -> {:ok, ret}
295296
other -> other
296297
end
297298
end
@@ -358,9 +359,9 @@ defmodule Protocol do
358359
change_impl_for(tail, protocol, info, types, protocol?, [head | acc])
359360
end
360361

361-
defp change_impl_for([], protocol, _info, _types, protocol?, acc) do
362+
defp change_impl_for([], _protocol, _info, _types, protocol?, acc) do
362363
if protocol? do
363-
{:ok, {protocol, Enum.reverse(acc)}}
364+
{:ok, Enum.reverse(acc)}
364365
else
365366
{:error, :not_a_protocol}
366367
end
@@ -405,8 +406,9 @@ defmodule Protocol do
405406
end
406407

407408
# Finally compile the module and emit its bytecode.
408-
defp compile({protocol, code}, docs) do
409-
opts = if Code.compiler_options[:debug_info], do: [:debug_info], else: []
409+
defp compile(protocol, code, {compile_info, docs}) do
410+
opts = Keyword.take(compile_info, [:source])
411+
opts = if Code.compiler_options[:debug_info], do: [:debug_info | opts], else: opts
410412
{:ok, ^protocol, binary, _warnings} = :compile.forms(code, [:return | opts])
411413
{:ok,
412414
case docs do

lib/elixir/test/elixir/protocol_test.exs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,10 @@ defmodule Protocol.ConsolidationTest do
377377
List.keyfind(docs, {:ok, 1}, 0)
378378
end
379379

380+
test "consolidation keeps source" do
381+
assert Sample.__info__(:compile)[:source]
382+
end
383+
380384
test "consolidated keeps callbacks" do
381385
callbacks = Kernel.Typespec.beam_callbacks(@sample_binary)
382386
assert callbacks != []

lib/ex_unit/lib/ex_unit/doc_test.ex

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -193,8 +193,8 @@ defmodule ExUnit.DocTest do
193193
end
194194
end
195195

196-
tests = quote bind_quoted: binding() do
197-
file = "(for doctest at) " <> Path.relative_to_cwd(mod.__info__(:compile)[:source])
196+
tests = quote bind_quoted: [mod: mod, opts: opts] do
197+
file = ExUnit.DocTest.__file__(mod)
198198
for {name, test} <- ExUnit.DocTest.__doctests__(mod, opts) do
199199
@tag :doctest
200200
@file file
@@ -205,6 +205,13 @@ defmodule ExUnit.DocTest do
205205
[require, tests]
206206
end
207207

208+
@doc false
209+
def __file__(module) do
210+
source = module.__info__(:compile)[:source] ||
211+
raise "#{inspect module} does not have compile-time source information"
212+
"(for doctest at) " <> Path.relative_to_cwd(source)
213+
end
214+
208215
@doc false
209216
def __doctests__(module, opts) do
210217
do_import = Keyword.get(opts, :import, false)

0 commit comments

Comments
 (0)