Skip to content

Commit 5b4840d

Browse files
committed
Auto merge of #6781 - ehuss:fix-panic-unwind-extra, r=Eh2406
Fix setting `panic=unwind` compiling lib a extra time. Explicitly setting `panic=unwind` in a profile could cause the `lib` target to be built multiple times when it shouldn't be. This is because libs as a test dependency explicitly clear the panic setting (because they are incompatible with `abort`). However, the deduplication logic doesn't know that `panic=None` is the same as `panic=Some("unwind")`. This changes it so there is an explicit enum that defaults to `PanicStrategy::Unwind`. Fixes #6774.
2 parents ed858da + 34b77b5 commit 5b4840d

File tree

4 files changed

+140
-69
lines changed

4 files changed

+140
-69
lines changed

src/cargo/core/compiler/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ use same_file::is_same_file;
2323
use serde::Serialize;
2424

2525
use crate::core::manifest::TargetSourcePath;
26-
use crate::core::profiles::{Lto, Profile};
26+
use crate::core::profiles::{Lto, PanicStrategy, Profile};
2727
use crate::core::{PackageId, Target};
2828
use crate::util::errors::{CargoResult, CargoResultExt, Internal, ProcessError};
2929
use crate::util::paths;
@@ -794,7 +794,7 @@ fn build_base_args<'a, 'cfg>(
794794
cmd.arg("-C").arg(&format!("opt-level={}", opt_level));
795795
}
796796

