Skip to content

Commit b4ba2a3

Browse files
committed
Auto merge of #64324 - alexcrichton:share-generics-again, r=<try>
rustc: Fix mixing crates with different `share_generics` This commit addresses #64319 by removing the `dylib` crate type from the list of crate type that exports generic symbols. The bug in #64319 arises because a `dylib` crate type was trying to export a symbol in an uptream crate but it miscalculated the symbol name of the uptream symbol. This isn't really necessary, though, since `dylib` crates aren't that heavily used, so we can just conservatively say that the `dylib` crate type never exports generic symbols, forcibly removing them from the exported symbol lists if were to otherwise find them. The fix here happens in two places: * First is in the `local_crate_exports_generics` method, indicating that it's now `false` for the `Dylib` crate type. Only rlibs actually export generics at this point. * Next is when we load exported symbols from upstream crate. If, for our compilation session, the crate may be included from a dynamic library, then its generic symbols are removed. When the crate was linked into a dynamic library its symbols weren't exported, so we can't consider them a candidate to link against. Overally this should avoid situations where we incorrectly calculate the upstream symbol names in the face of differnet `share_generics` options, ultimately... Closes #64319
2 parents 66bf391 + f00c634 commit b4ba2a3

File tree

26 files changed

+565
-433
lines changed

26 files changed

+565
-433
lines changed

src/librustc/middle/dependency_format.rs

+6-372
Large diffs are not rendered by default.

src/librustc/query/mod.rs

+6
Original file line numberDiff line numberDiff line change
@@ -630,6 +630,12 @@ rustc_queries! {
630630
-> &'tcx [(CrateNum, LinkagePreference)] {
631631
desc { "dylib dependency formats of crate" }
632632
}
633+
634+
query dependency_formats(_: CrateNum)
635+
-> Lrc<crate::middle::dependency_format::Dependencies>
636+
{
637+
desc { "get the linkage format of all dependencies" }
638+
}
633639
}
634640

