From d51440be07ded73de652b3a222b71ad5b01387c2 Mon Sep 17 00:00:00 2001 From: aerooneqq Date: Wed, 30 Sep 2026 18:15:16 +0300 Subject: [PATCH] Remap def indices for deterministic metadata encoding --- compiler/rustc_hir_id/src/definitions.rs | 17 +- compiler/rustc_metadata/src/rmeta/decoder.rs | 10 +- compiler/rustc_metadata/src/rmeta/encoder.rs | 228 +++++++++++++----- compiler/rustc_metadata/src/rmeta/mod.rs | 4 +- .../async-fns-issue-162202.rs | 3 + .../parallel-reproducible-build/rmake.rs | 33 +++ .../rpit-issue-162202.rs | 19 ++ .../static-muts-lib-issue-162203.rs | 4 + 8 files changed, 252 insertions(+), 66 deletions(-) create mode 100644 tests/run-make/parallel-reproducible-build/async-fns-issue-162202.rs create mode 100644 tests/run-make/parallel-reproducible-build/rpit-issue-162202.rs create mode 100644 tests/run-make/parallel-reproducible-build/static-muts-lib-issue-162203.rs diff --git a/compiler/rustc_hir_id/src/definitions.rs b/compiler/rustc_hir_id/src/definitions.rs index 426a4e0109153..54f5561d7e901 100644 --- a/compiler/rustc_hir_id/src/definitions.rs +++ b/compiler/rustc_hir_id/src/definitions.rs @@ -6,6 +6,7 @@ use std::fmt::{self, Write}; use std::hash::Hash; +use std::sync::OnceLock; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sorted_map::SortedMap; @@ -95,6 +96,7 @@ pub struct Definitions { def_id_to_key: IndexVec, // We do only store the local hash, as all the definitions are from the current crate. def_path_hashes: IndexVec, + last_deterministic_index: OnceLock, def_path_hash_to_index: DefPathToIndexMap, } @@ -292,13 +294,21 @@ pub enum DefPathData { } impl Definitions { - /// This function indicates that the order of def id allocations - /// may be non-deterministic after it was called. pub fn commit_end_of_determinism(&mut self) { assert!( self.def_path_hash_to_index.after_parallel_alloc.replace(Default::default()).is_none(), "this function should be called only once" - ) + ); + + self.last_deterministic_index + .set( + if self.def_id_to_key.is_empty() { 0 } else { self.def_id_to_key.len() - 1 }.into(), + ) + .expect("must be called once"); + } + + pub fn last_deterministic_index(&self) -> DefIndex { + self.last_deterministic_index.get().copied().expect("must contain index") } #[inline(always)] @@ -352,6 +362,7 @@ impl Definitions { def_path_hashes: Default::default(), def_id_to_key: Default::default(), def_path_hash_to_index: Default::default(), + last_deterministic_index: Default::default(), }; // Create the root definition. diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 7dd920c7e39bd..eb6deda93da27 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -1544,7 +1544,9 @@ impl CrateMetadata { fn get_proc_macro_quoted_span(&self, tcx: TyCtxt<'_>, index: usize) -> Span { self.root - .tables + .proc_macro_data + .as_ref() + .unwrap() .proc_macro_quoted_spans .get(self, index) .unwrap_or_else(|| panic!("Missing proc macro quoted span: {index:?}")) @@ -1965,8 +1967,12 @@ impl CrateMetadata { let trait_impls = root .impls .decode(&blob) - .map(|trait_impls| (trait_impls.trait_id, trait_impls.impls)) + .map(|trait_impls| { + let (krate, index) = trait_impls.trait_id; + ((krate, DefIndex::from_u32(index)), trait_impls.impls) + }) .collect(); + let alloc_decoding_state = AllocDecodingState::new(root.interpret_alloc_index.decode(&blob).collect()); diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 40b61a52d2310..ead5b2e2d78d5 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -21,7 +21,7 @@ use rustc_hir as hir; use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE, LocalDefId, LocalDefIdSet}; use rustc_hir::definitions::DefPathData; use rustc_hir_pretty::id_to_string; -use rustc_index::IndexVec; +use rustc_index::{Idx, IndexVec}; use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; use rustc_middle::hir::map::compute_hir_hash; use rustc_middle::middle::dependency_format::Linkage; @@ -78,6 +78,8 @@ pub(super) struct EncodeContext<'a, 'tcx> { hygiene_ctxt: Rc>, // Used for both `Symbol`s and `ByteSymbol`s. symbol_index_table: FxHashMap, + pub(super) def_indexes_remapping: FxHashMap, + last_deterministic_index: u32, } /// If the current crate is a proc-macro, returns early with `LazyArray::default()`. @@ -156,12 +158,14 @@ impl<'a, 'tcx> SpanEncoder for EncodeContext<'a, 'tcx> { } fn encode_def_index(&mut self, def_index: DefIndex) { - self.emit_u32(def_index.as_u32()); + self.emit_u32(self.map_index(def_index).as_u32()); } fn encode_def_id(&mut self, def_id: DefId) { + let def_id = self.map_def_id(def_id); + def_id.krate.encode(self); - def_id.index.encode(self); + self.emit_u32(def_id.index.as_u32()); } fn encode_syntax_context(&mut self, syntax_context: SyntaxContext) { @@ -409,7 +413,26 @@ macro_rules! record { { let value = $value; let lazy = $self.lazy(value); - $self.$tables.$table.set_some($def_id.index, lazy); + let def_id = $self.map_def_id($def_id); + $self.$tables.$table.set_some(def_id.index, lazy); + } + }}; +} + +macro_rules! record_non_lazy { + ($self:ident.$tables:ident.$table:ident[$def_id:expr] <- $value:expr) => {{ + { + let def_id = $self.map_def_id($def_id); + $self.$tables.$table.set_some(def_id.index, $value); + } + }}; +} + +macro_rules! record_defaulted { + ($self:ident.$tables:ident.$table:ident[$def_id:expr] <- $value:expr) => {{ + { + let def_id = $self.map_def_id($def_id); + $self.$tables.$table.set(def_id.index, $value); } }}; } @@ -421,7 +444,8 @@ macro_rules! record_array { { let value = $value; let lazy = $self.lazy_array(value); - $self.$tables.$table.set_some($def_id.index, lazy); + let def_id = $self.map_def_id($def_id); + $self.$tables.$table.set_some(def_id.index, lazy); } }}; } @@ -431,7 +455,8 @@ macro_rules! record_defaulted_array { { let value = $value; let lazy = $self.lazy_array(value); - $self.$tables.$table.set($def_id.index, lazy); + let def_id = $self.map_def_id($def_id); + $self.$tables.$table.set(def_id.index, lazy); } }}; } @@ -521,24 +546,28 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } } - fn encode_def_path_table(&mut self) { + fn encode_def_path_table(&mut self, sorted_ids: &[LocalDefId]) { let defs = self.tcx.definitions(); if self.is_proc_macro { for def_id in std::iter::once(CRATE_DEF_ID) .chain(self.tcx.resolutions(()).proc_macros.iter().copied()) { - let def_key = self.lazy(defs.def_key(def_id)); + let def_key = defs.def_key(def_id); let def_path_hash = defs.def_path_hash(def_id); - self.tables.def_keys.set_some(def_id.local_def_index, def_key); - self.tables - .def_path_hashes - .set(def_id.local_def_index, def_path_hash.local_hash().as_u64()); + let def_id = def_id.to_def_id(); + + record!(self.tables.def_keys[def_id] <- def_key); + record_defaulted!(self.tables.def_path_hashes[def_id] <- def_path_hash.local_hash().as_u64()) } } else { - for (def_index, def_key, def_path_hash) in defs.enumerated_keys_and_path_hashes() { - let def_key = self.lazy(def_key); - self.tables.def_keys.set_some(def_index, def_key); - self.tables.def_path_hashes.set(def_index, def_path_hash.local_hash().as_u64()); + for &def_id in sorted_ids { + let def_key = defs.def_key(def_id); + let hash = defs.def_path_hash(def_id).local_hash().as_u64(); + + let def_id = def_id.to_def_id(); + + record!(self.tables.def_keys[def_id] <- def_key); + record_defaulted!(self.tables.def_path_hashes[def_id] <- hash); } } } @@ -617,7 +646,13 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { adapted.encode(&mut self.opaque) } - fn encode_crate_root(&mut self) -> (LazyValue, LazyValue) { + fn encode_crate_root( + &mut self, + remapping: FxHashMap, + sorted_ids: Vec, + ) -> (LazyValue, LazyValue) { + self.def_indexes_remapping = remapping; + let tcx = self.tcx; let mut stats: Vec<(&'static str, usize)> = Vec::with_capacity(32); @@ -660,7 +695,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let foreign_modules = stat!("foreign-modules", || self.encode_foreign_modules()); - _ = stat!("def-path-table", || self.encode_def_path_table()); + _ = stat!("def-path-table", || self.encode_def_path_table(&sorted_ids)); // Encode the def IDs of traits, for rustdoc and diagnostics. let traits = stat!("traits", || self.encode_traits()); @@ -672,7 +707,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { _ = stat!("mir", || self.encode_mir()); - _ = stat!("def-ids", || self.encode_def_ids()); + _ = stat!("def-ids", || self.encode_def_ids(&sorted_ids)); let interpret_alloc_index = stat!("interpret-alloc-index", || { let mut interpret_alloc_index = Vec::new(); @@ -1444,10 +1479,30 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { if state.is_doc_hidden { attr_flags |= AttrFlags::IS_DOC_HIDDEN; } - self.tables.attr_flags.set(def_id.local_def_index, attr_flags); + + record_defaulted!(self.tables.attr_flags[def_id.to_def_id()] <- attr_flags) } - fn encode_def_ids(&mut self) { + fn map_def_id(&self, def_id: DefId) -> DefId { + if def_id.is_local() { + DefId { krate: LOCAL_CRATE, index: self.map_index(def_id.index) } + } else { + def_id + } + } + + #[inline] + fn map_index(&self, def_index: DefIndex) -> DefIndex { + let index = def_index.as_u32(); + + if index <= self.last_deterministic_index { + def_index + } else { + self.def_indexes_remapping.get(&def_index).copied().unwrap_or(def_index) + } + } + + fn encode_def_ids(&mut self, sorted_ids: &[LocalDefId]) { self.encode_info_for_mod(CRATE_DEF_ID); // Proc-macro crates only export proc-macro items, which are looked @@ -1457,11 +1512,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } let tcx = self.tcx; - - for local_id in tcx.iter_local_def_id() { + for &local_id in sorted_ids { let def_id = local_id.to_def_id(); let def_kind = tcx.def_kind(local_id); - self.tables.def_kind.set_some(def_id.index, def_kind); + record_non_lazy!(self.tables.def_kind[def_id] <- def_kind); // The `DefCollector` will sometimes create unnecessary `DefId`s // for trivial const arguments which are directly lowered to @@ -1545,11 +1599,11 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } if should_encode_constness(def_kind) { let constness = self.tcx.constness(def_id); - self.tables.constness.set(def_id.index, constness); + record_defaulted!(self.tables.constness[def_id] <- constness) } if let DefKind::Fn | DefKind::AssocFn = def_kind { let asyncness = tcx.asyncness(def_id); - self.tables.asyncness.set(def_id.index, asyncness); + record_defaulted!(self.tables.asyncness[def_id] <- asyncness); record_array!(self.tables.fn_arg_idents[def_id] <- tcx.fn_arg_idents(def_id)); } if let Some(name) = tcx.intrinsic(def_id) { @@ -1595,22 +1649,21 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { if let DefKind::Closure | DefKind::SyntheticCoroutineBody = def_kind && let Some(coroutine_kind) = self.tcx.coroutine_kind(def_id) { - self.tables.coroutine_kind.set(def_id.index, Some(coroutine_kind)) + record_defaulted!(self.tables.coroutine_kind[def_id] <- Some(coroutine_kind)) } if def_kind == DefKind::Closure && tcx.type_of(def_id).skip_binder().is_coroutine_closure() { let coroutine_for_closure = self.tcx.coroutine_for_closure(def_id); - self.tables - .coroutine_for_closure - .set_some(def_id.index, coroutine_for_closure.into()); + record_non_lazy!(self.tables.coroutine_for_closure[def_id] <- self.map_def_id(coroutine_for_closure).into()); // If this async closure has a by-move body, record it too. if tcx.needs_coroutine_by_move_body_def_id(coroutine_for_closure) { - self.tables.coroutine_by_move_body_def_id.set_some( - coroutine_for_closure.index, - self.tcx.coroutine_by_move_body_def_id(coroutine_for_closure).into(), - ); + record_non_lazy!(self.tables.coroutine_by_move_body_def_id[coroutine_for_closure] <- self.map_def_id( + self.tcx.coroutine_by_move_body_def_id(coroutine_for_closure), + ) + .into() + ) } } if let DefKind::Static { .. } = def_kind { @@ -1640,9 +1693,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { self.encode_info_for_macro(local_id); } if let DefKind::TyAlias = def_kind { - self.tables - .type_alias_is_checked - .set(def_id.index, self.tcx.type_alias_is_checked(def_id)); + record_defaulted!(self.tables.type_alias_is_checked[def_id] <- self.tcx.type_alias_is_checked(def_id)); + if self.tcx.type_alias_is_checked(def_id) { record!(self.tables.args_known_to_outlive_alias_params[def_id] <- tcx.args_known_to_outlive_alias_params(def_id)); } @@ -1753,7 +1805,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { })); for field in &variant.fields { - self.tables.safety.set(field.did.index, field.safety); + record_defaulted!(self.tables.safety[field.did] <- field.safety); record!( self.tables.mut_restriction[field.did] <- field.mut_restriction ); @@ -1826,7 +1878,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let item = tcx.associated_item(def_id); if matches!(item.container, AssocContainer::Trait | AssocContainer::TraitImpl(_)) { - self.tables.defaultness.set(def_id.index, item.defaultness(tcx)); + record_defaulted!(self.tables.defaultness[def_id] <- item.defaultness(tcx)); } record!(self.tables.assoc_container[def_id] <- item.container); @@ -1879,9 +1931,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { debug!("EntryBuilder::encode_mir({:?})", def_id); if encode_opt { record!(self.tables.optimized_mir[def_id.to_def_id()] <- tcx.optimized_mir(def_id)); - self.tables - .cross_crate_inlinable - .set(def_id.to_def_id().index, self.tcx.cross_crate_inlinable(def_id)); + + record_defaulted!(self.tables.cross_crate_inlinable[def_id.to_def_id()] <- self.tcx.cross_crate_inlinable(def_id)); + record!(self.tables.closure_saved_names_of_captured_variables[def_id.to_def_id()] <- tcx.closure_saved_names_of_captured_variables(def_id)); @@ -1989,7 +2041,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let tcx = self.tcx; let (_, macro_def, _) = tcx.hir_expect_item(def_id).expect_macro(); - self.tables.is_macro_rules.set(def_id.local_def_index, macro_def.macro_rules); + record_defaulted!(self.tables.is_macro_rules[def_id.to_def_id()] <- macro_def.macro_rules); record!(self.tables.macro_definition[def_id.to_def_id()] <- &*macro_def.body); } @@ -2039,12 +2091,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let tcx = self.tcx; let proc_macro_decls_static = tcx.proc_macro_decls_static(()).unwrap().local_def_index; let stability = tcx.lookup_stability(CRATE_DEF_ID); - for (i, span) in self.tcx.sess.proc_macro_quoted_spans() { - let span = self.lazy(span); - self.tables.proc_macro_quoted_spans.set_some(i, span); - } - self.tables.def_kind.set_some(LOCAL_CRATE.as_def_id().index, DefKind::Mod); + record_non_lazy!(self.tables.def_kind[LOCAL_CRATE.as_def_id()] <- DefKind::Mod); record!(self.tables.def_span[LOCAL_CRATE.as_def_id()] <- tcx.def_span(LOCAL_CRATE.as_def_id())); self.encode_attrs(LOCAL_CRATE.as_def_id().expect_local()); let vis = tcx @@ -2103,7 +2151,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { def_key.disambiguated_data.data = DefPathData::MacroNs(name); let def_id = id.to_def_id(); - self.tables.def_kind.set_some(def_id.index, DefKind::Macro(macro_kind.into())); + record_non_lazy!(self.tables.def_kind[def_id] <- DefKind::Macro(macro_kind.into())); + self.encode_attrs(id); record!(self.tables.def_keys[def_id] <- def_key); record!(self.tables.def_ident_span[def_id] <- span); @@ -2116,7 +2165,20 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let macros = self.lazy_array(macros); - Some(ProcMacroData { proc_macro_decls_static, stability, macros }) + let mut proc_macro_quoted_spans = TableBuilder::default(); + for (i, span) in self.tcx.sess.proc_macro_quoted_spans() { + let span = self.lazy(span); + proc_macro_quoted_spans.set_some(i, span); + } + + let proc_macro_quoted_spans = proc_macro_quoted_spans.encode(&mut self.opaque); + + Some(ProcMacroData { + proc_macro_decls_static, + stability, + macros, + proc_macro_quoted_spans, + }) } else { None } @@ -2267,11 +2329,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let impl_is_fully_generic_for_reflection = tcx.impl_is_fully_generic_for_reflection(def_id); - self.tables - .impl_is_fully_generic_for_reflection - .set(def_id.index, impl_is_fully_generic_for_reflection); - self.tables.defaultness.set(def_id.index, tcx.defaultness(def_id)); + record_defaulted!(self.tables.impl_is_fully_generic_for_reflection[def_id] <- impl_is_fully_generic_for_reflection); + record_defaulted!(self.tables.defaultness[def_id] <- tcx.defaultness(def_id)); let trait_ref = header.trait_ref.instantiate_identity().skip_norm_wip(); let simplified_self_ty = fast_reject::simplify_type( @@ -2288,7 +2348,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { if let Ok(mut an) = trait_def.ancestors(tcx, def_id) && let Some(specialization_graph::Node::Impl(parent)) = an.nth(1) { - self.tables.impl_parent.set_some(def_id.index, parent.into()); + record_non_lazy!(self.tables.impl_parent[def_id] <- self.map_def_id(parent).into()); } // if this is an impl of `CoerceUnsized`, create its @@ -2302,9 +2362,12 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let trait_impls: Vec<_> = trait_impls .into_iter() - .map(|(trait_def_id, impls)| TraitImpls { - trait_id: (trait_def_id.krate.as_u32(), trait_def_id.index), - impls: self.lazy_array(&impls), + .map(|(trait_id, impls)| { + let trait_id = self.map_def_id(trait_id); + TraitImpls { + trait_id: (trait_id.krate.as_u32(), trait_id.index.as_u32()), + impls: self.lazy_array(&impls), + } }) .collect(); @@ -2587,7 +2650,9 @@ pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path, ref_path: Option<&Path>) { with_encode_metadata_header(tcx, path, |ecx| { // Encode all the entries and extra information in the crate, // culminating in the `CrateRoot` which points to all of it. - let (root, unhashed) = ecx.encode_crate_root(); + let (remapping, sequence) = create_def_index_remapping(tcx); + + let (root, unhashed) = ecx.encode_crate_root(remapping, sequence); // Flush buffer to ensure backing file has the correct size. ecx.opaque.flush(); @@ -2620,6 +2685,49 @@ pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path, ref_path: Option<&Path>) { } } +fn create_def_index_remapping(tcx: TyCtxt<'_>) -> (FxHashMap, Vec) { + let defs = tcx.untracked().definitions.read(); + + let mut to_remap = vec![]; + let mut def_ids = vec![]; + + let start = tcx.definitions().last_deterministic_index().as_usize() + 1; + for idx in start..defs.num_definitions() { + let def_id = LocalDefId { local_def_index: idx.into() }; + if let Some(data) = defs.def_path(def_id).data.last() + && matches!( + data.data, + DefPathData::SyntheticCoroutineBody + | DefPathData::OpaqueLifetime(..) + | DefPathData::NestedStatic + | DefPathData::AnonAssocTy(..) + ) + { + to_remap.push((def_id, defs.def_path_hash(def_id).local_hash())); + def_ids.push(def_id); + } + } + + to_remap.sort_by_key(|(_, hash)| *hash); + + let mut remapping = FxHashMap::default(); + for ((orig_id, _), remapped_id) in to_remap.into_iter().zip(def_ids) { + remapping.insert(orig_id.local_def_index, remapped_id.local_def_index); + } + + let mut sorted_def_ids = (0..defs.num_definitions()) + .into_iter() + .map(|idx| LocalDefId { local_def_index: DefIndex::new(idx) }) + .collect::>(); + + sorted_def_ids.sort_by_key(|id| { + let def_index = id.local_def_index; + remapping.get(&def_index).copied().unwrap_or(def_index) + }); + + (remapping, sorted_def_ids) +} + fn with_encode_metadata_header( tcx: TyCtxt<'_>, path: &Path, @@ -2693,6 +2801,8 @@ fn with_encode_metadata_header( is_proc_macro: tcx.crate_types().contains(&CrateType::ProcMacro), hygiene_ctxt: Default::default(), symbol_index_table: Default::default(), + def_indexes_remapping: Default::default(), + last_deterministic_index: tcx.definitions().last_deterministic_index().as_u32(), }; // Encode the rustc version string in a predictable location. diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index b70151604f679..3848bb3eda88e 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -214,6 +214,7 @@ pub(crate) struct ProcMacroData { proc_macro_decls_static: DefIndex, stability: Option, macros: LazyArray<(DefIndex, LazyValue)>, + proc_macro_quoted_spans: LazyTableSingleIdx>>, } #[derive(MetadataEncodable, LazyDecodable)] @@ -377,7 +378,7 @@ pub(crate) struct CrateDep { #[derive(MetadataEncodable, LazyDecodable)] pub(crate) struct TraitImpls { - trait_id: (u32, DefIndex), + trait_id: (u32 /* crate */, u32 /* def index */), impls: LazyArray<(DefIndex, Option)>, } @@ -503,7 +504,6 @@ define_tables! { // `DefPathTable` up front, since we may only ever use a few // definitions from any given crate. def_keys: Table>, - proc_macro_quoted_spans: Table>, variant_data: Table>, assoc_container: Table>, macro_definition: Table>, diff --git a/tests/run-make/parallel-reproducible-build/async-fns-issue-162202.rs b/tests/run-make/parallel-reproducible-build/async-fns-issue-162202.rs new file mode 100644 index 0000000000000..1e959cfd62543 --- /dev/null +++ b/tests/run-make/parallel-reproducible-build/async-fns-issue-162202.rs @@ -0,0 +1,3 @@ +async fn test1(_: &'_ u8) {} +async fn test2<'s>(_: &'s u8) {} +fn main() {} diff --git a/tests/run-make/parallel-reproducible-build/rmake.rs b/tests/run-make/parallel-reproducible-build/rmake.rs index caaee1b47c583..01de08e0551f3 100644 --- a/tests/run-make/parallel-reproducible-build/rmake.rs +++ b/tests/run-make/parallel-reproducible-build/rmake.rs @@ -14,6 +14,39 @@ fn main() { const TESTS: &[(&str, &[&str])] = &[ ("static-muts-issue-140413", &["-Zthreads=50"]), ("derives-issue-129094", &["-Zthreads=16", "-Copt-level=3"]), + ( + "async-fns-issue-162202", + &[ + "-Zthreads=30", + "--crate-type=lib", + "--crate-name=test", + "-Ccodegen-units=1", + "-Zremap-cwd-prefix=reproducible_dir", + "--edition=2024", + ], + ), + ( + "rpit-issue-162202", + &[ + "-Zthreads=30", + "--crate-type=lib", + "--crate-name=test", + "-Ccodegen-units=1", + "-Zremap-cwd-prefix=reproducible_dir", + "--edition=2024", + ], + ), + ( + "static-muts-lib-issue-162203", + &[ + "-Zthreads=30", + "--edition=2024", + "-Zremap-cwd-prefix=reproducible_dir", + "--cap-lints=warn", + "-Ccodegen-units=1", + "-Clink-dead-code=true", + ], + ), ]; for (file, args) in TESTS { diff --git a/tests/run-make/parallel-reproducible-build/rpit-issue-162202.rs b/tests/run-make/parallel-reproducible-build/rpit-issue-162202.rs new file mode 100644 index 0000000000000..1147f4d450d7d --- /dev/null +++ b/tests/run-make/parallel-reproducible-build/rpit-issue-162202.rs @@ -0,0 +1,19 @@ +trait Foo { + fn test() -> impl IntoIterator + Send; +} + +struct A; +impl Foo for A { + fn test() -> impl IntoIterator + Send { + [] + } +} + +struct B; +impl Foo for B { + fn test() -> impl IntoIterator + Send { + [] + } +} + +fn main() {} diff --git a/tests/run-make/parallel-reproducible-build/static-muts-lib-issue-162203.rs b/tests/run-make/parallel-reproducible-build/static-muts-lib-issue-162203.rs new file mode 100644 index 0000000000000..adda309c8cd39 --- /dev/null +++ b/tests/run-make/parallel-reproducible-build/static-muts-lib-issue-162203.rs @@ -0,0 +1,4 @@ +#![crate_type = "lib"] +static mut TEST: &'static mut [isize] = &mut [1]; +static mut TEST_RAW: *mut [isize] = &mut [1isize] as *mut _; +pub fn main() {}