Skip to content

Commit 2a97225

Browse files
committed
Update assertions in LTO calculations
Turns out a case I thought didn't happen can indeed happen. Units may depend on other units which are LTO-able because integration tests can depend on binaries. Handle that case internally and remove a few panics. Closes #8223
1 parent 4399670 commit 2a97225

File tree

2 files changed

+67
-8
lines changed

2 files changed

+67
-8
lines changed

src/cargo/core/compiler/lto.rs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,10 @@ fn calculate(
4545
(Lto::None, false)
4646
} else if unit.target.can_lto() {
4747
// Otherwise if this target can perform LTO then we're going to read the
48-
// LTO value out of the profile.
49-
assert!(!require_bitcode); // can't depend on binaries/staticlib/etc
48+
// LTO value out of the profile. Note that we ignore `require_bitcode`
49+
// here because if a unit depends on another unit than can LTO this
50+
// isn't a rustc-level dependency but rather a Cargo-level dependency.
51+
// For example this is an integration test depending on a binary.
5052
match unit.profile.lto {
5153
profiles::Lto::Named(s) => match s.as_str() {
5254
"n" | "no" | "off" => (Lto::Run(Some(s)), false),
@@ -73,12 +75,11 @@ fn calculate(
7375

7476
Entry::Occupied(mut v) => {
7577
let result = match (lto, v.get()) {
76-
// Targets which execute LTO cannot be depended on, so these
77-
// units should only show up once in the dependency graph, so we
78-
// should never hit this case.
79-
(Lto::Run(_), _) | (_, Lto::Run(_)) => {
80-
unreachable!("lto-able targets shouldn't show up twice")
81-
}
78+
// Once we're running LTO we keep running LTO. We should always
79+
// calculate the same thing here each iteration because if we
80+
// see this twice then it means, for example, two unit tests
81+
// depend on a binary, which is normal.
82+
(Lto::Run(s), _) | (_, &Lto::Run(s)) => Lto::Run(s),
8283

8384
// If we calculated the same thing as before then we can bail
8485
// out quickly.

tests/testsuite/lto.rs

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,3 +278,61 @@ fn between_builds() {
278278
p.cargo("build -v --release --lib").run();
279279
p.cargo("build -v --release").run();
280280
}
281+
282+
#[cargo_test]
283+
fn test_all() {
284+
if !cargo_test_support::is_nightly() {
285+
return;
286+
}
287+
288+
let p = project()
289+
.file(
290+
"Cargo.toml",
291+
r#"
292+
[package]
293+
name = "foo"
294+
version = "0.0.0"
295+
296+
[profile.release]
297+
lto = true
298+
"#,
299+
)
300+
.file("src/main.rs", "fn main() {}")
301+
.file("tests/a.rs", "")
302+
.file("tests/b.rs", "")
303+
.build();
304+
p.cargo("test --release -v")
305+
.with_stderr_contains("[RUNNING] `rustc[..]--crate-name foo[..]-C lto[..]")
306+
.run();
307+
}
308+
309+
#[cargo_test]
310+
fn test_all_and_bench() {
311+
if !cargo_test_support::is_nightly() {
312+
return;
313+
}
314+
315+
let p = project()
316+
.file(
317+
"Cargo.toml",
318+
r#"
319+
[package]
320+
name = "foo"
321+
version = "0.0.0"
322+
323+
[profile.release]
324+
lto = true
325+
[profile.bench]
326+
lto = true
327+
"#,
328+
)
329+
.file("src/main.rs", "fn main() {}")
330+
.file("tests/a.rs", "")
331+
.file("tests/b.rs", "")
332+
.build();
333+
p.cargo("test --release -v")
334+
.with_stderr_contains("[RUNNING] `rustc[..]--crate-name a[..]-C lto[..]")
335+
.with_stderr_contains("[RUNNING] `rustc[..]--crate-name b[..]-C lto[..]")
336+
.with_stderr_contains("[RUNNING] `rustc[..]--crate-name foo[..]-C lto[..]")
337+
.run();
338+
}

0 commit comments

Comments
 (0)