Skip to content

Conversation

@pckrishnadas88
Copy link
Contributor

@pckrishnadas88 pckrishnadas88 commented Dec 15, 2025

Summary

This PR adds a warning in Mix.Project when a project’s application name is the same as one of its dependencies.

Details

Currently, if a project declares an app name that is identical to one of its dependencies, Elixir doesn’t warn the user. This can lead to unexpected behaviors, such as hanging compilers when trying to start tasks from the dependency.

This fix implements warn_on_duplicate_app_name/1 in mix/project.ex that prints a warning using Mix.shell().error/1. The associated test Mix.ProjectTest verifies the behavior.

Example

If a user creates a project with:

mix new aoc

and adds {:aoc, "~> 0.16.0"} to deps, running:

mix deps.get
mix aoc.set

will print:

warning: the application name :aoc is the same as one of its dependencies

Related Issue

Fixes: [elixir-lang/elixir#14972](#14972)

@josevalim
Copy link
Member

Hi @pckrishnadas88, thank you for the PR! Although I would likely move the check elsewhere, perhaps on Mix.Dep.Loader or somewhere else where we already traverse the dependencies...

This ensures Mix emits a warning if a project's app name conflicts with one of its dependencies.
@pckrishnadas88
Copy link
Contributor Author

Hi @josevalim,

Thanks for the feedback! I’ve moved the check to Mix.Dep.Loader and added a test that verifies the warning prints when the project app name matches a dependency. Verified locally with a temporary project.

I’m still learning Elixir, so any guidance or feedback is greatly appreciated.

PTAL!

—Krishnadas

mix_children(Mix.Project.config(), locked?, []) ++ Mix.Dep.Umbrella.unloaded()
deps = mix_children(Mix.Project.config(), locked?, []) ++ Mix.Dep.Umbrella.unloaded()
# warn if project app matches a dep
warn_on_duplicate_app_name(Mix.Project.config()[:app], deps)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please move it inside the with_scm_and_app, so we don't have to traverse deps twice!

Copy link
Contributor Author

@pckrishnadas88 pckrishnadas88 Dec 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the feedback!

I’ve moved the duplicate app name warning into with_scm_and_app. Please let me know if anything else is needed.


{scm, opts} =
if is_nil(scm) and Mix.Hex.ensure_installed?(locked?) do
if is_nil(scm) and locked? and Mix.Hex.ensure_installed?(locked?) do
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this change? 🤔

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the question — I might be missing something here.

I added the locked? check because when I remove it, the following test starts failing:

test raises when no SCM is specified (Mix.DepTest)
     test/mix/dep_test.exs:115
     Expected exception Mix.Error but got MatchError (no match of right hand side value:

         {:error, {:hex, {~c"no such file or directory", ~c"hex.app"}}}
     )
     code: with_deps(deps, fn ->
     stacktrace:
       lib/hex.ex:5: Hex.start/0
       (mix 1.20.0-dev) lib/mix/hex.ex:64: Mix.Hex.start/0
       (mix 1.20.0-dev) lib/mix/dep/loader.ex:193: Mix.Dep.Loader.with_scm_and_app/5
       (mix 1.20.0-dev) lib/mix/dep/loader.ex:145: Mix.Dep.Loader.to_dep/4
       (elixir 1.20.0-dev) lib/enum.ex:1717: Enum."-map/2-lists^map/1-1-"/2
       (mix 1.20.0-dev) lib/mix/dep/loader.ex:376: Mix.Dep.Loader.mix_children/3
       (mix 1.20.0-dev) lib/mix/dep/loader.ex:22: Mix.Dep.Loader.children/1
       (mix 1.20.0-dev) lib/mix/dep/converger.ex:101: Mix.Dep.Converger.all/4
       (mix 1.20.0-dev) lib/mix/dep/converger.ex:93: Mix.Dep.Converger.converge/4
       (mix 1.20.0-dev) lib/mix/dep/converger.ex:76: Mix.Dep.Converger.converge/1
       (elixir 1.20.0-dev) lib/file.ex:2013: File.cd!/2
       test/test_helper.exs:174: MixTest.Case.in_fixture/3
       test/mix/dep_test.exs:35: Mix.DepTest.with_deps/2
       test/mix/dep_test.exs:118: (test)

I’m not fully sure what the intended behavior is here, so I added the guard to keep the existing test behavior.
Happy to change this if there’s a better approach.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Take a look at test/mix/tasks/deps_test.exs and see how tests with dependencies are handled. We already have some dependencies that we can handle, such as ok and git_repo, and you can create a project with the same name as one of those deps. You can then also move the test to test/mix/tasks/deps_test.exs :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! I’ve moved the test to test/mix/tasks/deps_test.exs and reused the existing :ok dependency fixture as suggested. All make test_mix passes locally.

@josevalim josevalim merged commit 0f00cb0 into elixir-lang:main Dec 16, 2025
9 of 11 checks passed
@josevalim
Copy link
Member

💚 💙 💜 💛 ❤️

@pckrishnadas88
Copy link
Contributor Author

Thank you! 💚💙💜💛❤️

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants