| author | bors <bors@rust-lang.org> 2025-12-14 09:16:11 UTC |
| committer | bors <bors@rust-lang.org> 2025-12-14 09:16:11 UTC |
| log | 08de25c4ea16d7ecc3ceeb093d4f343a2be30df5 |
| tree | b7cc6f5a74171f1024869390f7472f250adb2515 |
| parent | 3f4dc1e02d759aa3c3807d4efc1f7f6e293536a5 |
| parent | 7f1828c5926e67cec899d73ebe1af64a610d49c2 |
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/14796617 files changed, 185 insertions(+), 127 deletions(-)
compiler/rustc_codegen_ssa/src/back/link.rs+6-12| ... | @@ -277,7 +277,7 @@ pub fn each_linked_rlib( | ... | @@ -277,7 +277,7 @@ pub fn each_linked_rlib( |
| 277 | } | 277 | } |
| 278 | let crate_name = info.crate_name[&cnum]; | 278 | let crate_name = info.crate_name[&cnum]; |
| 279 | let used_crate_source = &info.used_crate_source[&cnum]; | 279 | let used_crate_source = &info.used_crate_source[&cnum]; |
| 280 | if let Some((path, _)) = &used_crate_source.rlib { | 280 | if let Some(path) = &used_crate_source.rlib { |
| 281 | f(cnum, path); | 281 | f(cnum, path); |
| 282 | } else if used_crate_source.rmeta.is_some() { | 282 | } else if used_crate_source.rmeta.is_some() { |
| 283 | return Err(errors::LinkRlibError::OnlyRmetaFound { crate_name }); | 283 | return Err(errors::LinkRlibError::OnlyRmetaFound { crate_name }); |
| ... | @@ -541,7 +541,7 @@ fn link_staticlib( | ... | @@ -541,7 +541,7 @@ fn link_staticlib( |
| 541 | }; | 541 | }; |
| 542 | let crate_name = codegen_results.crate_info.crate_name[&cnum]; | 542 | let crate_name = codegen_results.crate_info.crate_name[&cnum]; |
| 543 | let used_crate_source = &codegen_results.crate_info.used_crate_source[&cnum]; | 543 | let used_crate_source = &codegen_results.crate_info.used_crate_source[&cnum]; |
| 544 | if let Some((path, _)) = &used_crate_source.dylib { | 544 | if let Some(path) = &used_crate_source.dylib { |
| 545 | all_rust_dylibs.push(&**path); | 545 | all_rust_dylibs.push(&**path); |
| 546 | } else if used_crate_source.rmeta.is_some() { | 546 | } else if used_crate_source.rmeta.is_some() { |
| 547 | sess.dcx().emit_fatal(errors::LinkRlibError::OnlyRmetaFound { crate_name }); | 547 | sess.dcx().emit_fatal(errors::LinkRlibError::OnlyRmetaFound { crate_name }); |
| ... | @@ -619,7 +619,6 @@ fn link_dwarf_object(sess: &Session, cg_results: &CodegenResults, executable_out | ... | @@ -619,7 +619,6 @@ fn link_dwarf_object(sess: &Session, cg_results: &CodegenResults, executable_out |
| 619 | .used_crate_source | 619 | .used_crate_source |
| 620 | .items() | 620 | .items() |
| 621 | .filter_map(|(_, csource)| csource.rlib.as_ref()) | 621 | .filter_map(|(_, csource)| csource.rlib.as_ref()) |
| 622 | .map(|(path, _)| path) | ||
| 623 | .into_sorted_stable_ord(); | 622 | .into_sorted_stable_ord(); |
| 624 | 623 | ||
| 625 | for input_rlib in input_rlibs { | 624 | for input_rlib in input_rlibs { |
| ... | @@ -2173,12 +2172,7 @@ fn add_rpath_args( | ... | @@ -2173,12 +2172,7 @@ fn add_rpath_args( |
| 2173 | .crate_info | 2172 | .crate_info |
| 2174 | .used_crates | 2173 | .used_crates |
| 2175 | .iter() | 2174 | .iter() |
| 2176 | .filter_map(|cnum| { | 2175 | .filter_map(|cnum| codegen_results.crate_info.used_crate_source[cnum].dylib.as_deref()) |
| 2177 | codegen_results.crate_info.used_crate_source[cnum] | ||
| 2178 | .dylib | ||
| 2179 | .as_ref() | ||
| 2180 | .map(|(path, _)| &**path) | ||
| 2181 | }) | ||
| 2182 | .collect::<Vec<_>>(); | 2176 | .collect::<Vec<_>>(); |
| 2183 | let rpath_config = RPathConfig { | 2177 | let rpath_config = RPathConfig { |
| 2184 | libs: &*libs, | 2178 | libs: &*libs, |
| ... | @@ -2656,7 +2650,7 @@ fn add_native_libs_from_crate( | ... | @@ -2656,7 +2650,7 @@ fn add_native_libs_from_crate( |
| 2656 | 2650 | ||
| 2657 | if link_static && cnum != LOCAL_CRATE && !bundled_libs.is_empty() { | 2651 | if link_static && cnum != LOCAL_CRATE && !bundled_libs.is_empty() { |
| 2658 | // If rlib contains native libs as archives, unpack them to tmpdir. | 2652 | // If rlib contains native libs as archives, unpack them to tmpdir. |
| 2659 | let rlib = &codegen_results.crate_info.used_crate_source[&cnum].rlib.as_ref().unwrap().0; | 2653 | let rlib = codegen_results.crate_info.used_crate_source[&cnum].rlib.as_ref().unwrap(); |
| 2660 | archive_builder_builder | 2654 | archive_builder_builder |
| 2661 | .extract_bundled_libs(rlib, tmpdir, bundled_libs) | 2655 | .extract_bundled_libs(rlib, tmpdir, bundled_libs) |
| 2662 | .unwrap_or_else(|e| sess.dcx().emit_fatal(e)); | 2656 | .unwrap_or_else(|e| sess.dcx().emit_fatal(e)); |
| ... | @@ -2827,7 +2821,7 @@ fn add_upstream_rust_crates( | ... | @@ -2827,7 +2821,7 @@ fn add_upstream_rust_crates( |
| 2827 | } | 2821 | } |
| 2828 | Linkage::Dynamic => { | 2822 | Linkage::Dynamic => { |
| 2829 | let src = &codegen_results.crate_info.used_crate_source[&cnum]; | 2823 | let src = &codegen_results.crate_info.used_crate_source[&cnum]; |
| 2830 | add_dynamic_crate(cmd, sess, &src.dylib.as_ref().unwrap().0); | 2824 | add_dynamic_crate(cmd, sess, src.dylib.as_ref().unwrap()); |
| 2831 | } | 2825 | } |
| 2832 | } | 2826 | } |
| 2833 | 2827 | ||
| ... | @@ -2955,7 +2949,7 @@ fn add_static_crate( | ... | @@ -2955,7 +2949,7 @@ fn add_static_crate( |
| 2955 | bundled_lib_file_names: &FxIndexSet<Symbol>, | 2949 | bundled_lib_file_names: &FxIndexSet<Symbol>, |
| 2956 | ) { | 2950 | ) { |
| 2957 | let src = &codegen_results.crate_info.used_crate_source[&cnum]; | 2951 | let src = &codegen_results.crate_info.used_crate_source[&cnum]; |
| 2958 | let cratepath = &src.rlib.as_ref().unwrap().0; | 2952 | let cratepath = src.rlib.as_ref().unwrap(); |
| 2959 | 2953 | ||
| 2960 | let mut link_upstream = | 2954 | let mut link_upstream = |
| 2961 | |path: &Path| cmd.link_staticlib_by_path(&rehome_lib_path(sess, path), false); | 2955 | |path: &Path| cmd.link_staticlib_by_path(&rehome_lib_path(sess, path), false); |
compiler/rustc_data_structures/src/fx.rs+1-1| ... | @@ -1,6 +1,6 @@ | ... | @@ -1,6 +1,6 @@ |
| 1 | use std::hash::BuildHasherDefault; | 1 | use std::hash::BuildHasherDefault; |
| 2 | 2 | ||
| 3 | pub use rustc_hash::{FxHashMap, FxHashSet, FxHasher}; | 3 | pub use rustc_hash::{FxBuildHasher, FxHashMap, FxHashSet, FxHasher}; |
| 4 | 4 | ||
| 5 | pub type StdEntry<'a, K, V> = std::collections::hash_map::Entry<'a, K, V>; | 5 | pub type StdEntry<'a, K, V> = std::collections::hash_map::Entry<'a, K, V>; |
| 6 | 6 |
compiler/rustc_interface/src/passes.rs+3-3| ... | @@ -680,19 +680,19 @@ fn write_out_deps(tcx: TyCtxt<'_>, outputs: &OutputFilenames, out_filenames: &[P | ... | @@ -680,19 +680,19 @@ fn write_out_deps(tcx: TyCtxt<'_>, outputs: &OutputFilenames, out_filenames: &[P |
| 680 | 680 | ||
| 681 | for &cnum in tcx.crates(()) { | 681 | for &cnum in tcx.crates(()) { |
| 682 | let source = tcx.used_crate_source(cnum); | 682 | let source = tcx.used_crate_source(cnum); |
| 683 | if let Some((path, _)) = &source.dylib { | 683 | if let Some(path) = &source.dylib { |
| 684 | files.extend(hash_iter_files( | 684 | files.extend(hash_iter_files( |
| 685 | iter::once(escape_dep_filename(&path.display().to_string())), | 685 | iter::once(escape_dep_filename(&path.display().to_string())), |
| 686 | checksum_hash_algo, | 686 | checksum_hash_algo, |
| 687 | )); | 687 | )); |
| 688 | } | 688 | } |
| 689 | if let Some((path, _)) = &source.rlib { | 689 | if let Some(path) = &source.rlib { |
| 690 | files.extend(hash_iter_files( | 690 | files.extend(hash_iter_files( |
| 691 | iter::once(escape_dep_filename(&path.display().to_string())), | 691 | iter::once(escape_dep_filename(&path.display().to_string())), |
| 692 | checksum_hash_algo, | 692 | checksum_hash_algo, |
| 693 | )); | 693 | )); |
| 694 | } | 694 | } |
| 695 | if let Some((path, _)) = &source.rmeta { | 695 | if let Some(path) = &source.rmeta { |
| 696 | files.extend(hash_iter_files( | 696 | files.extend(hash_iter_files( |
| 697 | iter::once(escape_dep_filename(&path.display().to_string())), | 697 | iter::once(escape_dep_filename(&path.display().to_string())), |
| 698 | checksum_hash_algo, | 698 | checksum_hash_algo, |
compiler/rustc_metadata/src/creader.rs+11-67| ... | @@ -135,16 +135,16 @@ impl<'a> std::fmt::Debug for CrateDump<'a> { | ... | @@ -135,16 +135,16 @@ impl<'a> std::fmt::Debug for CrateDump<'a> { |
| 135 | writeln!(fmt, " priv: {:?}", data.is_private_dep())?; | 135 | writeln!(fmt, " priv: {:?}", data.is_private_dep())?; |
| 136 | let CrateSource { dylib, rlib, rmeta, sdylib_interface } = data.source(); | 136 | let CrateSource { dylib, rlib, rmeta, sdylib_interface } = data.source(); |
| 137 | if let Some(dylib) = dylib { | 137 | if let Some(dylib) = dylib { |
| 138 | writeln!(fmt, " dylib: {}", dylib.0.display())?; | 138 | writeln!(fmt, " dylib: {}", dylib.display())?; |
| 139 | } | 139 | } |
| 140 | if let Some(rlib) = rlib { | 140 | if let Some(rlib) = rlib { |
| 141 | writeln!(fmt, " rlib: {}", rlib.0.display())?; | 141 | writeln!(fmt, " rlib: {}", rlib.display())?; |
| 142 | } | 142 | } |
| 143 | if let Some(rmeta) = rmeta { | 143 | if let Some(rmeta) = rmeta { |
| 144 | writeln!(fmt, " rmeta: {}", rmeta.0.display())?; | 144 | writeln!(fmt, " rmeta: {}", rmeta.display())?; |
| 145 | } | 145 | } |
| 146 | if let Some(sdylib_interface) = sdylib_interface { | 146 | if let Some(sdylib_interface) = sdylib_interface { |
| 147 | writeln!(fmt, " sdylib interface: {}", sdylib_interface.0.display())?; | 147 | writeln!(fmt, " sdylib interface: {}", sdylib_interface.display())?; |
| 148 | } | 148 | } |
| 149 | } | 149 | } |
| 150 | Ok(()) | 150 | Ok(()) |
| ... | @@ -515,73 +515,19 @@ impl CStore { | ... | @@ -515,73 +515,19 @@ impl CStore { |
| 515 | } | 515 | } |
| 516 | } | 516 | } |
| 517 | 517 | ||
| 518 | fn existing_match( | 518 | fn existing_match(&self, name: Symbol, hash: Option<Svh>) -> Option<CrateNum> { |
| 519 | &self, | 519 | let hash = hash?; |
| 520 | externs: &Externs, | 520 | |
| 521 | name: Symbol, | ||
| 522 | hash: Option<Svh>, | ||
| 523 | kind: PathKind, | ||
| 524 | ) -> Option<CrateNum> { | ||
| 525 | for (cnum, data) in self.iter_crate_data() { | 521 | for (cnum, data) in self.iter_crate_data() { |
| 526 | if data.name() != name { | 522 | if data.name() != name { |
| 527 | trace!("{} did not match {}", data.name(), name); | 523 | trace!("{} did not match {}", data.name(), name); |
| 528 | continue; | 524 | continue; |
| 529 | } | 525 | } |
| 530 | 526 | ||
| 531 | match hash { | 527 | if hash == data.hash() { |
| 532 | Some(hash) if hash == data.hash() => return Some(cnum), | ||
| 533 | Some(hash) => { | ||
| 534 | debug!("actual hash {} did not match expected {}", hash, data.hash()); | ||
| 535 | continue; | ||
| 536 | } | ||
| 537 | None => {} | ||
| 538 | } | ||
| 539 | |||
| 540 | // When the hash is None we're dealing with a top-level dependency | ||
| 541 | // in which case we may have a specification on the command line for | ||
| 542 | // this library. Even though an upstream library may have loaded | ||
| 543 | // something of the same name, we have to make sure it was loaded | ||
| 544 | // from the exact same location as well. | ||
| 545 | // | ||
| 546 | // We're also sure to compare *paths*, not actual byte slices. The | ||
| 547 | // `source` stores paths which are normalized which may be different | ||
| 548 | // from the strings on the command line. | ||
| 549 | let source = data.source(); | ||
| 550 | if let Some(entry) = externs.get(name.as_str()) { | ||
| 551 | // Only use `--extern crate_name=path` here, not `--extern crate_name`. | ||
| 552 | if let Some(mut files) = entry.files() { | ||
| 553 | if files.any(|l| { | ||
| 554 | let l = l.canonicalized(); | ||
| 555 | source.dylib.as_ref().map(|(p, _)| p) == Some(l) | ||
| 556 | || source.rlib.as_ref().map(|(p, _)| p) == Some(l) | ||
| 557 | || source.rmeta.as_ref().map(|(p, _)| p) == Some(l) | ||
| 558 | }) { | ||
| 559 | return Some(cnum); | ||
| 560 | } | ||
| 561 | } | ||
| 562 | continue; | ||
| 563 | } | ||
| 564 | |||
| 565 | // Alright, so we've gotten this far which means that `data` has the | ||
| 566 | // right name, we don't have a hash, and we don't have a --extern | ||
| 567 | // pointing for ourselves. We're still not quite yet done because we | ||
| 568 | // have to make sure that this crate was found in the crate lookup | ||
| 569 | // path (this is a top-level dependency) as we don't want to | ||
| 570 | // implicitly load anything inside the dependency lookup path. | ||
| 571 | let prev_kind = source | ||
| 572 | .dylib | ||
| 573 | .as_ref() | ||
| 574 | .or(source.rlib.as_ref()) | ||
| 575 | .or(source.rmeta.as_ref()) | ||
| 576 | .expect("No sources for crate") | ||
| 577 | .1; | ||
| 578 | if kind.matches(prev_kind) { | ||
| 579 | return Some(cnum); | 528 | return Some(cnum); |
| 580 | } else { | 529 | } else { |
| 581 | debug!( | 530 | debug!("actual hash {} did not match expected {}", hash, data.hash()); |
| 582 | "failed to load existing crate {}; kind {:?} did not match prev_kind {:?}", | ||
| 583 | name, kind, prev_kind | ||
| 584 | ); | ||
| 585 | } | 531 | } |
| 586 | } | 532 | } |
| 587 | 533 | ||
| ... | @@ -678,7 +624,7 @@ impl CStore { | ... | @@ -678,7 +624,7 @@ impl CStore { |
| 678 | None => (&source, &crate_root), | 624 | None => (&source, &crate_root), |
| 679 | }; | 625 | }; |
| 680 | let dlsym_dylib = dlsym_source.dylib.as_ref().expect("no dylib for a proc-macro crate"); | 626 | let dlsym_dylib = dlsym_source.dylib.as_ref().expect("no dylib for a proc-macro crate"); |
| 681 | Some(self.dlsym_proc_macros(tcx.sess, &dlsym_dylib.0, dlsym_root.stable_crate_id())?) | 627 | Some(self.dlsym_proc_macros(tcx.sess, dlsym_dylib, dlsym_root.stable_crate_id())?) |
| 682 | } else { | 628 | } else { |
| 683 | None | 629 | None |
| 684 | }; | 630 | }; |
| ... | @@ -819,9 +765,7 @@ impl CStore { | ... | @@ -819,9 +765,7 @@ impl CStore { |
| 819 | let path_kind = if dep.is_some() { PathKind::Dependency } else { PathKind::Crate }; | 765 | let path_kind = if dep.is_some() { PathKind::Dependency } else { PathKind::Crate }; |
| 820 | let private_dep = origin.private_dep(); | 766 | let private_dep = origin.private_dep(); |
| 821 | 767 | ||
| 822 | let result = if let Some(cnum) = | 768 | let result = if let Some(cnum) = self.existing_match(name, hash) { |
| 823 | self.existing_match(&tcx.sess.opts.externs, name, hash, path_kind) | ||
| 824 | { | ||
| 825 | (LoadResult::Previous(cnum), None) | 769 | (LoadResult::Previous(cnum), None) |
| 826 | } else { | 770 | } else { |
| 827 | info!("falling back to a load"); | 771 | info!("falling back to a load"); |
compiler/rustc_metadata/src/locator.rs+25-25| ... | @@ -218,7 +218,7 @@ use std::ops::Deref; | ... | @@ -218,7 +218,7 @@ use std::ops::Deref; |
| 218 | use std::path::{Path, PathBuf}; | 218 | use std::path::{Path, PathBuf}; |
| 219 | use std::{cmp, fmt}; | 219 | use std::{cmp, fmt}; |
| 220 | 220 | ||
| 221 | use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; | 221 | use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; |
| 222 | use rustc_data_structures::memmap::Mmap; | 222 | use rustc_data_structures::memmap::Mmap; |
| 223 | use rustc_data_structures::owned_slice::{OwnedSlice, slice_owned}; | 223 | use rustc_data_structures::owned_slice::{OwnedSlice, slice_owned}; |
| 224 | use rustc_data_structures::svh::Svh; | 224 | use rustc_data_structures::svh::Svh; |
| ... | @@ -401,7 +401,7 @@ impl<'a> CrateLocator<'a> { | ... | @@ -401,7 +401,7 @@ impl<'a> CrateLocator<'a> { |
| 401 | 401 | ||
| 402 | let mut candidates: FxIndexMap< | 402 | let mut candidates: FxIndexMap< |
| 403 | _, | 403 | _, |
| 404 | (FxIndexMap<_, _>, FxIndexMap<_, _>, FxIndexMap<_, _>, FxIndexMap<_, _>), | 404 | (FxIndexSet<_>, FxIndexSet<_>, FxIndexSet<_>, FxIndexSet<_>), |
| 405 | > = Default::default(); | 405 | > = Default::default(); |
| 406 | 406 | ||
| 407 | // First, find all possible candidate rlibs and dylibs purely based on | 407 | // First, find all possible candidate rlibs and dylibs purely based on |
| ... | @@ -460,10 +460,10 @@ impl<'a> CrateLocator<'a> { | ... | @@ -460,10 +460,10 @@ impl<'a> CrateLocator<'a> { |
| 460 | // filesystem code should not care, but this is nicer for diagnostics. | 460 | // filesystem code should not care, but this is nicer for diagnostics. |
| 461 | let path = spf.path.to_path_buf(); | 461 | let path = spf.path.to_path_buf(); |
| 462 | match kind { | 462 | match kind { |
| 463 | CrateFlavor::Rlib => rlibs.insert(path, search_path.kind), | 463 | CrateFlavor::Rlib => rlibs.insert(path), |
| 464 | CrateFlavor::Rmeta => rmetas.insert(path, search_path.kind), | 464 | CrateFlavor::Rmeta => rmetas.insert(path), |
| 465 | CrateFlavor::Dylib => dylibs.insert(path, search_path.kind), | 465 | CrateFlavor::Dylib => dylibs.insert(path), |
| 466 | CrateFlavor::SDylib => interfaces.insert(path, search_path.kind), | 466 | CrateFlavor::SDylib => interfaces.insert(path), |
| 467 | }; | 467 | }; |
| 468 | } | 468 | } |
| 469 | } | 469 | } |
| ... | @@ -524,10 +524,10 @@ impl<'a> CrateLocator<'a> { | ... | @@ -524,10 +524,10 @@ impl<'a> CrateLocator<'a> { |
| 524 | fn extract_lib( | 524 | fn extract_lib( |
| 525 | &self, | 525 | &self, |
| 526 | crate_rejections: &mut CrateRejections, | 526 | crate_rejections: &mut CrateRejections, |
| 527 | rlibs: FxIndexMap<PathBuf, PathKind>, | 527 | rlibs: FxIndexSet<PathBuf>, |
| 528 | rmetas: FxIndexMap<PathBuf, PathKind>, | 528 | rmetas: FxIndexSet<PathBuf>, |
| 529 | dylibs: FxIndexMap<PathBuf, PathKind>, | 529 | dylibs: FxIndexSet<PathBuf>, |
| 530 | interfaces: FxIndexMap<PathBuf, PathKind>, | 530 | interfaces: FxIndexSet<PathBuf>, |
| 531 | ) -> Result<Option<(Svh, Library)>, CrateError> { | 531 | ) -> Result<Option<(Svh, Library)>, CrateError> { |
| 532 | let mut slot = None; | 532 | let mut slot = None; |
| 533 | // Order here matters, rmeta should come first. | 533 | // Order here matters, rmeta should come first. |
| ... | @@ -575,10 +575,10 @@ impl<'a> CrateLocator<'a> { | ... | @@ -575,10 +575,10 @@ impl<'a> CrateLocator<'a> { |
| 575 | fn extract_one( | 575 | fn extract_one( |
| 576 | &self, | 576 | &self, |
| 577 | crate_rejections: &mut CrateRejections, | 577 | crate_rejections: &mut CrateRejections, |
| 578 | m: FxIndexMap<PathBuf, PathKind>, | 578 | m: FxIndexSet<PathBuf>, |
| 579 | flavor: CrateFlavor, | 579 | flavor: CrateFlavor, |
| 580 | slot: &mut Option<(Svh, MetadataBlob, PathBuf, CrateFlavor)>, | 580 | slot: &mut Option<(Svh, MetadataBlob, PathBuf, CrateFlavor)>, |
| 581 | ) -> Result<Option<(PathBuf, PathKind)>, CrateError> { | 581 | ) -> Result<Option<PathBuf>, CrateError> { |
| 582 | // If we are producing an rlib, and we've already loaded metadata, then | 582 | // If we are producing an rlib, and we've already loaded metadata, then |
| 583 | // we should not attempt to discover further crate sources (unless we're | 583 | // we should not attempt to discover further crate sources (unless we're |
| 584 | // locating a proc macro; exact logic is in needs_crate_flavor). This means | 584 | // locating a proc macro; exact logic is in needs_crate_flavor). This means |
| ... | @@ -594,9 +594,9 @@ impl<'a> CrateLocator<'a> { | ... | @@ -594,9 +594,9 @@ impl<'a> CrateLocator<'a> { |
| 594 | } | 594 | } |
| 595 | } | 595 | } |
| 596 | 596 | ||
| 597 | let mut ret: Option<(PathBuf, PathKind)> = None; | 597 | let mut ret: Option<PathBuf> = None; |
| 598 | let mut err_data: Option<Vec<PathBuf>> = None; | 598 | let mut err_data: Option<Vec<PathBuf>> = None; |
| 599 | for (lib, kind) in m { | 599 | for lib in m { |
| 600 | info!("{} reading metadata from: {}", flavor, lib.display()); | 600 | info!("{} reading metadata from: {}", flavor, lib.display()); |
| 601 | if flavor == CrateFlavor::Rmeta && lib.metadata().is_ok_and(|m| m.len() == 0) { | 601 | if flavor == CrateFlavor::Rmeta && lib.metadata().is_ok_and(|m| m.len() == 0) { |
| 602 | // Empty files will cause get_metadata_section to fail. Rmeta | 602 | // Empty files will cause get_metadata_section to fail. Rmeta |
| ... | @@ -640,7 +640,7 @@ impl<'a> CrateLocator<'a> { | ... | @@ -640,7 +640,7 @@ impl<'a> CrateLocator<'a> { |
| 640 | info!("no metadata found: {}", err); | 640 | info!("no metadata found: {}", err); |
| 641 | // Metadata was loaded from interface file earlier. | 641 | // Metadata was loaded from interface file earlier. |
| 642 | if let Some((.., CrateFlavor::SDylib)) = slot { | 642 | if let Some((.., CrateFlavor::SDylib)) = slot { |
| 643 | ret = Some((lib, kind)); | 643 | ret = Some(lib); |
| 644 | continue; | 644 | continue; |
| 645 | } | 645 | } |
| 646 | // The file was present and created by the same compiler version, but we | 646 | // The file was present and created by the same compiler version, but we |
| ... | @@ -689,7 +689,7 @@ impl<'a> CrateLocator<'a> { | ... | @@ -689,7 +689,7 @@ impl<'a> CrateLocator<'a> { |
| 689 | // As a result, we favor the sysroot crate here. Note that the | 689 | // As a result, we favor the sysroot crate here. Note that the |
| 690 | // candidates are all canonicalized, so we canonicalize the sysroot | 690 | // candidates are all canonicalized, so we canonicalize the sysroot |
| 691 | // as well. | 691 | // as well. |
| 692 | if let Some((prev, _)) = &ret { | 692 | if let Some(prev) = &ret { |
| 693 | let sysroot = self.sysroot; | 693 | let sysroot = self.sysroot; |
| 694 | let sysroot = try_canonicalize(sysroot).unwrap_or_else(|_| sysroot.to_path_buf()); | 694 | let sysroot = try_canonicalize(sysroot).unwrap_or_else(|_| sysroot.to_path_buf()); |
| 695 | if prev.starts_with(&sysroot) { | 695 | if prev.starts_with(&sysroot) { |
| ... | @@ -714,7 +714,7 @@ impl<'a> CrateLocator<'a> { | ... | @@ -714,7 +714,7 @@ impl<'a> CrateLocator<'a> { |
| 714 | } else { | 714 | } else { |
| 715 | *slot = Some((hash, metadata, lib.clone(), flavor)); | 715 | *slot = Some((hash, metadata, lib.clone(), flavor)); |
| 716 | } | 716 | } |
| 717 | ret = Some((lib, kind)); | 717 | ret = Some(lib); |
| 718 | } | 718 | } |
| 719 | 719 | ||
| 720 | if let Some(candidates) = err_data { | 720 | if let Some(candidates) = err_data { |
| ... | @@ -774,10 +774,10 @@ impl<'a> CrateLocator<'a> { | ... | @@ -774,10 +774,10 @@ impl<'a> CrateLocator<'a> { |
| 774 | // First, filter out all libraries that look suspicious. We only accept | 774 | // First, filter out all libraries that look suspicious. We only accept |
| 775 | // files which actually exist that have the correct naming scheme for | 775 | // files which actually exist that have the correct naming scheme for |
| 776 | // rlibs/dylibs. | 776 | // rlibs/dylibs. |
| 777 | let mut rlibs = FxIndexMap::default(); | 777 | let mut rlibs = FxIndexSet::default(); |
| 778 | let mut rmetas = FxIndexMap::default(); | 778 | let mut rmetas = FxIndexSet::default(); |
| 779 | let mut dylibs = FxIndexMap::default(); | 779 | let mut dylibs = FxIndexSet::default(); |
| 780 | let mut sdylib_interfaces = FxIndexMap::default(); | 780 | let mut sdylib_interfaces = FxIndexSet::default(); |
| 781 | for loc in &self.exact_paths { | 781 | for loc in &self.exact_paths { |
| 782 | let loc_canon = loc.canonicalized(); | 782 | let loc_canon = loc.canonicalized(); |
| 783 | let loc_orig = loc.original(); | 783 | let loc_orig = loc.original(); |
| ... | @@ -798,21 +798,21 @@ impl<'a> CrateLocator<'a> { | ... | @@ -798,21 +798,21 @@ impl<'a> CrateLocator<'a> { |
| 798 | }; | 798 | }; |
| 799 | if file.starts_with("lib") { | 799 | if file.starts_with("lib") { |
| 800 | if file.ends_with(".rlib") { | 800 | if file.ends_with(".rlib") { |
| 801 | rlibs.insert(loc_canon.clone(), PathKind::ExternFlag); | 801 | rlibs.insert(loc_canon.clone()); |
| 802 | continue; | 802 | continue; |
| 803 | } | 803 | } |
| 804 | if file.ends_with(".rmeta") { | 804 | if file.ends_with(".rmeta") { |
| 805 | rmetas.insert(loc_canon.clone(), PathKind::ExternFlag); | 805 | rmetas.insert(loc_canon.clone()); |
| 806 | continue; | 806 | continue; |
| 807 | } | 807 | } |
| 808 | if file.ends_with(".rs") { | 808 | if file.ends_with(".rs") { |
| 809 | sdylib_interfaces.insert(loc_canon.clone(), PathKind::ExternFlag); | 809 | sdylib_interfaces.insert(loc_canon.clone()); |
| 810 | } | 810 | } |
| 811 | } | 811 | } |
| 812 | let dll_prefix = self.target.dll_prefix.as_ref(); | 812 | let dll_prefix = self.target.dll_prefix.as_ref(); |
| 813 | let dll_suffix = self.target.dll_suffix.as_ref(); | 813 | let dll_suffix = self.target.dll_suffix.as_ref(); |
| 814 | if file.starts_with(dll_prefix) && file.ends_with(dll_suffix) { | 814 | if file.starts_with(dll_prefix) && file.ends_with(dll_suffix) { |
| 815 | dylibs.insert(loc_canon.clone(), PathKind::ExternFlag); | 815 | dylibs.insert(loc_canon.clone()); |
| 816 | continue; | 816 | continue; |
| 817 | } | 817 | } |
| 818 | crate_rejections | 818 | crate_rejections |
compiler/rustc_session/src/cstore.rs+5-7| ... | @@ -15,24 +15,22 @@ use rustc_hir::definitions::{DefKey, DefPath, DefPathHash, Definitions}; | ... | @@ -15,24 +15,22 @@ use rustc_hir::definitions::{DefKey, DefPath, DefPathHash, Definitions}; |
| 15 | use rustc_macros::{BlobDecodable, Decodable, Encodable, HashStable_Generic}; | 15 | use rustc_macros::{BlobDecodable, Decodable, Encodable, HashStable_Generic}; |
| 16 | use rustc_span::{Span, Symbol}; | 16 | use rustc_span::{Span, Symbol}; |
| 17 | 17 | ||
| 18 | use crate::search_paths::PathKind; | ||
| 19 | |||
| 20 | // lonely orphan structs and enums looking for a better home | 18 | // lonely orphan structs and enums looking for a better home |
| 21 | 19 | ||
| 22 | /// Where a crate came from on the local filesystem. One of these three options | 20 | /// Where a crate came from on the local filesystem. One of these three options |
| 23 | /// must be non-None. | 21 | /// must be non-None. |
| 24 | #[derive(PartialEq, Clone, Debug, HashStable_Generic, Encodable, Decodable)] | 22 | #[derive(PartialEq, Clone, Debug, HashStable_Generic, Encodable, Decodable)] |
| 25 | pub struct CrateSource { | 23 | pub struct CrateSource { |
| 26 | pub dylib: Option<(PathBuf, PathKind)>, | 24 | pub dylib: Option<PathBuf>, |
| 27 | pub rlib: Option<(PathBuf, PathKind)>, | 25 | pub rlib: Option<PathBuf>, |
| 28 | pub rmeta: Option<(PathBuf, PathKind)>, | 26 | pub rmeta: Option<PathBuf>, |
| 29 | pub sdylib_interface: Option<(PathBuf, PathKind)>, | 27 | pub sdylib_interface: Option<PathBuf>, |
| 30 | } | 28 | } |
| 31 | 29 | ||
| 32 | impl CrateSource { | 30 | impl CrateSource { |
| 33 | #[inline] | 31 | #[inline] |
| 34 | pub fn paths(&self) -> impl Iterator<Item = &PathBuf> { | 32 | pub fn paths(&self) -> impl Iterator<Item = &PathBuf> { |
| 35 | self.dylib.iter().chain(self.rlib.iter()).chain(self.rmeta.iter()).map(|p| &p.0) | 33 | self.dylib.iter().chain(self.rlib.iter()).chain(self.rmeta.iter()) |
| 36 | } | 34 | } |
| 37 | } | 35 | } |
| 38 | 36 |
compiler/rustc_session/src/search_paths.rs-1| ... | @@ -71,7 +71,6 @@ pub enum PathKind { | ... | @@ -71,7 +71,6 @@ pub enum PathKind { |
| 71 | Crate, | 71 | Crate, |
| 72 | Dependency, | 72 | Dependency, |
| 73 | Framework, | 73 | Framework, |
| 74 | ExternFlag, | ||
| 75 | All, | 74 | All, |
| 76 | } | 75 | } |
| 77 | 76 |
src/bootstrap/src/core/build_steps/compile.rs+51-6| ... | @@ -7,7 +7,7 @@ | ... | @@ -7,7 +7,7 @@ |
| 7 | //! goes along from the output of the previous stage. | 7 | //! goes along from the output of the previous stage. |
| 8 | 8 | ||
| 9 | use std::borrow::Cow; | 9 | use std::borrow::Cow; |
| 10 | use std::collections::HashSet; | 10 | use std::collections::{HashMap, HashSet}; |
| 11 | use std::ffi::OsStr; | 11 | use std::ffi::OsStr; |
| 12 | use std::io::BufReader; | 12 | use std::io::BufReader; |
| 13 | use std::io::prelude::*; | 13 | use std::io::prelude::*; |
| ... | @@ -1562,7 +1562,7 @@ impl Step for RustcLink { | ... | @@ -1562,7 +1562,7 @@ impl Step for RustcLink { |
| 1562 | run.never() | 1562 | run.never() |
| 1563 | } | 1563 | } |
| 1564 | 1564 | ||
| 1565 | /// Same as `std_link`, only for librustc | 1565 | /// Same as `StdLink`, only for librustc |
| 1566 | fn run(self, builder: &Builder<'_>) { | 1566 | fn run(self, builder: &Builder<'_>) { |
| 1567 | let build_compiler = self.build_compiler; | 1567 | let build_compiler = self.build_compiler; |
| 1568 | let sysroot_compiler = self.sysroot_compiler; | 1568 | let sysroot_compiler = self.sysroot_compiler; |
| ... | @@ -2422,13 +2422,52 @@ pub fn add_to_sysroot( | ... | @@ -2422,13 +2422,52 @@ pub fn add_to_sysroot( |
| 2422 | t!(fs::create_dir_all(sysroot_dst)); | 2422 | t!(fs::create_dir_all(sysroot_dst)); |
| 2423 | t!(fs::create_dir_all(sysroot_host_dst)); | 2423 | t!(fs::create_dir_all(sysroot_host_dst)); |
| 2424 | t!(fs::create_dir_all(self_contained_dst)); | 2424 | t!(fs::create_dir_all(self_contained_dst)); |
| 2425 | |||
| 2426 | let mut crates = HashMap::new(); | ||
| 2425 | for (path, dependency_type) in builder.read_stamp_file(stamp) { | 2427 | for (path, dependency_type) in builder.read_stamp_file(stamp) { |
| 2428 | let filename = path.file_name().unwrap().to_str().unwrap(); | ||
| 2426 | let dst = match dependency_type { | 2429 | let dst = match dependency_type { |
| 2427 | DependencyType::Host => sysroot_host_dst, | 2430 | DependencyType::Host => { |
| 2428 | DependencyType::Target => sysroot_dst, | 2431 | if sysroot_dst == sysroot_host_dst { |
| 2432 | // Only insert the part before the . to deduplicate different files for the same crate. | ||
| 2433 | // For example foo-1234.dll and foo-1234.dll.lib. | ||
| 2434 | crates.insert(filename.split_once('.').unwrap().0.to_owned(), path.clone()); | ||
| 2435 | } | ||
| 2436 | |||
| 2437 | sysroot_host_dst | ||
| 2438 | } | ||
| 2439 | DependencyType::Target => { | ||
| 2440 | // Only insert the part before the . to deduplicate different files for the same crate. | ||
| 2441 | // For example foo-1234.dll and foo-1234.dll.lib. | ||
| 2442 | crates.insert(filename.split_once('.').unwrap().0.to_owned(), path.clone()); | ||
| 2443 | |||
| 2444 | sysroot_dst | ||
| 2445 | } | ||
| 2429 | DependencyType::TargetSelfContained => self_contained_dst, | 2446 | DependencyType::TargetSelfContained => self_contained_dst, |
| 2430 | }; | 2447 | }; |
| 2431 | builder.copy_link(&path, &dst.join(path.file_name().unwrap()), FileType::Regular); | 2448 | builder.copy_link(&path, &dst.join(filename), FileType::Regular); |
| 2449 | } | ||
| 2450 | |||
| 2451 | // Check that none of the rustc_* crates have multiple versions. Otherwise using them from | ||
| 2452 | // the sysroot would cause ambiguity errors. We do allow rustc_hash however as it is an | ||
| 2453 | // external dependency that we build multiple copies of. It is re-exported by | ||
| 2454 | // rustc_data_structures, so not being able to use extern crate rustc_hash; is not a big | ||
| 2455 | // issue. | ||
| 2456 | let mut seen_crates = HashMap::new(); | ||
| 2457 | for (filestem, path) in crates { | ||
| 2458 | if !filestem.contains("rustc_") || filestem.contains("rustc_hash") { | ||
| 2459 | continue; | ||
| 2460 | } | ||
| 2461 | if let Some(other_path) = | ||
| 2462 | seen_crates.insert(filestem.split_once('-').unwrap().0.to_owned(), path.clone()) | ||
| 2463 | { | ||
| 2464 | panic!( | ||
| 2465 | "duplicate rustc crate {}\n- first copy at {}\n- second copy at {}", | ||
| 2466 | filestem.split_once('-').unwrap().0.to_owned(), | ||
| 2467 | other_path.display(), | ||
| 2468 | path.display(), | ||
| 2469 | ); | ||
| 2470 | } | ||
| 2432 | } | 2471 | } |
| 2433 | } | 2472 | } |
| 2434 | 2473 | ||
| ... | @@ -2515,7 +2554,13 @@ pub fn run_cargo( | ... | @@ -2515,7 +2554,13 @@ pub fn run_cargo( |
| 2515 | if filename.starts_with(&host_root_dir) { | 2554 | if filename.starts_with(&host_root_dir) { |
| 2516 | // Unless it's a proc macro used in the compiler | 2555 | // Unless it's a proc macro used in the compiler |
| 2517 | if crate_types.iter().any(|t| t == "proc-macro") { | 2556 | if crate_types.iter().any(|t| t == "proc-macro") { |
| 2518 | deps.push((filename.to_path_buf(), DependencyType::Host)); | 2557 | // Cargo will compile proc-macros that are part of the rustc workspace twice. |
| 2558 | // Once as libmacro-hash.so as build dependency and once as libmacro.so as | ||
| 2559 | // output artifact. Only keep the former to avoid ambiguity when trying to use | ||
| 2560 | // the proc macro from the sysroot. | ||
| 2561 | if filename.file_name().unwrap().to_str().unwrap().contains("-") { | ||
| 2562 | deps.push((filename.to_path_buf(), DependencyType::Host)); | ||
| 2563 | } | ||
| 2519 | } | 2564 | } |
| 2520 | continue; | 2565 | continue; |
| 2521 | } | 2566 | } |
src/tools/miri/src/diagnostics.rs+2-2| ... | @@ -3,8 +3,8 @@ use std::num::NonZero; | ... | @@ -3,8 +3,8 @@ use std::num::NonZero; |
| 3 | use std::sync::Mutex; | 3 | use std::sync::Mutex; |
| 4 | 4 | ||
| 5 | use rustc_abi::{Align, Size}; | 5 | use rustc_abi::{Align, Size}; |
| 6 | use rustc_data_structures::fx::{FxBuildHasher, FxHashSet}; | ||
| 6 | use rustc_errors::{Diag, DiagMessage, Level}; | 7 | use rustc_errors::{Diag, DiagMessage, Level}; |
| 7 | use rustc_hash::FxHashSet; | ||
| 8 | use rustc_span::{DUMMY_SP, Span, SpanData, Symbol}; | 8 | use rustc_span::{DUMMY_SP, Span, SpanData, Symbol}; |
| 9 | 9 | ||
| 10 | use crate::borrow_tracker::stacked_borrows::diagnostics::TagHistory; | 10 | use crate::borrow_tracker::stacked_borrows::diagnostics::TagHistory; |
| ... | @@ -899,6 +899,6 @@ pub struct SpanDedupDiagnostic(Mutex<FxHashSet<Span>>); | ... | @@ -899,6 +899,6 @@ pub struct SpanDedupDiagnostic(Mutex<FxHashSet<Span>>); |
| 899 | 899 | ||
| 900 | impl SpanDedupDiagnostic { | 900 | impl SpanDedupDiagnostic { |
| 901 | pub const fn new() -> Self { | 901 | pub const fn new() -> Self { |
| 902 | Self(Mutex::new(FxHashSet::with_hasher(rustc_hash::FxBuildHasher))) | 902 | Self(Mutex::new(FxHashSet::with_hasher(FxBuildHasher))) |
| 903 | } | 903 | } |
| 904 | } | 904 | } |
src/tools/miri/src/helpers.rs+2-2| ... | @@ -6,7 +6,7 @@ use std::{cmp, iter}; | ... | @@ -6,7 +6,7 @@ use std::{cmp, iter}; |
| 6 | use rand::RngCore; | 6 | use rand::RngCore; |
| 7 | use rustc_abi::{Align, ExternAbi, FieldIdx, FieldsShape, Size, Variants}; | 7 | use rustc_abi::{Align, ExternAbi, FieldIdx, FieldsShape, Size, Variants}; |
| 8 | use rustc_apfloat::Float; | 8 | use rustc_apfloat::Float; |
| 9 | use rustc_hash::FxHashSet; | 9 | use rustc_data_structures::fx::{FxBuildHasher, FxHashSet}; |
| 10 | use rustc_hir::Safety; | 10 | use rustc_hir::Safety; |
| 11 | use rustc_hir::def::{DefKind, Namespace}; | 11 | use rustc_hir::def::{DefKind, Namespace}; |
| 12 | use rustc_hir::def_id::{CRATE_DEF_INDEX, CrateNum, DefId, LOCAL_CRATE}; | 12 | use rustc_hir::def_id::{CRATE_DEF_INDEX, CrateNum, DefId, LOCAL_CRATE}; |
| ... | @@ -663,7 +663,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { | ... | @@ -663,7 +663,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { |
| 663 | RejectOpWith::WarningWithoutBacktrace => { | 663 | RejectOpWith::WarningWithoutBacktrace => { |
| 664 | // Deduplicate these warnings *by shim* (not by span) | 664 | // Deduplicate these warnings *by shim* (not by span) |
| 665 | static DEDUP: Mutex<FxHashSet<String>> = | 665 | static DEDUP: Mutex<FxHashSet<String>> = |
| 666 | Mutex::new(FxHashSet::with_hasher(rustc_hash::FxBuildHasher)); | 666 | Mutex::new(FxHashSet::with_hasher(FxBuildHasher)); |
| 667 | let mut emitted_warnings = DEDUP.lock().unwrap(); | 667 | let mut emitted_warnings = DEDUP.lock().unwrap(); |
| 668 | if !emitted_warnings.contains(op_name) { | 668 | if !emitted_warnings.contains(op_name) { |
| 669 | // First time we are seeing this. | 669 | // First time we are seeing this. |
src/tools/miri/src/lib.rs-1| ... | @@ -58,7 +58,6 @@ extern crate rustc_codegen_ssa; | ... | @@ -58,7 +58,6 @@ extern crate rustc_codegen_ssa; |
| 58 | extern crate rustc_const_eval; | 58 | extern crate rustc_const_eval; |
| 59 | extern crate rustc_data_structures; | 59 | extern crate rustc_data_structures; |
| 60 | extern crate rustc_errors; | 60 | extern crate rustc_errors; |
| 61 | extern crate rustc_hash; | ||
| 62 | extern crate rustc_hir; | 61 | extern crate rustc_hir; |
| 63 | extern crate rustc_index; | 62 | extern crate rustc_index; |
| 64 | extern crate rustc_log; | 63 | extern crate rustc_log; |
tests/run-make/duplicate-dependency-no-disambiguate/foo-v1.rs created+1| ... | @@ -0,0 +1 @@ | ||
| 1 | pub struct Foo; | ||
tests/run-make/duplicate-dependency-no-disambiguate/foo-v2.rs created+1| ... | @@ -0,0 +1 @@ | ||
| 1 | pub struct Foo; | ||
tests/run-make/duplicate-dependency-no-disambiguate/main.rs created+10| ... | @@ -0,0 +1,10 @@ | ||
| 1 | #![feature(custom_inner_attributes)] | ||
| 2 | #![rustfmt::skip] // use_foo must be referenced before foo | ||
| 3 | |||
| 4 | // Load foo-v2 through use-foo | ||
| 5 | use use_foo as _; | ||
| 6 | |||
| 7 | // Make sure we don't disambiguate this as foo-v2. | ||
| 8 | use foo as _; | ||
| 9 | |||
| 10 | fn main() {} | ||
tests/run-make/duplicate-dependency-no-disambiguate/main.stderr created+12| ... | @@ -0,0 +1,12 @@ | ||
| 1 | error[E0464]: multiple candidates for `rlib` dependency `foo` found | ||
| 2 | --> main.rs:8:5 | ||
| 3 | | | ||
| 4 | LL | use foo as _; | ||
| 5 | | ^^^ | ||
| 6 | | | ||
| 7 | = note: candidate #1: /build-root/test/run-make/duplicate-dependency-no-disambiguate/rmake_out/libfoo-v1.rlib | ||
| 8 | = note: candidate #2: /build-root/test/run-make/duplicate-dependency-no-disambiguate/rmake_out/libfoo-v2.rlib | ||
| 9 | |||
| 10 | error: aborting due to 1 previous error | ||
| 11 | |||
| 12 | For more information about this error, try `rustc --explain E0464`. | ||
tests/run-make/duplicate-dependency-no-disambiguate/rmake.rs created+54| ... | @@ -0,0 +1,54 @@ | ||
| 1 | //@ needs-target-std | ||
| 2 | |||
| 3 | use run_make_support::{Rustc, cwd, diff, regex, rust_lib_name, rustc}; | ||
| 4 | |||
| 5 | fn rustc_with_common_args() -> Rustc { | ||
| 6 | let mut rustc = rustc(); | ||
| 7 | rustc.remap_path_prefix(cwd(), "$DIR"); | ||
| 8 | rustc.edition("2018"); // Don't require `extern crate` | ||
| 9 | rustc | ||
| 10 | } | ||
| 11 | |||
| 12 | fn main() { | ||
| 13 | rustc_with_common_args() | ||
| 14 | .input("foo-v1.rs") | ||
| 15 | .crate_type("rlib") | ||
| 16 | .crate_name("foo") | ||
| 17 | .extra_filename("-v1") | ||
| 18 | .metadata("-v1") | ||
| 19 | .run(); | ||
| 20 | |||
| 21 | rustc_with_common_args() | ||
| 22 | .input("foo-v2.rs") | ||
| 23 | .crate_type("rlib") | ||
| 24 | .crate_name("foo") | ||
| 25 | .extra_filename("-v2") | ||
| 26 | .metadata("-v2") | ||
| 27 | .run(); | ||
| 28 | |||
| 29 | rustc_with_common_args() | ||
| 30 | .input("use-foo.rs") | ||
| 31 | .crate_type("rlib") | ||
| 32 | .extern_("foo", rust_lib_name("foo-v2")) | ||
| 33 | .run(); | ||
| 34 | |||
| 35 | let stderr = rustc_with_common_args() | ||
| 36 | .input("main.rs") | ||
| 37 | .extern_("foo", rust_lib_name("foo-v1")) | ||
| 38 | .extern_("foo", rust_lib_name("foo-v2")) | ||
| 39 | .extern_("use_foo", rust_lib_name("use_foo")) | ||
| 40 | .library_search_path(cwd()) | ||
| 41 | .ui_testing() | ||
| 42 | .run_fail() | ||
| 43 | .stderr_utf8(); | ||
| 44 | |||
| 45 | diff() | ||
| 46 | .expected_file("main.stderr") | ||
| 47 | .normalize( | ||
| 48 | regex::escape(run_make_support::build_root().canonicalize().unwrap().to_str().unwrap()), | ||
| 49 | "/build-root", | ||
| 50 | ) | ||
| 51 | .normalize(r"\\", "/") | ||
| 52 | .actual_text("(rustc)", &stderr) | ||
| 53 | .run(); | ||
| 54 | } | ||
tests/run-make/duplicate-dependency-no-disambiguate/use-foo.rs created+1| ... | @@ -0,0 +1 @@ | ||
| 1 | use foo as _; | ||