Skip to content

Commit 50c57d8

Browse files
committed
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
1 parent 5d531ae commit 50c57d8

File tree

15 files changed

+93
-14
lines changed

15 files changed

+93
-14
lines changed

src/librustc/query/mod.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -631,7 +631,9 @@ rustc_queries! {
631631
desc { "dylib dependency formats of crate" }
632632
}
633633

634-
query dependency_formats(_: CrateNum) -> Lrc<crate::middle::dependency_format::Dependencies> {
634+
query dependency_formats(_: CrateNum)
635+
-> Lrc<crate::middle::dependency_format::Dependencies>
636+
{
635637
desc { "get the linkage format of all dependencies" }
636638
}
637639
}

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/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_metadata/cstore_impl.rs

+26-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ 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;
14+
use rustc::session::config::CrateType;
1315
use rustc::hir::def;
1416
use rustc::hir;
1517
use rustc::session::{CrateDisambiguator, Session};
@@ -239,7 +241,30 @@ provide! { <'tcx> tcx, def_id, other, cdata,
239241

240242
used_crate_source => { Lrc::new(cdata.source.clone()) }
241243

242-
exported_symbols => { Arc::new(cdata.exported_symbols(tcx)) }
244+
exported_symbols => {
245+
let mut syms = cdata.exported_symbols(tcx);
246+
247+
// When linked into a dylib crates don't export their generic symbols,
248+
// so if that's happening then we can't load upstream monomorphizations
249+
// from this crate. As a result, if we're creating a dylib or this crate
250+
// is being included from a different dynamic library, then we filter
251+
// out all `Generic` symbols here.
252+
let formats = tcx.dependency_formats(LOCAL_CRATE);
253+
let remove_generics = formats.iter().any(|(ty, list)| {
254+
*ty == CrateType::Dylib ||
255+
list.get(def_id.krate.as_usize() - 1) == Some(&Linkage::IncludedFromDylib)
256+
});
257+
if remove_generics {
258+
syms.retain(|(sym, _threshold)| {
259+
match sym {
260+
ExportedSymbol::Generic(..) => false,
261+
_ => return true,
262+
}
263+
});
264+
}
265+
266+
Arc::new(syms)
267+
}
243268
}
244269

245270
pub fn provide(providers: &mut Providers<'_>) {

src/librustc_metadata/dependency_format.rs

-1
Original file line numberDiff line numberDiff line change
@@ -368,4 +368,3 @@ fn verify_ok(tcx: TyCtxt<'_>, list: &[Linkage]) {
368368
}
369369
}
370370
}
371-

src/test/codegen-units/partitioning/auxiliary/shared_generics_aux.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
// compile-flags:-Zshare-generics=yes
2+
// no-prefer-dynamic
23

34
#![crate_type="rlib"]
45

src/test/codegen-units/partitioning/shared-generics.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
// ignore-tidy-linelength
2+
// no-prefer-dynamic
23
// compile-flags:-Zprint-mono-items=eager -Zshare-generics=yes -Zincremental=tmp/partitioning-tests/shared-generics-exe
34

45
#![crate_type="rlib"]

src/test/compile-fail/two-panic-runtimes.rs

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
// aux-build:panic-runtime-lang-items.rs
66

77
#![no_std]
8+
#![no_main]
89

