From 4160337c8553e1083b12632eed7a94e51d57ea91 Mon Sep 17 00:00:00 2001 From: David Mo Date: Fri, 1 Sep 2023 10:53:50 -0700 Subject: [PATCH 01/12] Tests crash from inappropriate use of common linkage Normally, variables with common linkage must be zero-initialized. In Rust, common linkage variables that are not zero-initialized causes a crash in the compiler backend. This commit adds a test case to confirm this behavior, which will inform us if it changes in the future. --- .../linkage-attr/common-linkage-non-zero-init.rs | 14 ++++++++++++++ .../common-linkage-non-zero-init.stderr | 3 +++ 2 files changed, 17 insertions(+) create mode 100644 tests/ui/linkage-attr/common-linkage-non-zero-init.rs create mode 100644 tests/ui/linkage-attr/common-linkage-non-zero-init.stderr diff --git a/tests/ui/linkage-attr/common-linkage-non-zero-init.rs b/tests/ui/linkage-attr/common-linkage-non-zero-init.rs new file mode 100644 index 00000000000..ce8d9848e42 --- /dev/null +++ b/tests/ui/linkage-attr/common-linkage-non-zero-init.rs @@ -0,0 +1,14 @@ +// build-fail +// failure-status: 101 +// known-bug: #109681 + +// This test verifies that we continue to hit the LLVM error for common linkage with non-zero +// initializers, since it generates invalid LLVM IR. +// Linkages are internal features marked as perma-unstable, so we don't need to fix the issue +// for now. +#![crate_type="lib"] +#![feature(linkage)] + +#[linkage = "common"] +#[no_mangle] +pub static TEST: bool = true; diff --git a/tests/ui/linkage-attr/common-linkage-non-zero-init.stderr b/tests/ui/linkage-attr/common-linkage-non-zero-init.stderr new file mode 100644 index 00000000000..667bb3ec130 --- /dev/null +++ b/tests/ui/linkage-attr/common-linkage-non-zero-init.stderr @@ -0,0 +1,3 @@ +'common' global must have a zero initializer! +ptr @TEST +LLVM ERROR: Broken module found, compilation aborted! From 4da6eb2ec6141eb7b4172d62e48c277ea8a191fb Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 7 Sep 2023 05:11:41 +0000 Subject: [PATCH 02/12] Test showing it doesnt work --- ...suggest-import-without-clobbering-attrs.fixed | 16 ++++++++++++++++ .../suggest-import-without-clobbering-attrs.rs | 15 +++++++++++++++ ...uggest-import-without-clobbering-attrs.stderr | 14 ++++++++++++++ 3 files changed, 45 insertions(+) create mode 100644 tests/ui/resolve/suggest-import-without-clobbering-attrs.fixed create mode 100644 tests/ui/resolve/suggest-import-without-clobbering-attrs.rs create mode 100644 tests/ui/resolve/suggest-import-without-clobbering-attrs.stderr diff --git a/tests/ui/resolve/suggest-import-without-clobbering-attrs.fixed b/tests/ui/resolve/suggest-import-without-clobbering-attrs.fixed new file mode 100644 index 00000000000..881b973e3ef --- /dev/null +++ b/tests/ui/resolve/suggest-import-without-clobbering-attrs.fixed @@ -0,0 +1,16 @@ +// run-rustfix +// compile-flags: --cfg=whatever -Aunused + +#[cfg(whatever)] +use y::z; +use y::Whatever; + +mod y { + pub(crate) fn z() {} + pub(crate) struct Whatever; +} + +fn main() { + z(); + //~^ ERROR cannot find function `z` in this scope +} diff --git a/tests/ui/resolve/suggest-import-without-clobbering-attrs.rs b/tests/ui/resolve/suggest-import-without-clobbering-attrs.rs new file mode 100644 index 00000000000..38a1095703b --- /dev/null +++ b/tests/ui/resolve/suggest-import-without-clobbering-attrs.rs @@ -0,0 +1,15 @@ +// run-rustfix +// compile-flags: --cfg=whatever -Aunused + +#[cfg(whatever)] +use y::Whatever; + +mod y { + pub(crate) fn z() {} + pub(crate) struct Whatever; +} + +fn main() { + z(); + //~^ ERROR cannot find function `z` in this scope +} diff --git a/tests/ui/resolve/suggest-import-without-clobbering-attrs.stderr b/tests/ui/resolve/suggest-import-without-clobbering-attrs.stderr new file mode 100644 index 00000000000..d3574851d5c --- /dev/null +++ b/tests/ui/resolve/suggest-import-without-clobbering-attrs.stderr @@ -0,0 +1,14 @@ +error[E0425]: cannot find function `z` in this scope + --> $DIR/suggest-import-without-clobbering-attrs.rs:13:5 + | +LL | z(); + | ^ not found in this scope + | +help: consider importing this function + | +LL + use y::z; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0425`. From 03bee1f53dbf28c582d52ced9b165812514303f9 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 7 Sep 2023 05:13:52 +0000 Subject: [PATCH 03/12] Find lowest span out of use + attrs --- compiler/rustc_resolve/src/diagnostics.rs | 8 +++++++- .../resolve/suggest-import-without-clobbering-attrs.fixed | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index d99fc07a7cd..e9edfb53b44 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -2753,7 +2753,13 @@ fn search_for_any_use_in_items(items: &[P]) -> Option { for item in items { if let ItemKind::Use(..) = item.kind { if is_span_suitable_for_use_injection(item.span) { - return Some(item.span.shrink_to_lo()); + let mut lo = item.span.lo(); + for attr in &item.attrs { + if attr.span.eq_ctxt(item.span) { + lo = std::cmp::min(lo, attr.span.lo()); + } + } + return Some(Span::new(lo, lo, item.span.ctxt(), item.span.parent())); } } } diff --git a/tests/ui/resolve/suggest-import-without-clobbering-attrs.fixed b/tests/ui/resolve/suggest-import-without-clobbering-attrs.fixed index 881b973e3ef..fc68884fe9c 100644 --- a/tests/ui/resolve/suggest-import-without-clobbering-attrs.fixed +++ b/tests/ui/resolve/suggest-import-without-clobbering-attrs.fixed @@ -1,8 +1,8 @@ // run-rustfix // compile-flags: --cfg=whatever -Aunused -#[cfg(whatever)] use y::z; +#[cfg(whatever)] use y::Whatever; mod y { From 96c96645c7bb70a73ced2046df8fe083ad2ae3fc Mon Sep 17 00:00:00 2001 From: Lieselotte <52315535+she3py@users.noreply.github.com> Date: Fri, 8 Sep 2023 06:23:56 +0200 Subject: [PATCH 04/12] Improve "associated type not found" diagnostics --- .../rustc_hir_analysis/src/astconv/errors.rs | 53 +++++++++++++++---- .../assoc-const-eq-missing.stderr | 12 +++-- ...missing-trait-bound-for-assoc-fails.stderr | 4 +- .../associated-types-path-1.stderr | 4 +- .../ui/associated-types/issue-23595-2.stderr | 2 +- tests/ui/error-codes/E0220.stderr | 2 +- ...ature-gate-return_type_notation.cfg.stderr | 4 +- ...te-return_type_notation.cfg_current.stderr | 4 +- ...-gate-return_type_notation.cfg_next.stderr | 4 +- tests/ui/lifetimes/issue-95023.stderr | 2 +- 10 files changed, 69 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/astconv/errors.rs b/compiler/rustc_hir_analysis/src/astconv/errors.rs index 6082d446979..26bd3b0f6a9 100644 --- a/compiler/rustc_hir_analysis/src/astconv/errors.rs +++ b/compiler/rustc_hir_analysis/src/astconv/errors.rs @@ -110,16 +110,22 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { { // The fallback span is needed because `assoc_name` might be an `Fn()`'s `Output` without a // valid span, so we point at the whole path segment instead. - let span = if assoc_name.span != DUMMY_SP { assoc_name.span } else { span }; + let is_dummy = assoc_name.span == DUMMY_SP; + let mut err = struct_span_err!( self.tcx().sess, - span, + if is_dummy { span } else { assoc_name.span }, E0220, "associated type `{}` not found for `{}`", assoc_name, ty_param_name ); + if is_dummy { + err.span_label(span, format!("associated type `{assoc_name}` not found")); + return err.emit(); + } + let all_candidate_names: Vec<_> = all_candidates() .flat_map(|r| self.tcx().associated_items(r.def_id()).in_definition_order()) .filter_map(|item| { @@ -131,10 +137,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { }) .collect(); - if let (Some(suggested_name), true) = ( - find_best_match_for_name(&all_candidate_names, assoc_name.name, None), - assoc_name.span != DUMMY_SP, - ) { + if let Some(suggested_name) = + find_best_match_for_name(&all_candidate_names, assoc_name.name, None) + { err.span_suggestion( assoc_name.span, "there is an associated type with a similar name", @@ -172,10 +177,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { }) .collect(); - if let (Some(suggested_name), true) = ( - find_best_match_for_name(&wider_candidate_names, assoc_name.name, None), - assoc_name.span != DUMMY_SP, - ) { + if let Some(suggested_name) = + find_best_match_for_name(&wider_candidate_names, assoc_name.name, None) + { if let [best_trait] = visible_traits .iter() .filter(|trait_def_id| { @@ -197,7 +201,34 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } } - err.span_label(span, format!("associated type `{assoc_name}` not found")); + // If we still couldn't find any associated type, just list them all. + + if all_candidate_names.is_empty() { + err.help(format!( + "`{ty_param_name}` has no associated type, try removing `{assoc_name}`" + )); + return err.emit(); + } + + let msg = if all_candidate_names.len() > 1 { + format!("`{ty_param_name}` has the following associated types") + } else { + format!("`{ty_param_name}` has the following associated type") + }; + + let applicability = if self.tcx().features().associated_type_defaults { + Applicability::Unspecified // `type A = Self::B` would suggest `type A = Self::A` + } else { + Applicability::MaybeIncorrect + }; + + err.span_suggestions( + assoc_name.span, + msg, + all_candidate_names.iter().map(|symbol| symbol.to_string()), + applicability, + ); + err.emit() } diff --git a/tests/ui/associated-consts/assoc-const-eq-missing.stderr b/tests/ui/associated-consts/assoc-const-eq-missing.stderr index b4bd6456c85..9cd3865fc3b 100644 --- a/tests/ui/associated-consts/assoc-const-eq-missing.stderr +++ b/tests/ui/associated-consts/assoc-const-eq-missing.stderr @@ -2,19 +2,25 @@ error[E0220]: associated type `Z` not found for `Foo` --> $DIR/assoc-const-eq-missing.rs:15:16 | LL | fn foo1>() {} - | ^ associated type `Z` not found + | ^ + | + = help: `Foo` has no associated type, try removing `Z` error[E0220]: associated type `Z` not found for `Foo` --> $DIR/assoc-const-eq-missing.rs:17:16 | LL | fn foo2>() {} - | ^ associated type `Z` not found + | ^ + | + = help: `Foo` has no associated type, try removing `Z` error[E0220]: associated type `Z` not found for `Foo` --> $DIR/assoc-const-eq-missing.rs:19:16 | LL | fn foo3>() {} - | ^ associated type `Z` not found + | ^ + | + = help: `Foo` has no associated type, try removing `Z` error: aborting due to 3 previous errors diff --git a/tests/ui/associated-type-bounds/missing-trait-bound-for-assoc-fails.stderr b/tests/ui/associated-type-bounds/missing-trait-bound-for-assoc-fails.stderr index bc2807b0396..a964c9df2c5 100644 --- a/tests/ui/associated-type-bounds/missing-trait-bound-for-assoc-fails.stderr +++ b/tests/ui/associated-type-bounds/missing-trait-bound-for-assoc-fails.stderr @@ -8,7 +8,9 @@ error[E0220]: associated type `Item` not found for `M` --> $DIR/missing-trait-bound-for-assoc-fails.rs:4:8 | LL | M::Item: Temp, - | ^^^^ associated type `Item` not found + | ^^^^ + | + = help: `M` has no associated type, try removing `Item` error: aborting due to 2 previous errors diff --git a/tests/ui/associated-types/associated-types-path-1.stderr b/tests/ui/associated-types/associated-types-path-1.stderr index a67f77e37c7..195740359a3 100644 --- a/tests/ui/associated-types/associated-types-path-1.stderr +++ b/tests/ui/associated-types/associated-types-path-1.stderr @@ -2,7 +2,9 @@ error[E0220]: associated type `A` not found for `T` --> $DIR/associated-types-path-1.rs:10:26 | LL | pub fn f1(a: T, x: T::A) {} - | ^ associated type `A` not found + | ^ + | + = help: `T` has no associated type, try removing `A` error[E0221]: ambiguous associated type `A` in bounds of `T` --> $DIR/associated-types-path-1.rs:11:34 diff --git a/tests/ui/associated-types/issue-23595-2.stderr b/tests/ui/associated-types/issue-23595-2.stderr index dded673f6ee..73effa9f955 100644 --- a/tests/ui/associated-types/issue-23595-2.stderr +++ b/tests/ui/associated-types/issue-23595-2.stderr @@ -2,7 +2,7 @@ error[E0220]: associated type `anything_here_kills_it` not found for `Self` --> $DIR/issue-23595-2.rs:6:22 | LL | type B = C; - | ^^^^^^^^^^^^^^^^^^^^^^ associated type `anything_here_kills_it` not found + | ^^^^^^^^^^^^^^^^^^^^^^ help: `Self` has the following associated type: `B` error: aborting due to previous error diff --git a/tests/ui/error-codes/E0220.stderr b/tests/ui/error-codes/E0220.stderr index 11763ce788d..e03eadacae4 100644 --- a/tests/ui/error-codes/E0220.stderr +++ b/tests/ui/error-codes/E0220.stderr @@ -2,7 +2,7 @@ error[E0220]: associated type `F` not found for `Trait` --> $DIR/E0220.rs:5:22 | LL | type Foo = dyn Trait; - | ^ associated type `F` not found + | ^ help: `Trait` has the following associated type: `Bar` error[E0191]: the value of the associated type `Bar` (from trait `Trait`) must be specified --> $DIR/E0220.rs:5:16 diff --git a/tests/ui/feature-gates/feature-gate-return_type_notation.cfg.stderr b/tests/ui/feature-gates/feature-gate-return_type_notation.cfg.stderr index 1bdb2574ead..012913fd0e0 100644 --- a/tests/ui/feature-gates/feature-gate-return_type_notation.cfg.stderr +++ b/tests/ui/feature-gates/feature-gate-return_type_notation.cfg.stderr @@ -19,7 +19,9 @@ error[E0220]: associated type `m` not found for `Trait` --> $DIR/feature-gate-return_type_notation.rs:14:17 | LL | fn foo>() {} - | ^ associated type `m` not found + | ^ + | + = help: `Trait` has no associated type, try removing `m` error: aborting due to 3 previous errors diff --git a/tests/ui/feature-gates/feature-gate-return_type_notation.cfg_current.stderr b/tests/ui/feature-gates/feature-gate-return_type_notation.cfg_current.stderr index ce39f6b2971..68cf8e36fcc 100644 --- a/tests/ui/feature-gates/feature-gate-return_type_notation.cfg_current.stderr +++ b/tests/ui/feature-gates/feature-gate-return_type_notation.cfg_current.stderr @@ -19,7 +19,9 @@ error[E0220]: associated type `m` not found for `Trait` --> $DIR/feature-gate-return_type_notation.rs:17:17 | LL | fn foo>() {} - | ^ associated type `m` not found + | ^ + | + = help: `Trait` has no associated type, try removing `m` error: aborting due to 3 previous errors diff --git a/tests/ui/feature-gates/feature-gate-return_type_notation.cfg_next.stderr b/tests/ui/feature-gates/feature-gate-return_type_notation.cfg_next.stderr index ce39f6b2971..68cf8e36fcc 100644 --- a/tests/ui/feature-gates/feature-gate-return_type_notation.cfg_next.stderr +++ b/tests/ui/feature-gates/feature-gate-return_type_notation.cfg_next.stderr @@ -19,7 +19,9 @@ error[E0220]: associated type `m` not found for `Trait` --> $DIR/feature-gate-return_type_notation.rs:17:17 | LL | fn foo>() {} - | ^ associated type `m` not found + | ^ + | + = help: `Trait` has no associated type, try removing `m` error: aborting due to 3 previous errors diff --git a/tests/ui/lifetimes/issue-95023.stderr b/tests/ui/lifetimes/issue-95023.stderr index 5b93eff8614..6361d8ad30b 100644 --- a/tests/ui/lifetimes/issue-95023.stderr +++ b/tests/ui/lifetimes/issue-95023.stderr @@ -36,7 +36,7 @@ error[E0220]: associated type `B` not found for `Self` --> $DIR/issue-95023.rs:6:44 | LL | fn foo(&self) -> Self::B<{N}>; - | ^ associated type `B` not found + | ^ help: `Self` has the following associated type: `Output` error: aborting due to 5 previous errors From a0e0a3261e5f8d4515621d90dc2a1e377eb19483 Mon Sep 17 00:00:00 2001 From: Lieselotte <52315535+she3py@users.noreply.github.com> Date: Fri, 8 Sep 2023 08:44:23 +0200 Subject: [PATCH 05/12] E0220: only suggests associated types if there's only one candidate --- .../rustc_hir_analysis/src/astconv/errors.rs | 44 ++++++++----------- .../assoc-const-eq-missing.stderr | 12 ++--- ...missing-trait-bound-for-assoc-fails.stderr | 4 +- .../associated-types-path-1.stderr | 4 +- ...ature-gate-return_type_notation.cfg.stderr | 4 +- ...te-return_type_notation.cfg_current.stderr | 4 +- ...-gate-return_type_notation.cfg_next.stderr | 4 +- 7 files changed, 27 insertions(+), 49 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/astconv/errors.rs b/compiler/rustc_hir_analysis/src/astconv/errors.rs index 26bd3b0f6a9..ed4dde419c4 100644 --- a/compiler/rustc_hir_analysis/src/astconv/errors.rs +++ b/compiler/rustc_hir_analysis/src/astconv/errors.rs @@ -201,34 +201,28 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } } - // If we still couldn't find any associated type, just list them all. + // If we still couldn't find any associated type, and only one associated type exists, + // suggests using it. - if all_candidate_names.is_empty() { - err.help(format!( - "`{ty_param_name}` has no associated type, try removing `{assoc_name}`" - )); - return err.emit(); + if all_candidate_names.len() == 1 { + // this should still compile, except on `#![feature(associated_type_defaults)]` + // where it could suggests `type A = Self::A`, thus recursing infinitely + let applicability = if self.tcx().features().associated_type_defaults { + Applicability::Unspecified + } else { + Applicability::MaybeIncorrect + }; + + err.span_suggestion( + assoc_name.span, + format!("`{ty_param_name}` has the following associated type"), + all_candidate_names.first().unwrap().to_string(), + applicability, + ); + } else { + err.span_label(assoc_name.span, format!("associated type `{assoc_name}` not found")); } - let msg = if all_candidate_names.len() > 1 { - format!("`{ty_param_name}` has the following associated types") - } else { - format!("`{ty_param_name}` has the following associated type") - }; - - let applicability = if self.tcx().features().associated_type_defaults { - Applicability::Unspecified // `type A = Self::B` would suggest `type A = Self::A` - } else { - Applicability::MaybeIncorrect - }; - - err.span_suggestions( - assoc_name.span, - msg, - all_candidate_names.iter().map(|symbol| symbol.to_string()), - applicability, - ); - err.emit() } diff --git a/tests/ui/associated-consts/assoc-const-eq-missing.stderr b/tests/ui/associated-consts/assoc-const-eq-missing.stderr index 9cd3865fc3b..b4bd6456c85 100644 --- a/tests/ui/associated-consts/assoc-const-eq-missing.stderr +++ b/tests/ui/associated-consts/assoc-const-eq-missing.stderr @@ -2,25 +2,19 @@ error[E0220]: associated type `Z` not found for `Foo` --> $DIR/assoc-const-eq-missing.rs:15:16 | LL | fn foo1>() {} - | ^ - | - = help: `Foo` has no associated type, try removing `Z` + | ^ associated type `Z` not found error[E0220]: associated type `Z` not found for `Foo` --> $DIR/assoc-const-eq-missing.rs:17:16 | LL | fn foo2>() {} - | ^ - | - = help: `Foo` has no associated type, try removing `Z` + | ^ associated type `Z` not found error[E0220]: associated type `Z` not found for `Foo` --> $DIR/assoc-const-eq-missing.rs:19:16 | LL | fn foo3>() {} - | ^ - | - = help: `Foo` has no associated type, try removing `Z` + | ^ associated type `Z` not found error: aborting due to 3 previous errors diff --git a/tests/ui/associated-type-bounds/missing-trait-bound-for-assoc-fails.stderr b/tests/ui/associated-type-bounds/missing-trait-bound-for-assoc-fails.stderr index a964c9df2c5..bc2807b0396 100644 --- a/tests/ui/associated-type-bounds/missing-trait-bound-for-assoc-fails.stderr +++ b/tests/ui/associated-type-bounds/missing-trait-bound-for-assoc-fails.stderr @@ -8,9 +8,7 @@ error[E0220]: associated type `Item` not found for `M` --> $DIR/missing-trait-bound-for-assoc-fails.rs:4:8 | LL | M::Item: Temp, - | ^^^^ - | - = help: `M` has no associated type, try removing `Item` + | ^^^^ associated type `Item` not found error: aborting due to 2 previous errors diff --git a/tests/ui/associated-types/associated-types-path-1.stderr b/tests/ui/associated-types/associated-types-path-1.stderr index 195740359a3..a67f77e37c7 100644 --- a/tests/ui/associated-types/associated-types-path-1.stderr +++ b/tests/ui/associated-types/associated-types-path-1.stderr @@ -2,9 +2,7 @@ error[E0220]: associated type `A` not found for `T` --> $DIR/associated-types-path-1.rs:10:26 | LL | pub fn f1(a: T, x: T::A) {} - | ^ - | - = help: `T` has no associated type, try removing `A` + | ^ associated type `A` not found error[E0221]: ambiguous associated type `A` in bounds of `T` --> $DIR/associated-types-path-1.rs:11:34 diff --git a/tests/ui/feature-gates/feature-gate-return_type_notation.cfg.stderr b/tests/ui/feature-gates/feature-gate-return_type_notation.cfg.stderr index 012913fd0e0..1bdb2574ead 100644 --- a/tests/ui/feature-gates/feature-gate-return_type_notation.cfg.stderr +++ b/tests/ui/feature-gates/feature-gate-return_type_notation.cfg.stderr @@ -19,9 +19,7 @@ error[E0220]: associated type `m` not found for `Trait` --> $DIR/feature-gate-return_type_notation.rs:14:17 | LL | fn foo>() {} - | ^ - | - = help: `Trait` has no associated type, try removing `m` + | ^ associated type `m` not found error: aborting due to 3 previous errors diff --git a/tests/ui/feature-gates/feature-gate-return_type_notation.cfg_current.stderr b/tests/ui/feature-gates/feature-gate-return_type_notation.cfg_current.stderr index 68cf8e36fcc..ce39f6b2971 100644 --- a/tests/ui/feature-gates/feature-gate-return_type_notation.cfg_current.stderr +++ b/tests/ui/feature-gates/feature-gate-return_type_notation.cfg_current.stderr @@ -19,9 +19,7 @@ error[E0220]: associated type `m` not found for `Trait` --> $DIR/feature-gate-return_type_notation.rs:17:17 | LL | fn foo>() {} - | ^ - | - = help: `Trait` has no associated type, try removing `m` + | ^ associated type `m` not found error: aborting due to 3 previous errors diff --git a/tests/ui/feature-gates/feature-gate-return_type_notation.cfg_next.stderr b/tests/ui/feature-gates/feature-gate-return_type_notation.cfg_next.stderr index 68cf8e36fcc..ce39f6b2971 100644 --- a/tests/ui/feature-gates/feature-gate-return_type_notation.cfg_next.stderr +++ b/tests/ui/feature-gates/feature-gate-return_type_notation.cfg_next.stderr @@ -19,9 +19,7 @@ error[E0220]: associated type `m` not found for `Trait` --> $DIR/feature-gate-return_type_notation.rs:17:17 | LL | fn foo>() {} - | ^ - | - = help: `Trait` has no associated type, try removing `m` + | ^ associated type `m` not found error: aborting due to 3 previous errors From 7f45d16cb2c74f15bff26b42ed4994159ae1de4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Fri, 8 Sep 2023 00:00:00 +0000 Subject: [PATCH 06/12] Fix sanitize/cfg.rs test * Move needs-sanitizer conditions to specific revisions that require them (otherwise the conditions are mutually exclusive with needs-sanitizer-kcfi and test is always ignored). * Add missing revisions --- tests/ui/sanitize/cfg.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/ui/sanitize/cfg.rs b/tests/ui/sanitize/cfg.rs index c0f08a6d1e5..523de1ceaee 100644 --- a/tests/ui/sanitize/cfg.rs +++ b/tests/ui/sanitize/cfg.rs @@ -2,19 +2,19 @@ // the `#[cfg(sanitize = "option")]` attribute is configured. // needs-sanitizer-support -// needs-sanitizer-address -// needs-sanitizer-cfi -// needs-sanitizer-kcfi -// needs-sanitizer-leak -// needs-sanitizer-memory -// needs-sanitizer-thread // check-pass -// revisions: address leak memory thread +// revisions: address cfi kcfi leak memory thread +//[address]needs-sanitizer-address //[address]compile-flags: -Zsanitizer=address --cfg address -//[cfi]compile-flags: -Zsanitizer=cfi --cfg cfi +//[cfi]needs-sanitizer-cfi +//[cfi]compile-flags: -Zsanitizer=cfi --cfg cfi -Clto +//[kcfi]needs-sanitizer-kcfi //[kcfi]compile-flags: -Zsanitizer=kcfi --cfg kcfi +//[leak]needs-sanitizer-leak //[leak]compile-flags: -Zsanitizer=leak --cfg leak +//[memory]needs-sanitizer-memory //[memory]compile-flags: -Zsanitizer=memory --cfg memory +//[thread]needs-sanitizer-thread //[thread]compile-flags: -Zsanitizer=thread --cfg thread #![feature(cfg_sanitize)] From 942bdf910cc85e6389546e25cfb391062095cbd8 Mon Sep 17 00:00:00 2001 From: Augie Fackler Date: Thu, 7 Sep 2023 09:48:50 -0400 Subject: [PATCH 07/12] lto: load bitcode sections by name Upstream change llvm/llvm-project@6b539f5eb8ef1d3a3c87873caa2dbd5147e1adbd changed `isSectionBitcode` works and it now only respects `.llvm.lto` sections instead of also `.llvmbc`, which it says was never intended to be used for LTO. We instead load sections by name, and sniff for raw bitcode by hand. r? @nikic @rustbot label: +llvm-main --- compiler/rustc_codegen_llvm/src/back/lto.rs | 27 +++++++++++--- compiler/rustc_codegen_llvm/src/back/write.rs | 36 ++++++++++++------- compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 6 ++++ .../rustc_llvm/llvm-wrapper/PassWrapper.cpp | 33 +++++++++++++++++ 4 files changed, 86 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs index c1d3392386c..3964039ac2d 100644 --- a/compiler/rustc_codegen_llvm/src/back/lto.rs +++ b/compiler/rustc_codegen_llvm/src/back/lto.rs @@ -1,4 +1,6 @@ -use crate::back::write::{self, save_temp_bitcode, CodegenDiagnosticsStage, DiagnosticHandlers}; +use crate::back::write::{ + self, bitcode_section_name, save_temp_bitcode, CodegenDiagnosticsStage, DiagnosticHandlers, +}; use crate::errors::{ DynamicLinkingWithLTO, LlvmError, LtoBitcodeFromRlib, LtoDisallowed, LtoDylib, }; @@ -120,6 +122,7 @@ fn prepare_lto( info!("adding bitcode from {}", name); match get_bitcode_slice_from_object_data( child.data(&*archive_data).expect("corrupt rlib"), + cgcx, ) { Ok(data) => { let module = SerializedModule::FromRlib(data.to_vec()); @@ -141,10 +144,26 @@ fn prepare_lto( Ok((symbols_below_threshold, upstream_modules)) } -fn get_bitcode_slice_from_object_data(obj: &[u8]) -> Result<&[u8], LtoBitcodeFromRlib> { +fn get_bitcode_slice_from_object_data<'a>( + obj: &'a [u8], + cgcx: &CodegenContext, +) -> Result<&'a [u8], LtoBitcodeFromRlib> { + // We're about to assume the data here is an object file with sections, but if it's raw LLVM IR that + // won't work. Fortunately, if that's what we have we can just return the object directly, so we sniff + // the relevant magic strings here and return. + if obj.starts_with(b"\xDE\xC0\x17\x0B") || obj.starts_with(b"BC\xC0\xDE") { + return Ok(obj); + } + let section_name = bitcode_section_name(cgcx); let mut len = 0; - let data = - unsafe { llvm::LLVMRustGetBitcodeSliceFromObjectData(obj.as_ptr(), obj.len(), &mut len) }; + let data = unsafe { + llvm::LLVMRustGetSliceFromObjectDataByName( + obj.as_ptr(), + obj.len(), + section_name.as_ptr(), + &mut len, + ) + }; if !data.is_null() { assert!(len != 0); let bc = unsafe { slice::from_raw_parts(data, len) }; diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index c49d322fc00..de6541635cf 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -873,6 +873,27 @@ fn create_section_with_flags_asm(section_name: &str, section_flags: &str, data: asm } +fn target_is_apple(cgcx: &CodegenContext) -> bool { + cgcx.opts.target_triple.triple().contains("-ios") + || cgcx.opts.target_triple.triple().contains("-darwin") + || cgcx.opts.target_triple.triple().contains("-tvos") + || cgcx.opts.target_triple.triple().contains("-watchos") +} + +fn target_is_aix(cgcx: &CodegenContext) -> bool { + cgcx.opts.target_triple.triple().contains("-aix") +} + +pub(crate) fn bitcode_section_name(cgcx: &CodegenContext) -> &'static str { + if target_is_apple(cgcx) { + "__LLVM,__bitcode\0" + } else if target_is_aix(cgcx) { + ".ipa\0" + } else { + ".llvmbc\0" + } +} + /// Embed the bitcode of an LLVM module in the LLVM module itself. /// /// This is done primarily for iOS where it appears to be standard to compile C @@ -933,11 +954,8 @@ unsafe fn embed_bitcode( // Unfortunately, LLVM provides no way to set custom section flags. For ELF // and COFF we emit the sections using module level inline assembly for that // reason (see issue #90326 for historical background). - let is_aix = cgcx.opts.target_triple.triple().contains("-aix"); - let is_apple = cgcx.opts.target_triple.triple().contains("-ios") - || cgcx.opts.target_triple.triple().contains("-darwin") - || cgcx.opts.target_triple.triple().contains("-tvos") - || cgcx.opts.target_triple.triple().contains("-watchos"); + let is_aix = target_is_aix(cgcx); + let is_apple = target_is_apple(cgcx); if is_apple || is_aix || cgcx.opts.target_triple.triple().starts_with("wasm") @@ -952,13 +970,7 @@ unsafe fn embed_bitcode( ); llvm::LLVMSetInitializer(llglobal, llconst); - let section = if is_apple { - "__LLVM,__bitcode\0" - } else if is_aix { - ".ipa\0" - } else { - ".llvmbc\0" - }; + let section = bitcode_section_name(cgcx); llvm::LLVMSetSection(llglobal, section.as_ptr().cast()); llvm::LLVMRustSetLinkage(llglobal, llvm::Linkage::PrivateLinkage); llvm::LLVMSetGlobalConstant(llglobal, llvm::True); diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 1f03c932cfd..8e96410deaf 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -2322,6 +2322,12 @@ extern "C" { len: usize, out_len: &mut usize, ) -> *const u8; + pub fn LLVMRustGetSliceFromObjectDataByName( + data: *const u8, + len: usize, + name: *const u8, + out_len: &mut usize, + ) -> *const u8; pub fn LLVMRustLinkerNew(M: &Module) -> &mut Linker<'_>; pub fn LLVMRustLinkerAdd( diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index 4ed086ff42f..204f833de92 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -1,5 +1,6 @@ #include +#include #include #include #include @@ -1555,6 +1556,38 @@ LLVMRustGetBitcodeSliceFromObjectData(const char *data, return BitcodeOrError->getBufferStart(); } +// Find a section of an object file by name. Fail if the section is missing or +// empty. +extern "C" const char *LLVMRustGetSliceFromObjectDataByName(const char *data, + size_t len, + const char *name, + size_t *out_len) { + *out_len = 0; + StringRef Data(data, len); + MemoryBufferRef Buffer(Data, ""); // The id is unused. + file_magic Type = identify_magic(Buffer.getBuffer()); + Expected> ObjFileOrError = + object::ObjectFile::createObjectFile(Buffer, Type); + if (!ObjFileOrError) { + LLVMRustSetLastError(toString(ObjFileOrError.takeError()).c_str()); + return nullptr; + } + for (const object::SectionRef &Sec : (*ObjFileOrError)->sections()) { + Expected Name = Sec.getName(); + if (Name && *Name == name) { + Expected SectionOrError = Sec.getContents(); + if (!SectionOrError) { + LLVMRustSetLastError(toString(SectionOrError.takeError()).c_str()); + return nullptr; + } + *out_len = SectionOrError->size(); + return SectionOrError->data(); + } + } + LLVMRustSetLastError("could not find requested section"); + return nullptr; +} + // Computes the LTO cache key for the provided 'ModId' in the given 'Data', // storing the result in 'KeyOut'. // Currently, this cache key is a SHA-1 hash of anything that could affect From 9ad0396a34bdfa11fe0e4f8636f82da165ffad01 Mon Sep 17 00:00:00 2001 From: Augie Fackler Date: Thu, 7 Sep 2023 11:56:25 -0400 Subject: [PATCH 08/12] lto: handle Apple platforms correctly by eliding __LLVM, from section name --- compiler/rustc_codegen_llvm/src/back/lto.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs index 3964039ac2d..5cf83b1accb 100644 --- a/compiler/rustc_codegen_llvm/src/back/lto.rs +++ b/compiler/rustc_codegen_llvm/src/back/lto.rs @@ -154,7 +154,10 @@ fn get_bitcode_slice_from_object_data<'a>( if obj.starts_with(b"\xDE\xC0\x17\x0B") || obj.starts_with(b"BC\xC0\xDE") { return Ok(obj); } - let section_name = bitcode_section_name(cgcx); + // We drop the "__LLVM," prefix here because on Apple platforms there's a notion of "segment name" + // which in the public API for sections gets treated as part of the section name, but internally + // in MachOObjectFile.cpp gets treated separately. + let section_name = bitcode_section_name(cgcx).trim_start_matches("__LLVM,"); let mut len = 0; let data = unsafe { llvm::LLVMRustGetSliceFromObjectDataByName( From af9e55068c2e38b1f7afc7f7374a5a53c59b2001 Mon Sep 17 00:00:00 2001 From: Augie Fackler Date: Wed, 12 Jul 2023 17:07:34 -0400 Subject: [PATCH 09/12] debuginfo: add compiler option to allow compressed debuginfo sections LLVM already supports emitting compressed debuginfo. In debuginfo=full builds, the debug section is often a large amount of data, and it typically compresses very well (3x is not unreasonable.) We add a new knob to allow debuginfo to be compressed when the matching LLVM functionality is present. Like clang, if a known-but-disabled compression mechanism is requested, we disable compression and emit uncompressed debuginfo sections. The API is different enough on older LLVMs we just pretend the support is missing on LLVM older than 16. --- compiler/rustc_codegen_llvm/messages.ftl | 2 + compiler/rustc_codegen_llvm/src/back/write.rs | 23 ++++++++++- compiler/rustc_codegen_llvm/src/errors.rs | 6 +++ compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 5 +++ .../rustc_llvm/llvm-wrapper/PassWrapper.cpp | 11 +++++ .../rustc_llvm/llvm-wrapper/RustWrapper.cpp | 16 ++++++++ compiler/rustc_session/src/config.rs | 40 ++++++++++++++++--- compiler/rustc_session/src/options.rs | 19 ++++++++- tests/run-make/compressed-debuginfo/Makefile | 17 ++++++++ tests/run-make/compressed-debuginfo/foo.rs | 3 ++ 10 files changed, 135 insertions(+), 7 deletions(-) create mode 100644 tests/run-make/compressed-debuginfo/Makefile create mode 100644 tests/run-make/compressed-debuginfo/foo.rs diff --git a/compiler/rustc_codegen_llvm/messages.ftl b/compiler/rustc_codegen_llvm/messages.ftl index aed4a8f3c85..ddaff36f24b 100644 --- a/compiler/rustc_codegen_llvm/messages.ftl +++ b/compiler/rustc_codegen_llvm/messages.ftl @@ -83,6 +83,8 @@ codegen_llvm_unknown_ctarget_feature_prefix = unknown feature specified for `-Ctarget-feature`: `{$feature}` .note = features must begin with a `+` to enable or `-` to disable it +codegen_llvm_unknown_debuginfo_compression = unknown debuginfo compression algorithm {$algorithm} - will fall back to uncompressed debuginfo + codegen_llvm_write_bytecode = failed to write bytecode to {$path}: {$err} codegen_llvm_write_ir = failed to write LLVM IR to {$path} diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index de6541635cf..1f394a7335c 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -5,13 +5,17 @@ use crate::back::profiling::{ use crate::base; use crate::common; use crate::errors::{ - CopyBitcode, FromLlvmDiag, FromLlvmOptimizationDiag, LlvmError, WithLlvmError, WriteBytecode, + CopyBitcode, FromLlvmDiag, FromLlvmOptimizationDiag, LlvmError, UnknownCompression, + WithLlvmError, WriteBytecode, }; use crate::llvm::{self, DiagnosticInfo, PassManager}; use crate::llvm_util; use crate::type_::Type; use crate::LlvmCodegenBackend; use crate::ModuleLlvm; +use llvm::{ + LLVMRustLLVMHasZlibCompressionForDebugSymbols, LLVMRustLLVMHasZstdCompressionForDebugSymbols, +}; use rustc_codegen_ssa::back::link::ensure_removed; use rustc_codegen_ssa::back::write::{ BitcodeSection, CodegenContext, EmitObj, ModuleConfig, TargetMachineFactoryConfig, @@ -234,6 +238,22 @@ pub fn target_machine_factory( args_cstr_buff }; + let debuginfo_compression = sess.opts.debuginfo_compression.to_string(); + match sess.opts.debuginfo_compression { + rustc_session::config::DebugInfoCompression::Zlib => { + if !unsafe { LLVMRustLLVMHasZlibCompressionForDebugSymbols() } { + sess.emit_warning(UnknownCompression { algorithm: "zlib" }); + } + } + rustc_session::config::DebugInfoCompression::Zstd => { + if !unsafe { LLVMRustLLVMHasZstdCompressionForDebugSymbols() } { + sess.emit_warning(UnknownCompression { algorithm: "zstd" }); + } + } + rustc_session::config::DebugInfoCompression::None => {} + }; + let debuginfo_compression = SmallCStr::new(&debuginfo_compression); + Arc::new(move |config: TargetMachineFactoryConfig| { let split_dwarf_file = path_mapping.map_prefix(config.split_dwarf_file.unwrap_or_default()).0; @@ -259,6 +279,7 @@ pub fn target_machine_factory( relax_elf_relocations, use_init_array, split_dwarf_file.as_ptr(), + debuginfo_compression.as_ptr(), force_emulated_tls, args_cstr_buff.as_ptr() as *const c_char, args_cstr_buff.len(), diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs index fced6d504d2..264c273ba30 100644 --- a/compiler/rustc_codegen_llvm/src/errors.rs +++ b/compiler/rustc_codegen_llvm/src/errors.rs @@ -226,3 +226,9 @@ pub(crate) struct WriteBytecode<'a> { pub(crate) struct CopyBitcode { pub err: std::io::Error, } + +#[derive(Diagnostic)] +#[diag(codegen_llvm_unknown_debuginfo_compression)] +pub struct UnknownCompression { + pub algorithm: &'static str, +} diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 8e96410deaf..2ebfdae39e8 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -2131,6 +2131,7 @@ extern "C" { RelaxELFRelocations: bool, UseInitArray: bool, SplitDwarfFile: *const c_char, + DebugInfoCompression: *const c_char, ForceEmulatedTls: bool, ArgsCstrBuff: *const c_char, ArgsCstrBuffLen: usize, @@ -2366,6 +2367,10 @@ extern "C" { pub fn LLVMRustIsBitcode(ptr: *const u8, len: usize) -> bool; + pub fn LLVMRustLLVMHasZlibCompressionForDebugSymbols() -> bool; + + pub fn LLVMRustLLVMHasZstdCompressionForDebugSymbols() -> bool; + pub fn LLVMRustGetSymbols( buf_ptr: *const u8, buf_len: usize, diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index 204f833de92..87ef74b9264 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -407,6 +407,7 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine( bool RelaxELFRelocations, bool UseInitArray, const char *SplitDwarfFile, + const char *DebugInfoCompression, bool ForceEmulatedTls, const char *ArgsCstrBuff, size_t ArgsCstrBuffLen) { @@ -438,6 +439,16 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine( if (SplitDwarfFile) { Options.MCOptions.SplitDwarfFile = SplitDwarfFile; } +#if LLVM_VERSION_GE(16, 0) + if (!strcmp("zlib", DebugInfoCompression) && llvm::compression::zlib::isAvailable()) { + Options.CompressDebugSections = DebugCompressionType::Zlib; + } else if (!strcmp("zstd", DebugInfoCompression) && llvm::compression::zstd::isAvailable()) { + Options.CompressDebugSections = DebugCompressionType::Zstd; + } else if (!strcmp("none", DebugInfoCompression)) { + Options.CompressDebugSections = DebugCompressionType::None; + } +#endif + Options.RelaxELFRelocations = RelaxELFRelocations; Options.UseInitArray = UseInitArray; diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index 70cdf3d6d23..4390486b0de 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -2044,3 +2044,19 @@ extern "C" bool LLVMRustIsNonGVFunctionPointerTy(LLVMValueRef V) { } return false; } + +extern "C" bool LLVMRustLLVMHasZlibCompressionForDebugSymbols() { +#if LLVM_VERSION_GE(16, 0) + return llvm::compression::zlib::isAvailable(); +#else + return false; +#endif +} + +extern "C" bool LLVMRustLLVMHasZstdCompressionForDebugSymbols() { +#if LLVM_VERSION_GE(16, 0) + return llvm::compression::zstd::isAvailable(); +#else + return false; +#endif +} diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 302e4e55d59..86a03124fe1 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -381,6 +381,24 @@ pub enum DebugInfo { Full, } +#[derive(Clone, Copy, Debug, PartialEq, Hash)] +pub enum DebugInfoCompression { + None, + Zlib, + Zstd, +} + +impl ToString for DebugInfoCompression { + fn to_string(&self) -> String { + match self { + DebugInfoCompression::None => "none", + DebugInfoCompression::Zlib => "zlib", + DebugInfoCompression::Zstd => "zstd", + } + .to_owned() + } +} + /// Split debug-information is enabled by `-C split-debuginfo`, this enum is only used if split /// debug-information is enabled (in either `Packed` or `Unpacked` modes), and the platform /// uses DWARF for debug-information. @@ -1015,6 +1033,7 @@ impl Default for Options { crate_types: Vec::new(), optimize: OptLevel::No, debuginfo: DebugInfo::None, + debuginfo_compression: DebugInfoCompression::None, lint_opts: Vec::new(), lint_cap: None, describe_lints: false, @@ -2277,6 +2296,13 @@ fn select_debuginfo(matches: &getopts::Matches, cg: &CodegenOptions) -> DebugInf if max_g > max_c { DebugInfo::Full } else { cg.debuginfo } } +fn select_debuginfo_compression( + _handler: &EarlyErrorHandler, + unstable_opts: &UnstableOptions, +) -> DebugInfoCompression { + unstable_opts.debuginfo_compression +} + pub(crate) fn parse_assert_incr_state( handler: &EarlyErrorHandler, opt_assertion: &Option, @@ -2752,6 +2778,8 @@ pub fn build_session_options( // for more details. let debug_assertions = cg.debug_assertions.unwrap_or(opt_level == OptLevel::No); let debuginfo = select_debuginfo(matches, &cg); + let debuginfo_compression: DebugInfoCompression = + select_debuginfo_compression(handler, &unstable_opts); let mut search_paths = vec![]; for s in &matches.opt_strs("L") { @@ -2828,6 +2856,7 @@ pub fn build_session_options( crate_types, optimize: opt_level, debuginfo, + debuginfo_compression, lint_opts, lint_cap, describe_lints, @@ -3113,11 +3142,11 @@ impl PpMode { /// how the hash should be calculated when adding a new command-line argument. pub(crate) mod dep_tracking { use super::{ - BranchProtection, CFGuard, CFProtection, CrateType, DebugInfo, ErrorOutputType, - InstrumentCoverage, InstrumentXRay, LdImpl, LinkerPluginLto, LocationDetail, LtoCli, - OomStrategy, OptLevel, OutFileName, OutputType, OutputTypes, Passes, ResolveDocLinks, - SourceFileHashAlgorithm, SplitDwarfKind, SwitchWithOptPath, SymbolManglingVersion, - TraitSolver, TrimmedDefPaths, + BranchProtection, CFGuard, CFProtection, CrateType, DebugInfo, DebugInfoCompression, + ErrorOutputType, InstrumentCoverage, InstrumentXRay, LdImpl, LinkerPluginLto, + LocationDetail, LtoCli, OomStrategy, OptLevel, OutFileName, OutputType, OutputTypes, + Passes, ResolveDocLinks, SourceFileHashAlgorithm, SplitDwarfKind, SwitchWithOptPath, + SymbolManglingVersion, TraitSolver, TrimmedDefPaths, }; use crate::lint; use crate::options::WasiExecModel; @@ -3195,6 +3224,7 @@ pub(crate) mod dep_tracking { OptLevel, LtoCli, DebugInfo, + DebugInfoCompression, UnstableFeatures, NativeLib, NativeLibKind, diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 40099de707b..5ddefb2260e 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -139,6 +139,7 @@ top_level_options!( /// can influence whether overflow checks are done or not. debug_assertions: bool [TRACKED], debuginfo: DebugInfo [TRACKED], + debuginfo_compression: DebugInfoCompression [TRACKED], lint_opts: Vec<(String, lint::Level)> [TRACKED_NO_CRATE_HASH], lint_cap: Option [TRACKED_NO_CRATE_HASH], describe_lints: bool [UNTRACKED], @@ -376,6 +377,7 @@ mod desc { "either a boolean (`yes`, `no`, `on`, `off`, etc), `checks`, or `nochecks`"; pub const parse_cfprotection: &str = "`none`|`no`|`n` (default), `branch`, `return`, or `full`|`yes`|`y` (equivalent to `branch` and `return`)"; pub const parse_debuginfo: &str = "either an integer (0, 1, 2), `none`, `line-directives-only`, `line-tables-only`, `limited`, or `full`"; + pub const parse_debuginfo_compression: &str = "one of `none`, `zlib`, or `zstd`"; pub const parse_strip: &str = "either `none`, `debuginfo`, or `symbols`"; pub const parse_linker_flavor: &str = ::rustc_target::spec::LinkerFlavorCli::one_of(); pub const parse_optimization_fuel: &str = "crate=integer"; @@ -782,6 +784,19 @@ mod parse { true } + pub(crate) fn parse_debuginfo_compression( + slot: &mut DebugInfoCompression, + v: Option<&str>, + ) -> bool { + match v { + Some("none") => *slot = DebugInfoCompression::None, + Some("zlib") => *slot = DebugInfoCompression::Zlib, + Some("zstd") => *slot = DebugInfoCompression::Zstd, + _ => return false, + }; + true + } + pub(crate) fn parse_linker_flavor(slot: &mut Option, v: Option<&str>) -> bool { match v.and_then(LinkerFlavorCli::from_str) { Some(lf) => *slot = Some(lf), @@ -1422,7 +1437,9 @@ options! { "inject the given attribute in the crate"), debug_info_for_profiling: bool = (false, parse_bool, [TRACKED], "emit discriminators and other data necessary for AutoFDO"), - debug_macros: bool = (false, parse_bool, [TRACKED], + debuginfo_compression: DebugInfoCompression = (DebugInfoCompression::None, parse_debuginfo_compression, [TRACKED], + "compress debug info sections (none, zlib, zstd, default: none)"), + debug_macros: bool = (false, parse_bool, [TRACKED], "emit line numbers debug info inside macros (default: no)"), deduplicate_diagnostics: bool = (true, parse_bool, [UNTRACKED], "deduplicate identical diagnostics (default: yes)"), diff --git a/tests/run-make/compressed-debuginfo/Makefile b/tests/run-make/compressed-debuginfo/Makefile new file mode 100644 index 00000000000..3c50d4df17a --- /dev/null +++ b/tests/run-make/compressed-debuginfo/Makefile @@ -0,0 +1,17 @@ +# ignore-cross-compile +include ../tools.mk + +# only-linux +# min-llvm-version: 16.0 +# +# This tests debuginfo-compression. + +all: zlib zstandard + +zlib: + $(RUSTC) --crate-name=foo --crate-type=lib --emit=obj -C debuginfo=full -Z debuginfo-compression=zlib foo.rs + test "`ld.lld --compress-debug-sections=zlib 2>&1 | sed 's/.*unknown.*zlib/missing/'`" = missing || readelf -t $(TMPDIR)/foo.o | grep -q ZLIB + +zstandard: + $(RUSTC) --crate-name=foo --crate-type=lib --emit=obj -C debuginfo=full -Z debuginfo-compression=zstd foo.rs + test "`ld.lld --compress-debug-sections=zstd 2>&1 | sed 's/.*unknown.*zstd/missing/'`" = missing || readelf -t $(TMPDIR)/foo.o | grep -q ZST diff --git a/tests/run-make/compressed-debuginfo/foo.rs b/tests/run-make/compressed-debuginfo/foo.rs new file mode 100644 index 00000000000..185ce22450c --- /dev/null +++ b/tests/run-make/compressed-debuginfo/foo.rs @@ -0,0 +1,3 @@ +pub fn foo() -> i32 { + 42 +} From ed17b568e3fc2e0fe6a263b12d5a40ca2bfb1482 Mon Sep 17 00:00:00 2001 From: Augie Fackler Date: Tue, 5 Sep 2023 09:41:37 -0400 Subject: [PATCH 10/12] options: fix indentation rustfmt didn't save me here, sigh --- compiler/rustc_session/src/options.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 5ddefb2260e..9eab00e362f 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1437,9 +1437,9 @@ options! { "inject the given attribute in the crate"), debug_info_for_profiling: bool = (false, parse_bool, [TRACKED], "emit discriminators and other data necessary for AutoFDO"), - debuginfo_compression: DebugInfoCompression = (DebugInfoCompression::None, parse_debuginfo_compression, [TRACKED], - "compress debug info sections (none, zlib, zstd, default: none)"), - debug_macros: bool = (false, parse_bool, [TRACKED], + debuginfo_compression: DebugInfoCompression = (DebugInfoCompression::None, parse_debuginfo_compression, [TRACKED], + "compress debug info sections (none, zlib, zstd, default: none)"), + debug_macros: bool = (false, parse_bool, [TRACKED], "emit line numbers debug info inside macros (default: no)"), deduplicate_diagnostics: bool = (true, parse_bool, [UNTRACKED], "deduplicate identical diagnostics (default: yes)"), From a52990b8d5094588905c1b1d7a586174377fe330 Mon Sep 17 00:00:00 2001 From: Augie Fackler Date: Tue, 5 Sep 2023 09:56:51 -0400 Subject: [PATCH 11/12] sort --- compiler/rustc_session/src/options.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 9eab00e362f..6c26859228c 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1437,10 +1437,10 @@ options! { "inject the given attribute in the crate"), debug_info_for_profiling: bool = (false, parse_bool, [TRACKED], "emit discriminators and other data necessary for AutoFDO"), - debuginfo_compression: DebugInfoCompression = (DebugInfoCompression::None, parse_debuginfo_compression, [TRACKED], - "compress debug info sections (none, zlib, zstd, default: none)"), debug_macros: bool = (false, parse_bool, [TRACKED], "emit line numbers debug info inside macros (default: no)"), + debuginfo_compression: DebugInfoCompression = (DebugInfoCompression::None, parse_debuginfo_compression, [TRACKED], + "compress debug info sections (none, zlib, zstd, default: none)"), deduplicate_diagnostics: bool = (true, parse_bool, [UNTRACKED], "deduplicate identical diagnostics (default: yes)"), dep_info_omit_d_target: bool = (false, parse_bool, [TRACKED], From 78d805cd87f8d7500db841daa6fe24f77faff3ce Mon Sep 17 00:00:00 2001 From: Augie Fackler Date: Fri, 8 Sep 2023 11:30:24 -0400 Subject: [PATCH 12/12] tests: use warning output from rustc to catch missing compression Using `ld.lld` may have been clever, but that was getting the /system/ ld.lld, not one we may have built as part of building llvm. By using the warning message coming directly from rustc we now correctly skip the zlib and zstd tests when the support is missing. --- tests/run-make/compressed-debuginfo/Makefile | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/tests/run-make/compressed-debuginfo/Makefile b/tests/run-make/compressed-debuginfo/Makefile index 3c50d4df17a..f9e4927d008 100644 --- a/tests/run-make/compressed-debuginfo/Makefile +++ b/tests/run-make/compressed-debuginfo/Makefile @@ -9,9 +9,7 @@ include ../tools.mk all: zlib zstandard zlib: - $(RUSTC) --crate-name=foo --crate-type=lib --emit=obj -C debuginfo=full -Z debuginfo-compression=zlib foo.rs - test "`ld.lld --compress-debug-sections=zlib 2>&1 | sed 's/.*unknown.*zlib/missing/'`" = missing || readelf -t $(TMPDIR)/foo.o | grep -q ZLIB + test "`$(RUSTC) --crate-name=foo --crate-type=lib --emit=obj -C debuginfo=full -Z debuginfo-compression=zlib foo.rs 2>&1 | sed 's/.*unknown.*zlib.*/missing/' | head -n 1`" = missing || readelf -t $(TMPDIR)/foo.o | grep -q ZLIB zstandard: - $(RUSTC) --crate-name=foo --crate-type=lib --emit=obj -C debuginfo=full -Z debuginfo-compression=zstd foo.rs - test "`ld.lld --compress-debug-sections=zstd 2>&1 | sed 's/.*unknown.*zstd/missing/'`" = missing || readelf -t $(TMPDIR)/foo.o | grep -q ZST + test "`$(RUSTC) --crate-name=foo --crate-type=lib --emit=obj -C debuginfo=full -Z debuginfo-compression=zstd foo.rs 2>&1 | sed 's/.*unknown.*zstd.*/missing/' | head -n 1`" = missing || readelf -t $(TMPDIR)/foo.o | grep -q ZST