cargo icon indicating copy to clipboard operation
cargo copied to clipboard

"can't find crate for..." proc-macro crates when the crate is clearly present and is passed to rustc

Open NoraCodes opened this issue 7 months ago • 13 comments

Problem

When compiling some crates (poem 3.1.10, salvo 0.78.0), I expect them to build; they fail to build with errors like:

error[E0463]: can't find crate for `salvo_macros`
  --> /home/nora/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/salvo_core-0.78.0/src/lib.rs:31:9
   |
31 | pub use salvo_macros::handler;
   |         ^^^^^^^^^^^^ can't find crate

error[E0463]: can't find crate for `salvo_macros`
  --> /home/nora/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/salvo_core-0.78.0/src/lib.rs:33:9
   |
33 | pub use salvo_macros as macros;
   |         ^^^^^^^^^^^^ can't find crate

error[E0463]: can't find crate for `salvo_macros`
  --> /home/nora/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/salvo_core-0.78.0/src/lib.rs:85:13
   |
85 |     pub use salvo_macros::{Extractible, handler};
   |             ^^^^^^^^^^^^ can't find crate

For more information about this error, try `rustc --explain E0463`.
error: could not compile `salvo_core` (lib) due to 3 previous errors

Steps

  1. cargo new whatever && cd whatever
  2. cargo add poem (or salvo)
  3. cargo build

However, I tried this on a new VM and wasn't able to reproduce it. It's something to do with my system, and I haven't yet figured out what.

Possible Solution(s)

I tried uninstalling (rustup self uninstall) and reinstalling Rust, as well as cargo clean and rm -r ~/.cargo/registry/cache.

This appears not to happen under rust 1.80 but does happen under 1.81.

Notes

I ran cargo build --verbose and can see that the "missing" crates are indeed being passed to rustc:

