Skip to content

Commit 2c54f9a

Browse files
authored
More cleanup: remove compatibility code for OTP26- (#15166)
* Remove compatibility code for OTP26- * Remove support for application/erlang+html docs v1 * Remove workaround for bug in older OTP versions * Update OTP version checks * Remove OTP25- skipping in tests * More test cleanup
1 parent 2817a70 commit 2c54f9a

10 files changed

Lines changed: 86 additions & 187 deletions

File tree

Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,9 @@ SOURCE_DATE_EPOCH_FILE = $(SOURCE_DATE_EPOCH_PATH)/SOURCE_DATE_EPOCH
3232
#==> Functions
3333

3434
define CHECK_ERLANG_RELEASE
35-
erl -noshell -eval '{V,_} = string:to_integer(erlang:system_info(otp_release)), io:fwrite("~s", [is_integer(V) and (V >= 26)])' -s erlang halt | grep -q '^true'; \
35+
erl -noshell -eval '{V,_} = string:to_integer(erlang:system_info(otp_release)), io:fwrite("~s", [is_integer(V) and (V >= 27)])' -s erlang halt | grep -q '^true'; \
3636
if [ $$? != 0 ]; then \
37-
echo "At least Erlang/OTP 26.0 is required to build Elixir"; \
37+
echo "At least Erlang/OTP 27.0 is required to build Elixir"; \
3838
exit 1; \
3939
fi
4040
endef

lib/elixir/lib/float.ex

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -379,8 +379,8 @@ defmodule Float do
379379
case rounding do
380380
:ceil when sign === 0 -> 1 / power_of_10(precision)
381381
:floor when sign === 1 -> -1 / power_of_10(precision)
382-
:ceil when sign === 1 -> minus_zero()
383-
:half_up when sign === 1 -> minus_zero()
382+
:ceil when sign === 1 -> -0.0
383+
:half_up when sign === 1 -> -0.0
384384
_ -> 0.0
385385
end
386386

@@ -411,7 +411,7 @@ defmodule Float do
411411

412412
cond do
413413
num == 0 and sign == 1 ->
414-
minus_zero()
414+
-0.0
415415

416416
num == 0 ->
417417
0.0
@@ -427,11 +427,6 @@ defmodule Float do
427427
end
428428
end
429429

430-
# TODO remove once we require Erlang/OTP 27+
431-
# This function tricks the compiler to avoid this bug in previous versions:
432-
# https://github.com/elixir-lang/elixir/blob/main/lib/elixir/lib/float.ex#L408-L412
433-
defp minus_zero, do: -0.0
434-
435430
defp decompose(significant, initial) do
436431
decompose(significant, 1, 0, initial)
437432
end

lib/elixir/src/elixir.erl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -133,20 +133,20 @@ preload_common_modules() ->
133133
parse_otp_release() ->
134134
%% Whenever we change this check, we should also change Makefile.
135135
case string:to_integer(erlang:system_info(otp_release)) of
136-
{Num, _} when Num >= 26 ->
136+
{Num, _} when Num >= 27 ->
137137
case Num == 28 andalso (code:ensure_loaded(re) == {module, re}) andalso not erlang:function_exported(re, import, 1) of
138138
true ->
139139
io:format(standard_error,
140140
"warning! Erlang/OTP 28.0 detected.~n"
141141
"Regexes will be re-compiled from source at runtime, which will cause degraded performance.~n"
142-
"This can be fixed by using Erlang OTP 28.1+ or 27-.~n"
142+
"This can be fixed by using Erlang OTP 28.1+ or 27.~n"
143143
, []);
144144
false ->
145145
ok
146146
end,
147147
Num;
148148
_ ->
149-
io:format(standard_error, "ERROR! Unsupported Erlang/OTP version, expected Erlang/OTP 26+~n", []),
149+
io:format(standard_error, "ERROR! Unsupported Erlang/OTP version, expected Erlang/OTP 27+~n", []),
150150
erlang:halt(1)
151151
end.
152152

lib/elixir/test/elixir/code_test.exs

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -739,26 +739,21 @@ defmodule Code.SyncTest do
739739

740740
import PathHelpers
741741

742-
if System.otp_release() >= "26" do
743-
defp assert_cached(path) do
744-
assert find_path(path) != :nocache
745-
end
742+
defp assert_cached(path) do
743+
assert find_path(path) != :nocache
744+
end
746745

747-
defp refute_cached(path) do
748-
assert find_path(path) == :nocache
749-
end
746+
defp refute_cached(path) do
747+
assert find_path(path) == :nocache
748+
end
750749

751-
defp find_path(path) do
752-
{:status, _, {:module, :code_server}, [_, :running, _, _, state]} =
753-
:sys.get_status(:code_server)
750+
defp find_path(path) do
751+
{:status, _, {:module, :code_server}, [_, :running, _, _, state]} =
752+
:sys.get_status(:code_server)
754753

755-
[:state, _, _otp_root, paths | _] = Tuple.to_list(state)
756-
{_, value} = List.keyfind(paths, to_charlist(path), 0)
757-
value
758-
end
759-
else
760-
defp assert_cached(_path), do: :ok
761-
defp refute_cached(_path), do: :ok
754+
[:state, _, _otp_root, paths | _] = Tuple.to_list(state)
755+
{_, value} = List.keyfind(paths, to_charlist(path), 0)
756+
value
762757
end
763758

764759
test "evaluates module definitions" do

lib/elixir/test/elixir/kernel/cli_test.exs

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -95,25 +95,6 @@ defmodule Kernel.CLI.ExecutableTest do
9595
# Check for -e and exclamation mark handling on Windows
9696
assert {_output, 0} =
9797
System.cmd(elixir_executable(context.cli_extension), ["-e", "Time.new!(0, 0, 0)"])
98-
99-
# TODO: remove this once we bump CI to Erlang/OTP 27
100-
if not (windows?() and System.otp_release() == "26") do
101-
{output, 0} =
102-
System.cmd(iex_executable(context.cli_extension), [
103-
"--eval",
104-
"IO.puts :hello_world123; System.halt()"
105-
])
106-
107-
assert output =~ "hello_world123"
108-
109-
{output, 0} =
110-
System.cmd(iex_executable(context.cli_extension), [
111-
"-e",
112-
"IO.puts :hello_world123; System.halt()"
113-
])
114-
115-
assert output =~ "hello_world123"
116-
end
11798
end
11899

119100
@tag :unix

lib/iex/lib/iex/config.ex

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -26,21 +26,10 @@ defmodule IEx.Config do
2626
case Enum.split_while(prompt, &(&1 != ?()) do
2727
# It is not the default Elixir shell, so we use the default prompt
2828
{_, []} ->
29-
List.duplicate(?\s, max(0, prompt_width(prompt) - 3)) ++ ~c".. "
29+
List.duplicate(?\s, max(0, :shell.prompt_width(prompt) - 3)) ++ ~c".. "
3030

3131
{left, right} ->
32-
List.duplicate(?., prompt_width(left)) ++ right
33-
end
34-
end
35-
36-
# TODO: Remove this when we require Erlang/OTP 27+
37-
@compile {:no_warn_undefined, :prim_tty}
38-
@compile {:no_warn_undefined, :shell}
39-
defp prompt_width(prompt) do
40-
if function_exported?(:prim_tty, :npwcwidthstring, 1) do
41-
:prim_tty.npwcwidthstring(prompt)
42-
else
43-
:shell.prompt_width(prompt)
32+
List.duplicate(?., :shell.prompt_width(left)) ++ right
4433
end
4534
end
4635

lib/iex/lib/iex/introspection.ex

Lines changed: 57 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -274,10 +274,6 @@ defmodule IEx.Introspection do
274274
case Code.ensure_loaded(module) do
275275
{:module, _} ->
276276
case Code.fetch_docs(module) do
277-
# TODO remove once we require Erlang/OTP 27+
278-
{:docs_v1, _, :erlang, "application/erlang+html", _, _, _} = erl_docs ->
279-
:shell_docs.render(module, erl_docs) |> IO.puts()
280-
281277
{:docs_v1, _, _, format, doc, metadata, _} when is_map(doc) or doc == :none ->
282278
print_doc([inspect(module)], [], format, doc, metadata)
283279

@@ -298,7 +294,7 @@ defmodule IEx.Introspection do
298294
def h({module, function}) when is_atom(module) and is_atom(function) do
299295
case Code.ensure_loaded(module) do
300296
{:module, _} ->
301-
{_language, _format, docs, _} = get_docs(module, [:function, :macro])
297+
{_language, _format, docs} = get_docs(module, [:function, :macro])
302298

303299
exports =
304300
cond do
@@ -390,15 +386,10 @@ defmodule IEx.Introspection do
390386
end
391387

392388
defp h_mod_fun_arity(mod, fun, arity) when is_atom(mod) do
393-
{language, format, docs, docs_v1} = get_docs(mod, [:function, :macro])
389+
{language, format, docs} = get_docs(mod, [:function, :macro])
394390
spec = get_spec(mod, fun, arity)
395391

396392
cond do
397-
# TODO remove once we require Erlang/OTP 27+
398-
language == :erlang and format == "application/erlang+html" ->
399-
print_erlang_doc(mod, fun, arity, docs_v1)
400-
:ok
401-
402393
doc_tuple = find_doc_with_content(docs, fun, arity) ->
403394
print_fun(mod, language, format, doc_tuple, spec)
404395
:ok
@@ -432,23 +423,23 @@ defmodule IEx.Introspection do
432423
end
433424

434425
defp has_type?(mod, fun) do
435-
{_, _, docs, _} = get_docs(mod, [:type])
426+
{_, _, docs} = get_docs(mod, [:type])
436427
Enum.any?(docs, &match?({_, ^fun, _}, elem(&1, 0)))
437428
end
438429

439430
defp has_type?(mod, fun, arity) do
440-
{_, _, docs, _} = get_docs(mod, [:type])
431+
{_, _, docs} = get_docs(mod, [:type])
441432
Enum.any?(docs, &match?({_, ^fun, ^arity}, elem(&1, 0)))
442433
end
443434

444435
defp get_docs(mod, kinds) do
445436
case Code.fetch_docs(mod) do
446-
{:docs_v1, _, language, format, _, _, docs} = docs_v1 ->
437+
{:docs_v1, _, language, format, _, _, docs} ->
447438
docs = for {{kind, _, _}, _, _, _, _} = doc <- docs, kind in kinds, do: doc
448-
{language, format, docs, docs_v1}
439+
{language, format, docs}
449440

450441
{:error, _} ->
451-
{nil, nil, nil, nil}
442+
{nil, nil, nil}
452443
end
453444
end
454445

@@ -588,7 +579,7 @@ defmodule IEx.Introspection do
588579
end
589580

590581
defp get_callback_docs(mod, filter) do
591-
{_, format, docs, _} = get_docs(mod, [:callback, :macrocallback])
582+
{_, format, docs} = get_docs(mod, [:callback, :macrocallback])
592583

593584
case Typespec.fetch_callbacks(mod) do
594585
:error ->
@@ -677,95 +668,72 @@ defmodule IEx.Introspection do
677668
Prints the types for the given module and type documentation.
678669
"""
679670
def t(module) when is_atom(module) do
680-
case :code.get_doc(module) do
681-
# TODO remove once we require Erlang/OTP 27+
682-
{:ok, {:docs_v1, _, :erlang, "application/erlang+html", _, _, _} = erl_docs} ->
683-
:shell_docs.render_type(module, erl_docs) |> IO.puts()
684-
685-
_ ->
686-
case Typespec.fetch_types(module) do
687-
:error ->
688-
no_beam(module)
671+
case Typespec.fetch_types(module) do
672+
:error ->
673+
no_beam(module)
689674

690-
{:ok, []} ->
691-
types_not_found(inspect(module))
675+
{:ok, []} ->
676+
types_not_found(inspect(module))
692677

693-
{:ok, types} ->
694-
types
695-
|> Enum.sort_by(fn {_, {name, _, args}} -> {name, length(args)} end)
696-
|> Enum.each(&(&1 |> format_type() |> IO.puts()))
697-
end
678+
{:ok, types} ->
679+
types
680+
|> Enum.sort_by(fn {_, {name, _, args}} -> {name, length(args)} end)
681+
|> Enum.each(&(&1 |> format_type() |> IO.puts()))
698682
end
699683

700684
dont_display_result()
701685
end
702686

703687
def t({module, type}) when is_atom(module) and is_atom(type) do
704-
case get_docs(module, [:type]) do
705-
# TODO remove once we require Erlang/OTP 27+
706-
{:erlang, "application/erlang+html", _, erl_docs} ->
707-
case :shell_docs.render_type(module, type, erl_docs) do
708-
{:error, :type_missing} -> types_not_found_or_private("#{inspect(module)}.#{type}")
709-
iodata -> IO.puts(iodata)
710-
end
688+
{_, format, docs} = get_docs(module, [:type])
711689

712-
{_, format, docs, _} ->
713-
case Typespec.fetch_types(module) do
714-
:error ->
715-
no_beam(module)
716-
717-
{:ok, types} ->
718-
types
719-
|> Enum.filter(&match?({kind, {^type, _, _}} when kind in [:type, :opaque], &1))
720-
|> Enum.sort_by(fn {_, {name, _, args}} -> {name, length(args)} end)
721-
|> case do
722-
[] ->
723-
types_not_found_or_private("#{inspect(module)}.#{type}")
724-
725-
types ->
726-
Enum.map(types, fn {_, {_, _, args}} = typespec ->
727-
type
728-
|> type_doc(length(args), typespec, format, docs)
729-
|> print_typespec()
730-
end)
731-
end
690+
case Typespec.fetch_types(module) do
691+
:error ->
692+
no_beam(module)
693+
694+
{:ok, types} ->
695+
types
696+
|> Enum.filter(&match?({kind, {^type, _, _}} when kind in [:type, :opaque], &1))
697+
|> Enum.sort_by(fn {_, {name, _, args}} -> {name, length(args)} end)
698+
|> case do
699+
[] ->
700+
types_not_found_or_private("#{inspect(module)}.#{type}")
701+
702+
types ->
703+
Enum.map(types, fn {_, {_, _, args}} = typespec ->
704+
type
705+
|> type_doc(length(args), typespec, format, docs)
706+
|> print_typespec()
707+
end)
732708
end
733709
end
734710

735711
dont_display_result()
736712
end
737713

738714
def t({module, type, arity}) when is_atom(module) and is_atom(type) and is_integer(arity) do
739-
case get_docs(module, [:type]) do
740-
# TODO remove once we require Erlang/OTP 27+
741-
{:erlang, "application/erlang+html", _, erl_docs} ->
742-
case :shell_docs.render_type(module, type, arity, erl_docs) do
743-
{:error, :type_missing} -> types_not_found_or_private("#{inspect(module)}.#{type}")
744-
chardata -> IO.puts(chardata)
745-
end
715+
{_, format, docs} = get_docs(module, [:type])
746716

747-
{_, format, docs, _} ->
748-
case Typespec.fetch_types(module) do
749-
:error ->
750-
no_beam(module)
751-
752-
{:ok, types} ->
753-
types
754-
|> Enum.find(
755-
&match?(
756-
{kind, {^type, _, args}} when kind in [:type, :opaque] and length(args) == arity,
757-
&1
758-
)
759-
)
760-
|> case do
761-
nil ->
762-
types_not_found_or_private("#{inspect(module)}.#{type}")
763-
764-
typespec ->
765-
type
766-
|> type_doc(arity, typespec, format, docs)
767-
|> print_typespec()
768-
end
717+
case Typespec.fetch_types(module) do
718+
:error ->
719+
no_beam(module)
720+
721+
{:ok, types} ->
722+
types
723+
|> Enum.find(
724+
&match?(
725+
{kind, {^type, _, args}} when kind in [:type, :opaque] and length(args) == arity,
726+
&1
727+
)
728+
)
729+
|> case do
730+
nil ->
731+
types_not_found_or_private("#{inspect(module)}.#{type}")
732+
733+
typespec ->
734+
type
735+
|> type_doc(arity, typespec, format, docs)
736+
|> print_typespec()
769737
end
770738
end
771739

@@ -841,20 +809,6 @@ defmodule IEx.Introspection do
841809
defp translate_doc(%{"en" => doc}), do: doc
842810
defp translate_doc(_), do: nil
843811

844-
defp print_erlang_doc(mod, fun, arity, docs) do
845-
heading = Exception.format_mfa(mod, fun, arity)
846-
opts = IEx.Config.ansi_docs()
847-
848-
case :shell_docs.render(mod, fun, arity, docs) do
849-
{:error, :function_missing} ->
850-
docs_not_found("#{inspect(mod)}.#{fun}")
851-
852-
chardata ->
853-
IO.ANSI.Docs.print_headings([heading], opts)
854-
IO.puts(chardata)
855-
end
856-
end
857-
858812
defp no_beam(module) do
859813
case Code.ensure_loaded(module) do
860814
{:module, _} ->

0 commit comments

Comments
 (0)