diff --git a/lib/elixir/lib/kernel/lexical_tracker.ex b/lib/elixir/lib/kernel/lexical_tracker.ex index 8a32e33f1ee..365c39234c7 100644 --- a/lib/elixir/lib/kernel/lexical_tracker.ex +++ b/lib/elixir/lib/kernel/lexical_tracker.ex @@ -40,8 +40,8 @@ defmodule Kernel.LexicalTracker do end @doc false - def add_alias(pid, module, meta, warn) when is_atom(module) do - :gen_server.cast(pid, {:add_alias, module, meta, warn}) + def add_alias(pid, module, meta, warn, function?) when is_atom(module) do + :gen_server.cast(pid, {:add_alias, module, meta, warn, function?}) end @doc false @@ -225,12 +225,16 @@ defmodule Kernel.LexicalTracker do end end - def handle_cast({:add_alias, module, meta, warn}, state) do + def handle_cast({:add_alias, module, meta, warn, function?}, state) do if warn do state = case state do - %{aliases: %{^module => meta}} -> put_in(state.aliases[{:shadowed, module}], meta) - _ -> state + # we only track shadowed unused aliases at the top-level + %{aliases: %{^module => meta}} when not function? -> + put_in(state.aliases[{:shadowed, module}], meta) + + _ -> + state end {:noreply, put_in(state.aliases[module], meta)} diff --git a/lib/elixir/src/elixir_lexical.erl b/lib/elixir/src/elixir_lexical.erl index f5c891570e6..e76d8044ed5 100644 --- a/lib/elixir/src/elixir_lexical.erl +++ b/lib/elixir/src/elixir_lexical.erl @@ -40,8 +40,8 @@ trace({import, Meta, Module, Opts}, #{lexical_tracker := Pid}) -> ?tracker:add_import(Pid, Module, Only, Meta, Imported and should_warn(Meta, Opts)), ok; -trace({alias, Meta, _Old, New, Opts}, #{lexical_tracker := Pid}) -> - ?tracker:add_alias(Pid, New, Meta, should_warn(Meta, Opts)), +trace({alias, Meta, _Old, New, Opts}, #{lexical_tracker := Pid, function := Function}) -> + ?tracker:add_alias(Pid, New, Meta, should_warn(Meta, Opts), Function /= nil), ok; trace({alias_expansion, _Meta, Lookup, _Result}, #{lexical_tracker := Pid}) -> ?tracker:alias_dispatch(Pid, Lookup), diff --git a/lib/elixir/test/elixir/kernel/lexical_tracker_test.exs b/lib/elixir/test/elixir/kernel/lexical_tracker_test.exs index 34ff5ebd47e..4c807effa66 100644 --- a/lib/elixir/test/elixir/kernel/lexical_tracker_test.exs +++ b/lib/elixir/test/elixir/kernel/lexical_tracker_test.exs @@ -52,7 +52,7 @@ defmodule Kernel.LexicalTrackerTest do end test "can add aliases", config do - D.add_alias(config[:pid], String, 1, true) + D.add_alias(config[:pid], String, 1, true, false) D.alias_dispatch(config[:pid], String) assert D.references(config[:pid]) == {[], [], [], []} end @@ -93,18 +93,18 @@ defmodule Kernel.LexicalTrackerTest do end test "unused aliases", config do - D.add_alias(config[:pid], String, 1, true) + D.add_alias(config[:pid], String, 1, true, false) assert D.collect_unused_aliases(config[:pid]) == [{String, 1}] end test "used aliases are not unused", config do - D.add_alias(config[:pid], String, 1, true) + D.add_alias(config[:pid], String, 1, true, false) D.alias_dispatch(config[:pid], String) assert D.collect_unused_aliases(config[:pid]) == [] end test "aliases with no warn are not unused", config do - D.add_alias(config[:pid], String, 1, false) + D.add_alias(config[:pid], String, 1, false, false) assert D.collect_unused_aliases(config[:pid]) == [] end diff --git a/lib/elixir/test/elixir/kernel/warning_test.exs b/lib/elixir/test/elixir/kernel/warning_test.exs index 2863f0d8638..e9d631d5457 100644 --- a/lib/elixir/test/elixir/kernel/warning_test.exs +++ b/lib/elixir/test/elixir/kernel/warning_test.exs @@ -910,6 +910,23 @@ defmodule Kernel.WarningTest do purge(Sample) end + test "does not warn when shadowing alias in nested block" do + assert capture_compile(""" + defmodule Sample do + alias Foo.Baz + + def foo do + alias Bar.Baz + Baz + end + + def baz, do: Baz + end + """) == "" + after + purge(Sample) + end + test "unused inside dynamic module" do import List, only: [flatten: 1], warn: false