/home/nora/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/bin/rustc 
--crate-name salvo_core 
--edition=2024 /home/nora/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/salvo_core-0.78.0/src/lib.rs 
# ...
--extern salvo_macros=/tmp/salvotest/target/debug/deps/libsalvo_macros-2d16cc326ba6665d.so 
# ...
--cap-lints allow`

Version

cargo 1.86.0 (adf9b6ad1 2025-02-28)
release: 1.86.0
commit-hash: adf9b6ad14cfa10ff680d5806741a144f7163698
commit-date: 2025-02-28
host: x86_64-unknown-linux-gnu
libgit2: 1.9.0 (sys:0.20.0 vendored)
libcurl: 8.12.0-DEV (sys:0.4.79+curl-8.12.0 vendored ssl:OpenSSL/1.1.1w)
ssl: OpenSSL 1.1.1w  11 Sep 2023
os: Debian 12.0.0 (bookworm) [64-bit]

NoraCodes avatar May 04 '25 16:05 NoraCodes

nora ran cargo bisect-rustc and found this:

Regression in nightly-2024-07-13

...

looking for regression commit between 2024-07-12 and 2024-07-13
fetching (via remote github) commits from max(5315cbe15b79533f380bbb6685aa5480d5ff4ef5, 2024-07-10) to c6727fc9b5c64cefa7263486497ee95e529bd0f8
ending github query because we found starting sha: 5315cbe15b79533f380bbb6685aa5480d5ff4ef5
get_commits_between returning commits, len: 8
  commit[0] 2024-07-11: Auto merge of #127609 - flip1995:clippy-subtree-update, r=Manishearth
  commit[1] 2024-07-11: Auto merge of #127614 - matthiaskrgr:rollup-8geziwi, r=matthiaskrgr
  commit[2] 2024-07-12: Auto merge of #127382 - estebank:const-let, r=compiler-errors
  commit[3] 2024-07-12: Auto merge of #127635 - matthiaskrgr:rollup-foopajr, r=matthiaskrgr
  commit[4] 2024-07-12: Auto merge of #127479 - Urgau:rustc-stable-hash, r=michaelwoerister
  commit[5] 2024-07-12: Auto merge of #127653 - matthiaskrgr:rollup-72bqgvp, r=matthiaskrgr
  commit[6] 2024-07-12: Auto merge of #127636 - nnethercote:fix-Parser-look_ahead, r=oli-obk
  commit[7] 2024-07-12: Auto merge of #123351 - beetrees:x86-ret-snan-rust, r=nikic,workingjubilee

so a) this is a rustc bug, and b) i suspect it is related to rustc-stable-hash somehow.

we also ran RUSTC_LOG=rustc_metadata=info and found this mismatch between the working and non-working builds:

# working
 INFO rustc_metadata::creader resolving crate `poem_derive`
 INFO rustc_metadata::creader library for `poem_derive` was loaded previously

# non-working
 INFO rustc_metadata::creader resolving crate `poem_derive`
 INFO rustc_metadata::creader falling back to a load
 INFO rustc_metadata::locator dylib reading metadata from: /tmp/whatever/target/debug/deps/libpoem_derive-a4fba4f212f1e51d.so
 INFO rustc_metadata::locator Rejecting via proc macro: expected false got true
 INFO rustc_metadata::locator metadata mismatch
 INFO rustc_metadata::creader falling back to loading proc_macro
 INFO rustc_metadata::locator dylib reading metadata from: /tmp/whatever/target/debug/deps/libpoem_derive-a4fba4f212f1e51d.so
 INFO rustc_metadata::creader register newly loaded library for `poem_derive`
 INFO rustc_metadata::creader register crate `poem_derive` (cnum = 84. private_dep = false)

jyn514 avatar May 04 '25 21:05 jyn514

this bit here: https://github.com/rust-lang/rust/blob/c9f690a1e3d42f80788e9e4f2aa25547b1d8df58/compiler/rustc_metadata/src/creader.rs#L516-L535 is rejecting a previously loaded crate, but i'm not sure why

jyn514 avatar May 04 '25 21:05 jyn514

there is additional logging in the non-working case that i didn't post at first; here it is:

 INFO rustc_metadata::creader resolving crate `poem_derive`
 INFO rustc_metadata::creader falling back to a load
 INFO rustc_metadata::locator dylib reading metadata from: /tmp/whatever/target/debug/deps/libpoem_derive-a4fba4f212f1e51d.so
 INFO rustc_metadata::locator Rejecting via proc macro: expected false got true
 INFO rustc_metadata::locator metadata mismatch
 INFO rustc_metadata::creader falling back to loading proc_macro
 INFO rustc_metadata::locator dylib reading metadata from: /tmp/whatever/target/debug/deps/libpoem_derive-a4fba4f212f1e51d.so
 INFO rustc_metadata::creader register newly loaded library for `poem_derive`
 INFO rustc_metadata::creader resolving crate `poem_derive`

in particular note those last two lines. "register newly loaded library" should always be followed by "register crate"; the only way it can go wrong is if intern_stable_crate_id returns an error.

my working theory:

  1. existing_match, for some reason, incorrectly thinks it needs to reload the crate because of a mismatch.
  2. CrateLocator successfully finds the crate and passes it to register_crate
  3. register_crate fails to reregister it, because it is the same crate and it rejects duplicate StableCrateIds.

cc @petrochenkov @Urgau i suspect this is related to https://github.com/rust-lang/rust/pull/127479 somehow but i'm not sure how. do you have ideas on what could be going wrong in existing_match?

jyn514 avatar May 04 '25 21:05 jyn514

i think there is a secondary issue which is that this should have reported E0519 instead of "crate not found". the last code to touch that was https://github.com/rust-lang/rust/pull/111461 but that says it was just readding existing logic.

jyn514 avatar May 04 '25 22:05 jyn514

ok yeah https://github.com/rust-lang/rust/pull/109213/ really should not have removed the bug!; cc @oli-obk

jyn514 avatar May 04 '25 22:05 jyn514

I re-examine https://github.com/rust-lang/rust/pull/127479 and I don't see anything that would explain the behavior seen here.

I also re-compared the extracted code with the code inside rustc-stable-hash and didn't find any meaningful difference.

@jyn514 Are you able to confirm that the crate hash are not the same? Does reverting the PR fixes the issue?

Urgau avatar May 05 '25 19:05 Urgau

@Urgau i'm not able to replicate this locally, so i can't confirm anything about the hashes one way or another. but i don't see anything else in the range bisect-rustc shows that could possible affect metadata loading. and the error seems related to hashing somehow, because the issue is that rustc_resolve thinks the .so file doesn't match the already loaded cnum, even though later it errors because file has the same StableCrateId.

jyn514 avatar May 05 '25 20:05 jyn514

I tried locally and on a VM and I'm also unable to reproduce it, with both poem and salvo.

Urgau avatar May 06 '25 05:05 Urgau

Do you have the Nix package manager installed? I am using Nix on Ubuntu and ran into a similar issue with wasmtime. Removing gcc that was installed via the Nix Home Manager solved it for me. Someone else on the Rust user forums seems to have encountered the same problem.

shunby avatar May 10 '25 17:05 shunby

I bumped into this a couple of times with nixpkgs but never remembered how I fixed it. Guess it might be nix patch-elf at sometimes patching rustc wrongly, or my rust toolchain frkm nixpkgs was missing some dependencies.

weihanglo avatar May 10 '25 17:05 weihanglo

if someone encountering this problem could run nm -g target/debug/deps/*.so | grep __rustc_proc_macro_decls_ and send me the output, that would be very helpful. if that has no output, send the output without the pipe to grep.

jyn514 avatar May 10 '25 20:05 jyn514

$ nm -g target/debug/deps/*.so | grep __rustc_proc_macro_decls_
00000000001ed5e8 D __rustc_proc_macro_decls_43a8767dcd1f163b__
000000000033d008 D __rustc_proc_macro_decls_9ad6036aa6c77638__
0000000000308618 D __rustc_proc_macro_decls_2ed9d063c2b4b61a__
00000000002676a0 D __rustc_proc_macro_decls_2ed462a267df31a2__
00000000002178b0 D __rustc_proc_macro_decls_f3fa41c5b5ca6687__
0000000000288908 D __rustc_proc_macro_decls_7f632681e18fe3f7__

Removing the home-manager managed gcc did not help; I am using a Rustup not installed through Nix.

NoraCodes avatar May 11 '25 13:05 NoraCodes

I've tried to reproduce it and wasn't able to. It would be useful to get more details on the OS setup:

  • What distro? NixOS or a different distro with Nix installed or something different entirely?
  • Where was Rust installed from?
  • What sort of relevant toolchains are present and from where?

Noratrieb avatar May 25 '25 14:05 Noratrieb

Apologies for the long delay.

What distro? NixOS or a different distro with Nix installed or something different entirely?

Debian GNU/Linux 12 (bookworm) x86_64 with Nix managing packages via home-manager.

Where was Rust installed from?

rustup.rs

What sort of relevant toolchains are present and from where?

Rust toolchains installed:
~
❯ rustup show
Default host: x86_64-unknown-linux-gnu
rustup home:  /home/nora/.rustup

installed toolchains
--------------------
stable-x86_64-unknown-linux-gnu (active, default)
nightly-x86_64-unknown-linux-gnu
1.80.0-x86_64-unknown-linux-gnu
1.81.0-x86_64-unknown-linux-gnu
1.85.0-x86_64-unknown-linux-gnu
stage1

active toolchain
----------------
name: stable-x86_64-unknown-linux-gnu
active because: it's the default toolchain
installed targets:
  x86_64-unknown-linux-gnu
  x86_64-unknown-linux-musl
C toolchains installed:
~
❯ apt-cache policy gcc
gcc:
  Installed: 4:12.2.0-3
  Candidate: 4:12.2.0-3
  Version table:
 *** 4:12.2.0-3 500
        500 http://debian.uchicago.edu/debian bookworm/main amd64 Packages
        100 /var/lib/dpkg/status

~
❯ apt-cache policy clang
clang:
  Installed: 1:14.0-55.7~deb12u1
  Candidate: 1:14.0-55.7~deb12u1
  Version table:
 *** 1:14.0-55.7~deb12u1 500
        500 http://debian.uchicago.edu/debian bookworm/main amd64 Packages
        100 /var/lib/dpkg/status
home-manager stuff installed: ``` ~ ❯ home-manager packages act-0.2.71 atuin-18.4.0 bat-0.25.0 bottom-0.10.2 broot-1.44.6 chafa-1.14.5 ctpv-1.1 cyme-1.8.5 delta-0.18.2 deno-2.1.7 dfc-3.1.1 direnv-2.35.0 dua-2.29.4 exercism-3.5.4 eza-0.20.18 eza-0.20.18-man fd-10.2.0 fend-1.5.5 fortune-kind-custom freshfetch-0.2.0 fzf-0.58.0 fzf-0.58.0-man git-2.47.1 go-1.23.4 graphviz-12.2.1 hexyl-0.16.0 hm-session-vars.sh home-configuration-reference-manpage home-manager htop-3.3.0 iotop-0.6 jq-1.7.1-bin jq-1.7.1-man jujutsu-0.25.0 just-1.39.0 just-1.39.0-man man-db-2.13.0 monolith-2.8.3 neocities-0.0.18 neofetch-unstable-2021-12-10 neofetch-unstable-2021-12-10-man neovim-0.10.3 nix-output-monitor-2.1.4 nix-zsh-completions-0.5.1 npins-0.2.4 pandoc-cli-3.1.11.1 procs-0.14.9 ripgrep-14.1.1 starship-1.22.1 syncthing-1.29.2 timg-1.6.1 tor-browser-14.0.4 uutils-coreutils-0.0.29 uv-0.3.0 viddy-1.3.0 wget-1.25.0 wl-clipboard-2.2.1 xclip-0.13 xsel-1.2.1 yt-dlp-2025.1.26 zellij-0.41.2 zsh-5.9 zsh-5.9-man ```

NoraCodes avatar Jun 06 '25 15:06 NoraCodes

EDIT: This was a user error, I'd asked and no one noticed it was missing -L. But this does at least show the error message has become worse:

Previous contents

Trying to compile some crates with rustc directly, I encountered this error.

Here is my MWE: https://github.com/midnightveil/rustc-cant-find-crate. The RUSTC_LOG="debug" log is similar as the above outputs. Interestingly enough even attaching -C metadata=<random> makes no difference.

mkdir -p build/
rustc --target aarch64-unknown-none --edition 2021 \
    --emit=link=build/libsecond.rlib \
        --emit=metadata=build/libsecond.rmeta \
        --crate-type rlib \
        --crate-name second \
        second.rs
rustc --target aarch64-unknown-none --edition 2021 \
        --emit=link=build/libfirst.rlib \
        --emit=metadata=build/libfirst.rmeta \
        --crate-type rlib \
        --crate-name first \
        --extern second=build/libsecond.rlib \
        first.rs
rustc --target aarch64-unknown-none --edition 2021 \
        --emit=link=build/main.a \
        --crate-type staticlib \
        --crate-name main \
        --extern first=build/libfirst.rlib \
        main.rs
error[E0463]: can't find crate for `first`
 --> main.rs:6:5
  |
6 | use first;
  |     ^^^^^ can't find crate

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0463`.
make: *** [Makefile:6: build/main.a] Error 1