635641
Codegen {

src/librustc/session/config.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -687,7 +687,7 @@ pub enum EntryFnType {
687687

688688
impl_stable_hash_via_hash!(EntryFnType);
689689

690-
#[derive(Copy, PartialEq, PartialOrd, Clone, Ord, Eq, Hash, Debug)]
690+
#[derive(Copy, PartialEq, PartialOrd, Clone, Ord, Eq, Hash, Debug, HashStable)]
691691
pub enum CrateType {
692692
Executable,
693693
Dylib,

src/librustc/session/mod.rs

-3
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ use rustc_data_structures::fingerprint::Fingerprint;
77

88
use crate::lint;
99
use crate::lint::builtin::BuiltinLintDiagnostics;
10-
use crate::middle::dependency_format;
1110
use crate::session::config::{OutputType, PrintRequest, SwitchWithOptPath};
1211
use crate::session::search_paths::{PathKind, SearchPath};
1312
use crate::util::nodemap::{FxHashMap, FxHashSet};
@@ -91,7 +90,6 @@ pub struct Session {
9190
pub plugin_llvm_passes: OneThread<RefCell<Vec<String>>>,
9291
pub plugin_attributes: Lock<Vec<(Symbol, AttributeType)>>,
9392
pub crate_types: Once<Vec<config::CrateType>>,
94-
pub dependency_formats: Once<dependency_format::Dependencies>,
9593
/// The `crate_disambiguator` is constructed out of all the `-C metadata`
9694
/// arguments passed to the compiler. Its value together with the crate-name
9795
/// forms a unique global identifier for the crate. It is used to allow
@@ -1247,7 +1245,6 @@ fn build_session_(
12471245
plugin_llvm_passes: OneThread::new(RefCell::new(Vec::new())),
12481246
plugin_attributes: Lock::new(Vec::new()),
12491247
crate_types: Once::new(),
1250-
dependency_formats: Once::new(),
12511248
crate_disambiguator: Once::new(),
12521249
features: Once::new(),
12531250
recursion_limit: Once::new(),

src/librustc/ty/context.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1510,9 +1510,9 @@ impl<'tcx> TyCtxt<'tcx> {
15101510
CrateType::Executable |
15111511
CrateType::Staticlib |
15121512
CrateType::ProcMacro |
1513+
CrateType::Dylib |
15131514
CrateType::Cdylib => false,
1514-
CrateType::Rlib |
1515-
CrateType::Dylib => true,
1515+
CrateType::Rlib => true,
15161516
}
15171517
})
15181518
}

src/librustc_codegen_ssa/back/link.rs

+39-22
Original file line numberDiff line numberDiff line change
@@ -219,15 +219,24 @@ pub fn get_linker(sess: &Session, linker: &Path, flavor: LinkerFlavor) -> (PathB
219219
(linker.to_path_buf(), cmd)
220220
}
221221

222-
pub fn each_linked_rlib(sess: &Session,
223-
info: &CrateInfo,
224-
f: &mut dyn FnMut(CrateNum, &Path)) -> Result<(), String> {
222+
pub fn each_linked_rlib(
223+
info: &CrateInfo,
224+
f: &mut dyn FnMut(CrateNum, &Path),
225+
) -> Result<(), String> {
225226
let crates = info.used_crates_static.iter();
226-
let fmts = sess.dependency_formats.borrow();
227-
let fmts = fmts.get(&config::CrateType::Executable)
228-
.or_else(|| fmts.get(&config::CrateType::Staticlib))
229-
.or_else(|| fmts.get(&config::CrateType::Cdylib))
230-
.or_else(|| fmts.get(&config::CrateType::ProcMacro));
227+
let mut fmts = None;
228+
for (ty, list) in info.dependency_formats.iter() {
229+
match ty {
230+
config::CrateType::Executable |
231+
config::CrateType::Staticlib |
232+
config::CrateType::Cdylib |
233+
config::CrateType::ProcMacro => {
234+
fmts = Some(list);
235+
break;
236+
}
237+
_ => {}
238+
}
239+
}
231240
let fmts = match fmts {
232241
Some(f) => f,
233242
None => return Err("could not find formats for rlibs".to_string())
@@ -406,7 +415,7 @@ fn link_staticlib<'a, B: ArchiveBuilder<'a>>(sess: &'a Session,
406415
tempdir);
407416
let mut all_native_libs = vec![];
408417

409-
let res = each_linked_rlib(sess, &codegen_results.crate_info, &mut |cnum, path| {
418+
let res = each_linked_rlib(&codegen_results.crate_info, &mut |cnum, path| {
410419
let name = &codegen_results.crate_info.crate_name[&cnum];
411420
let native_libs = &codegen_results.crate_info.native_libraries[&cnum];
412421

@@ -1294,11 +1303,13 @@ pub fn add_local_native_libraries(cmd: &mut dyn Linker,
12941303
// Rust crates are not considered at all when creating an rlib output. All
12951304
// dependencies will be linked when producing the final output (instead of
12961305
// the intermediate rlib version)
1297-
fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>(cmd: &mut dyn Linker,
1298-
sess: &'a Session,
1299-
codegen_results: &CodegenResults,
1300-
crate_type: config::CrateType,
1301-
tmpdir: &Path) {
1306+
fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>(
1307+
cmd: &mut dyn Linker,
1308+
sess: &'a Session,
1309+
codegen_results: &CodegenResults,
1310+
crate_type: config::CrateType,
1311+
tmpdir: &Path,
1312+
) {
13021313
// All of the heavy lifting has previously been accomplished by the
13031314
// dependency_format module of the compiler. This is just crawling the
13041315
// output of that module, adding crates as necessary.
@@ -1307,8 +1318,10 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>(cmd: &mut dyn Linker,
13071318
// will slurp up the object files inside), and linking to a dynamic library
13081319
// involves just passing the right -l flag.
13091320

1310-
let formats = sess.dependency_formats.borrow();
1311-
let data = formats.get(&crate_type).unwrap();
1321+
let (_, data) = codegen_results.crate_info.dependency_formats
1322+
.iter()
1323+
.find(|(ty, _)| *ty == crate_type)
1324+
.expect("failed to find crate type in dependency format list");
13121325

13131326
// Invoke get_used_crates to ensure that we get a topological sorting of
13141327
// crates.
@@ -1620,10 +1633,12 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>(cmd: &mut dyn Linker,
16201633
// generic function calls a native function, then the generic function must
16211634
// be instantiated in the target crate, meaning that the native symbol must
16221635
// also be resolved in the target crate.
1623-
pub fn add_upstream_native_libraries(cmd: &mut dyn Linker,
1624-
sess: &Session,
1625-
codegen_results: &CodegenResults,
1626-
crate_type: config::CrateType) {
1636+
pub fn add_upstream_native_libraries(
1637+
cmd: &mut dyn Linker,
1638+
sess: &Session,
1639+
codegen_results: &CodegenResults,
1640+
crate_type: config::CrateType,
1641+
) {
16271642
// Be sure to use a topological sorting of crates because there may be
16281643
// interdependencies between native libraries. When passing -nodefaultlibs,
16291644
// for example, almost all native libraries depend on libc, so we have to
@@ -1633,8 +1648,10 @@ pub fn add_upstream_native_libraries(cmd: &mut dyn Linker,
16331648
// This passes RequireStatic, but the actual requirement doesn't matter,
16341649
// we're just getting an ordering of crate numbers, we're not worried about
16351650
// the paths.
1636-
let formats = sess.dependency_formats.borrow();
1637-
let data = formats.get(&crate_type).unwrap();
1651+
let (_, data) = codegen_results.crate_info.dependency_formats
1652+
.iter()
1653+
.find(|(ty, _)| *ty == crate_type)
1654+
.expect("failed to find crate type in dependency format list");
16381655

16391656
let crates = &codegen_results.crate_info.used_crates_static;
16401657
for &(cnum, _) in crates {

src/librustc_codegen_ssa/back/linker.rs

+29-5
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use rustc::middle::dependency_format::Linkage;
1414
use rustc::session::Session;
1515
use rustc::session::config::{self, CrateType, OptLevel, DebugInfo,
1616
LinkerPluginLto, Lto};
17+
use rustc::middle::exported_symbols::ExportedSymbol;
1718
use rustc::ty::TyCtxt;
1819
use rustc_target::spec::{LinkerFlavor, LldFlavor};
1920
use rustc_serialize::{json, Encoder};
@@ -1092,18 +1093,41 @@ fn exported_symbols(tcx: TyCtxt<'_>, crate_type: CrateType) -> Vec<String> {
10921093
}
10931094
}
10941095

1095-
let formats = tcx.sess.dependency_formats.borrow();
1096-
let deps = formats[&crate_type].iter();
1096+
let formats = tcx.dependency_formats(LOCAL_CRATE);
1097+
let deps = formats.iter().filter_map(|(t, list)| {
1098+
if *t == crate_type {
1099+
Some(list)
1100+
} else {
1101+
None
1102+
}
1103+
}).next().unwrap();
10971104

1098-
for (index, dep_format) in deps.enumerate() {
1105+
for (index, dep_format) in deps.iter().enumerate() {
10991106
let cnum = CrateNum::new(index + 1);
11001107
// For each dependency that we are linking to statically ...
11011108
if *dep_format == Linkage::Static {
11021109
// ... we add its symbol list to our export list.
11031110
for &(symbol, level) in tcx.exported_symbols(cnum).iter() {
1104-
if level.is_below_threshold(export_threshold) {
1105-
symbols.push(symbol.symbol_name(tcx).to_string());
1111+
if !level.is_below_threshold(export_threshold) {
1112+
continue;
11061113
}
1114+
1115+
// Do not export generic symbols from upstream crates in linked
1116+
// artifact (notably the `dylib` crate type). The main reason
1117+
// for this is that `symbol_name` is actually wrong for generic
1118+
// symbols because it guesses the name we'd give them locally
1119+
// rather than the name it has upstream (depending on
1120+
// `share_generics` settings and such).
1121+
//
1122+
// To fix that issue we just say that linked artifacts, aka
1123+
// `dylib`s, never export generic symbols and they aren't
1124+
// available to downstream crates. (the not available part is
1125+
// handled elsewhere).
1126+
if let ExportedSymbol::Generic(..) = symbol {
1127+
continue;
1128+
}
1129+
1130+
symbols.push(symbol.symbol_name(tcx).to_string());
11071131
}
11081132
}
11091133
}

src/librustc_codegen_ssa/back/symbol_export.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,7 @@ fn upstream_monomorphizations_provider(
298298
};
299299

300300
for &cnum in cnums.iter() {
301-
for &(ref exported_symbol, _) in tcx.exported_symbols(cnum).iter() {
301+
for (exported_symbol, _) in tcx.exported_symbols(cnum).iter() {
302302
if let &ExportedSymbol::Generic(def_id, substs) = exported_symbol {
303303
let substs_map = instances.entry(def_id).or_default();
304304

src/librustc_codegen_ssa/back/write.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1048,7 +1048,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
10481048
}).expect("failed to spawn helper thread");
10491049

10501050
let mut each_linked_rlib_for_lto = Vec::new();
1051-
drop(link::each_linked_rlib(sess, crate_info, &mut |cnum, path| {
1051+
drop(link::each_linked_rlib(crate_info, &mut |cnum, path| {
10521052
if link::ignored_for_lto(sess, crate_info, cnum) {
10531053
return
10541054
}

src/librustc_codegen_ssa/base.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -539,7 +539,7 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
539539
// linkage, then it's already got an allocator shim and we'll be using that
540540
// one instead. If nothing exists then it's our job to generate the
541541
// allocator!
542-
let any_dynamic_crate = tcx.sess.dependency_formats.borrow()
542+
let any_dynamic_crate = tcx.dependency_formats(LOCAL_CRATE)
543543
.iter()
544544
.any(|(_, list)| {
545545
use rustc::middle::dependency_format::Linkage;
@@ -731,6 +731,7 @@ impl CrateInfo {
731731
used_crate_source: Default::default(),
732732
lang_item_to_crate: Default::default(),
733733
missing_lang_items: Default::default(),
734+
dependency_formats: tcx.dependency_formats(LOCAL_CRATE),
734735
};
735736
let lang_items = tcx.lang_items();
736737

src/librustc_codegen_ssa/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
3333
use rustc_data_structures::sync::Lrc;
3434
use rustc_data_structures::svh::Svh;
3535
use rustc::middle::cstore::{LibSource, CrateSource, NativeLibrary};
36+
use rustc::middle::dependency_format::Dependencies;
3637
use syntax_pos::symbol::Symbol;
3738

3839
mod error_codes;
@@ -142,6 +143,7 @@ pub struct CrateInfo {
142143
pub used_crates_dynamic: Vec<(CrateNum, LibSource)>,
143144
pub lang_item_to_crate: FxHashMap<LangItem, CrateNum>,
144145
pub missing_lang_items: FxHashMap<CrateNum, Vec<LangItem>>,
146+
pub dependency_formats: Lrc<Dependencies>,
145147
}
146148

147149

src/librustc_interface/passes.rs

-4
Original file line numberDiff line numberDiff line change
@@ -1079,10 +1079,6 @@ pub fn start_codegen<'tcx>(
10791079
tcx.print_debug_stats();
10801080
}
10811081

1082-
time(tcx.sess, "resolving dependency formats", || {
1083-
middle::dependency_format::calculate(tcx)
1084-
});
1085-
10861082
let (metadata, need_metadata_module) = time(tcx.sess, "metadata encoding and writing", || {
10871083
encode_and_write_metadata(tcx, outputs)
10881084
});

src/librustc_metadata/cstore_impl.rs

+30-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use rustc::middle::cstore::{CrateStore, DepKind,
1010
EncodedMetadata, NativeLibraryKind};
1111
use rustc::middle::exported_symbols::ExportedSymbol;
1212
use rustc::middle::stability::DeprecationEntry;
13+
use rustc::middle::dependency_format::Linkage;
1314
use rustc::hir::def;
1415
use rustc::hir;
1516
use rustc::session::{CrateDisambiguator, Session};
@@ -239,7 +240,30 @@ provide! { <'tcx> tcx, def_id, other, cdata,
239240

240241
used_crate_source => { Lrc::new(cdata.source.clone()) }
241242

242-
exported_symbols => { Arc::new(cdata.exported_symbols(tcx)) }
243+
exported_symbols => {
244+
let mut syms = cdata.exported_symbols(tcx);
245+
246+
// When linked into a dylib crates don't export their generic symbols,
247+
// so if that's happening then we can't load upstream monomorphizations
248+
// from this crate.
249+
let formats = tcx.dependency_formats(LOCAL_CRATE);
250+
let remove_generics = formats.iter().any(|(_ty, list)| {
251+
match list.get(def_id.krate.as_usize() - 1) {
252+
Some(Linkage::IncludedFromDylib) | Some(Linkage::Dynamic) => true,
253+
_ => false,
254+
}
255+
});
256+
if remove_generics {
257+
syms.retain(|(sym, _threshold)| {
258+
match sym {
259+
ExportedSymbol::Generic(..) => false,
260+
_ => return true,
261+
}
262+
});
263+
}
264+
265+
Arc::new(syms)
266+
}
243267
}
244268

245269
pub fn provide(providers: &mut Providers<'_>) {
@@ -370,6 +394,11 @@ pub fn provide(providers: &mut Providers<'_>) {
370394
tcx.arena.alloc(visible_parent_map)
371395
},
372396

397+
dependency_formats: |tcx, cnum| {
398+
assert_eq!(cnum, LOCAL_CRATE);
399+
Lrc::new(crate::dependency_format::calculate(tcx))
400+
},
401+
373402
..*providers
374403
};
375404
}

0 commit comments

Comments
 (0)