From 2e56b6f98e34edcafe0d7691939c4c33302a1a5c Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Tue, 5 Oct 2021 19:43:44 -0700 Subject: [PATCH] Include rmeta candidates in "multiple matching crates" error Only dylib and rlib candidates were included in the error. I think the reason is that at the time this error was originally implemented, rmeta crate sources were represented different from dylib and rlib sources. I wrote up more detailed analysis in [this comment][1]. The new version of the code is also a bit easier to read and should be more robust to future changes since it uses `CrateSources::paths()`. [1]: https://github.com/rust-lang/rust/pull/88675#issuecomment-935282436 --- compiler/rustc_metadata/src/locator.rs | 28 ++++++++++--------- .../ui/crate-loading/crateresolve2.stderr | 3 ++ 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs index f1ada3e1b75..c54ea610602 100644 --- a/compiler/rustc_metadata/src/locator.rs +++ b/compiler/rustc_metadata/src/locator.rs @@ -232,6 +232,7 @@ use rustc_target::spec::{Target, TargetTriple}; use snap::read::FrameDecoder; +use std::fmt::Write as _; use std::io::{Read, Result as IoResult, Write}; use std::path::{Path, PathBuf}; use std::{cmp, fmt, fs}; @@ -918,21 +919,22 @@ impl CrateError { libraries.sort_by_cached_key(|lib| lib.source.paths().next().unwrap().clone()); let candidates = libraries .iter() - .filter_map(|lib| { + .map(|lib| { let crate_name = &lib.metadata.get_root().name().as_str(); - match (&lib.source.dylib, &lib.source.rlib) { - (Some((pd, _)), Some((pr, _))) => Some(format!( - "\ncrate `{}`: {}\n{:>padding$}", - crate_name, - pd.display(), - pr.display(), - padding = 8 + crate_name.len() - )), - (Some((p, _)), None) | (None, Some((p, _))) => { - Some(format!("\ncrate `{}`: {}", crate_name, p.display())) - } - (None, None) => None, + let mut paths = lib.source.paths(); + + // This `unwrap()` should be okay because there has to be at least one + // source file. `CrateSource`'s docs confirm that too. + let mut s = format!( + "\ncrate `{}`: {}", + crate_name, + paths.next().unwrap().display() + ); + let padding = 8 + crate_name.len(); + for path in paths { + write!(s, "\n{:>padding$}", path.display(), padding = padding).unwrap(); } + s }) .collect::(); err.note(&format!("candidates:{}", candidates)); diff --git a/src/test/ui/crate-loading/crateresolve2.stderr b/src/test/ui/crate-loading/crateresolve2.stderr index 9a8ef6f2a60..c6da629df27 100644 --- a/src/test/ui/crate-loading/crateresolve2.stderr +++ b/src/test/ui/crate-loading/crateresolve2.stderr @@ -5,6 +5,9 @@ LL | extern crate crateresolve2; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: candidates: + crate `crateresolve2`: $TEST_BUILD_DIR/crate-loading/crateresolve2/auxiliary/libcrateresolve2-1.rmeta + crate `crateresolve2`: $TEST_BUILD_DIR/crate-loading/crateresolve2/auxiliary/libcrateresolve2-2.rmeta + crate `crateresolve2`: $TEST_BUILD_DIR/crate-loading/crateresolve2/auxiliary/libcrateresolve2-3.rmeta error: aborting due to previous error