On an older version of rustc, this error occurs, which doesn't make much sense to me either:

make RUSTC="rustc +1.70.0"
mkdir -p build/
rustc +1.70.0 --target aarch64-unknown-none --edition 2021 \
    --emit=link=build/libsecond.rlib \
        --emit=metadata=build/libsecond.rmeta \
        --crate-type rlib \
        --crate-name second \
        second.rs
rustc +1.70.0 --target aarch64-unknown-none --edition 2021 \
        --emit=link=build/libfirst.rlib \
        --emit=metadata=build/libfirst.rmeta \
        --crate-type rlib \
        --crate-name first \
        --extern second=build/libsecond.rlib \
        first.rs
rustc +1.70.0 --target aarch64-unknown-none --edition 2021 \
        --emit=link=build/main.a \
        --crate-type staticlib \
        --crate-name main \
        --extern first=build/libfirst.rlib \
        main.rs
error[E0519]: the current crate is indistinguishable from one of its dependencies: it has the same crate-name `first` and was compiled with the same `-C metadata` arguments. This will result in symbol conflicts between the two.
 --> main.rs:6:5
  |
6 | use first;
  |     ^^^^^

error: aborting due to previous error

For more information about this error, try `rustc --explain E0519`.
make: *** [Makefile:6: build/main.a] Error 1

