From ca9988ec49debec4cd567d0aa719e2ee108c038b Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 25 Mar 2025 20:17:29 +1100 Subject: [PATCH 01/15] Remove `kw::Empty` uses from `rustc_middle`. There are several places in `rustc_middle` that check for an empty lifetime name. These checks appear to be totally unnecessary, because empty lifetime names aren't produced here. (Empty lifetime names *are* possible in `hir::Lifetime`. Perhaps there was some confusion between it and the `rustc_middle` types?) This commit removes the `kw::Empty` checks. --- compiler/rustc_middle/src/ty/generics.rs | 4 +--- compiler/rustc_middle/src/ty/mod.rs | 2 +- compiler/rustc_middle/src/ty/print/pretty.rs | 10 ++++------ compiler/rustc_middle/src/ty/region.rs | 6 ++---- 4 files changed, 8 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs index 85d9db7ee7473..d4cc562e70cc7 100644 --- a/compiler/rustc_middle/src/ty/generics.rs +++ b/compiler/rustc_middle/src/ty/generics.rs @@ -73,9 +73,7 @@ impl GenericParamDef { pub fn is_anonymous_lifetime(&self) -> bool { match self.kind { - GenericParamDefKind::Lifetime => { - self.name == kw::UnderscoreLifetime || self.name == kw::Empty - } + GenericParamDefKind::Lifetime => self.name == kw::UnderscoreLifetime, _ => false, } } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 6bdd0a0647d30..ac98cbc8d6cba 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -457,7 +457,7 @@ impl EarlyParamRegion { /// Does this early bound region have a name? Early bound regions normally /// always have names except when using anonymous lifetimes (`'_`). pub fn has_name(&self) -> bool { - self.name != kw::UnderscoreLifetime && self.name != kw::Empty + self.name != kw::UnderscoreLifetime } } diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 3ef8ecc59e402..3281cb4135a0a 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -2591,11 +2591,9 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { // to fit that into a short string. Hence the recommendation to use // `explain_region()` or `note_and_explain_region()`. match *region { - ty::ReEarlyParam(ref data) => { - if data.name != kw::Empty { - p!(write("{}", data.name)); - return Ok(()); - } + ty::ReEarlyParam(data) => { + p!(write("{}", data.name)); + return Ok(()); } ty::ReLateParam(ty::LateParamRegion { kind, .. }) => { if let Some(name) = kind.get_name() { @@ -2834,7 +2832,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { (name, ty::BoundRegionKind::Named(CRATE_DEF_ID.to_def_id(), name)) } - ty::BoundRegionKind::Named(def_id, kw::UnderscoreLifetime | kw::Empty) => { + ty::BoundRegionKind::Named(def_id, kw::UnderscoreLifetime) => { let name = next_name(self); if let Some(lt_idx) = lifetime_idx { diff --git a/compiler/rustc_middle/src/ty/region.rs b/compiler/rustc_middle/src/ty/region.rs index fb52cf96b0297..c78306f2ca379 100644 --- a/compiler/rustc_middle/src/ty/region.rs +++ b/compiler/rustc_middle/src/ty/region.rs @@ -400,9 +400,7 @@ impl LateParamRegionKind { pub fn is_named(&self) -> bool { match *self { - LateParamRegionKind::Named(_, name) => { - name != kw::UnderscoreLifetime && name != kw::Empty - } + LateParamRegionKind::Named(_, name) => name != kw::UnderscoreLifetime, _ => false, } } @@ -475,7 +473,7 @@ impl core::fmt::Debug for BoundRegion { impl BoundRegionKind { pub fn is_named(&self) -> bool { match *self { - BoundRegionKind::Named(_, name) => name != kw::UnderscoreLifetime && name != kw::Empty, + BoundRegionKind::Named(_, name) => name != kw::UnderscoreLifetime, _ => false, } } From 92d802eda669d69481b99139523008df1c456ba8 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 22 Mar 2025 21:42:34 +0300 Subject: [PATCH 02/15] expand: Leave traces when expanding `cfg` attributes --- .../rustc_ast_passes/src/ast_validation.rs | 3 +- compiler/rustc_ast_pretty/src/pprust/state.rs | 2 +- compiler/rustc_expand/src/config.rs | 24 ++++++----- compiler/rustc_expand/src/expand.rs | 13 +++--- compiler/rustc_feature/src/builtin_attrs.rs | 12 ++++-- compiler/rustc_parse/src/validate_attr.rs | 9 ++--- compiler/rustc_passes/src/check_attr.rs | 6 +-- compiler/rustc_query_system/src/ich/mod.rs | 2 +- compiler/rustc_span/src/symbol.rs | 1 + src/librustdoc/clean/mod.rs | 2 +- src/librustdoc/clean/types.rs | 2 +- .../src/attrs/duplicated_attributes.rs | 3 +- .../clippy/clippy_lints/src/cfg_not_test.rs | 2 +- .../clippy_lints/src/methods/is_empty.rs | 2 +- src/tools/clippy/clippy_utils/src/lib.rs | 8 ++-- tests/pretty/tests-are-sorted.pp | 3 -- .../cfg-attr-syntax-validation.rs | 1 - .../cfg-attr-syntax-validation.stderr | 14 +------ .../invalid-node-range-issue-129166.rs | 3 +- .../invalid-node-range-issue-129166.stderr | 8 ---- tests/ui/parser/attribute/attr-bad-meta-4.rs | 2 - .../parser/attribute/attr-bad-meta-4.stderr | 24 +---------- tests/ui/proc-macro/cfg-attr-trace.rs | 10 ++++- tests/ui/proc-macro/cfg-attr-trace.stdout | 40 +++++++++++++------ 24 files changed, 88 insertions(+), 108 deletions(-) delete mode 100644 tests/ui/conditional-compilation/invalid-node-range-issue-129166.stderr diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index a1487ca74be87..da739b0e4532b 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -334,8 +334,7 @@ impl<'a> AstValidator<'a> { .filter(|attr| { let arr = [ sym::allow, - sym::cfg, - sym::cfg_attr, + sym::cfg_trace, sym::cfg_attr_trace, sym::deny, sym::expect, diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index cdb1817944987..3dbfc191f8f50 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -593,7 +593,7 @@ pub trait PrintState<'a>: std::ops::Deref + std::ops::Dere } fn print_attribute_inline(&mut self, attr: &ast::Attribute, is_inline: bool) -> bool { - if attr.has_name(sym::cfg_attr_trace) { + if attr.has_name(sym::cfg_trace) || attr.has_name(sym::cfg_attr_trace) { // It's not a valid identifier, so avoid printing it // to keep the printed code reasonably parse-able. return false; diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs index ada49eef7b2d9..bcc2703c39b39 100644 --- a/compiler/rustc_expand/src/config.rs +++ b/compiler/rustc_expand/src/config.rs @@ -156,6 +156,19 @@ pub fn pre_configure_attrs(sess: &Session, attrs: &[Attribute]) -> ast::AttrVec .collect() } +pub(crate) fn attr_into_trace(mut attr: Attribute, trace_name: Symbol) -> Attribute { + match &mut attr.kind { + AttrKind::Normal(normal) => { + let NormalAttr { item, tokens } = &mut **normal; + item.path.segments[0].ident.name = trace_name; + // This makes the trace attributes unobservable to token-based proc macros. + *tokens = Some(LazyAttrTokenStream::new(AttrTokenStream::default())); + } + AttrKind::DocComment(..) => unreachable!(), + } + attr +} + #[macro_export] macro_rules! configure { ($this:ident, $node:ident) => { @@ -280,16 +293,7 @@ impl<'a> StripUnconfigured<'a> { // A trace attribute left in AST in place of the original `cfg_attr` attribute. // It can later be used by lints or other diagnostics. - let mut trace_attr = cfg_attr.clone(); - match &mut trace_attr.kind { - AttrKind::Normal(normal) => { - let NormalAttr { item, tokens } = &mut **normal; - item.path.segments[0].ident.name = sym::cfg_attr_trace; - // This makes the trace attributes unobservable to token-based proc macros. - *tokens = Some(LazyAttrTokenStream::new(AttrTokenStream::default())); - } - AttrKind::DocComment(..) => unreachable!(), - } + let trace_attr = attr_into_trace(cfg_attr.clone(), sym::cfg_attr_trace); let Some((cfg_predicate, expanded_attrs)) = rustc_parse::parse_cfg_attr(cfg_attr, &self.sess.psess) diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index d0bd8a89d9bdb..22da1179feb98 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -33,7 +33,7 @@ use rustc_span::{ErrorGuaranteed, FileName, Ident, LocalExpnId, Span, sym}; use smallvec::SmallVec; use crate::base::*; -use crate::config::StripUnconfigured; +use crate::config::{StripUnconfigured, attr_into_trace}; use crate::errors::{ EmptyDelegationMac, GlobDelegationOutsideImpls, GlobDelegationTraitlessQpath, IncompleteParse, RecursionLimitReached, RemoveExprNotSupported, RemoveNodeNotSupported, UnsupportedKeyValue, @@ -2003,7 +2003,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { let attr_name = attr.ident().unwrap().name; // `#[cfg]` and `#[cfg_attr]` are special - they are // eagerly evaluated. - if attr_name != sym::cfg && attr_name != sym::cfg_attr_trace { + if attr_name != sym::cfg_trace && attr_name != sym::cfg_attr_trace { self.cx.sess.psess.buffer_lint( UNUSED_ATTRIBUTES, attr.span, @@ -2027,11 +2027,10 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { ) -> (bool, Option) { let (res, meta_item) = self.cfg().cfg_true(&attr); if res { - // FIXME: `cfg(TRUE)` attributes do not currently remove themselves during expansion, - // and some tools like rustdoc and clippy rely on that. Find a way to remove them - // while keeping the tools working. - self.cx.expanded_inert_attrs.mark(&attr); - node.visit_attrs(|attrs| attrs.insert(pos, attr)); + // A trace attribute left in AST in place of the original `cfg` attribute. + // It can later be used by lints or other diagnostics. + let trace_attr = attr_into_trace(attr, sym::cfg_trace); + node.visit_attrs(|attrs| attrs.insert(pos, trace_attr)); } (res, meta_item) diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index fd936458f1115..6fe65c88f712a 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -760,10 +760,14 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ template!(Word, List: r#""...""#), DuplicatesOk, EncodeCrossCrate::Yes, INTERNAL_UNSTABLE ), - // Trace that is left when a `cfg_attr` attribute is expanded. - // The attribute is not gated, to avoid stability errors, but it cannot be used in stable or - // unstable code directly because `sym::cfg_attr_trace` is not a valid identifier, it can only - // be generated by the compiler. + // Traces that are left when `cfg` and `cfg_attr` attributes are expanded. + // The attributes are not gated, to avoid stability errors, but they cannot be used in stable + // or unstable code directly because `sym::cfg_(attr_)trace` are not valid identifiers, they + // can only be generated by the compiler. + ungated!( + cfg_trace, Normal, template!(Word /* irrelevant */), DuplicatesOk, + EncodeCrossCrate::No + ), ungated!( cfg_attr_trace, Normal, template!(Word /* irrelevant */), DuplicatesOk, EncodeCrossCrate::No diff --git a/compiler/rustc_parse/src/validate_attr.rs b/compiler/rustc_parse/src/validate_attr.rs index 9ecde2a9eb504..6bbd650dcdfe3 100644 --- a/compiler/rustc_parse/src/validate_attr.rs +++ b/compiler/rustc_parse/src/validate_attr.rs @@ -16,7 +16,8 @@ use rustc_span::{Span, Symbol, sym}; use crate::{errors, parse_in}; pub fn check_attr(psess: &ParseSess, attr: &Attribute) { - if attr.is_doc_comment() || attr.has_name(sym::cfg_attr_trace) { + if attr.is_doc_comment() || attr.has_name(sym::cfg_trace) || attr.has_name(sym::cfg_attr_trace) + { return; } @@ -215,11 +216,7 @@ pub fn check_builtin_meta_item( template: AttributeTemplate, deny_unsafety: bool, ) { - // Some special attributes like `cfg` must be checked - // before the generic check, so we skip them here. - let should_skip = |name| name == sym::cfg; - - if !should_skip(name) && !is_attr_template_compatible(&template, &meta.kind) { + if !is_attr_template_compatible(&template, &meta.kind) { emit_malformed_attribute(psess, style, meta.span, name, template); } diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 9238c73cdb113..1e1fb42a48fe2 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -272,6 +272,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | sym::forbid | sym::cfg | sym::cfg_attr + | sym::cfg_trace | sym::cfg_attr_trace // need to be fixed | sym::cfi_encoding // FIXME(cfi_encoding) @@ -574,8 +575,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { // NOTE: when making changes to this list, check that `error_codes/E0736.md` remains accurate const ALLOW_LIST: &[rustc_span::Symbol] = &[ // conditional compilation - sym::cfg, - sym::cfg_attr, + sym::cfg_trace, sym::cfg_attr_trace, // testing (allowed here so better errors can be generated in `rustc_builtin_macros::test`) sym::test, @@ -2656,7 +2656,7 @@ impl<'tcx> Visitor<'tcx> for CheckAttrVisitor<'tcx> { // only `#[cfg]` and `#[cfg_attr]` are allowed, but it should be removed // if we allow more attributes (e.g., tool attributes and `allow/deny/warn`) // in where clauses. After that, only `self.check_attributes` should be enough. - const ATTRS_ALLOWED: &[Symbol] = &[sym::cfg, sym::cfg_attr, sym::cfg_attr_trace]; + const ATTRS_ALLOWED: &[Symbol] = &[sym::cfg_trace, sym::cfg_attr_trace]; let spans = self .tcx .hir_attrs(where_predicate.hir_id) diff --git a/compiler/rustc_query_system/src/ich/mod.rs b/compiler/rustc_query_system/src/ich/mod.rs index 852d93b711f88..25778add60a98 100644 --- a/compiler/rustc_query_system/src/ich/mod.rs +++ b/compiler/rustc_query_system/src/ich/mod.rs @@ -8,7 +8,7 @@ mod hcx; mod impls_syntax; pub const IGNORED_ATTRIBUTES: &[Symbol] = &[ - sym::cfg, + sym::cfg_trace, // FIXME should this really be ignored? sym::rustc_if_this_changed, sym::rustc_then_this_would_need, sym::rustc_dirty, diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 3e4742439655a..171f553e9c1a3 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -623,6 +623,7 @@ symbols! { cfg_target_has_atomic_equal_alignment, cfg_target_thread_local, cfg_target_vendor, + cfg_trace: "", // must not be a valid identifier cfg_ub_checks, cfg_version, cfi, diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index de6dc088176ff..6f660df4d7d45 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2773,7 +2773,7 @@ fn add_without_unwanted_attributes<'hir>( if ident == sym::doc { filter_doc_attr(&mut normal.args, is_inline); attrs.push((Cow::Owned(attr), import_parent)); - } else if is_inline || ident != sym::cfg { + } else if is_inline || ident != sym::cfg_trace { // If it's not a `cfg()` attribute, we keep it. attrs.push((Cow::Owned(attr), import_parent)); } diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 27eb56a9858b8..150b00dbb48a4 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -1059,7 +1059,7 @@ pub(crate) fn extract_cfg_from_attrs<'a, I: Iterator // `doc(cfg())` overrides `cfg()`). attrs .clone() - .filter(|attr| attr.has_name(sym::cfg)) + .filter(|attr| attr.has_name(sym::cfg_trace)) .filter_map(|attr| single(attr.meta_item_list()?)) .filter_map(|attr| Cfg::parse_without(attr.meta_item()?, hidden_cfg).ok().flatten()) .fold(Cfg::True, |cfg, new_cfg| cfg & new_cfg) diff --git a/src/tools/clippy/clippy_lints/src/attrs/duplicated_attributes.rs b/src/tools/clippy/clippy_lints/src/attrs/duplicated_attributes.rs index 5c486eb90cc2b..4c84e61b1f26c 100644 --- a/src/tools/clippy/clippy_lints/src/attrs/duplicated_attributes.rs +++ b/src/tools/clippy/clippy_lints/src/attrs/duplicated_attributes.rs @@ -37,7 +37,6 @@ fn check_duplicated_attr( let Some(ident) = attr.ident() else { return }; let name = ident.name; if name == sym::doc - || name == sym::cfg_attr || name == sym::cfg_attr_trace || name == sym::rustc_on_unimplemented || name == sym::reason { @@ -47,7 +46,7 @@ fn check_duplicated_attr( return; } if let Some(direct_parent) = parent.last() - && ["cfg", "cfg_attr"].contains(&direct_parent.as_str()) + && direct_parent == sym::cfg_trace.as_str() && [sym::all, sym::not, sym::any].contains(&name) { // FIXME: We don't correctly check `cfg`s for now, so if it's more complex than just a one diff --git a/src/tools/clippy/clippy_lints/src/cfg_not_test.rs b/src/tools/clippy/clippy_lints/src/cfg_not_test.rs index 84136a2e6c28f..7590fe96fd214 100644 --- a/src/tools/clippy/clippy_lints/src/cfg_not_test.rs +++ b/src/tools/clippy/clippy_lints/src/cfg_not_test.rs @@ -32,7 +32,7 @@ declare_lint_pass!(CfgNotTest => [CFG_NOT_TEST]); impl EarlyLintPass for CfgNotTest { fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &rustc_ast::Attribute) { - if attr.has_name(rustc_span::sym::cfg) && contains_not_test(attr.meta_item_list().as_deref(), false) { + if attr.has_name(rustc_span::sym::cfg_trace) && contains_not_test(attr.meta_item_list().as_deref(), false) { span_lint_and_then( cx, CFG_NOT_TEST, diff --git a/src/tools/clippy/clippy_lints/src/methods/is_empty.rs b/src/tools/clippy/clippy_lints/src/methods/is_empty.rs index 7c190e123b72e..4c81b22861b4c 100644 --- a/src/tools/clippy/clippy_lints/src/methods/is_empty.rs +++ b/src/tools/clippy/clippy_lints/src/methods/is_empty.rs @@ -41,7 +41,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &'_ Expr<'_>, receiver: &Expr<'_ fn is_under_cfg(cx: &LateContext<'_>, id: HirId) -> bool { cx.tcx .hir_parent_id_iter(id) - .any(|id| cx.tcx.hir_attrs(id).iter().any(|attr| attr.has_name(sym::cfg))) + .any(|id| cx.tcx.hir_attrs(id).iter().any(|attr| attr.has_name(sym::cfg_trace))) } /// Similar to [`clippy_utils::expr_or_init`], but does not go up the chain if the initialization diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index 1307ff79bc5dd..668b0cb69e204 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -2629,7 +2629,7 @@ pub fn peel_ref_operators<'hir>(cx: &LateContext<'_>, mut expr: &'hir Expr<'hir> pub fn is_hir_ty_cfg_dependant(cx: &LateContext<'_>, ty: &hir::Ty<'_>) -> bool { if let TyKind::Path(QPath::Resolved(_, path)) = ty.kind { if let Res::Def(_, def_id) = path.res { - return cx.tcx.has_attr(def_id, sym::cfg) || cx.tcx.has_attr(def_id, sym::cfg_attr); + return cx.tcx.has_attr(def_id, sym::cfg_trace) || cx.tcx.has_attr(def_id, sym::cfg_attr); } } false @@ -2699,7 +2699,7 @@ pub fn is_in_test_function(tcx: TyCtxt<'_>, id: HirId) -> bool { /// use [`is_in_cfg_test`] pub fn is_cfg_test(tcx: TyCtxt<'_>, id: HirId) -> bool { tcx.hir_attrs(id).iter().any(|attr| { - if attr.has_name(sym::cfg) + if attr.has_name(sym::cfg_trace) && let Some(items) = attr.meta_item_list() && let [item] = &*items && item.has_name(sym::test) @@ -2723,11 +2723,11 @@ pub fn is_in_test(tcx: TyCtxt<'_>, hir_id: HirId) -> bool { /// Checks if the item of any of its parents has `#[cfg(...)]` attribute applied. pub fn inherits_cfg(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { - tcx.has_attr(def_id, sym::cfg) + tcx.has_attr(def_id, sym::cfg_trace) || tcx .hir_parent_iter(tcx.local_def_id_to_hir_id(def_id)) .flat_map(|(parent_id, _)| tcx.hir_attrs(parent_id)) - .any(|attr| attr.has_name(sym::cfg)) + .any(|attr| attr.has_name(sym::cfg_trace)) } /// Walks up the HIR tree from the given expression in an attempt to find where the value is diff --git a/tests/pretty/tests-are-sorted.pp b/tests/pretty/tests-are-sorted.pp index 31449b51dc3e1..d6a2c0ff9796b 100644 --- a/tests/pretty/tests-are-sorted.pp +++ b/tests/pretty/tests-are-sorted.pp @@ -10,7 +10,6 @@ //@ pp-exact:tests-are-sorted.pp extern crate test; -#[cfg(test)] #[rustc_test_marker = "m_test"] #[doc(hidden)] pub const m_test: test::TestDescAndFn = @@ -35,7 +34,6 @@ fn m_test() {} extern crate test; -#[cfg(test)] #[rustc_test_marker = "z_test"] #[doc(hidden)] pub const z_test: test::TestDescAndFn = @@ -61,7 +59,6 @@ fn z_test() {} extern crate test; -#[cfg(test)] #[rustc_test_marker = "a_test"] #[doc(hidden)] pub const a_test: test::TestDescAndFn = diff --git a/tests/ui/conditional-compilation/cfg-attr-syntax-validation.rs b/tests/ui/conditional-compilation/cfg-attr-syntax-validation.rs index 9a041557c7cc9..416145a0c1560 100644 --- a/tests/ui/conditional-compilation/cfg-attr-syntax-validation.rs +++ b/tests/ui/conditional-compilation/cfg-attr-syntax-validation.rs @@ -29,7 +29,6 @@ macro_rules! generate_s10 { ($expr: expr) => { #[cfg(feature = $expr)] //~^ ERROR expected unsuffixed literal, found expression `concat!("nonexistent")` - //~| ERROR expected unsuffixed literal, found expression `concat!("nonexistent")` struct S10; } } diff --git a/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr b/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr index 21a3712d9391a..d02d0d70a8bcf 100644 --- a/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr +++ b/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr @@ -65,19 +65,7 @@ LL | generate_s10!(concat!("nonexistent")); | = note: this error originates in the macro `generate_s10` (in Nightly builds, run with -Z macro-backtrace for more info) -error: expected unsuffixed literal, found expression `concat!("nonexistent")` - --> $DIR/cfg-attr-syntax-validation.rs:30:25 - | -LL | #[cfg(feature = $expr)] - | ^^^^^ -... -LL | generate_s10!(concat!("nonexistent")); - | ------------------------------------- in this macro invocation - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - = note: this error originates in the macro `generate_s10` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: aborting due to 11 previous errors +error: aborting due to 10 previous errors Some errors have detailed explanations: E0537, E0565. For more information about an error, try `rustc --explain E0537`. diff --git a/tests/ui/conditional-compilation/invalid-node-range-issue-129166.rs b/tests/ui/conditional-compilation/invalid-node-range-issue-129166.rs index 794e6fad3fc22..7c42be3ed4d6e 100644 --- a/tests/ui/conditional-compilation/invalid-node-range-issue-129166.rs +++ b/tests/ui/conditional-compilation/invalid-node-range-issue-129166.rs @@ -1,11 +1,12 @@ // This was triggering an assertion failure in `NodeRange::new`. +//@ check-pass + #![feature(cfg_eval)] #![feature(stmt_expr_attributes)] fn f() -> u32 { #[cfg_eval] #[cfg(not(FALSE))] 0 - //~^ ERROR removing an expression is not supported in this position } fn main() {} diff --git a/tests/ui/conditional-compilation/invalid-node-range-issue-129166.stderr b/tests/ui/conditional-compilation/invalid-node-range-issue-129166.stderr deleted file mode 100644 index 0699e182bd5f2..0000000000000 --- a/tests/ui/conditional-compilation/invalid-node-range-issue-129166.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: removing an expression is not supported in this position - --> $DIR/invalid-node-range-issue-129166.rs:7:17 - | -LL | #[cfg_eval] #[cfg(not(FALSE))] 0 - | ^^^^^^^^^^^^^^^^^^ - -error: aborting due to 1 previous error - diff --git a/tests/ui/parser/attribute/attr-bad-meta-4.rs b/tests/ui/parser/attribute/attr-bad-meta-4.rs index 2d0c6dbb50ab8..937390a6da5ba 100644 --- a/tests/ui/parser/attribute/attr-bad-meta-4.rs +++ b/tests/ui/parser/attribute/attr-bad-meta-4.rs @@ -2,7 +2,6 @@ macro_rules! mac { ($attr_item: meta) => { #[cfg($attr_item)] //~^ ERROR expected unsuffixed literal, found `meta` metavariable - //~| ERROR expected unsuffixed literal, found `meta` metavariable struct S; } } @@ -11,7 +10,6 @@ mac!(an(arbitrary token stream)); #[cfg(feature = -1)] //~^ ERROR expected unsuffixed literal, found `-` -//~| ERROR expected unsuffixed literal, found `-` fn handler() {} fn main() {} diff --git a/tests/ui/parser/attribute/attr-bad-meta-4.stderr b/tests/ui/parser/attribute/attr-bad-meta-4.stderr index dea574fd36d5b..9c6ab5adadf70 100644 --- a/tests/ui/parser/attribute/attr-bad-meta-4.stderr +++ b/tests/ui/parser/attribute/attr-bad-meta-4.stderr @@ -1,5 +1,5 @@ error: expected unsuffixed literal, found `-` - --> $DIR/attr-bad-meta-4.rs:12:17 + --> $DIR/attr-bad-meta-4.rs:11:17 | LL | #[cfg(feature = -1)] | ^ @@ -15,25 +15,5 @@ LL | mac!(an(arbitrary token stream)); | = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) -error: expected unsuffixed literal, found `meta` metavariable - --> $DIR/attr-bad-meta-4.rs:3:15 - | -LL | #[cfg($attr_item)] - | ^^^^^^^^^^ -... -LL | mac!(an(arbitrary token stream)); - | -------------------------------- in this macro invocation - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: expected unsuffixed literal, found `-` - --> $DIR/attr-bad-meta-4.rs:12:17 - | -LL | #[cfg(feature = -1)] - | ^ - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors diff --git a/tests/ui/proc-macro/cfg-attr-trace.rs b/tests/ui/proc-macro/cfg-attr-trace.rs index b4927f7a730b6..140dd10a7e047 100644 --- a/tests/ui/proc-macro/cfg-attr-trace.rs +++ b/tests/ui/proc-macro/cfg-attr-trace.rs @@ -3,6 +3,7 @@ //@ check-pass //@ proc-macro: test-macros.rs +#![feature(cfg_boolean_literals)] #![feature(cfg_eval)] #[macro_use] @@ -10,8 +11,13 @@ extern crate test_macros; #[cfg_eval] #[test_macros::print_attr] -#[cfg_attr(FALSE, test_macros::print_attr)] -#[cfg_attr(all(), test_macros::print_attr)] +#[cfg_attr(false, test_macros::print_attr)] +#[cfg_attr(true, test_macros::print_attr)] struct S; +#[cfg_eval] +#[test_macros::print_attr] +#[cfg(true)] +struct Z; + fn main() {} diff --git a/tests/ui/proc-macro/cfg-attr-trace.stdout b/tests/ui/proc-macro/cfg-attr-trace.stdout index 394c3887fe79c..52f9ff4e05c59 100644 --- a/tests/ui/proc-macro/cfg-attr-trace.stdout +++ b/tests/ui/proc-macro/cfg-attr-trace.stdout @@ -4,59 +4,75 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ Punct { ch: '#', spacing: Alone, - span: #0 bytes(271..272), + span: #0 bytes(305..306), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "test_macros", - span: #0 bytes(289..300), + span: #0 bytes(322..333), }, Punct { ch: ':', spacing: Joint, - span: #0 bytes(300..301), + span: #0 bytes(333..334), }, Punct { ch: ':', spacing: Alone, - span: #0 bytes(301..302), + span: #0 bytes(334..335), }, Ident { ident: "print_attr", - span: #0 bytes(302..312), + span: #0 bytes(335..345), }, ], - span: #0 bytes(272..314), + span: #0 bytes(306..347), }, Ident { ident: "struct", - span: #0 bytes(315..321), + span: #0 bytes(348..354), }, Ident { ident: "S", - span: #0 bytes(322..323), + span: #0 bytes(355..356), }, Punct { ch: ';', spacing: Alone, - span: #0 bytes(323..324), + span: #0 bytes(356..357), }, ] PRINT-ATTR INPUT (DISPLAY): struct S; PRINT-ATTR INPUT (DEBUG): TokenStream [ Ident { ident: "struct", - span: #0 bytes(315..321), + span: #0 bytes(348..354), }, Ident { ident: "S", - span: #0 bytes(322..323), + span: #0 bytes(355..356), }, Punct { ch: ';', spacing: Alone, - span: #0 bytes(323..324), + span: #0 bytes(356..357), + }, +] +PRINT-ATTR INPUT (DISPLAY): struct Z; +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Ident { + ident: "struct", + span: #0 bytes(411..417), + }, + Ident { + ident: "Z", + span: #0 bytes(418..419), + }, + Punct { + ch: ';', + spacing: Alone, + span: #0 bytes(419..420), }, ] From 1da5e60ac59661bca0d09b50839600fe0deeb0aa Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Wed, 26 Mar 2025 14:48:14 +0100 Subject: [PATCH 03/15] Don't record child scopes for patterns. They are unused. --- compiler/rustc_hir_analysis/src/check/region.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs index 255f5fee52a80..c81f75eb31982 100644 --- a/compiler/rustc_hir_analysis/src/check/region.rs +++ b/compiler/rustc_hir_analysis/src/check/region.rs @@ -221,8 +221,6 @@ fn resolve_arm<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, arm: &'tcx hir: } fn resolve_pat<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, pat: &'tcx hir::Pat<'tcx>) { - visitor.record_child_scope(Scope { local_id: pat.hir_id.local_id, data: ScopeData::Node }); - // If this is a binding then record the lifetime of that binding. if let PatKind::Binding(..) = pat.kind { record_var_lifetime(visitor, pat.hir_id.local_id); From 227f93395a2cc86f6f66d26a68fdbd7955a8ec51 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Wed, 26 Mar 2025 14:49:07 +0100 Subject: [PATCH 04/15] Simplify RvalueCandidateType. There is no difference between the Patternand Borrow cases. Reduce it to a simple struct. --- .../rustc_hir_analysis/src/check/region.rs | 10 ++---- .../rustc_hir_typeck/src/rvalue_scopes.rs | 12 +++---- compiler/rustc_middle/src/middle/region.rs | 31 ++++++++----------- 3 files changed, 19 insertions(+), 34 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs index c81f75eb31982..a7007c5d831b3 100644 --- a/compiler/rustc_hir_analysis/src/check/region.rs +++ b/compiler/rustc_hir_analysis/src/check/region.rs @@ -623,10 +623,7 @@ fn resolve_local<'tcx>( if is_binding_pat(pat) { visitor.scope_tree.record_rvalue_candidate( expr.hir_id, - RvalueCandidateType::Pattern { - target: expr.hir_id.local_id, - lifetime: blk_scope, - }, + RvalueCandidate { target: expr.hir_id.local_id, lifetime: blk_scope }, ); } } @@ -731,10 +728,7 @@ fn resolve_local<'tcx>( record_rvalue_scope_if_borrow_expr(visitor, subexpr, blk_id); visitor.scope_tree.record_rvalue_candidate( subexpr.hir_id, - RvalueCandidateType::Borrow { - target: subexpr.hir_id.local_id, - lifetime: blk_id, - }, + RvalueCandidate { target: subexpr.hir_id.local_id, lifetime: blk_id }, ); } hir::ExprKind::Struct(_, fields, _) => { diff --git a/compiler/rustc_hir_typeck/src/rvalue_scopes.rs b/compiler/rustc_hir_typeck/src/rvalue_scopes.rs index 98d7f777d6b8a..973dc7141e64d 100644 --- a/compiler/rustc_hir_typeck/src/rvalue_scopes.rs +++ b/compiler/rustc_hir_typeck/src/rvalue_scopes.rs @@ -2,7 +2,7 @@ use hir::Node; use hir::def_id::DefId; use rustc_hir as hir; use rustc_middle::bug; -use rustc_middle::middle::region::{RvalueCandidateType, Scope, ScopeTree}; +use rustc_middle::middle::region::{RvalueCandidate, Scope, ScopeTree}; use rustc_middle::ty::RvalueScopes; use tracing::debug; @@ -55,15 +55,11 @@ fn record_rvalue_scope_rec( fn record_rvalue_scope( rvalue_scopes: &mut RvalueScopes, expr: &hir::Expr<'_>, - candidate: &RvalueCandidateType, + candidate: &RvalueCandidate, ) { debug!("resolve_rvalue_scope(expr={expr:?}, candidate={candidate:?})"); - match candidate { - RvalueCandidateType::Borrow { lifetime, .. } - | RvalueCandidateType::Pattern { lifetime, .. } => { - record_rvalue_scope_rec(rvalue_scopes, expr, *lifetime) - } // FIXME(@dingxiangfei2009): handle the candidates in the function call arguments - } + record_rvalue_scope_rec(rvalue_scopes, expr, candidate.lifetime) + // FIXME(@dingxiangfei2009): handle the candidates in the function call arguments } pub(crate) fn resolve_rvalue_scopes<'a, 'tcx>( diff --git a/compiler/rustc_middle/src/middle/region.rs b/compiler/rustc_middle/src/middle/region.rs index 66861519e17c8..66ece8f0e52fd 100644 --- a/compiler/rustc_middle/src/middle/region.rs +++ b/compiler/rustc_middle/src/middle/region.rs @@ -224,7 +224,7 @@ pub struct ScopeTree { /// and not the enclosing *statement*. Expressions that are not present in this /// table are not rvalue candidates. The set of rvalue candidates is computed /// during type check based on a traversal of the AST. - pub rvalue_candidates: HirIdMap, + pub rvalue_candidates: HirIdMap, /// Backwards incompatible scoping that will be introduced in future editions. /// This information is used later for linting to identify locals and @@ -308,15 +308,14 @@ pub struct ScopeTree { pub yield_in_scope: UnordMap>, } -/// Identifies the reason that a given expression is an rvalue candidate -/// (see the `rvalue_candidates` field for more information what rvalue -/// candidates in general). In constants, the `lifetime` field is None -/// to indicate that certain expressions escape into 'static and -/// should have no local cleanup scope. +/// See the `rvalue_candidates` field for more information on rvalue +/// candidates in general. +/// The `lifetime` field is None to indicate that certain expressions escape +/// into 'static and should have no local cleanup scope. #[derive(Debug, Copy, Clone, HashStable)] -pub enum RvalueCandidateType { - Borrow { target: hir::ItemLocalId, lifetime: Option }, - Pattern { target: hir::ItemLocalId, lifetime: Option }, +pub struct RvalueCandidate { + pub target: hir::ItemLocalId, + pub lifetime: Option, } #[derive(Debug, Copy, Clone, HashStable)] @@ -344,16 +343,12 @@ impl ScopeTree { self.var_map.insert(var, lifetime); } - pub fn record_rvalue_candidate(&mut self, var: HirId, candidate_type: RvalueCandidateType) { - debug!("record_rvalue_candidate(var={var:?}, type={candidate_type:?})"); - match &candidate_type { - RvalueCandidateType::Borrow { lifetime: Some(lifetime), .. } - | RvalueCandidateType::Pattern { lifetime: Some(lifetime), .. } => { - assert!(var.local_id != lifetime.local_id) - } - _ => {} + pub fn record_rvalue_candidate(&mut self, var: HirId, candidate: RvalueCandidate) { + debug!("record_rvalue_candidate(var={var:?}, candidate={candidate:?})"); + if let Some(lifetime) = &candidate.lifetime { + assert!(var.local_id != lifetime.local_id) } - self.rvalue_candidates.insert(var, candidate_type); + self.rvalue_candidates.insert(var, candidate); } /// Returns the narrowest scope that encloses `id`, if any. From 0ad0142a5be5c6aab4d0b5a897a7d11c78fbea12 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Wed, 26 Mar 2025 16:07:14 +0100 Subject: [PATCH 05/15] Don't set cx.parent to None; it seems unnecessary. --- compiler/rustc_hir_analysis/src/check/region.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs index a7007c5d831b3..4e4b975573659 100644 --- a/compiler/rustc_hir_analysis/src/check/region.rs +++ b/compiler/rustc_hir_analysis/src/check/region.rs @@ -849,13 +849,12 @@ impl<'tcx> Visitor<'tcx> for ScopeResolutionVisitor<'tcx> { self.enter_body(body.value.hir_id, |this| { if this.tcx.hir_body_owner_kind(owner_id).is_fn_or_closure() { // The arguments and `self` are parented to the fn. - this.cx.var_parent = this.cx.parent.take(); + this.cx.var_parent = this.cx.parent; for param in body.params { this.visit_pat(param.pat); } // The body of the every fn is a root scope. - this.cx.parent = this.cx.var_parent; this.visit_expr(body.value) } else { // Only functions have an outer terminating (drop) scope, while From 2cc3fa32ef0ac964c3c99b14d0cbc422a10788bb Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Wed, 26 Mar 2025 17:13:49 +0100 Subject: [PATCH 06/15] Remove ScopeDepth from var_parent. It was never used. --- .../rustc_hir_analysis/src/check/region.rs | 26 ++++++++++++------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs index 4e4b975573659..ba8124b11fc13 100644 --- a/compiler/rustc_hir_analysis/src/check/region.rs +++ b/compiler/rustc_hir_analysis/src/check/region.rs @@ -25,12 +25,18 @@ use tracing::debug; struct Context { /// The scope that contains any new variables declared, plus its depth in /// the scope tree. - var_parent: Option<(Scope, ScopeDepth)>, + var_parent: Option, /// Region parent of expressions, etc., plus its depth in the scope tree. parent: Option<(Scope, ScopeDepth)>, } +impl Context { + fn set_var_parent(&mut self) { + self.var_parent = self.parent.map(|(p, _)| p); + } +} + struct ScopeResolutionVisitor<'tcx> { tcx: TyCtxt<'tcx>, @@ -78,7 +84,7 @@ fn record_var_lifetime(visitor: &mut ScopeResolutionVisitor<'_>, var_id: hir::It // // extern fn isalnum(c: c_int) -> c_int } - Some((parent_scope, _)) => visitor.scope_tree.record_var_scope(var_id, parent_scope), + Some(parent_scope) => visitor.scope_tree.record_var_scope(var_id, parent_scope), } } @@ -113,7 +119,7 @@ fn resolve_block<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, blk: &'tcx hi // itself has returned. visitor.enter_node_scope_with_dtor(blk.hir_id.local_id); - visitor.cx.var_parent = visitor.cx.parent; + visitor.cx.set_var_parent(); { // This block should be kept approximately in sync with @@ -132,7 +138,7 @@ fn resolve_block<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, blk: &'tcx hi local_id: blk.hir_id.local_id, data: ScopeData::Remainder(FirstStatementIndex::new(i)), }); - visitor.cx.var_parent = visitor.cx.parent; + visitor.cx.set_var_parent(); visitor.visit_stmt(statement); // We need to back out temporarily to the last enclosing scope // for the `else` block, so that even the temporaries receiving @@ -157,7 +163,7 @@ fn resolve_block<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, blk: &'tcx hi local_id: blk.hir_id.local_id, data: ScopeData::Remainder(FirstStatementIndex::new(i)), }); - visitor.cx.var_parent = visitor.cx.parent; + visitor.cx.set_var_parent(); visitor.visit_stmt(statement) } hir::StmtKind::Item(..) => { @@ -207,7 +213,7 @@ fn resolve_arm<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, arm: &'tcx hir: visitor.terminating_scopes.insert(arm.hir_id.local_id); visitor.enter_node_scope_with_dtor(arm.hir_id.local_id); - visitor.cx.var_parent = visitor.cx.parent; + visitor.cx.set_var_parent(); if let Some(expr) = arm.guard && !has_let_expr(expr) @@ -484,7 +490,7 @@ fn resolve_expr<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, expr: &'tcx hi ScopeData::IfThen }; visitor.enter_scope(Scope { local_id: then.hir_id.local_id, data }); - visitor.cx.var_parent = visitor.cx.parent; + visitor.cx.set_var_parent(); visitor.visit_expr(cond); visitor.visit_expr(then); visitor.cx = expr_cx; @@ -499,7 +505,7 @@ fn resolve_expr<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, expr: &'tcx hi ScopeData::IfThen }; visitor.enter_scope(Scope { local_id: then.hir_id.local_id, data }); - visitor.cx.var_parent = visitor.cx.parent; + visitor.cx.set_var_parent(); visitor.visit_expr(cond); visitor.visit_expr(then); visitor.cx = expr_cx; @@ -558,7 +564,7 @@ fn resolve_local<'tcx>( ) { debug!("resolve_local(pat={:?}, init={:?})", pat, init); - let blk_scope = visitor.cx.var_parent.map(|(p, _)| p); + let blk_scope = visitor.cx.var_parent; // As an exception to the normal rules governing temporary // lifetimes, initializers in a let have a temporary lifetime @@ -849,7 +855,7 @@ impl<'tcx> Visitor<'tcx> for ScopeResolutionVisitor<'tcx> { self.enter_body(body.value.hir_id, |this| { if this.tcx.hir_body_owner_kind(owner_id).is_fn_or_closure() { // The arguments and `self` are parented to the fn. - this.cx.var_parent = this.cx.parent; + this.cx.set_var_parent(); for param in body.params { this.visit_pat(param.pat); } From 3d58aec0da0badcfdb9c185d317d6aa1c14ffb6e Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Thu, 27 Mar 2025 02:48:53 +0800 Subject: [PATCH 07/15] Report compiletest pass mode if forced This is very non-obvious if it fails in PR CI. --- src/tools/compiletest/src/lib.rs | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs index 3ec984edacbe8..950566b2582a8 100644 --- a/src/tools/compiletest/src/lib.rs +++ b/src/tools/compiletest/src/lib.rs @@ -22,6 +22,7 @@ pub mod util; use core::panic; use std::collections::HashSet; use std::ffi::OsString; +use std::fmt::Write; use std::io::{self, ErrorKind}; use std::path::{Path, PathBuf}; use std::process::{Command, Stdio}; @@ -570,18 +571,22 @@ pub fn run_tests(config: Arc) { // easy to miss which tests failed, and as such fail to reproduce // the failure locally. - println!( - "Some tests failed in compiletest suite={}{} mode={} host={} target={}", - config.suite, - config - .compare_mode - .as_ref() - .map(|c| format!(" compare_mode={:?}", c)) - .unwrap_or_default(), - config.mode, - config.host, - config.target - ); + let mut msg = String::from("Some tests failed in compiletest"); + write!(msg, " suite={}", config.suite).unwrap(); + + if let Some(compare_mode) = config.compare_mode.as_ref() { + write!(msg, " compare_mode={}", compare_mode).unwrap(); + } + + if let Some(pass_mode) = config.force_pass_mode.as_ref() { + write!(msg, " pass_mode={}", pass_mode).unwrap(); + } + + write!(msg, " mode={}", config.mode).unwrap(); + write!(msg, " host={}", config.host).unwrap(); + write!(msg, " target={}", config.target).unwrap(); + + println!("{msg}"); std::process::exit(1); } From 5a6ed74a6cae1b8bd994a9b2738896b425726c52 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 27 Mar 2025 19:10:14 +1100 Subject: [PATCH 08/15] Remove `kw::Empty` uses from `src/librustdoc`. Much like the ones in the previous commit. --- src/librustdoc/clean/mod.rs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index de6dc088176ff..f72acaae02f23 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1943,14 +1943,11 @@ fn clean_trait_object_lifetime_bound<'tcx>( // latter contrary to `clean_middle_region`. match *region { ty::ReStatic => Some(Lifetime::statik()), - ty::ReEarlyParam(region) if region.name != kw::Empty => Some(Lifetime(region.name)), - ty::ReBound(_, ty::BoundRegion { kind: ty::BoundRegionKind::Named(_, name), .. }) - if name != kw::Empty => - { + ty::ReEarlyParam(region) => Some(Lifetime(region.name)), + ty::ReBound(_, ty::BoundRegion { kind: ty::BoundRegionKind::Named(_, name), .. }) => { Some(Lifetime(name)) } - ty::ReEarlyParam(_) - | ty::ReBound(..) + ty::ReBound(..) | ty::ReLateParam(_) | ty::ReVar(_) | ty::RePlaceholder(_) From 215c2c2f494e18791f9321f072a7c05c2f17238e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Thu, 27 Mar 2025 11:05:49 +0100 Subject: [PATCH 09/15] Remove some asserts from the `download_ci_llvm` bootstrap test --- src/bootstrap/src/core/config/tests.rs | 22 +--------------------- 1 file changed, 1 insertion(+), 21 deletions(-) diff --git a/src/bootstrap/src/core/config/tests.rs b/src/bootstrap/src/core/config/tests.rs index 068e237c2cdcd..6d63709f47406 100644 --- a/src/bootstrap/src/core/config/tests.rs +++ b/src/bootstrap/src/core/config/tests.rs @@ -24,31 +24,11 @@ pub(crate) fn parse(config: &str) -> Config { #[test] fn download_ci_llvm() { - let config = parse(""); - let is_available = llvm::is_ci_llvm_available_for_target(&config, config.llvm_assertions); - if is_available { - assert!(config.llvm_from_ci); - } - - let config = Config::parse_inner( - Flags::parse(&[ - "check".to_string(), - "--config=/does/not/exist".to_string(), - "--ci".to_string(), - "false".to_string(), - ]), - |&_| toml::from_str("llvm.download-ci-llvm = true"), - ); - let is_available = llvm::is_ci_llvm_available_for_target(&config, config.llvm_assertions); - if is_available { - assert!(config.llvm_from_ci); - } - let config = parse("llvm.download-ci-llvm = false"); assert!(!config.llvm_from_ci); let if_unchanged_config = parse("llvm.download-ci-llvm = \"if-unchanged\""); - if if_unchanged_config.llvm_from_ci { + if if_unchanged_config.llvm_from_ci && if_unchanged_config.is_running_on_ci { let has_changes = if_unchanged_config .last_modified_commit(LLVM_INVALIDATION_PATHS, "download-ci-llvm", true) .is_none(); From a3bafca14aa8e6ef1694f416ca00215e49771b0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Tue, 25 Mar 2025 22:36:05 +0100 Subject: [PATCH 10/15] Add job duration changes stats in post-merge analysis --- src/ci/citool/src/analysis.rs | 55 +++++++++++++++++++++++++++++++++-- src/ci/citool/src/main.rs | 7 +++-- 2 files changed, 57 insertions(+), 5 deletions(-) diff --git a/src/ci/citool/src/analysis.rs b/src/ci/citool/src/analysis.rs index 2b001f28b0eb4..fc18e438aab9e 100644 --- a/src/ci/citool/src/analysis.rs +++ b/src/ci/citool/src/analysis.rs @@ -1,10 +1,11 @@ -use std::collections::{BTreeMap, HashMap, HashSet}; use std::fmt::Debug; use build_helper::metrics::{ BuildStep, JsonRoot, TestOutcome, TestSuite, TestSuiteMetadata, escape_step_name, format_build_steps, }; +use std::collections::{BTreeMap, HashMap, HashSet}; +use std::time::Duration; use crate::metrics; use crate::metrics::{JobMetrics, JobName, get_test_suites}; @@ -184,11 +185,61 @@ fn render_table(suites: BTreeMap) -> String { } /// Outputs a report of test differences between the `parent` and `current` commits. -pub fn output_test_diffs(job_metrics: HashMap) { +pub fn output_test_diffs(job_metrics: &HashMap) { let aggregated_test_diffs = aggregate_test_diffs(&job_metrics); report_test_diffs(aggregated_test_diffs); } +/// Prints the ten largest differences in bootstrap durations. +pub fn output_largest_duration_changes(job_metrics: &HashMap) { + struct Entry<'a> { + job: &'a JobName, + before: Duration, + after: Duration, + change: f64, + } + + let mut changes: Vec = vec![]; + for (job, metrics) in job_metrics { + if let Some(parent) = &metrics.parent { + let duration_before = parent + .invocations + .iter() + .map(|i| BuildStep::from_invocation(i).duration) + .sum::(); + let duration_after = metrics + .current + .invocations + .iter() + .map(|i| BuildStep::from_invocation(i).duration) + .sum::(); + let pct_change = duration_after.as_secs_f64() / duration_before.as_secs_f64(); + let pct_change = pct_change * 100.0; + // Normalize around 100, to get + for regression and - for improvements + let pct_change = pct_change - 100.0; + changes.push(Entry { + job, + before: duration_before, + after: duration_after, + change: pct_change, + }); + } + } + changes.sort_by(|e1, e2| e1.change.partial_cmp(&e2.change).unwrap().reverse()); + + println!("# Job duration changes"); + for (index, entry) in changes.into_iter().take(10).enumerate() { + println!( + "{}. `{}`: {:.1}s -> {:.1}s ({:.1}%)", + index + 1, + entry.job, + entry.before.as_secs_f64(), + entry.after.as_secs_f64(), + entry.change + ); + } +} + #[derive(Default)] struct TestSuiteRecord { passed: u64, diff --git a/src/ci/citool/src/main.rs b/src/ci/citool/src/main.rs index 5f5c50dc43a0e..6db5eab458cca 100644 --- a/src/ci/citool/src/main.rs +++ b/src/ci/citool/src/main.rs @@ -15,7 +15,7 @@ use clap::Parser; use jobs::JobDatabase; use serde_yaml::Value; -use crate::analysis::output_test_diffs; +use crate::analysis::{output_largest_duration_changes, output_test_diffs}; use crate::cpu_usage::load_cpu_usage; use crate::datadog::upload_datadog_metric; use crate::jobs::RunType; @@ -160,7 +160,7 @@ fn postprocess_metrics( job_name, JobMetrics { parent: Some(parent_metrics), current: metrics }, )]); - output_test_diffs(job_metrics); + output_test_diffs(&job_metrics); return Ok(()); } Err(error) => { @@ -180,7 +180,8 @@ fn post_merge_report(db: JobDatabase, current: String, parent: String) -> anyhow let metrics = download_auto_job_metrics(&db, &parent, ¤t)?; println!("\nComparing {parent} (parent) -> {current} (this PR)\n"); - output_test_diffs(metrics); + output_test_diffs(&metrics); + output_largest_duration_changes(&metrics); Ok(()) } From 4a4367535339d119a6a3c4f515c8912667b30be4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Thu, 27 Mar 2025 11:25:25 +0100 Subject: [PATCH 11/15] Add cache for job metrics --- src/ci/citool/src/metrics.rs | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/ci/citool/src/metrics.rs b/src/ci/citool/src/metrics.rs index 086aa5009f341..a816fb3c4f165 100644 --- a/src/ci/citool/src/metrics.rs +++ b/src/ci/citool/src/metrics.rs @@ -1,5 +1,5 @@ use std::collections::HashMap; -use std::path::Path; +use std::path::{Path, PathBuf}; use anyhow::Context; use build_helper::metrics::{JsonNode, JsonRoot, TestSuite}; @@ -74,6 +74,17 @@ Maybe it was newly added?"#, } pub fn download_job_metrics(job_name: &str, sha: &str) -> anyhow::Result { + // Best effort cache to speed-up local re-executions of citool + let cache_path = PathBuf::from(".citool-cache").join(sha).join(format!("{job_name}.json")); + if cache_path.is_file() { + if let Ok(metrics) = std::fs::read_to_string(&cache_path) + .map_err(|err| err.into()) + .and_then(|data| anyhow::Ok::(serde_json::from_str::(&data)?)) + { + return Ok(metrics); + } + } + let url = get_metrics_url(job_name, sha); let mut response = ureq::get(&url).call()?; if !response.status().is_success() { @@ -87,6 +98,13 @@ pub fn download_job_metrics(job_name: &str, sha: &str) -> anyhow::Result Date: Thu, 27 Mar 2025 11:29:48 +0100 Subject: [PATCH 12/15] Add a note about interpreting job duration changes --- src/ci/citool/src/analysis.rs | 9 +++++++++ src/ci/citool/src/utils.rs | 1 - 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/ci/citool/src/analysis.rs b/src/ci/citool/src/analysis.rs index fc18e438aab9e..2e1ede126dc36 100644 --- a/src/ci/citool/src/analysis.rs +++ b/src/ci/citool/src/analysis.rs @@ -238,6 +238,15 @@ pub fn output_largest_duration_changes(job_metrics: &HashMap {summary} - " ); func(); From d0353f5c7ac0c73c6ae97623ac3e01fab1f657ae Mon Sep 17 00:00:00 2001 From: xizheyin Date: Thu, 27 Mar 2025 17:25:22 +0800 Subject: [PATCH 13/15] Add ui test for struct construction by calling syntax Signed-off-by: xizheyin --- ...struct-construct-with-call-issue-138931.rs | 25 +++++++++++ ...ct-construct-with-call-issue-138931.stderr | 45 +++++++++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 tests/ui/structs/struct-construct-with-call-issue-138931.rs create mode 100644 tests/ui/structs/struct-construct-with-call-issue-138931.stderr diff --git a/tests/ui/structs/struct-construct-with-call-issue-138931.rs b/tests/ui/structs/struct-construct-with-call-issue-138931.rs new file mode 100644 index 0000000000000..5d50eb14bff1a --- /dev/null +++ b/tests/ui/structs/struct-construct-with-call-issue-138931.rs @@ -0,0 +1,25 @@ +struct PersonOnlyName { + name: String +} + +struct PersonWithAge { + name: String, + age: u8, + height: u8, +} + + + +fn main() { + let wilfred = PersonOnlyName("Name1".to_owned()); + //~^ ERROR expected function, tuple struct or tuple variant, found struct `PersonOnlyName` [E0423] + + let bill = PersonWithAge( //~ ERROR expected function, tuple struct or tuple variant, found struct `PersonWithAge` [E0423] + "Name2".to_owned(), + 20, + 180, + ); + + let person = PersonWithAge("Name3".to_owned()); + //~^ ERROR expected function, tuple struct or tuple variant, found struct `PersonWithAge` [E0423] +} diff --git a/tests/ui/structs/struct-construct-with-call-issue-138931.stderr b/tests/ui/structs/struct-construct-with-call-issue-138931.stderr new file mode 100644 index 0000000000000..af68b37a891eb --- /dev/null +++ b/tests/ui/structs/struct-construct-with-call-issue-138931.stderr @@ -0,0 +1,45 @@ +error[E0423]: expected function, tuple struct or tuple variant, found struct `PersonOnlyName` + --> $DIR/struct-construct-with-call-issue-138931.rs:14:19 + | +LL | / struct PersonOnlyName { +LL | | name: String +LL | | } + | |_- `PersonOnlyName` defined here +... +LL | let wilfred = PersonOnlyName("Name1".to_owned()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use struct literal syntax instead: `PersonOnlyName { name: val }` + +error[E0423]: expected function, tuple struct or tuple variant, found struct `PersonWithAge` + --> $DIR/struct-construct-with-call-issue-138931.rs:17:16 + | +LL | / struct PersonWithAge { +LL | | name: String, +LL | | age: u8, +LL | | height: u8, +LL | | } + | |_- `PersonWithAge` defined here +... +LL | let bill = PersonWithAge( + | ________________^ +LL | | "Name2".to_owned(), +LL | | 20, +LL | | 180, +LL | | ); + | |_____^ help: use struct literal syntax instead: `PersonWithAge { name: val, age: val, height: val }` + +error[E0423]: expected function, tuple struct or tuple variant, found struct `PersonWithAge` + --> $DIR/struct-construct-with-call-issue-138931.rs:23:18 + | +LL | / struct PersonWithAge { +LL | | name: String, +LL | | age: u8, +LL | | height: u8, +LL | | } + | |_- `PersonWithAge` defined here +... +LL | let person = PersonWithAge("Name3".to_owned()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use struct literal syntax instead: `PersonWithAge { name: val, age: val, height: val }` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0423`. From 4648650d899ba01a6ed30e7ada3795b5c56465eb Mon Sep 17 00:00:00 2001 From: xizheyin Date: Thu, 27 Mar 2025 17:28:15 +0800 Subject: [PATCH 14/15] Improve suggest construct with literal syntax instead of calling Signed-off-by: xizheyin --- .../rustc_resolve/src/late/diagnostics.rs | 108 ++++++++++++------ ...ct-construct-with-call-issue-138931.stderr | 17 ++- 2 files changed, 89 insertions(+), 36 deletions(-) diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 3d666055a94fb..97dd9faf6dec6 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -1681,41 +1681,81 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { // the struct literal syntax at all, as that will cause a subsequent error. let fields = this.r.field_idents(def_id); let has_fields = fields.as_ref().is_some_and(|f| !f.is_empty()); - let (fields, applicability) = match fields { - Some(fields) => { - let fields = if let Some(old_fields) = old_fields { - fields - .iter() - .enumerate() - .map(|(idx, new)| (new, old_fields.get(idx))) - .map(|(new, old)| { - if let Some(Some(old)) = old - && new.as_str() != old - { - format!("{new}: {old}") - } else { - new.to_string() - } - }) - .collect::>() - } else { - fields - .iter() - .map(|f| format!("{f}{tail}")) - .collect::>() - }; - - (fields.join(", "), applicability) - } - None => ("/* fields */".to_string(), Applicability::HasPlaceholders), - }; - let pad = if has_fields { " " } else { "" }; - err.span_suggestion( + + if let PathSource::Expr(Some(Expr { + kind: ExprKind::Call(path, args), span, - format!("use struct {descr} syntax instead"), - format!("{path_str} {{{pad}{fields}{pad}}}"), - applicability, - ); + .. + })) = source + && !args.is_empty() + && let Some(fields) = &fields + && args.len() == fields.len() + // Make sure we have same number of args as fields + { + let path_span = path.span; + let mut parts = Vec::new(); + + // Start with the opening brace + parts.push(( + path_span.shrink_to_hi().until(args[0].span), + "{".to_owned(), + )); + + for (field, arg) in fields.iter().zip(args.iter()) { + // Add the field name before the argument + parts.push((arg.span.shrink_to_lo(), format!("{}: ", field))); + } + + // Add the closing brace + parts.push(( + args.last().unwrap().span.shrink_to_hi().until(span.shrink_to_hi()), + "}".to_owned(), + )); + + err.multipart_suggestion_verbose( + format!("use struct {descr} syntax instead of calling"), + parts, + applicability, + ); + } else { + let (fields, applicability) = match fields { + Some(fields) => { + let fields = if let Some(old_fields) = old_fields { + fields + .iter() + .enumerate() + .map(|(idx, new)| (new, old_fields.get(idx))) + .map(|(new, old)| { + if let Some(Some(old)) = old + && new.as_str() != old + { + format!("{new}: {old}") + } else { + new.to_string() + } + }) + .collect::>() + } else { + fields + .iter() + .map(|f| format!("{f}{tail}")) + .collect::>() + }; + + (fields.join(", "), applicability) + } + None => { + ("/* fields */".to_string(), Applicability::HasPlaceholders) + } + }; + let pad = if has_fields { " " } else { "" }; + err.span_suggestion( + span, + format!("use struct {descr} syntax instead"), + format!("{path_str} {{{pad}{fields}{pad}}}"), + applicability, + ); + } } if let PathSource::Expr(Some(Expr { kind: ExprKind::Call(path, args), diff --git a/tests/ui/structs/struct-construct-with-call-issue-138931.stderr b/tests/ui/structs/struct-construct-with-call-issue-138931.stderr index af68b37a891eb..acae01df56361 100644 --- a/tests/ui/structs/struct-construct-with-call-issue-138931.stderr +++ b/tests/ui/structs/struct-construct-with-call-issue-138931.stderr @@ -7,7 +7,13 @@ LL | | } | |_- `PersonOnlyName` defined here ... LL | let wilfred = PersonOnlyName("Name1".to_owned()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use struct literal syntax instead: `PersonOnlyName { name: val }` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use struct literal syntax instead of calling + | +LL - let wilfred = PersonOnlyName("Name1".to_owned()); +LL + let wilfred = PersonOnlyName{name: "Name1".to_owned()}; + | error[E0423]: expected function, tuple struct or tuple variant, found struct `PersonWithAge` --> $DIR/struct-construct-with-call-issue-138931.rs:17:16 @@ -25,7 +31,14 @@ LL | | "Name2".to_owned(), LL | | 20, LL | | 180, LL | | ); - | |_____^ help: use struct literal syntax instead: `PersonWithAge { name: val, age: val, height: val }` + | |_____^ + | +help: use struct literal syntax instead of calling + | +LL ~ let bill = PersonWithAge{name: "Name2".to_owned(), +LL ~ age: 20, +LL ~ height: 180}; + | error[E0423]: expected function, tuple struct or tuple variant, found struct `PersonWithAge` --> $DIR/struct-construct-with-call-issue-138931.rs:23:18 From 27cca0a161ff913852f8344636e17489ef37672b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Thu, 27 Mar 2025 11:36:29 +0100 Subject: [PATCH 15/15] Add CI metadata to bootstrap metrics This will allow us to provide links to CI workflows, jobs and summaries in the post-merge analysis report. --- .github/workflows/ci.yml | 2 ++ src/bootstrap/src/utils/metrics.rs | 22 +++++++++++++++++++--- src/build_helper/src/metrics.rs | 13 +++++++++++++ src/ci/citool/src/analysis.rs | 4 ++-- src/ci/docker/run.sh | 2 ++ 5 files changed, 38 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 25397006ee23c..51dd0f81ed147 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -69,6 +69,8 @@ jobs: env: CI_JOB_NAME: ${{ matrix.name }} CI_JOB_DOC_URL: ${{ matrix.doc_url }} + GITHUB_WORKFLOW_RUN_ID: ${{ github.run_id }} + GITHUB_REPOSITORY: ${{ github.repository }} CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse # commit of PR sha or commit sha. `GITHUB_SHA` is not accurate for PRs. HEAD_SHA: ${{ github.event.pull_request.head.sha || github.sha }} diff --git a/src/bootstrap/src/utils/metrics.rs b/src/bootstrap/src/utils/metrics.rs index 885fff9c32c5a..862c444962415 100644 --- a/src/bootstrap/src/utils/metrics.rs +++ b/src/bootstrap/src/utils/metrics.rs @@ -9,9 +9,10 @@ use std::fs::File; use std::io::BufWriter; use std::time::{Duration, Instant, SystemTime}; +use build_helper::ci::CiEnv; use build_helper::metrics::{ - JsonInvocation, JsonInvocationSystemStats, JsonNode, JsonRoot, JsonStepSystemStats, Test, - TestOutcome, TestSuite, TestSuiteMetadata, + CiMetadata, JsonInvocation, JsonInvocationSystemStats, JsonNode, JsonRoot, JsonStepSystemStats, + Test, TestOutcome, TestSuite, TestSuiteMetadata, }; use sysinfo::{CpuRefreshKind, RefreshKind, System}; @@ -217,7 +218,12 @@ impl BuildMetrics { children: steps.into_iter().map(|step| self.prepare_json_step(step)).collect(), }); - let json = JsonRoot { format_version: CURRENT_FORMAT_VERSION, system_stats, invocations }; + let json = JsonRoot { + format_version: CURRENT_FORMAT_VERSION, + system_stats, + invocations, + ci_metadata: get_ci_metadata(CiEnv::current()), + }; t!(std::fs::create_dir_all(dest.parent().unwrap())); let mut file = BufWriter::new(t!(File::create(&dest))); @@ -245,6 +251,16 @@ impl BuildMetrics { } } +fn get_ci_metadata(ci_env: CiEnv) -> Option { + if ci_env != CiEnv::GitHubActions { + return None; + } + let workflow_run_id = + std::env::var("GITHUB_WORKFLOW_RUN_ID").ok().and_then(|id| id.parse::().ok())?; + let repository = std::env::var("GITHUB_REPOSITORY").ok()?; + Some(CiMetadata { workflow_run_id, repository }) +} + struct MetricsState { finished_steps: Vec, running_steps: Vec, diff --git a/src/build_helper/src/metrics.rs b/src/build_helper/src/metrics.rs index fdff9cd18cea7..8b82e62a32770 100644 --- a/src/build_helper/src/metrics.rs +++ b/src/build_helper/src/metrics.rs @@ -9,6 +9,19 @@ pub struct JsonRoot { pub format_version: usize, pub system_stats: JsonInvocationSystemStats, pub invocations: Vec, + #[serde(default)] + pub ci_metadata: Option, +} + +/// Represents metadata about bootstrap's execution in CI. +#[derive(Serialize, Deserialize)] +pub struct CiMetadata { + /// GitHub run ID of the workflow where bootstrap was executed. + /// Note that the run ID will be shared amongst all jobs executed in that workflow. + pub workflow_run_id: u64, + /// Full name of a GitHub repository where bootstrap was executed in CI. + /// e.g. `rust-lang-ci/rust`. + pub repository: String, } #[derive(Serialize, Deserialize)] diff --git a/src/ci/citool/src/analysis.rs b/src/ci/citool/src/analysis.rs index 2e1ede126dc36..7fbfad467c641 100644 --- a/src/ci/citool/src/analysis.rs +++ b/src/ci/citool/src/analysis.rs @@ -1,11 +1,11 @@ +use std::collections::{BTreeMap, HashMap, HashSet}; use std::fmt::Debug; +use std::time::Duration; use build_helper::metrics::{ BuildStep, JsonRoot, TestOutcome, TestSuite, TestSuiteMetadata, escape_step_name, format_build_steps, }; -use std::collections::{BTreeMap, HashMap, HashSet}; -use std::time::Duration; use crate::metrics; use crate::metrics::{JobMetrics, JobName, get_test_suites}; diff --git a/src/ci/docker/run.sh b/src/ci/docker/run.sh index 2805bb1118d82..00d791eeb6b38 100755 --- a/src/ci/docker/run.sh +++ b/src/ci/docker/run.sh @@ -355,6 +355,8 @@ docker \ --env GITHUB_ACTIONS \ --env GITHUB_REF \ --env GITHUB_STEP_SUMMARY="/checkout/obj/${SUMMARY_FILE}" \ + --env GITHUB_WORKFLOW_RUN_ID \ + --env GITHUB_REPOSITORY \ --env RUST_BACKTRACE \ --env TOOLSTATE_REPO_ACCESS_TOKEN \ --env TOOLSTATE_REPO \