Skip to content

Commit fb252b9

Browse files
committed
add "force" option to --extern
1 parent a732883 commit fb252b9

File tree

7 files changed

+71
-2
lines changed

7 files changed

+71
-2
lines changed

compiler/rustc_interface/src/tests.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ where
6969
is_private_dep: false,
7070
add_prelude: true,
7171
nounused_dep: false,
72+
force: false,
7273
}
7374
}
7475

compiler/rustc_metadata/src/creader.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -864,6 +864,17 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
864864
}
865865
}
866866

867+
fn inject_forced_externs(&mut self) {
868+
for (name, entry) in self.sess.opts.externs.iter() {
869+
if entry.force {
870+
let name_interned = Symbol::intern(name);
871+
if !self.used_extern_options.contains(&name_interned) {
872+
self.resolve_crate(name_interned, DUMMY_SP, CrateDepKind::Explicit);
873+
}
874+
}
875+
}
876+
}
877+
867878
fn inject_dependency_if(
868879
&self,
869880
krate: CrateNum,
@@ -912,7 +923,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
912923
// Don't worry about pathless `--extern foo` sysroot references
913924
continue;
914925
}
915-
if entry.nounused_dep {
926+
if entry.nounused_dep || entry.force {
916927
// We're not worried about this one
917928
continue;
918929
}
@@ -941,6 +952,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
941952
}
942953

943954
pub fn postprocess(&mut self, krate: &ast::Crate) {
955+
self.inject_forced_externs();
944956
self.inject_profiler_runtime(krate);
945957
self.inject_allocator_crate(krate);
946958
self.inject_panic_runtime(krate);

compiler/rustc_session/src/config.rs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -518,6 +518,12 @@ pub struct ExternEntry {
518518
/// `--extern nounused:std=/path/to/lib/libstd.rlib`. This is used to
519519
/// suppress `unused-crate-dependencies` warnings.
520520
pub nounused_dep: bool,
521+
/// If the extern entry is not referenced in the crate, force it to be resolved anyway.
522+
///
523+
/// Allows a dependency satisfying, for instance, a missing panic handler to be injected
524+
/// without modifying source:
525+
/// `--extern force:extras=/path/to/lib/libstd.rlib`
526+
pub force: bool,
521527
}
522528

523529
#[derive(Clone, Debug)]
@@ -556,7 +562,13 @@ impl Externs {
556562

557563
impl ExternEntry {
558564
fn new(location: ExternLocation) -> ExternEntry {
559-
ExternEntry { location, is_private_dep: false, add_prelude: false, nounused_dep: false }
565+
ExternEntry {
566+
location,
567+
is_private_dep: false,
568+
add_prelude: false,
569+
nounused_dep: false,
570+
force: false,
571+
}
560572
}
561573

562574
pub fn files(&self) -> Option<impl Iterator<Item = &CanonicalizedPath>> {
@@ -2235,6 +2247,7 @@ pub fn parse_externs(
22352247
let mut is_private_dep = false;
22362248
let mut add_prelude = true;
22372249
let mut nounused_dep = false;
2250+
let mut force = false;
22382251
if let Some(opts) = options {
22392252
if !is_unstable_enabled {
22402253
early_error(
@@ -2257,6 +2270,7 @@ pub fn parse_externs(
22572270
}
22582271
}
22592272
"nounused" => nounused_dep = true,
2273+
"force" => force = true,
22602274
_ => early_error(error_format, &format!("unknown --extern option `{opt}`")),
22612275
}
22622276
}
@@ -2267,6 +2281,8 @@ pub fn parse_externs(
22672281
entry.is_private_dep |= is_private_dep;
22682282
// likewise `nounused`
22692283
entry.nounused_dep |= nounused_dep;
2284+
// and `force`
2285+
entry.force |= force;
22702286
// If any flag is missing `noprelude`, then add to the prelude.
22712287
entry.add_prelude |= add_prelude;
22722288
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#![feature(lang_items)]
2+
#![no_std]
3+
4+
#[panic_handler]
5+
pub fn begin_panic_handler(_info: &core::panic::PanicInfo<'_>) -> ! {
6+
loop {}
7+
}
8+
9+
#[lang = "eh_personality"]
10+
extern "C" fn eh_personality() {}

tests/ui/extern-flag/force-extern.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// check-pass
2+
// ignore-cross-compile (needs dylibs and compiletest doesn't have a more specific header)
3+
// aux-crate:force:panic_handler=panic_handler.rs
4+
// compile-flags: -Zunstable-options --crate-type dylib
5+
// edition:2018
6+
7+
#![no_std]
8+
9+
fn foo() {}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// aux-crate:panic_handler=panic_handler.rs
2+
// ignore-cross-compile (needs dylibs and compiletest doesn't have a more specific header)
3+
// compile_flags: -Zunstable-options --crate-type dylib
4+
// error-pattern: `#[panic_handler]` function required, but not found
5+
// dont-check-compiler-stderr
6+
// edition: 2018
7+
8+
#![no_std]
9+
10+
fn foo() {}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// check-pass
2+
// ignore-cross-compile (needs dylibs and compiletest doesn't have a more specific header)
3+
// aux-crate:force:panic_handler=panic_handler.rs
4+
// compile-flags: -Zunstable-options --crate-type dylib
5+
// edition:2018
6+
7+
#![no_std]
8+
9+
extern crate panic_handler;
10+
11+
fn foo() {}

0 commit comments

Comments
 (0)