I can reproduce this both with and without nix.

(There's a couple more comments in the repo: for one, adding both crates as deps of the main crate doens't make a difference, and also using extern crate first; instead of use first; tells us that it's complaining about not being able to find the dependency second or first)

Relevant-ish metadata

I use Fedora, with rustup installed via nix home-manager. I can also reproduce this on a debian system with rustc installed via rustup.

> rustc --version
rustc 1.87.0 (17067e9ac 2025-05-09)
> which rustc
/home/julia/.nix-profile/bin/rustc
> rustup show
Default host: x86_64-unknown-linux-gnu
rustup home:  /home/julia/.rustup

installed toolchains
--------------------

stable-x86_64-unknown-linux-gnu (default)
nightly-2025-02-26-x86_64-unknown-linux-gnu
nightly-x86_64-unknown-linux-gnu
1.70.0-x86_64-unknown-linux-gnu
1.81.0-x86_64-unknown-linux-gnu

installed targets for active toolchain
--------------------------------------

aarch64-unknown-linux-gnu
aarch64-unknown-none
riscv64gc-unknown-none-elf
x86_64-unknown-linux-gnu
x86_64-unknown-linux-musl
x86_64-unknown-none

active toolchain
----------------

stable-x86_64-unknown-linux-gnu (default)
rustc 1.87.0 (17067e9ac 2025-05-09)
> make
mkdir -p build/
rustc --target aarch64-unknown-none --edition 2021 \
    --emit=link=build/libsecond.rlib \
        --emit=metadata=build/libsecond.rmeta \
        --crate-type rlib \
        --crate-name second \
        second.rs
rustc --target aarch64-unknown-none --edition 2021 \
        --emit=link=build/libfirst.rlib \
        --emit=metadata=build/libfirst.rmeta \
        --crate-type rlib \
        --crate-name first \
        --extern second=build/libsecond.rlib \
        first.rs
rustc --target aarch64-unknown-none --edition 2021 \
        --emit=link=build/main.a \
        --crate-type staticlib \
        --crate-name main \
        --extern first=build/libfirst.rlib \
        main.rs
error[E0463]: can't find crate for `first`
 --> main.rs:6:5
  |
6 | use first;
  |     ^^^^^ can't find crate

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0463`.
make: *** [Makefile:6: build/main.a] Error 1
> which rustup
/home/juliab/.cargo/bin/rustup
> which rustc
/home/juliab/.cargo/bin/rustc

(jyn sent me here 💜)

midnightveil avatar Jul 11 '25 12:07 midnightveil

@midnightveil That's normal. rustc does not implicitly have a search path for transitive dependencies. You'll need to add -L build for it to find them.

ehuss avatar Jul 13 '25 17:07 ehuss