diff --git a/lib/elixir/lib/kernel/lexical_tracker.ex b/lib/elixir/lib/kernel/lexical_tracker.ex index 08475769f02..8a32e33f1ee 100644 --- a/lib/elixir/lib/kernel/lexical_tracker.ex +++ b/lib/elixir/lib/kernel/lexical_tracker.ex @@ -123,7 +123,14 @@ defmodule Kernel.LexicalTracker do @doc false def handle_call(:unused_aliases, _from, state) do - {:reply, Enum.sort(state.aliases), state} + unused_aliases = + Enum.map(state.aliases, fn + {{:shadowed, module}, meta} -> {module, meta} + {module, meta} when is_atom(module) -> {module, meta} + end) + |> Enum.sort() + + {:reply, unused_aliases, state} end def handle_call(:unused_imports, _from, state) do @@ -220,6 +227,12 @@ defmodule Kernel.LexicalTracker do def handle_cast({:add_alias, module, meta, warn}, state) do if warn do + state = + case state do + %{aliases: %{^module => meta}} -> put_in(state.aliases[{:shadowed, module}], meta) + _ -> state + end + {:noreply, put_in(state.aliases[module], meta)} else {:noreply, state} diff --git a/lib/elixir/lib/macro/env.ex b/lib/elixir/lib/macro/env.ex index e5e62e8abce..57433ac1fdf 100644 --- a/lib/elixir/lib/macro/env.ex +++ b/lib/elixir/lib/macro/env.ex @@ -447,7 +447,7 @@ defmodule Macro.Env do ## Examples - iex> alias List, as: MyList + iex> alias List, as: MyList, warn: false iex> Macro.Env.expand_alias(__ENV__, [], [:MyList]) {:alias, List} iex> Macro.Env.expand_alias(__ENV__, [], [:MyList, :Nested]) @@ -456,7 +456,7 @@ defmodule Macro.Env do If there is no alias or the alias starts with `Elixir.` (which disables aliasing), then `:error` is returned: - iex> alias List, as: MyList + iex> alias List, as: MyList, warn: false iex> Macro.Env.expand_alias(__ENV__, [], [:Elixir, MyList]) :error iex> Macro.Env.expand_alias(__ENV__, [], [:AnotherList]) diff --git a/lib/elixir/test/elixir/kernel/alias_test.exs b/lib/elixir/test/elixir/kernel/alias_test.exs index a1e3d0f5cbb..4e91f7a6e5b 100644 --- a/lib/elixir/test/elixir/kernel/alias_test.exs +++ b/lib/elixir/test/elixir/kernel/alias_test.exs @@ -34,6 +34,12 @@ defmodule Kernel.AliasTest do assert Billing == :"Elixir.MyApp.Billing" end + test "overriding parent alias with child alias" do + alias MyApp.Billing + alias Billing.Billing + assert Billing == :"Elixir.MyApp.Billing.Billing" + end + test "lexical" do if true_fun() do alias OMG, as: List, warn: false diff --git a/lib/elixir/test/elixir/kernel/warning_test.exs b/lib/elixir/test/elixir/kernel/warning_test.exs index b957bd25b3e..2863f0d8638 100644 --- a/lib/elixir/test/elixir/kernel/warning_test.exs +++ b/lib/elixir/test/elixir/kernel/warning_test.exs @@ -894,6 +894,22 @@ defmodule Kernel.WarningTest do purge(Sample) end + test "unused alias due to shadowing" do + assert_warn_compile( + ["nofile:2:3", "unused alias Baz"], + """ + defmodule Sample do + alias Foo.Baz + alias Bar.Baz + + def baz, do: Baz + end + """ + ) + after + purge(Sample) + end + test "unused inside dynamic module" do import List, only: [flatten: 1], warn: false