Auto merge of #149273 - bjorn3:crate_locator_improvements, r=petrochenkov
Don't leak sysroot crates through dependencies Previously if a dependency of the current crate depended on a sysroot crate, then `extern crate` would in the current crate would pick the first loaded version of said sysroot crate even in case of an ambiguity. This is surprising and brittle. For `-Ldependency=` we already blocked this since rust-lang/rust#110229, but the fix didn't account for sysroot crates. Should fix https://github.com/rust-lang/rust/issues/147966
This commit is contained in:
commit
08de25c4ea
17 changed files with 185 additions and 127 deletions
|
|
@ -277,7 +277,7 @@ pub fn each_linked_rlib(
|
|||
}
|
||||
let crate_name = info.crate_name[&cnum];
|
||||
let used_crate_source = &info.used_crate_source[&cnum];
|
||||
if let Some((path, _)) = &used_crate_source.rlib {
|
||||
if let Some(path) = &used_crate_source.rlib {
|
||||
f(cnum, path);
|
||||
} else if used_crate_source.rmeta.is_some() {
|
||||
return Err(errors::LinkRlibError::OnlyRmetaFound { crate_name });
|
||||
|
|
@ -541,7 +541,7 @@ fn link_staticlib(
|
|||
};
|
||||
let crate_name = codegen_results.crate_info.crate_name[&cnum];
|
||||
let used_crate_source = &codegen_results.crate_info.used_crate_source[&cnum];
|
||||
if let Some((path, _)) = &used_crate_source.dylib {
|
||||
if let Some(path) = &used_crate_source.dylib {
|
||||
all_rust_dylibs.push(&**path);
|
||||
} else if used_crate_source.rmeta.is_some() {
|
||||
sess.dcx().emit_fatal(errors::LinkRlibError::OnlyRmetaFound { crate_name });
|
||||
|
|
@ -619,7 +619,6 @@ fn link_dwarf_object(sess: &Session, cg_results: &CodegenResults, executable_out
|
|||
.used_crate_source
|
||||
.items()
|
||||
.filter_map(|(_, csource)| csource.rlib.as_ref())
|
||||
.map(|(path, _)| path)
|
||||
.into_sorted_stable_ord();
|
||||
|
||||
for input_rlib in input_rlibs {
|
||||
|
|
@ -2173,12 +2172,7 @@ fn add_rpath_args(
|
|||
.crate_info
|
||||
.used_crates
|
||||
.iter()
|
||||
.filter_map(|cnum| {
|
||||
codegen_results.crate_info.used_crate_source[cnum]
|
||||
.dylib
|
||||
.as_ref()
|
||||
.map(|(path, _)| &**path)
|
||||
})
|
||||
.filter_map(|cnum| codegen_results.crate_info.used_crate_source[cnum].dylib.as_deref())
|
||||
.collect::<Vec<_>>();
|
||||
let rpath_config = RPathConfig {
|
||||
libs: &*libs,
|
||||
|
|
@ -2656,7 +2650,7 @@ fn add_native_libs_from_crate(
|
|||
|
||||
if link_static && cnum != LOCAL_CRATE && !bundled_libs.is_empty() {
|
||||
// If rlib contains native libs as archives, unpack them to tmpdir.
|
||||
let rlib = &codegen_results.crate_info.used_crate_source[&cnum].rlib.as_ref().unwrap().0;
|
||||
let rlib = codegen_results.crate_info.used_crate_source[&cnum].rlib.as_ref().unwrap();
|
||||
archive_builder_builder
|
||||
.extract_bundled_libs(rlib, tmpdir, bundled_libs)
|
||||
.unwrap_or_else(|e| sess.dcx().emit_fatal(e));
|
||||
|
|
@ -2827,7 +2821,7 @@ fn add_upstream_rust_crates(
|
|||
}
|
||||
Linkage::Dynamic => {
|
||||
let src = &codegen_results.crate_info.used_crate_source[&cnum];
|
||||
add_dynamic_crate(cmd, sess, &src.dylib.as_ref().unwrap().0);
|
||||
add_dynamic_crate(cmd, sess, src.dylib.as_ref().unwrap());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2955,7 +2949,7 @@ fn add_static_crate(
|
|||
bundled_lib_file_names: &FxIndexSet<Symbol>,
|
||||
) {
|
||||
let src = &codegen_results.crate_info.used_crate_source[&cnum];
|
||||
let cratepath = &src.rlib.as_ref().unwrap().0;
|
||||
let cratepath = src.rlib.as_ref().unwrap();
|
||||
|
||||
let mut link_upstream =
|
||||
|path: &Path| cmd.link_staticlib_by_path(&rehome_lib_path(sess, path), false);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use std::hash::BuildHasherDefault;
|
||||
|
||||
pub use rustc_hash::{FxHashMap, FxHashSet, FxHasher};
|
||||
pub use rustc_hash::{FxBuildHasher, FxHashMap, FxHashSet, FxHasher};
|
||||
|
||||
pub type StdEntry<'a, K, V> = std::collections::hash_map::Entry<'a, K, V>;
|
||||
|
||||
|
|
|
|||
|
|
@ -680,19 +680,19 @@ fn write_out_deps(tcx: TyCtxt<'_>, outputs: &OutputFilenames, out_filenames: &[P
|
|||
|
||||
for &cnum in tcx.crates(()) {
|
||||
let source = tcx.used_crate_source(cnum);
|
||||
if let Some((path, _)) = &source.dylib {
|
||||
if let Some(path) = &source.dylib {
|
||||
files.extend(hash_iter_files(
|
||||
iter::once(escape_dep_filename(&path.display().to_string())),
|
||||
checksum_hash_algo,
|
||||
));
|
||||
}
|
||||
if let Some((path, _)) = &source.rlib {
|
||||
if let Some(path) = &source.rlib {
|
||||
files.extend(hash_iter_files(
|
||||
iter::once(escape_dep_filename(&path.display().to_string())),
|
||||
checksum_hash_algo,
|
||||
));
|
||||
}
|
||||
if let Some((path, _)) = &source.rmeta {
|
||||
if let Some(path) = &source.rmeta {
|
||||
files.extend(hash_iter_files(
|
||||
iter::once(escape_dep_filename(&path.display().to_string())),
|
||||
checksum_hash_algo,
|
||||
|
|
|
|||
|
|
@ -135,16 +135,16 @@ impl<'a> std::fmt::Debug for CrateDump<'a> {
|
|||
writeln!(fmt, " priv: {:?}", data.is_private_dep())?;
|
||||
let CrateSource { dylib, rlib, rmeta, sdylib_interface } = data.source();
|
||||
if let Some(dylib) = dylib {
|
||||
writeln!(fmt, " dylib: {}", dylib.0.display())?;
|
||||
writeln!(fmt, " dylib: {}", dylib.display())?;
|
||||
}
|
||||
if let Some(rlib) = rlib {
|
||||
writeln!(fmt, " rlib: {}", rlib.0.display())?;
|
||||
writeln!(fmt, " rlib: {}", rlib.display())?;
|
||||
}
|
||||
if let Some(rmeta) = rmeta {
|
||||
writeln!(fmt, " rmeta: {}", rmeta.0.display())?;
|
||||
writeln!(fmt, " rmeta: {}", rmeta.display())?;
|
||||
}
|
||||
if let Some(sdylib_interface) = sdylib_interface {
|
||||
writeln!(fmt, " sdylib interface: {}", sdylib_interface.0.display())?;
|
||||
writeln!(fmt, " sdylib interface: {}", sdylib_interface.display())?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
|
|
@ -515,73 +515,19 @@ impl CStore {
|
|||
}
|
||||
}
|
||||
|
||||
fn existing_match(
|
||||
&self,
|
||||
externs: &Externs,
|
||||
name: Symbol,
|
||||
hash: Option<Svh>,
|
||||
kind: PathKind,
|
||||
) -> Option<CrateNum> {
|
||||
fn existing_match(&self, name: Symbol, hash: Option<Svh>) -> Option<CrateNum> {
|
||||
let hash = hash?;
|
||||
|
||||
for (cnum, data) in self.iter_crate_data() {
|
||||
if data.name() != name {
|
||||
trace!("{} did not match {}", data.name(), name);
|
||||
continue;
|
||||
}
|
||||
|
||||
match hash {
|
||||
Some(hash) if hash == data.hash() => return Some(cnum),
|
||||
Some(hash) => {
|
||||
debug!("actual hash {} did not match expected {}", hash, data.hash());
|
||||
continue;
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
|
||||
// When the hash is None we're dealing with a top-level dependency
|
||||
// in which case we may have a specification on the command line for
|
||||
// this library. Even though an upstream library may have loaded
|
||||
// something of the same name, we have to make sure it was loaded
|
||||
// from the exact same location as well.
|
||||
//
|
||||
// We're also sure to compare *paths*, not actual byte slices. The
|
||||
// `source` stores paths which are normalized which may be different
|
||||
// from the strings on the command line.
|
||||
let source = data.source();
|
||||
if let Some(entry) = externs.get(name.as_str()) {
|
||||
// Only use `--extern crate_name=path` here, not `--extern crate_name`.
|
||||
if let Some(mut files) = entry.files() {
|
||||
if files.any(|l| {
|
||||
let l = l.canonicalized();
|
||||
source.dylib.as_ref().map(|(p, _)| p) == Some(l)
|
||||
|| source.rlib.as_ref().map(|(p, _)| p) == Some(l)
|
||||
|| source.rmeta.as_ref().map(|(p, _)| p) == Some(l)
|
||||
}) {
|
||||
return Some(cnum);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// Alright, so we've gotten this far which means that `data` has the
|
||||
// right name, we don't have a hash, and we don't have a --extern
|
||||
// pointing for ourselves. We're still not quite yet done because we
|
||||
// have to make sure that this crate was found in the crate lookup
|
||||
// path (this is a top-level dependency) as we don't want to
|
||||
// implicitly load anything inside the dependency lookup path.
|
||||
let prev_kind = source
|
||||
.dylib
|
||||
.as_ref()
|
||||
.or(source.rlib.as_ref())
|
||||
.or(source.rmeta.as_ref())
|
||||
.expect("No sources for crate")
|
||||
.1;
|
||||
if kind.matches(prev_kind) {
|
||||
if hash == data.hash() {
|
||||
return Some(cnum);
|
||||
} else {
|
||||
debug!(
|
||||
"failed to load existing crate {}; kind {:?} did not match prev_kind {:?}",
|
||||
name, kind, prev_kind
|
||||
);
|
||||
debug!("actual hash {} did not match expected {}", hash, data.hash());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -678,7 +624,7 @@ impl CStore {
|
|||
None => (&source, &crate_root),
|
||||
};
|
||||
let dlsym_dylib = dlsym_source.dylib.as_ref().expect("no dylib for a proc-macro crate");
|
||||
Some(self.dlsym_proc_macros(tcx.sess, &dlsym_dylib.0, dlsym_root.stable_crate_id())?)
|
||||
Some(self.dlsym_proc_macros(tcx.sess, dlsym_dylib, dlsym_root.stable_crate_id())?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
|
@ -819,9 +765,7 @@ impl CStore {
|
|||
let path_kind = if dep.is_some() { PathKind::Dependency } else { PathKind::Crate };
|
||||
let private_dep = origin.private_dep();
|
||||
|
||||
let result = if let Some(cnum) =
|
||||
self.existing_match(&tcx.sess.opts.externs, name, hash, path_kind)
|
||||
{
|
||||
let result = if let Some(cnum) = self.existing_match(name, hash) {
|
||||
(LoadResult::Previous(cnum), None)
|
||||
} else {
|
||||
info!("falling back to a load");
|
||||
|
|
|
|||
|
|
@ -218,7 +218,7 @@ use std::ops::Deref;
|
|||
use std::path::{Path, PathBuf};
|
||||
use std::{cmp, fmt};
|
||||
|
||||
use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
|
||||
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
|
||||
use rustc_data_structures::memmap::Mmap;
|
||||
use rustc_data_structures::owned_slice::{OwnedSlice, slice_owned};
|
||||
use rustc_data_structures::svh::Svh;
|
||||
|
|
@ -401,7 +401,7 @@ impl<'a> CrateLocator<'a> {
|
|||
|
||||
let mut candidates: FxIndexMap<
|
||||
_,
|
||||
(FxIndexMap<_, _>, FxIndexMap<_, _>, FxIndexMap<_, _>, FxIndexMap<_, _>),
|
||||
(FxIndexSet<_>, FxIndexSet<_>, FxIndexSet<_>, FxIndexSet<_>),
|
||||
> = Default::default();
|
||||
|
||||
// First, find all possible candidate rlibs and dylibs purely based on
|
||||
|
|
@ -460,10 +460,10 @@ impl<'a> CrateLocator<'a> {
|
|||
// filesystem code should not care, but this is nicer for diagnostics.
|
||||
let path = spf.path.to_path_buf();
|
||||
match kind {
|
||||
CrateFlavor::Rlib => rlibs.insert(path, search_path.kind),
|
||||
CrateFlavor::Rmeta => rmetas.insert(path, search_path.kind),
|
||||
CrateFlavor::Dylib => dylibs.insert(path, search_path.kind),
|
||||
CrateFlavor::SDylib => interfaces.insert(path, search_path.kind),
|
||||
CrateFlavor::Rlib => rlibs.insert(path),
|
||||
CrateFlavor::Rmeta => rmetas.insert(path),
|
||||
CrateFlavor::Dylib => dylibs.insert(path),
|
||||
CrateFlavor::SDylib => interfaces.insert(path),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -524,10 +524,10 @@ impl<'a> CrateLocator<'a> {
|
|||
fn extract_lib(
|
||||
&self,
|
||||
crate_rejections: &mut CrateRejections,
|
||||
rlibs: FxIndexMap<PathBuf, PathKind>,
|
||||
rmetas: FxIndexMap<PathBuf, PathKind>,
|
||||
dylibs: FxIndexMap<PathBuf, PathKind>,
|
||||
interfaces: FxIndexMap<PathBuf, PathKind>,
|
||||
rlibs: FxIndexSet<PathBuf>,
|
||||
rmetas: FxIndexSet<PathBuf>,
|
||||
dylibs: FxIndexSet<PathBuf>,
|
||||
interfaces: FxIndexSet<PathBuf>,
|
||||
) -> Result<Option<(Svh, Library)>, CrateError> {
|
||||
let mut slot = None;
|
||||
// Order here matters, rmeta should come first.
|
||||
|
|
@ -575,10 +575,10 @@ impl<'a> CrateLocator<'a> {
|
|||
fn extract_one(
|
||||
&self,
|
||||
crate_rejections: &mut CrateRejections,
|
||||
m: FxIndexMap<PathBuf, PathKind>,
|
||||
m: FxIndexSet<PathBuf>,
|
||||
flavor: CrateFlavor,
|
||||
slot: &mut Option<(Svh, MetadataBlob, PathBuf, CrateFlavor)>,
|
||||
) -> Result<Option<(PathBuf, PathKind)>, CrateError> {
|
||||
) -> Result<Option<PathBuf>, CrateError> {
|
||||
// If we are producing an rlib, and we've already loaded metadata, then
|
||||
// we should not attempt to discover further crate sources (unless we're
|
||||
// locating a proc macro; exact logic is in needs_crate_flavor). This means
|
||||
|
|
@ -594,9 +594,9 @@ impl<'a> CrateLocator<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
let mut ret: Option<(PathBuf, PathKind)> = None;
|
||||
let mut ret: Option<PathBuf> = None;
|
||||
let mut err_data: Option<Vec<PathBuf>> = None;
|
||||
for (lib, kind) in m {
|
||||
for lib in m {
|
||||
info!("{} reading metadata from: {}", flavor, lib.display());
|
||||
if flavor == CrateFlavor::Rmeta && lib.metadata().is_ok_and(|m| m.len() == 0) {
|
||||
// Empty files will cause get_metadata_section to fail. Rmeta
|
||||
|
|
@ -640,7 +640,7 @@ impl<'a> CrateLocator<'a> {
|
|||
info!("no metadata found: {}", err);
|
||||
// Metadata was loaded from interface file earlier.
|
||||
if let Some((.., CrateFlavor::SDylib)) = slot {
|
||||
ret = Some((lib, kind));
|
||||
ret = Some(lib);
|
||||
continue;
|
||||
}
|
||||
// The file was present and created by the same compiler version, but we
|
||||
|
|
@ -689,7 +689,7 @@ impl<'a> CrateLocator<'a> {
|
|||
// As a result, we favor the sysroot crate here. Note that the
|
||||
// candidates are all canonicalized, so we canonicalize the sysroot
|
||||
// as well.
|
||||
if let Some((prev, _)) = &ret {
|
||||
if let Some(prev) = &ret {
|
||||
let sysroot = self.sysroot;
|
||||
let sysroot = try_canonicalize(sysroot).unwrap_or_else(|_| sysroot.to_path_buf());
|
||||
if prev.starts_with(&sysroot) {
|
||||
|
|
@ -714,7 +714,7 @@ impl<'a> CrateLocator<'a> {
|
|||
} else {
|
||||
*slot = Some((hash, metadata, lib.clone(), flavor));
|
||||
}
|
||||
ret = Some((lib, kind));
|
||||
ret = Some(lib);
|
||||
}
|
||||
|
||||
if let Some(candidates) = err_data {
|
||||
|
|
@ -774,10 +774,10 @@ impl<'a> CrateLocator<'a> {
|
|||
// First, filter out all libraries that look suspicious. We only accept
|
||||
// files which actually exist that have the correct naming scheme for
|
||||
// rlibs/dylibs.
|
||||
let mut rlibs = FxIndexMap::default();
|
||||
let mut rmetas = FxIndexMap::default();
|
||||
let mut dylibs = FxIndexMap::default();
|
||||
let mut sdylib_interfaces = FxIndexMap::default();
|
||||
let mut rlibs = FxIndexSet::default();
|
||||
let mut rmetas = FxIndexSet::default();
|
||||
let mut dylibs = FxIndexSet::default();
|
||||
let mut sdylib_interfaces = FxIndexSet::default();
|
||||
for loc in &self.exact_paths {
|
||||
let loc_canon = loc.canonicalized();
|
||||
let loc_orig = loc.original();
|
||||
|
|
@ -798,21 +798,21 @@ impl<'a> CrateLocator<'a> {
|
|||
};
|
||||
if file.starts_with("lib") {
|
||||
if file.ends_with(".rlib") {
|
||||
rlibs.insert(loc_canon.clone(), PathKind::ExternFlag);
|
||||
rlibs.insert(loc_canon.clone());
|
||||
continue;
|
||||
}
|
||||
if file.ends_with(".rmeta") {
|
||||
rmetas.insert(loc_canon.clone(), PathKind::ExternFlag);
|
||||
rmetas.insert(loc_canon.clone());
|
||||
continue;
|
||||
}
|
||||
if file.ends_with(".rs") {
|
||||
sdylib_interfaces.insert(loc_canon.clone(), PathKind::ExternFlag);
|
||||
sdylib_interfaces.insert(loc_canon.clone());
|
||||
}
|
||||
}
|
||||
let dll_prefix = self.target.dll_prefix.as_ref();
|
||||
let dll_suffix = self.target.dll_suffix.as_ref();
|
||||
if file.starts_with(dll_prefix) && file.ends_with(dll_suffix) {
|
||||
dylibs.insert(loc_canon.clone(), PathKind::ExternFlag);
|
||||
dylibs.insert(loc_canon.clone());
|
||||
continue;
|
||||
}
|
||||
crate_rejections
|
||||
|
|
|
|||
|
|
@ -15,24 +15,22 @@ use rustc_hir::definitions::{DefKey, DefPath, DefPathHash, Definitions};
|
|||
use rustc_macros::{BlobDecodable, Decodable, Encodable, HashStable_Generic};
|
||||
use rustc_span::{Span, Symbol};
|
||||
|
||||
use crate::search_paths::PathKind;
|
||||
|
||||
// lonely orphan structs and enums looking for a better home
|
||||
|
||||
/// Where a crate came from on the local filesystem. One of these three options
|
||||
/// must be non-None.
|
||||
#[derive(PartialEq, Clone, Debug, HashStable_Generic, Encodable, Decodable)]
|
||||
pub struct CrateSource {
|
||||
pub dylib: Option<(PathBuf, PathKind)>,
|
||||
pub rlib: Option<(PathBuf, PathKind)>,
|
||||
pub rmeta: Option<(PathBuf, PathKind)>,
|
||||
pub sdylib_interface: Option<(PathBuf, PathKind)>,
|
||||
pub dylib: Option<PathBuf>,
|
||||
pub rlib: Option<PathBuf>,
|
||||
pub rmeta: Option<PathBuf>,
|
||||
pub sdylib_interface: Option<PathBuf>,
|
||||
}
|
||||
|
||||
impl CrateSource {
|
||||
#[inline]
|
||||
pub fn paths(&self) -> impl Iterator<Item = &PathBuf> {
|
||||
self.dylib.iter().chain(self.rlib.iter()).chain(self.rmeta.iter()).map(|p| &p.0)
|
||||
self.dylib.iter().chain(self.rlib.iter()).chain(self.rmeta.iter())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -71,7 +71,6 @@ pub enum PathKind {
|
|||
Crate,
|
||||
Dependency,
|
||||
Framework,
|
||||
ExternFlag,
|
||||
All,
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
//! goes along from the output of the previous stage.
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::collections::HashSet;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::ffi::OsStr;
|
||||
use std::io::BufReader;
|
||||
use std::io::prelude::*;
|
||||
|
|
@ -1562,7 +1562,7 @@ impl Step for RustcLink {
|
|||
run.never()
|
||||
}
|
||||
|
||||
/// Same as `std_link`, only for librustc
|
||||
/// Same as `StdLink`, only for librustc
|
||||
fn run(self, builder: &Builder<'_>) {
|
||||
let build_compiler = self.build_compiler;
|
||||
let sysroot_compiler = self.sysroot_compiler;
|
||||
|
|
@ -2422,13 +2422,52 @@ pub fn add_to_sysroot(
|
|||
t!(fs::create_dir_all(sysroot_dst));
|
||||
t!(fs::create_dir_all(sysroot_host_dst));
|
||||
t!(fs::create_dir_all(self_contained_dst));
|
||||
|
||||
let mut crates = HashMap::new();
|
||||
for (path, dependency_type) in builder.read_stamp_file(stamp) {
|
||||
let filename = path.file_name().unwrap().to_str().unwrap();
|
||||
let dst = match dependency_type {
|
||||
DependencyType::Host => sysroot_host_dst,
|
||||
DependencyType::Target => sysroot_dst,
|
||||
DependencyType::Host => {
|
||||
if sysroot_dst == sysroot_host_dst {
|
||||
// Only insert the part before the . to deduplicate different files for the same crate.
|
||||
// For example foo-1234.dll and foo-1234.dll.lib.
|
||||
crates.insert(filename.split_once('.').unwrap().0.to_owned(), path.clone());
|
||||
}
|
||||
|
||||
sysroot_host_dst
|
||||
}
|
||||
DependencyType::Target => {
|
||||
// Only insert the part before the . to deduplicate different files for the same crate.
|
||||
// For example foo-1234.dll and foo-1234.dll.lib.
|
||||
crates.insert(filename.split_once('.').unwrap().0.to_owned(), path.clone());
|
||||
|
||||
sysroot_dst
|
||||
}
|
||||
DependencyType::TargetSelfContained => self_contained_dst,
|
||||
};
|
||||
builder.copy_link(&path, &dst.join(path.file_name().unwrap()), FileType::Regular);
|
||||
builder.copy_link(&path, &dst.join(filename), FileType::Regular);
|
||||
}
|
||||
|
||||
// Check that none of the rustc_* crates have multiple versions. Otherwise using them from
|
||||
// the sysroot would cause ambiguity errors. We do allow rustc_hash however as it is an
|
||||
// external dependency that we build multiple copies of. It is re-exported by
|
||||
// rustc_data_structures, so not being able to use extern crate rustc_hash; is not a big
|
||||
// issue.
|
||||
let mut seen_crates = HashMap::new();
|
||||
for (filestem, path) in crates {
|
||||
if !filestem.contains("rustc_") || filestem.contains("rustc_hash") {
|
||||
continue;
|
||||
}
|
||||
if let Some(other_path) =
|
||||
seen_crates.insert(filestem.split_once('-').unwrap().0.to_owned(), path.clone())
|
||||
{
|
||||
panic!(
|
||||
"duplicate rustc crate {}\n- first copy at {}\n- second copy at {}",
|
||||
filestem.split_once('-').unwrap().0.to_owned(),
|
||||
other_path.display(),
|
||||
path.display(),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2515,7 +2554,13 @@ pub fn run_cargo(
|
|||
if filename.starts_with(&host_root_dir) {
|
||||
// Unless it's a proc macro used in the compiler
|
||||
if crate_types.iter().any(|t| t == "proc-macro") {
|
||||
deps.push((filename.to_path_buf(), DependencyType::Host));
|
||||
// Cargo will compile proc-macros that are part of the rustc workspace twice.
|
||||
// Once as libmacro-hash.so as build dependency and once as libmacro.so as
|
||||
// output artifact. Only keep the former to avoid ambiguity when trying to use
|
||||
// the proc macro from the sysroot.
|
||||
if filename.file_name().unwrap().to_str().unwrap().contains("-") {
|
||||
deps.push((filename.to_path_buf(), DependencyType::Host));
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@ use std::num::NonZero;
|
|||
use std::sync::Mutex;
|
||||
|
||||
use rustc_abi::{Align, Size};
|
||||
use rustc_data_structures::fx::{FxBuildHasher, FxHashSet};
|
||||
use rustc_errors::{Diag, DiagMessage, Level};
|
||||
use rustc_hash::FxHashSet;
|
||||
use rustc_span::{DUMMY_SP, Span, SpanData, Symbol};
|
||||
|
||||
use crate::borrow_tracker::stacked_borrows::diagnostics::TagHistory;
|
||||
|
|
@ -899,6 +899,6 @@ pub struct SpanDedupDiagnostic(Mutex<FxHashSet<Span>>);
|
|||
|
||||
impl SpanDedupDiagnostic {
|
||||
pub const fn new() -> Self {
|
||||
Self(Mutex::new(FxHashSet::with_hasher(rustc_hash::FxBuildHasher)))
|
||||
Self(Mutex::new(FxHashSet::with_hasher(FxBuildHasher)))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ use std::{cmp, iter};
|
|||
use rand::RngCore;
|
||||
use rustc_abi::{Align, ExternAbi, FieldIdx, FieldsShape, Size, Variants};
|
||||
use rustc_apfloat::Float;
|
||||
use rustc_hash::FxHashSet;
|
||||
use rustc_data_structures::fx::{FxBuildHasher, FxHashSet};
|
||||
use rustc_hir::Safety;
|
||||
use rustc_hir::def::{DefKind, Namespace};
|
||||
use rustc_hir::def_id::{CRATE_DEF_INDEX, CrateNum, DefId, LOCAL_CRATE};
|
||||
|
|
@ -663,7 +663,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
RejectOpWith::WarningWithoutBacktrace => {
|
||||
// Deduplicate these warnings *by shim* (not by span)
|
||||
static DEDUP: Mutex<FxHashSet<String>> =
|
||||
Mutex::new(FxHashSet::with_hasher(rustc_hash::FxBuildHasher));
|
||||
Mutex::new(FxHashSet::with_hasher(FxBuildHasher));
|
||||
let mut emitted_warnings = DEDUP.lock().unwrap();
|
||||
if !emitted_warnings.contains(op_name) {
|
||||
// First time we are seeing this.
|
||||
|
|
|
|||
|
|
@ -58,7 +58,6 @@ extern crate rustc_codegen_ssa;
|
|||
extern crate rustc_const_eval;
|
||||
extern crate rustc_data_structures;
|
||||
extern crate rustc_errors;
|
||||
extern crate rustc_hash;
|
||||
extern crate rustc_hir;
|
||||
extern crate rustc_index;
|
||||
extern crate rustc_log;
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
pub struct Foo;
|
||||
|
|
@ -0,0 +1 @@
|
|||
pub struct Foo;
|
||||
10
tests/run-make/duplicate-dependency-no-disambiguate/main.rs
Normal file
10
tests/run-make/duplicate-dependency-no-disambiguate/main.rs
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
#![feature(custom_inner_attributes)]
|
||||
#![rustfmt::skip] // use_foo must be referenced before foo
|
||||
|
||||
// Load foo-v2 through use-foo
|
||||
use use_foo as _;
|
||||
|
||||
// Make sure we don't disambiguate this as foo-v2.
|
||||
use foo as _;
|
||||
|
||||
fn main() {}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
error[E0464]: multiple candidates for `rlib` dependency `foo` found
|
||||
--> main.rs:8:5
|
||||
|
|
||||
LL | use foo as _;
|
||||
| ^^^
|
||||
|
|
||||
= note: candidate #1: /build-root/test/run-make/duplicate-dependency-no-disambiguate/rmake_out/libfoo-v1.rlib
|
||||
= note: candidate #2: /build-root/test/run-make/duplicate-dependency-no-disambiguate/rmake_out/libfoo-v2.rlib
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0464`.
|
||||
54
tests/run-make/duplicate-dependency-no-disambiguate/rmake.rs
Normal file
54
tests/run-make/duplicate-dependency-no-disambiguate/rmake.rs
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
//@ needs-target-std
|
||||
|
||||
use run_make_support::{Rustc, cwd, diff, regex, rust_lib_name, rustc};
|
||||
|
||||
fn rustc_with_common_args() -> Rustc {
|
||||
let mut rustc = rustc();
|
||||
rustc.remap_path_prefix(cwd(), "$DIR");
|
||||
rustc.edition("2018"); // Don't require `extern crate`
|
||||
rustc
|
||||
}
|
||||
|
||||
fn main() {
|
||||
rustc_with_common_args()
|
||||
.input("foo-v1.rs")
|
||||
.crate_type("rlib")
|
||||
.crate_name("foo")
|
||||
.extra_filename("-v1")
|
||||
.metadata("-v1")
|
||||
.run();
|
||||
|
||||
rustc_with_common_args()
|
||||
.input("foo-v2.rs")
|
||||
.crate_type("rlib")
|
||||
.crate_name("foo")
|
||||
.extra_filename("-v2")
|
||||
.metadata("-v2")
|
||||
.run();
|
||||
|
||||
rustc_with_common_args()
|
||||
.input("use-foo.rs")
|
||||
.crate_type("rlib")
|
||||
.extern_("foo", rust_lib_name("foo-v2"))
|
||||
.run();
|
||||
|
||||
let stderr = rustc_with_common_args()
|
||||
.input("main.rs")
|
||||
.extern_("foo", rust_lib_name("foo-v1"))
|
||||
.extern_("foo", rust_lib_name("foo-v2"))
|
||||
.extern_("use_foo", rust_lib_name("use_foo"))
|
||||
.library_search_path(cwd())
|
||||
.ui_testing()
|
||||
.run_fail()
|
||||
.stderr_utf8();
|
||||
|
||||
diff()
|
||||
.expected_file("main.stderr")
|
||||
.normalize(
|
||||
regex::escape(run_make_support::build_root().canonicalize().unwrap().to_str().unwrap()),
|
||||
"/build-root",
|
||||
)
|
||||
.normalize(r"\\", "/")
|
||||
.actual_text("(rustc)", &stderr)
|
||||
.run();
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
use foo as _;
|
||||
Loading…
Add table
Add a link
Reference in a new issue