Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add force option for --extern flag #109421

Merged
merged 1 commit into from
May 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions compiler/rustc_interface/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ where
is_private_dep: false,
add_prelude: true,
nounused_dep: false,
force: false,
}
}

Expand Down
14 changes: 13 additions & 1 deletion compiler/rustc_metadata/src/creader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -865,6 +865,17 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
}
}

fn inject_forced_externs(&mut self) {
for (name, entry) in self.sess.opts.externs.iter() {
if entry.force {
let name_interned = Symbol::intern(name);
if !self.used_extern_options.contains(&name_interned) {
self.resolve_crate(name_interned, DUMMY_SP, CrateDepKind::Explicit);
}
}
}
}

fn inject_dependency_if(
&self,
krate: CrateNum,
Expand Down Expand Up @@ -913,7 +924,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
// Don't worry about pathless `--extern foo` sysroot references
continue;
}
if entry.nounused_dep {
if entry.nounused_dep || entry.force {
// We're not worried about this one
continue;
}
Expand Down Expand Up @@ -942,6 +953,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
}

pub fn postprocess(&mut self, krate: &ast::Crate) {
self.inject_forced_externs();
self.inject_profiler_runtime(krate);
self.inject_allocator_crate(krate);
self.inject_panic_runtime(krate);
Expand Down
18 changes: 17 additions & 1 deletion compiler/rustc_session/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -518,6 +518,12 @@ pub struct ExternEntry {
/// `--extern nounused:std=/path/to/lib/libstd.rlib`. This is used to
/// suppress `unused-crate-dependencies` warnings.
pub nounused_dep: bool,
/// If the extern entry is not referenced in the crate, force it to be resolved anyway.
///
/// Allows a dependency satisfying, for instance, a missing panic handler to be injected
/// without modifying source:
/// `--extern force:extras=/path/to/lib/libstd.rlib`
pub force: bool,
}

#[derive(Clone, Debug)]
Expand Down Expand Up @@ -556,7 +562,13 @@ impl Externs {

impl ExternEntry {
fn new(location: ExternLocation) -> ExternEntry {
ExternEntry { location, is_private_dep: false, add_prelude: false, nounused_dep: false }
ExternEntry {
location,
is_private_dep: false,
add_prelude: false,
nounused_dep: false,
force: false,
}
}

pub fn files(&self) -> Option<impl Iterator<Item = &CanonicalizedPath>> {
Expand Down Expand Up @@ -2261,6 +2273,7 @@ pub fn parse_externs(
let mut is_private_dep = false;
let mut add_prelude = true;
let mut nounused_dep = false;
let mut force = false;
if let Some(opts) = options {
if !is_unstable_enabled {
early_error(
Expand All @@ -2283,6 +2296,7 @@ pub fn parse_externs(
}
}
"nounused" => nounused_dep = true,
"force" => force = true,
_ => early_error(error_format, &format!("unknown --extern option `{opt}`")),
}
}
Expand All @@ -2293,6 +2307,8 @@ pub fn parse_externs(
entry.is_private_dep |= is_private_dep;
// likewise `nounused`
entry.nounused_dep |= nounused_dep;
// and `force`
entry.force |= force;
// If any flag is missing `noprelude`, then add to the prelude.
entry.add_prelude |= add_prelude;
}
Expand Down
17 changes: 17 additions & 0 deletions tests/ui/extern-flag/auxiliary/panic_handler.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#![feature(lang_items)]
#![no_std]

// Since `rustc` generally passes `-nodefaultlibs` to the linker,
// Rust programs link necessary system libraries via `#[link()]`
// attributes in the `libc` crate. `libc` is a dependency of `std`,
// but as we are `#![no_std]`, we need to include it manually.
#![feature(rustc_private)]
extern crate libc;

#[panic_handler]
pub fn begin_panic_handler(_info: &core::panic::PanicInfo<'_>) -> ! {
loop {}
}

#[lang = "eh_personality"]
extern "C" fn eh_personality() {}
9 changes: 9 additions & 0 deletions tests/ui/extern-flag/force-extern.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// check-pass
// ignore-cross-compile (needs dylibs and compiletest doesn't have a more specific header)
// aux-crate:force:panic_handler=panic_handler.rs
// compile-flags: -Zunstable-options --crate-type dylib
// edition:2018

#![no_std]

fn foo() {}
10 changes: 10 additions & 0 deletions tests/ui/extern-flag/no-force-extern.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// aux-crate:panic_handler=panic_handler.rs
// ignore-cross-compile (needs dylibs and compiletest doesn't have a more specific header)
// compile_flags: -Zunstable-options --crate-type dylib
// error-pattern: `#[panic_handler]` function required, but not found
// dont-check-compiler-stderr
// edition: 2018

#![no_std]

fn foo() {}
11 changes: 11 additions & 0 deletions tests/ui/extern-flag/redundant-force-extern.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// check-pass
// ignore-cross-compile (needs dylibs and compiletest doesn't have a more specific header)
// aux-crate:force:panic_handler=panic_handler.rs
// compile-flags: -Zunstable-options --crate-type dylib
// edition:2018

#![no_std]

extern crate panic_handler;

fn foo() {}