From 1e05dbb5e686e819e1df12e3af167266a692481b Mon Sep 17 00:00:00 2001
From: Alex Crichton <alex@alexcrichton.com>
Date: Wed, 17 Feb 2021 11:40:38 -0800
Subject: [PATCH] Propagate `lto=off` harder

This commit fixes an issue with LTO calculation for various units when
`lto=off` is specified in the profile. This ensures now that `lto=off`
is passed to all transitive dependencies as well to disable thin-local
LTO. As an added bonus this also passed `embed-bitcode=no` whenever
`lto=off` is specified since we know we won't be using bitcode anyway.

Closes #9171
---
 src/cargo/core/compiler/lto.rs | 7 ++++---
 src/cargo/core/compiler/mod.rs | 5 ++++-
 tests/testsuite/lto.rs         | 4 ++--
 3 files changed, 10 insertions(+), 6 deletions(-)

diff --git a/src/cargo/core/compiler/lto.rs b/src/cargo/core/compiler/lto.rs
index 71e135566da..661d1d266e1 100644
--- a/src/cargo/core/compiler/lto.rs
+++ b/src/cargo/core/compiler/lto.rs
@@ -45,7 +45,8 @@ pub fn generate(bcx: &BuildContext<'_, '_>) -> CargoResult<HashMap<Unit, Lto>> {
     for unit in bcx.roots.iter() {
         let root_lto = match unit.profile.lto {
             // LTO not requested, no need for bitcode.
-            profiles::Lto::Bool(false) | profiles::Lto::Off => Lto::OnlyObject,
+            profiles::Lto::Bool(false) => Lto::OnlyObject,
+            profiles::Lto::Off => Lto::Off,
             _ => {
                 let crate_types = unit.target.rustc_crate_types();
                 if unit.target.for_host() {
@@ -127,8 +128,8 @@ fn calculate(
             (Lto::Run(_), false) => Lto::OnlyBitcode,
             // LTO when something needs object code.
             (Lto::Run(_), true) | (Lto::OnlyBitcode, true) => lto_when_needs_object(&crate_types),
-            // LTO is disabled, no need for bitcode.
-            (Lto::Off, _) => Lto::OnlyObject,
+            // LTO is disabled, continue to disable it.
+            (Lto::Off, _) => Lto::Off,
             // If this doesn't have any requirements, or the requirements are
             // already satisfied, then stay with our parent.
             (_, false) | (Lto::OnlyObject, true) | (Lto::ObjectAndBitcode, true) => parent_lto,
diff --git a/src/cargo/core/compiler/mod.rs b/src/cargo/core/compiler/mod.rs
index b9c3a15c581..238deaab8a1 100644
--- a/src/cargo/core/compiler/mod.rs
+++ b/src/cargo/core/compiler/mod.rs
@@ -968,7 +968,10 @@ fn lto_args(cx: &Context<'_, '_>, unit: &Unit) -> Vec<OsString> {
     match cx.lto[unit] {
         lto::Lto::Run(None) => push("lto"),
         lto::Lto::Run(Some(s)) => push(&format!("lto={}", s)),
-        lto::Lto::Off => push("lto=off"),
+        lto::Lto::Off => {
+            push("lto=off");
+            push("embed-bitcode=no");
+        }
         lto::Lto::ObjectAndBitcode => {} // this is rustc's default
         lto::Lto::OnlyBitcode => push("linker-plugin-lto"),
         lto::Lto::OnlyObject => push("embed-bitcode=no"),
diff --git a/tests/testsuite/lto.rs b/tests/testsuite/lto.rs
index 0c771329f00..f3bfe8e829f 100644
--- a/tests/testsuite/lto.rs
+++ b/tests/testsuite/lto.rs
@@ -254,9 +254,9 @@ fn off_in_manifest_works() {
 [DOWNLOADING] [..]
 [DOWNLOADED] [..]
 [COMPILING] bar v0.0.1
-[RUNNING] `rustc --crate-name bar [..]--crate-type lib [..]-C embed-bitcode=no[..]
+[RUNNING] `rustc --crate-name bar [..]--crate-type lib [..]-C lto=off -C embed-bitcode=no[..]
 [COMPILING] test [..]
-[RUNNING] `rustc --crate-name test [..]--crate-type lib [..]-C embed-bitcode=no[..]
+[RUNNING] `rustc --crate-name test [..]--crate-type lib [..]-C lto=off -C embed-bitcode=no[..]
 [RUNNING] `rustc --crate-name test src/main.rs [..]--crate-type bin [..]-C lto=off[..]
 [FINISHED] [..]
 ",