797-
if let Some(panic) = panic.as_ref() {
797+
if *panic != PanicStrategy::Unwind {
798798
cmd.arg("-C").arg(format!("panic={}", panic));
799799
}
800800

src/cargo/core/profiles.rs

Lines changed: 60 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -111,8 +111,8 @@ impl Profiles {
111111
let mut profile = maker.get_profile(Some(pkg_id), is_member, unit_for);
112112
// `panic` should not be set for tests/benches, or any of their
113113
// dependencies.
114-
if !unit_for.is_panic_ok() || mode.is_any_test() {
115-
profile.panic = None;
114+
if !unit_for.is_panic_abort_ok() || mode.is_any_test() {
115+
profile.panic = PanicStrategy::Unwind;
116116
}
117117

118118
// Incremental can be globally overridden.
@@ -390,8 +390,13 @@ fn merge_profile(profile: &mut Profile, toml: &TomlProfile) {
390390
if let Some(rpath) = toml.rpath {
391391
profile.rpath = rpath;
392392
}
393-
if let Some(ref panic) = toml.panic {
394-
profile.panic = Some(InternedString::new(panic));
393+
if let Some(panic) = &toml.panic {
394+
profile.panic = match panic.as_str() {
395+
"unwind" => PanicStrategy::Unwind,
396+
"abort" => PanicStrategy::Abort,
397+
// This should be validated in TomlProfile::validate
398+
_ => panic!("Unexpected panic setting `{}`", panic),
399+
};
395400
}
396401
if let Some(overflow_checks) = toml.overflow_checks {
397402
profile.overflow_checks = overflow_checks;
@@ -415,7 +420,7 @@ pub struct Profile {
415420
pub overflow_checks: bool,
416421
pub rpath: bool,
417422
pub incremental: bool,
418-
pub panic: Option<InternedString>,
423+
pub panic: PanicStrategy,
419424
}
420425

421426
impl Default for Profile {
@@ -430,7 +435,7 @@ impl Default for Profile {
430435
overflow_checks: false,
431436
rpath: false,
432437
incremental: false,
433-
panic: None,
438+
panic: PanicStrategy::Unwind,
434439
}
435440
}
436441
}
@@ -530,26 +535,26 @@ impl Profile {
530535
fn comparable(
531536
&self,
532537
) -> (
533-
&InternedString,
534-
&Lto,
535-
&Option<u32>,
536-
&Option<u32>,
537-
&bool,
538-
&bool,
539-
&bool,
540-
&bool,
541-
&Option<InternedString>,
538+
InternedString,
539+
Lto,
540+
Option<u32>,
541+
Option<u32>,
542+
bool,
543+
bool,
544+
bool,
545+
bool,
546+
PanicStrategy,
542547
) {
543548
(
544-
&self.opt_level,
545-
&self.lto,
546-
&self.codegen_units,
547-
&self.debuginfo,
548-
&self.debug_assertions,
549-
&self.overflow_checks,
550-
&self.rpath,
551-
&self.incremental,
552-
&self.panic,
549+
self.opt_level,
550+
self.lto,
551+
self.codegen_units,
552+
self.debuginfo,
553+
self.debug_assertions,
554+
self.overflow_checks,
555+
self.rpath,
556+
self.incremental,
557+
self.panic,
553558
)
554559
}
555560
}
@@ -564,18 +569,35 @@ pub enum Lto {
564569
Named(InternedString),
565570
}
566571

572+
/// The `panic` setting.
573+
#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash, PartialOrd, Ord)]
574+
pub enum PanicStrategy {
575+
Unwind,
576+
Abort,
577+
}
578+
579+
impl fmt::Display for PanicStrategy {
580+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
581+
match *self {
582+
PanicStrategy::Unwind => "unwind",
583+
PanicStrategy::Abort => "abort",
584+
}
585+
.fmt(f)
586+
}
587+
}
588+
567589
/// Flags used in creating `Unit`s to indicate the purpose for the target, and
568590
/// to ensure the target's dependencies have the correct settings.
569591
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
570592
pub struct UnitFor {
571593
/// A target for `build.rs` or any of its dependencies. This enables
572594
/// `build-override` profiles for these targets.
573595
custom_build: bool,
574-
/// This is true if it is *allowed* to set the `panic` flag. Currently
596+
/// This is true if it is *allowed* to set the `panic=abort` flag. Currently
575597
/// this is false for test/bench targets and all their dependencies, and
576598
/// "for_host" units such as proc macro and custom build scripts and their
577599
/// dependencies.
578-
panic_ok: bool,
600+
panic_abort_ok: bool,
579601
}
580602

581603
impl UnitFor {
@@ -584,42 +606,42 @@ impl UnitFor {
584606
pub fn new_normal() -> UnitFor {
585607
UnitFor {
586608
custom_build: false,
587-
panic_ok: true,
609+
panic_abort_ok: true,
588610
}
589611
}
590612

591613
/// A unit for a custom build script or its dependencies.
592614
pub fn new_build() -> UnitFor {
593615
UnitFor {
594616
custom_build: true,
595-
panic_ok: false,
617+
panic_abort_ok: false,
596618
}
597619
}
598620

599621
/// A unit for a proc macro or compiler plugin or their dependencies.
600622
pub fn new_compiler() -> UnitFor {
601623
UnitFor {
602624
custom_build: false,
603-
panic_ok: false,
625+
panic_abort_ok: false,
604626
}
605627
}
606628

607629
/// A unit for a test/bench target or their dependencies.
608630
pub fn new_test() -> UnitFor {
609631
UnitFor {
610632
custom_build: false,
611-
panic_ok: false,
633+
panic_abort_ok: false,
612634
}
613635
}
614636

615637
/// Creates a variant based on `for_host` setting.
616638
///
617-
/// When `for_host` is true, this clears `panic_ok` in a sticky fashion so
618-
/// that all its dependencies also have `panic_ok=false`.
639+
/// When `for_host` is true, this clears `panic_abort_ok` in a sticky fashion so
640+
/// that all its dependencies also have `panic_abort_ok=false`.
619641
pub fn with_for_host(self, for_host: bool) -> UnitFor {
620642
UnitFor {
621643
custom_build: self.custom_build,
622-
panic_ok: self.panic_ok && !for_host,
644+
panic_abort_ok: self.panic_abort_ok && !for_host,
623645
}
624646
}
625647

@@ -630,24 +652,24 @@ impl UnitFor {
630652
}
631653

632654
/// Returns `true` if this unit is allowed to set the `panic` compiler flag.
633-
pub fn is_panic_ok(self) -> bool {
634-
self.panic_ok
655+
pub fn is_panic_abort_ok(self) -> bool {
656+
self.panic_abort_ok
635657
}
636658

637659
/// All possible values, used by `clean`.
638660
pub fn all_values() -> &'static [UnitFor] {
639661
static ALL: [UnitFor; 3] = [
640662
UnitFor {
641663
custom_build: false,
642-
panic_ok: true,
664+
panic_abort_ok: true,
643665
},
644666
UnitFor {
645667
custom_build: true,
646-
panic_ok: false,
668+
panic_abort_ok: false,
647669
},
648670
UnitFor {
649671
custom_build: false,
650-
panic_ok: false,
672+
panic_abort_ok: false,
651673
},
652674
];
653675
&ALL

0 commit comments

Comments
 (0)