910
extern crate panic_runtime_unwind;
1011
extern crate panic_runtime_unwind2;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
-include ../tools.mk
2+
3+
# Different optimization levels imply different values for `-Zshare-generics`,
4+
# so try out a whole bunch of combinations to make sure everything is compatible
5+
all:
6+
# First up, try some defaults
7+
$(RUSTC) --crate-type rlib foo.rs
8+
$(RUSTC) --crate-type dylib bar.rs -C opt-level=3
9+
10+
# Next try mixing up some things explicitly
11+
$(RUSTC) --crate-type rlib foo.rs -Z share-generics=no
12+
$(RUSTC) --crate-type dylib bar.rs -Z share-generics=no
13+
$(RUSTC) --crate-type rlib foo.rs -Z share-generics=no
14+
$(RUSTC) --crate-type dylib bar.rs -Z share-generics=yes
15+
$(RUSTC) --crate-type rlib foo.rs -Z share-generics=yes
16+
$(RUSTC) --crate-type dylib bar.rs -Z share-generics=no
17+
$(RUSTC) --crate-type rlib foo.rs -Z share-generics=yes
18+
$(RUSTC) --crate-type dylib bar.rs -Z share-generics=yes
19+
20+
# Now combine a whole bunch of options together
21+
$(RUSTC) --crate-type rlib foo.rs
22+
$(RUSTC) --crate-type dylib bar.rs
23+
$(RUSTC) --crate-type dylib bar.rs -Z share-generics=no
24+
$(RUSTC) --crate-type dylib bar.rs -Z share-generics=yes
25+
$(RUSTC) --crate-type dylib bar.rs -C opt-level=1
26+
$(RUSTC) --crate-type dylib bar.rs -C opt-level=1 -Z share-generics=no
27+
$(RUSTC) --crate-type dylib bar.rs -C opt-level=1 -Z share-generics=yes
28+
$(RUSTC) --crate-type dylib bar.rs -C opt-level=2
29+
$(RUSTC) --crate-type dylib bar.rs -C opt-level=2 -Z share-generics=no
30+
$(RUSTC) --crate-type dylib bar.rs -C opt-level=2 -Z share-generics=yes
31+
$(RUSTC) --crate-type dylib bar.rs -C opt-level=3
32+
$(RUSTC) --crate-type dylib bar.rs -C opt-level=3 -Z share-generics=no
33+
$(RUSTC) --crate-type dylib bar.rs -C opt-level=3 -Z share-generics=yes
34+
$(RUSTC) --crate-type dylib bar.rs -C opt-level=s
35+
$(RUSTC) --crate-type dylib bar.rs -C opt-level=s -Z share-generics=no
36+
$(RUSTC) --crate-type dylib bar.rs -C opt-level=s -Z share-generics=yes
37+
$(RUSTC) --crate-type dylib bar.rs -C opt-level=z
38+
$(RUSTC) --crate-type dylib bar.rs -C opt-level=z -Z share-generics=no
39+
$(RUSTC) --crate-type dylib bar.rs -C opt-level=z -Z share-generics=yes
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
extern crate foo;
2+
3+
pub fn bar() {
4+
foo::foo();
5+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
pub fn foo() {
2+
bar::<usize>();
3+
}
4+
5+
pub fn bar<T>() {
6+
baz();
7+
}
8+
9+
fn baz() {}

src/test/run-make-fulldeps/symbol-visibility/Makefile

+2-2
Original file line numberDiff line numberDiff line change
@@ -79,12 +79,12 @@ all:
7979
# Check that a Rust dylib exports its monomorphic functions, including generics this time
8080
[ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -c public_c_function_from_rust_dylib)" -eq "1" ]
8181
[ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -c public_rust_function_from_rust_dylib)" -eq "1" ]
82-
[ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -c public_generic_function_from_rust_dylib)" -eq "1" ]
82+
[ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -c public_generic_function_from_rust_dylib)" -eq "0" ]
8383

8484
# Check that a Rust dylib exports the monomorphic functions from its dependencies
8585
[ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -c public_c_function_from_rlib)" -eq "1" ]
8686
[ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -c public_rust_function_from_rlib)" -eq "1" ]
87-
[ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -c public_generic_function_from_rlib)" -eq "1" ]
87+
[ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -c public_generic_function_from_rlib)" -eq "0" ]
8888

8989
# Check that an executable does not export any dynamic symbols
9090
[ "$$($(NM) $(TMPDIR)/$(EXE_NAME) | grep -c public_c_function_from_rlib)" -eq "0" ]

src/test/ui/panic-runtime/transitive-link-a-bunch.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,8 @@
77
// ignore-wasm32-bare compiled with panic=abort by default
88

99
#![no_std]
10+
#![no_main]
1011

1112
extern crate wants_panic_runtime_unwind;
1213
extern crate wants_panic_runtime_abort;
1314
extern crate panic_runtime_lang_items;
14-
15-
fn main() {}

src/test/ui/panic-runtime/want-unwind-got-abort.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@
44
// ignore-wasm32-bare compiled with panic=abort by default
55

66
#![no_std]
7+
#![no_main]
78

89
extern crate panic_runtime_abort;
910
extern crate panic_runtime_lang_items;
10-
11-
fn main() {}

src/test/ui/panic-runtime/want-unwind-got-abort2.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,7 @@
55
// ignore-wasm32-bare compiled with panic=abort by default
66

77
#![no_std]
8+
#![no_main]
89

910
extern crate wants_panic_runtime_abort;
1011
extern crate panic_runtime_lang_items;
11-
12-
fn main() {}

0 commit comments

Comments
 (0)