diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs index 706a60d84f402..bdd22ab7a2524 100644 --- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs +++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs @@ -610,7 +610,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> { // loop iteration. In this case, try using the loop terminator location in // `find_sub_region_live_at`. if let Some(loop_terminator_location) = - regioncx.find_loop_terminator_location(borrow.region, body) + regioncx.find_loop_terminator_location(borrow.region, body, location) { region_sub = self .regioncx diff --git a/compiler/rustc_borrowck/src/region_infer/region_context.rs b/compiler/rustc_borrowck/src/region_infer/region_context.rs index 327acb7da3fb8..6f29c42eed249 100644 --- a/compiler/rustc_borrowck/src/region_infer/region_context.rs +++ b/compiler/rustc_borrowck/src/region_infer/region_context.rs @@ -816,16 +816,19 @@ impl<'tcx> RegionInferenceContextInner<'tcx> { &self, r: RegionVid, body: &Body<'_>, + from_location: Location, ) -> Option { let scc = self.constraint_sccs.scc(r); let locations = self.scc_values.locations_outlived_by(scc); for location in locations { - let bb = &body[location.block]; - if let Some(terminator) = &bb.terminator + if from_location.is_predecessor_of(location, body) { + let bb = &body[location.block]; + if let Some(terminator) = &bb.terminator // terminator of a loop should be TerminatorKind::FalseUnwind && let TerminatorKind::FalseUnwind { .. } = terminator.kind - { - return Some(location); + { + return Some(location); + } } } None diff --git a/compiler/rustc_hir_id/src/definitions.rs b/compiler/rustc_hir_id/src/definitions.rs index 92c8aeb43f283..557b87bedff85 100644 --- a/compiler/rustc_hir_id/src/definitions.rs +++ b/compiler/rustc_hir_id/src/definitions.rs @@ -98,6 +98,9 @@ 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, + // The first non deterministic def index, may correspond to non-allocated + // def id, in this case `first_non_det_index.as_usize() == num_definitions`. + first_non_det_index: Option, def_path_hash_to_index: DefPathToIndexMap, } @@ -302,13 +305,18 @@ pub enum DefPathData { } impl Definitions { - /// This function indicates that the order of def id allocations + /// This function indicates that the 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" - ) + let prev = self.def_path_hash_to_index.after_parallel_alloc.replace(Default::default()); + assert!(prev.is_none(), "this function should be called only once"); + + let def_index = DefIndex::from_usize(self.def_id_to_key.len()); + self.first_non_det_index.replace(def_index); + } + + pub fn first_non_det_index(&self) -> DefIndex { + self.first_non_det_index.expect("must contain index") } #[inline(always)] @@ -362,6 +370,7 @@ impl Definitions { def_path_hashes: Default::default(), def_id_to_key: Default::default(), def_path_hash_to_index: Default::default(), + first_non_det_index: Default::default(), }; // Create the root definition. diff --git a/compiler/rustc_interface/src/limits.rs b/compiler/rustc_interface/src/limits.rs index a0791bb22df6d..a97aef1a66058 100644 --- a/compiler/rustc_interface/src/limits.rs +++ b/compiler/rustc_interface/src/limits.rs @@ -8,28 +8,51 @@ //! Users can override these limits via an attribute on the crate like //! `#![recursion_limit="22"]`. This pass just looks for those attributes. +use rustc_ast::{self as ast, DUMMY_NODE_ID}; +use rustc_attr_ir::target::Target; use rustc_attr_ir::{Attribute, find_attr}; -use rustc_middle::query::Providers; +use rustc_attr_parsing::{AttributeParser, ShouldEmit}; +use rustc_feature::Features; use rustc_session::{Limits, Session}; +use rustc_span::{DUMMY_SP, sym}; use rustc_structures::Limit; -pub(crate) fn provide(providers: &mut Providers) { - providers.limits = |tcx, ()| { - let attrs = tcx.hir_krate_attrs(); - Limits { - recursion_limit: get_recursion_limit(tcx.hir_krate_attrs(), tcx.sess), - move_size_limit: find_attr!(attrs, MoveSizeLimit { limit } => *limit) - .unwrap_or(Limit::new(tcx.sess.opts.unstable_opts.move_size_limit.unwrap_or(0))), - type_length_limit: find_attr!(attrs, TypeLengthLimit { limit } => *limit) - .unwrap_or(Limit::new(2usize.pow(24))), - pattern_complexity_limit: find_attr!(attrs, PatternComplexityLimit { limit } => *limit) - .unwrap_or(Limit::unlimited()), - } +pub fn get_limits(krate_attrs: &[ast::Attribute], sess: &Session, features: &Features) -> Limits { + let attrs = AttributeParser::parse_limited_all( + sess, + &krate_attrs, + Some(&|attr| { + attr.has_any_name(&[ + sym::recursion_limit, + sym::move_size_limit, + sym::type_length_limit, + sym::pattern_complexity_limit, + ]) + }), + Target::Crate, + DUMMY_SP, + DUMMY_NODE_ID, + Some(features), + // errors are fatal here, but lints aren't. + // If things aren't fatal we continue, and will parse this again. + // That makes the same lint trigger again. + // So, no lints here to avoid duplicates. + ShouldEmit::EarlyFatal { also_emit_lints: false }, + None, + ); + let attrs = &attrs; + Limits { + recursion_limit: get_recursion_limit(attrs, sess), + move_size_limit: find_attr!(attrs, MoveSizeLimit { limit } => *limit) + .unwrap_or(Limit::new(sess.opts.unstable_opts.move_size_limit.unwrap_or(0))), + type_length_limit: find_attr!(attrs, TypeLengthLimit { limit } => *limit) + .unwrap_or(Limit::new(2usize.pow(24))), + pattern_complexity_limit: find_attr!(attrs, PatternComplexityLimit { limit } => *limit) + .unwrap_or(Limit::unlimited()), } } -// This one is separate because it must be read prior to macro expansion. -pub(crate) fn get_recursion_limit(attrs: &[Attribute], sess: &Session) -> Limit { +fn get_recursion_limit(attrs: &[Attribute], sess: &Session) -> Limit { let limit_from_crate = find_attr!(attrs, RecursionLimit { limit } => limit.0).unwrap_or(128); Limit::new( sess.opts diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index f0990d075e396..73bebb22bc508 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -44,7 +44,7 @@ use rustc_session::{IncrCompSession, Session}; use rustc_span::{ DUMMY_SP, ErrorGuaranteed, ExpnKind, SourceFileHash, SourceFileHashAlgorithm, Span, Symbol, sym, }; -use rustc_structures::{CrateType, Limit}; +use rustc_structures::CrateType; use rustc_trait_selection::{solve, traits}; use tracing::{info, instrument}; @@ -201,7 +201,7 @@ fn configure_and_expand( } // Create the config for macro expansion - let recursion_limit = get_recursion_limit(pre_configured_attrs, sess); + let recursion_limit = tcx.recursion_limit(); let cfg = rustc_expand::expand::ExpansionConfig { crate_name, features, @@ -905,7 +905,6 @@ pub static DEFAULT_QUERY_PROVIDERS: LazyLock = LazyLock::new(|| { providers.queries.env_var_os = env_var_os; providers.queries.proc_macro_decls_static = |tcx, _| tcx.hir_crate_items(()).proc_macro_decls(); rustc_ast_lowering::provide(&mut providers.queries); - limits::provide(&mut providers.queries); rustc_expand_queries::provide(&mut providers.queries); rustc_const_eval::provide(providers); rustc_middle::hir::provide(&mut providers.queries); @@ -1037,11 +1036,13 @@ pub fn create_and_enter_global_ctxt FnOnce(TyCtxt<'tcx>) -> T>( feed.crate_name(crate_name); let feed = tcx.feed_unit_query(); - feed.features_query(tcx.arena.alloc(rustc_expand::config::features( + let features = tcx.arena.alloc(rustc_expand::config::features( tcx.sess, &pre_configured_attrs, crate_name, - ))); + )); + feed.features_query(features); + feed.limits(limits::get_limits(&pre_configured_attrs, tcx.sess, features)); feed.crate_for_resolver(tcx.arena.alloc(Steal::new((krate, pre_configured_attrs)))); feed.output_filenames(Arc::new(outputs)); @@ -1523,19 +1524,3 @@ pub fn collect_crate_types( fn default_output_for_target(sess: &Session) -> CrateType { if !sess.target.executables { CrateType::StaticLib } else { CrateType::Executable } } - -fn get_recursion_limit(krate_attrs: &[ast::Attribute], sess: &Session) -> Limit { - let attr = AttributeParser::parse_limited_sym_should_emit( - sess, - &krate_attrs, - &[sym::recursion_limit], - DUMMY_SP, - None, - // errors are fatal here, but lints aren't. - // If things aren't fatal we continue, and will parse this again. - // That makes the same lint trigger again. - // So, no lints here to avoid duplicates. - ShouldEmit::EarlyFatal { also_emit_lints: false }, - ); - crate::limits::get_recursion_limit(attr.as_slice(), sess) -} diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 5705831bcfaee..f68cfcc0d388b 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -41,6 +41,7 @@ use tracing::debug; use crate::creader::CStore; use crate::eii::EiiMapEncodedKeyValue; +use crate::rmeta::remapped_def_id::RemappedRawDefId; use crate::rmeta::table::IsDefault; use crate::rmeta::*; @@ -103,7 +104,7 @@ pub(crate) struct CrateMetadata { /// FIXME: make type of the value `LazyArray<(DefIndex, Option)>` /// through transmuting or somehow else, as `LocalDefId` here should be `DefIndex`, /// as it is from external crate. - trait_impls: FxIndexMap)>>, + trait_impls: FxIndexMap)>>, /// Inherent impls which do not follow the normal coherence rules. /// /// These can be introduced using either `#![rustc_coherence_is_core]` @@ -2163,10 +2164,10 @@ impl CrateMetadata { // Translate a DefId from the current compilation environment to a DefId // for an external crate. - fn reverse_translate_def_id(&self, did: DefId) -> Option { + fn reverse_translate_def_id(&self, did: DefId) -> Option { for (local, &global) in self.cnum_map.iter_enumerated() { if global == did.krate { - return Some(RawDefId { krate: local.as_u32(), index: did.index.as_u32() }); + return Some(RemappedRawDefId::new_unchecked(local.as_u32(), did.index.as_u32())); } } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index f9f4c52b79d3b..2970bc0b7ed78 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -47,6 +47,7 @@ use twox_hash::XxHash3_128; use crate::diagnostics::{FailCreateFileEncoder, FailWriteFile}; use crate::eii::EiiMapEncodedKeyValue; +use crate::rmeta::remapped_def_id::RemappedRawDefId; use crate::rmeta::*; pub(super) struct EncodeContext<'a, 'tcx> { @@ -78,6 +79,7 @@ pub(super) struct EncodeContext<'a, 'tcx> { hygiene_ctxt: Rc>, // Used for both `Symbol`s and `ByteSymbol`s. symbol_index_table: FxHashMap, + local_defs_remapping: LocalDefsRemapping, } /// If the current crate is a proc-macro, returns early with `LazyArray::default()`. @@ -164,6 +166,8 @@ impl<'a, 'tcx> SpanEncoder for EncodeContext<'a, 'tcx> { } fn encode_def_id(&mut self, def_id: DefId) { + let def_id = self.local_defs_remapping.map_def_id(def_id); + def_id.krate.encode(self); self.emit_u32(def_id.index.as_u32()); } @@ -235,7 +239,7 @@ impl<'a, 'tcx> SpanEncoder for EncodeContext<'a, 'tcx> { /// `LocalDefId` as a wrapper around def index we want to encode /// def index only, so we override the encode implementation. fn encode_local_def_id(&mut self, def_id: LocalDefId) { - self.emit_u32(def_id.local_def_index.as_u32()); + self.emit_u32(self.local_defs_remapping.map_local_def_id(def_id).index.as_u32()); } /// We override encoding logic for `DefKey` during metadata encoding, @@ -434,20 +438,23 @@ macro_rules! record_some_lazy { ($self:ident.$tables:ident.$table:ident[$def_id:expr] <- $value:expr) => {{ let value = $value; let lazy = $self.lazy(value); - $self.$tables.$table.set_some($def_id, lazy); + let def_id = $self.local_defs_remapping.map_local_def_id($def_id); + $self.$tables.$table.set_some(def_id, lazy); }}; } macro_rules! record_some { - ($self:ident.$tables:ident.$table:ident[$def_id:expr] <- $value:expr) => { - $self.$tables.$table.set_some($def_id, $value) - }; + ($self:ident.$tables:ident.$table:ident[$def_id:expr] <- $value:expr) => {{ + let def_id = $self.local_defs_remapping.map_local_def_id($def_id); + $self.$tables.$table.set_some(def_id, $value) + }}; } macro_rules! record_value { - ($self:ident.$tables:ident.$table:ident[$def_id:expr] <- $value:expr) => { - $self.$tables.$table.set($def_id, $value) - }; + ($self:ident.$tables:ident.$table:ident[$def_id:expr] <- $value:expr) => {{ + let def_id = $self.local_defs_remapping.map_local_def_id($def_id); + $self.$tables.$table.set(def_id, $value) + }}; } // Shorthand for `$self.$tables.$table.set_some($def_id.index, $self.lazy_array($value))`, which would @@ -456,7 +463,8 @@ macro_rules! record_array { ($self:ident.$tables:ident.$table:ident[$def_id:expr] <- $value:expr) => {{ let value = $value; let lazy = $self.lazy_array(value); - $self.$tables.$table.set_some($def_id, lazy); + let def_id = $self.local_defs_remapping.map_local_def_id($def_id); + $self.$tables.$table.set_some(def_id, lazy); }}; } @@ -464,7 +472,8 @@ macro_rules! record_defaulted_array { ($self:ident.$tables:ident.$table:ident[$def_id:expr] <- $value:expr) => {{ let value = $value; let lazy = $self.lazy_array(value); - $self.$tables.$table.set($def_id, lazy); + let def_id = $self.local_defs_remapping.map_local_def_id($def_id); + $self.$tables.$table.set(def_id, lazy); }}; } @@ -566,10 +575,12 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { record_value!(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_id = LocalDefId { local_def_index: def_index }; + for def_id in self.local_defs_remapping.iter_sorted_local_ids() { + let def_key = defs.def_key(def_id); + let hash = defs.def_path_hash(def_id).local_hash().as_u64(); + record_some_lazy!(self.tables.def_keys[def_id] <- def_key); - record_value!(self.tables.def_path_hashes[def_id] <- def_path_hash.local_hash().as_u64()) + record_value!(self.tables.def_path_hashes[def_id] <- hash); } } } @@ -650,6 +661,11 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { fn encode_crate_root(&mut self) -> (LazyValue, LazyValue) { let tcx = self.tcx; + + // We set it here as we need it only for metadata encoding, + // while `with_encode_metadata_header` is used in some other places too. + self.local_defs_remapping = LocalDefsRemapping::new(tcx); + let mut stats: Vec<(&'static str, usize)> = Vec::with_capacity(32); macro_rules! stat { @@ -1489,8 +1505,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } let tcx = self.tcx; - - for local_id in tcx.iter_local_def_id() { + for local_id in self.local_defs_remapping.iter_sorted_local_ids() { let def_id = local_id.to_def_id(); let def_kind = tcx.def_kind(local_id); record_some!(self.tables.def_kind[local_id] <- def_kind); @@ -1630,13 +1645,18 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { && tcx.type_of(def_id).skip_binder().is_coroutine_closure() { let coroutine_for_closure = self.tcx.coroutine_for_closure(def_id); - record_some!(self.tables.coroutine_for_closure[local_id] <- coroutine_for_closure.into()); + let remapped_id = + RemappedRawDefId::create(coroutine_for_closure, &self.local_defs_remapping); + + record_some!(self.tables.coroutine_for_closure[local_id] <- remapped_id); // If this async closure has a by-move body, record it too. if tcx.needs_coroutine_by_move_body_def_id(coroutine_for_closure) { let id = self.tcx.coroutine_by_move_body_def_id(coroutine_for_closure); + let id = RemappedRawDefId::create(id, &self.local_defs_remapping); + record_some!( - self.tables.coroutine_by_move_body_def_id[coroutine_for_closure.expect_local()] <- id.into() + self.tables.coroutine_by_move_body_def_id[coroutine_for_closure.expect_local()] <- id ) } } @@ -2325,7 +2345,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { if let Ok(mut an) = trait_def.ancestors(tcx, local_id.to_def_id()) && let Some(specialization_graph::Node::Impl(parent)) = an.nth(1) { - record_some!(self.tables.impl_parent[local_id] <- parent.into()); + let parent = RemappedRawDefId::create(parent, &self.local_defs_remapping); + record_some!(self.tables.impl_parent[local_id] <- parent); } // if this is an impl of `CoerceUnsized`, create its @@ -2340,7 +2361,7 @@ 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.into(), + trait_id: RemappedRawDefId::create(trait_def_id, &self.local_defs_remapping), impls: self.lazy_array(&impls), }) .collect(); @@ -2734,6 +2755,7 @@ fn with_encode_metadata_header( is_proc_macro: tcx.crate_types().contains(&CrateType::ProcMacro), hygiene_ctxt: Default::default(), symbol_index_table: Default::default(), + local_defs_remapping: Default::default(), }; // 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 eef513382b57e..e0356d75c0a85 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -1,6 +1,7 @@ use std::marker::PhantomData; use std::mem::size_of; use std::num::NonZero; +use std::rc::Rc; use decoder::LazyDecoder; pub(crate) use decoder::{CrateMetadata, CrateNumMap, MetadataBlob, TargetModifiers}; @@ -22,11 +23,12 @@ use rustc_hir as hir; use rustc_hir::PreciseCapturingArgKind; use rustc_hir::def::{CtorKind, DefKind, MacroKinds}; use rustc_hir::def_id::{ - CrateNum, DefId, DefIdMap, DefIndex, DefPathHash, LocalDefId, StableCrateId, + CRATE_DEF_INDEX, CrateNum, DefId, DefIdMap, DefIndex, DefPathHash, LOCAL_CRATE, LocalDefId, + StableCrateId, }; use rustc_hir::definitions::DefKey; -use rustc_index::IndexVec; use rustc_index::bit_set::DenseBitSet; +use rustc_index::{Idx, IndexVec}; use rustc_macros::{ BlobDecodable, Decodable, Encodable, LazyDecodable, MetadataEncodable, TyDecodable, TyEncodable, }; @@ -52,6 +54,7 @@ use rustc_target::spec::{PanicStrategy, TargetTuple}; use table::TableBuilder; use crate::eii::EiiMapEncodedKeyValue; +use crate::rmeta::remapped_def_id::RemappedRawDefId; mod decoder; mod def_path_hash_map; @@ -340,27 +343,179 @@ pub(crate) struct CrateRootUnhashed { dep_extra_filenames: IndexVec, } -/// On-disk representation of `DefId`. -/// This creates a type-safe way to enforce that we remap the CrateNum between the on-disk -/// representation and the compilation session. -#[derive(Copy, Clone, Hash, PartialEq, Eq, Encodable, BlobDecodable)] -pub(crate) struct RawDefId { - krate: u32, - index: u32, +#[derive(Default)] +pub(crate) struct LocalDefsRemapping { + /// See `Definitions::first_non_det_index`, it is just cached version of it. + pub first_non_det_index: u32, + + /// The map where for each non-det local def id the remapped def index + /// is stored. It can be accessed by + /// `remapping[id.local_def_index - first_non_det_index]`, the caller should + /// ensure that `id.local_def_index >= first_non_det_index`. + pub remapping: Vec, + + /// The ordered list of NON-remapped non-det local def ids. This + /// list is used when we need to iterate over all local defs in a + /// stable order. + pub sorted_non_det_ids: Rc<[LocalDefId]>, } -impl From for RawDefId { - fn from(val: DefId) -> Self { - RawDefId { krate: val.krate.as_u32(), index: val.index.as_u32() } +#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] +pub(crate) struct RemappedLocalDefId { + pub index: DefIndex, +} + +impl Idx for RemappedLocalDefId { + #[inline] + fn new(idx: usize) -> Self { + RemappedLocalDefId { index: DefIndex::from_usize(idx) } + } + + #[inline] + fn index(self) -> usize { + self.index.as_usize() + } +} + +impl LocalDefsRemapping { + /// This method should be used whenever the `LocalDefId` is encoded, as it remaps + /// it's `local_def_index` for deterministic metadata encoding, this + /// remapping needs to be applied to all `LocalDefId`s during metadata encoding. + /// Note that when implementing custom structs that represent `LocalDefId` the + /// remapping should also be applied (see `RawDefId`). + #[inline] + fn map_local_def_id(&self, local_def_id: LocalDefId) -> RemappedLocalDefId { + RemappedLocalDefId { index: self.map_index(local_def_id.local_def_index) } + } + + /// Remaps `DefId` only if it local for deterministic metadata encoding. External + /// def ids are not needed to be remapped as they are already deterministic. + /// Whenever a `DefId` is encoded this method should be called. + /// Note that when implementing custom structs that represent `DefId` the + /// remapping should also be applied (see `RawDefId`). + #[inline] + 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 + } + } + + /// Shared part of `map_local_def_id` and `map_def_id` which remaps a def index. + /// Given only def index we do not know whether it belongs to local or external + /// def id, so this method should not be called on `DefIndex`es whose origin is unknown. + /// Prefer to use above-mentioned methods instead or use it when it is clear that + /// `DefIndex` is local. + #[inline] + fn map_index(&self, def_index: DefIndex) -> DefIndex { + let index = def_index.as_u32(); + + if index < self.first_non_det_index { + def_index + } else { + let shifted_idx = index - self.first_non_det_index; + self.remapping[shifted_idx as usize] + } + } + + fn iter_sorted_local_ids(&self) -> impl Iterator + use<> { + let first_non_det_index = self.first_non_det_index; + let non_det_part = Rc::clone(&self.sorted_non_det_ids); + + gen move { + for i in 0..first_non_det_index { + yield LocalDefId { local_def_index: DefIndex::from_u32(i) } + } + + let len = non_det_part.len(); + for i in 0..len { + yield non_det_part[i] + } + } + } + + fn new(tcx: TyCtxt<'_>) -> LocalDefsRemapping { + let defs = tcx.definitions(); + + let mut non_det_ids = vec![]; + let start = defs.first_non_det_index().as_usize(); + let num_defs = defs.num_definitions(); + + for idx in start..num_defs { + let def_id_level = |mut id| { + let mut level = 0; + while let Some(parent) = tcx.opt_local_parent(id) { + level += 1; + id = parent; + } + + level + }; + + let def_id = LocalDefId { local_def_index: idx.into() }; + non_det_ids.push(( + def_id, + def_id_level(def_id), + defs.def_path_hash(def_id).local_hash(), + )); + } + + // Sort by level first in order to satisfy the invariant that child def id + // always has a higher def index than its parent (see `def_id_partial_cmp`), + // in context of one level sort by stable hash. Ids from higher level will + // get higher remapped def index. + non_det_ids.sort_by_key(|(_, level, hash)| (*level, *hash)); + + let mut remapping = vec![CRATE_DEF_INDEX; non_det_ids.len()]; + for (idx, (id, ..)) in non_det_ids.into_iter().enumerate() { + remapping[id.local_def_index.as_usize() - start] = DefIndex::from_usize(start + idx); + } + + let mut sorted_non_det_ids = (start..num_defs) + .into_iter() + .map(|idx| LocalDefId { local_def_index: DefIndex::from(idx) }) + .collect::>(); + + sorted_non_det_ids.sort_by_key(|id| remapping[id.local_def_index.as_usize() - start]); + + let sorted_non_det_ids = Rc::from(sorted_non_det_ids); + LocalDefsRemapping { first_non_det_index: start as u32, remapping, sorted_non_det_ids } } } -impl RawDefId { - /// This exists so that `provide_one!` is happy - fn decode(self, meta: (&CrateMetadata, TyCtxt<'_>)) -> DefId { - let krate = CrateNum::from_u32(self.krate); - let krate = meta.0.map_encoded_cnum_to_current(krate); - DefId { krate, index: DefIndex::from_u32(self.index) } +pub(crate) mod remapped_def_id { + use super::*; + + /// On-disk representation of `DefId`. + /// This creates a type-safe way to enforce that we remap the CrateNum between the on-disk + /// representation and the compilation session. + #[derive(Copy, Clone, Hash, PartialEq, Eq, Encodable, BlobDecodable)] + pub(crate) struct RemappedRawDefId { + krate: u32, + index: u32, + } + + impl RemappedRawDefId { + pub(crate) fn new_unchecked(krate: u32, index: u32) -> RemappedRawDefId { + RemappedRawDefId { krate, index } + } + + pub(crate) fn create(def_id: DefId, remapping: &LocalDefsRemapping) -> RemappedRawDefId { + let def_id = remapping.map_def_id(def_id); + RemappedRawDefId { krate: def_id.krate.as_u32(), index: def_id.index.as_u32() } + } + + /// This exists so that `provide_one!` is happy + pub(crate) fn decode(self, meta: (&CrateMetadata, TyCtxt<'_>)) -> DefId { + let krate = CrateNum::from_u32(self.krate); + let krate = meta.0.map_encoded_cnum_to_current(krate); + DefId { krate, index: DefIndex::from_u32(self.index) } + } + + pub(crate) fn decompose(&self) -> (u32, u32) { + (self.krate, self.index) + } } } @@ -379,7 +534,7 @@ pub(crate) struct CrateDep { #[derive(MetadataEncodable, LazyDecodable)] pub(crate) struct TraitImpls { - trait_id: RawDefId, + trait_id: RemappedRawDefId, impls: LazyArray<(LocalDefId, Option)>, } @@ -397,14 +552,14 @@ macro_rules! define_tables { ) => { #[derive(MetadataEncodable, LazyDecodable)] pub(crate) struct LazyTables { - $($name1: LazyTable,)+ - $($name2: LazyTable>,)+ + $($name1: LazyTable,)+ + $($name2: LazyTable>,)+ } #[derive(Default)] struct TableBuilders { - $($name1: TableBuilder,)+ - $($name2: TableBuilder>,)+ + $($name1: TableBuilder,)+ + $($name2: TableBuilder>,)+ } impl TableBuilders { @@ -481,7 +636,7 @@ define_tables! { mir_coroutine_witnesses: Table>>, promoted_mir: Table>>>, thir_abstract_const: Table>>>, - impl_parent: Table, + impl_parent: Table, const_conditions: Table>>, // FIXME(eddyb) perhaps compute this on the fly if cheap enough? coerce_unsized_info: Table>, @@ -490,10 +645,10 @@ define_tables! { rendered_precise_capturing_args: Table>>, fn_arg_idents: Table>>, coroutine_kind: Table, - coroutine_for_closure: Table, + coroutine_for_closure: Table, adt_destructor: Table>, adt_async_destructor: Table>, - coroutine_by_move_body_def_id: Table, + coroutine_by_move_body_def_id: Table, eval_static_initializer: Table>>, trait_def: Table>, expn_that_defined: Table>, diff --git a/compiler/rustc_metadata/src/rmeta/parameterized.rs b/compiler/rustc_metadata/src/rmeta/parameterized.rs index 24177e4f83de8..299a5ca906ea1 100644 --- a/compiler/rustc_metadata/src/rmeta/parameterized.rs +++ b/compiler/rustc_metadata/src/rmeta/parameterized.rs @@ -81,9 +81,9 @@ trivially_parameterized_over_tcx! { crate::rmeta::IncoherentImpls, crate::rmeta::LocalDefId, crate::rmeta::ProcMacroKind, - crate::rmeta::RawDefId, crate::rmeta::TraitImpls, crate::rmeta::VariantData, + crate::rmeta::remapped_def_id::RemappedRawDefId, rustc_abi::ReprOptions, rustc_ast::DelimArgs, rustc_attr_ir::Attribute, diff --git a/compiler/rustc_metadata/src/rmeta/table.rs b/compiler/rustc_metadata/src/rmeta/table.rs index bbac0b5ad5435..2844b7c26a550 100644 --- a/compiler/rustc_metadata/src/rmeta/table.rs +++ b/compiler/rustc_metadata/src/rmeta/table.rs @@ -2,6 +2,7 @@ use rustc_hir::def::CtorOf; use rustc_index::Idx; use crate::rmeta::decoder::MetaBlob; +use crate::rmeta::remapped_def_id::RemappedRawDefId; use crate::rmeta::*; pub(super) trait IsDefault: Default { @@ -253,7 +254,7 @@ fixed_size_enum! { } // We directly encode RawDefId because using a `LazyValue` would incur a 50% overhead in the worst case. -impl FixedSizeEncoding for Option { +impl FixedSizeEncoding for Option { type ByteArray = [u8; 8]; #[inline] @@ -265,14 +266,15 @@ impl FixedSizeEncoding for Option { } let index = u32::from_le_bytes(index); - Some(RawDefId { krate: krate - 1, index }) + Some(RemappedRawDefId::new_unchecked(krate - 1, index)) } #[inline] fn write_to_bytes(self, dest: &mut [u8; 8]) { match self { None => unreachable!(), - Some(RawDefId { krate, index }) => { + Some(id) => { + let (krate, index) = id.decompose(); debug_assert!(krate < u32::MAX); // CrateNum is less than `CrateNum::MAX_AS_U32`. let krate = (krate + 1).to_le_bytes(); diff --git a/compiler/rustc_middle/src/queries.rs b/compiler/rustc_middle/src/queries.rs index d0429df43d1dd..4632c3ca1fc12 100644 --- a/compiler/rustc_middle/src/queries.rs +++ b/compiler/rustc_middle/src/queries.rs @@ -2721,6 +2721,7 @@ rustc_queries! { } query limits(key: ()) -> Limits { + feedable desc { "looking up limits" } } diff --git a/compiler/rustc_mir_transform/src/canonicalization.rs b/compiler/rustc_mir_transform/src/canonicalization.rs new file mode 100644 index 0000000000000..c0416bacd7412 --- /dev/null +++ b/compiler/rustc_mir_transform/src/canonicalization.rs @@ -0,0 +1,128 @@ +use rustc_middle::mir::*; +use rustc_middle::ty::{Ty, TyCtxt}; + +/// Canonicalize operands of binary operations. +/// This only canonicalize their ordering for now. +pub(super) fn canonicalize_binary_operands<'tcx, 'body>( + tcx: TyCtxt<'tcx>, + local_decls: &'body LocalDecls<'tcx>, + op: BinOp, + lhs: &mut Operand<'tcx>, + rhs: &mut Operand<'tcx>, +) -> bool { + fn needs_swap(lhs: &T, rhs: &T) -> Option { + use std::cmp::Ordering; + + match lhs.cmp(rhs) { + Ordering::Less => Some(false), + Ordering::Equal => None, + Ordering::Greater => Some(true), + } + } + + fn projection_rank<'tcx>(proj: &ProjectionElem>) -> usize { + match proj { + ProjectionElem::Deref => 0, + ProjectionElem::Field(..) => 1, + ProjectionElem::Index(_) => 2, + ProjectionElem::ConstantIndex { .. } => 3, + ProjectionElem::Subslice { .. } => 4, + ProjectionElem::Downcast(..) => 5, + ProjectionElem::OpaqueCast(_) => 6, + ProjectionElem::UnwrapUnsafeBinder(_) => 7, + ProjectionElem::PhantomDeref => 8, + } + } + + fn needs_swap_operands<'tcx>(lhs: &Operand<'tcx>, rhs: &Operand<'tcx>) -> bool { + let (lhs, rhs) = match (lhs, rhs) { + (Operand::Constant(_), Operand::Copy(_) | Operand::Move(_)) => return true, + (Operand::Copy(lhs) | Operand::Move(lhs), Operand::Copy(rhs) | Operand::Move(rhs)) => { + (lhs, rhs) + } + _ => return false, + }; + + if let Some(ns) = needs_swap(&lhs.local, &rhs.local) { + return ns; + } + + let lhs_proj = lhs.projection; + let rhs_proj = rhs.projection; + + if let Some(ns) = needs_swap(&lhs_proj.len(), &rhs_proj.len()) { + return ns; + } + + for (lhs_proj, rhs_proj) in lhs_proj.iter().zip(rhs_proj.iter()) { + if let Some(ns) = match (lhs_proj, rhs_proj) { + (ProjectionElem::Field(lhs, _), ProjectionElem::Field(rhs, _)) => { + needs_swap(&lhs, &rhs) + } + + (ProjectionElem::Index(lhs), ProjectionElem::Index(rhs)) => needs_swap(&lhs, &rhs), + + ( + ProjectionElem::ConstantIndex { offset: l0, min_length: l1, from_end: l2 }, + ProjectionElem::ConstantIndex { offset: r0, min_length: r1, from_end: r2 }, + ) => needs_swap(&(l0, l1, l2), &(r0, r1, r2)), + + ( + ProjectionElem::Subslice { from: l0, to: l1, from_end: l2 }, + ProjectionElem::Subslice { from: r0, to: r1, from_end: r2 }, + ) => needs_swap(&(l0, l1, l2), &(r0, r1, r2)), + + (ProjectionElem::Downcast(l0, l1), ProjectionElem::Downcast(r0, r1)) => { + needs_swap(&(l0, l1), &(r0, r1)) + } + + _ => needs_swap(&projection_rank(&lhs_proj), &projection_rank(&rhs_proj)), + } { + return ns; + } + } + + false + } + + let needs_integral = match op { + BinOp::Eq | BinOp::Ne => false, + + BinOp::Add + | BinOp::AddUnchecked + | BinOp::AddWithOverflow + | BinOp::Mul + | BinOp::MulUnchecked + | BinOp::MulWithOverflow + | BinOp::BitXor + | BinOp::BitAnd + | BinOp::BitOr => true, + + BinOp::Sub + | BinOp::SubUnchecked + | BinOp::SubWithOverflow + | BinOp::Div + | BinOp::Rem + | BinOp::Shl + | BinOp::ShlUnchecked + | BinOp::Shr + | BinOp::ShrUnchecked + | BinOp::Lt + | BinOp::Le + | BinOp::Ge + | BinOp::Gt + | BinOp::Cmp + | BinOp::Offset => return false, + }; + + if needs_integral && !lhs.ty(local_decls, tcx).is_integral() { + return false; + } + + if needs_swap_operands(lhs, rhs) { + std::mem::swap(lhs, rhs); + true + } else { + false + } +} diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index 4d543ff27e502..d74581b00980d 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -121,8 +121,8 @@ use rustc_span::{DUMMY_SP, bug}; use smallvec::SmallVec; use tracing::{debug, instrument, trace}; -use crate::PassPolicy; use crate::ssa::{MaybeUninitializedLocals, SsaLocals}; +use crate::{PassPolicy, canonicalization}; pub(super) struct GVN; @@ -1392,6 +1392,18 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> { let lhs = self.simplify_operand(lhs_operand, location); let rhs = self.simplify_operand(rhs_operand, location); + let (lhs, rhs) = if canonicalization::canonicalize_binary_operands( + self.tcx, + self.local_decls, + op, + lhs_operand, + rhs_operand, + ) { + (rhs, lhs) + } else { + (lhs, rhs) + }; + // Only short-circuit options after we called `simplify_operand` // on both operands for side effect. let mut lhs = lhs?; diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 02d77b96f7431..2a38b3b182184 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -37,6 +37,7 @@ use std::sync::LazyLock; use pass_manager::{self as pm, Lint, MirLint, MirPass, PassCtx, PassPolicy, WithMinOptLevel}; +mod canonicalization; mod check_pointers; mod cost_checker; mod cross_crate_inline; diff --git a/compiler/rustc_monomorphize/src/offload/manifest.rs b/compiler/rustc_monomorphize/src/offload/manifest.rs index a6f5d1228082e..8fdd8e10ab419 100644 --- a/compiler/rustc_monomorphize/src/offload/manifest.rs +++ b/compiler/rustc_monomorphize/src/offload/manifest.rs @@ -119,8 +119,8 @@ impl<'a, 'tcx> SpanEncoder for OffloadManifestEncoder<'a, 'tcx> { self.tcx.stable_crate_id(crate_num).encode(self); } - fn encode_def_index(&mut self, def_index: rustc_span::def_id::DefIndex) { - def_index.as_u32().encode(self); + fn encode_def_index(&mut self, _: rustc_span::def_id::DefIndex) { + panic!("encode def id instead") } fn encode_def_id(&mut self, def_id: rustc_span::def_id::DefId) { @@ -287,8 +287,7 @@ impl<'a, 'tcx> BlobDecoder for OffloadManifestDecoder<'a, 'tcx> { } fn decode_def_index(&mut self) -> rustc_span::def_id::DefIndex { - let v = self.read_u32(); - rustc_span::def_id::DefIndex::from_u32(v) + panic!("can't decode def indices as we do not encode them") } fn decode_local_def_id(&mut self) -> rustc_hir::def_id::LocalDefId { diff --git a/library/core/src/hash/mod.rs b/library/core/src/hash/mod.rs index f1a93a880e7f4..dbec6035e5217 100644 --- a/library/core/src/hash/mod.rs +++ b/library/core/src/hash/mod.rs @@ -436,7 +436,7 @@ pub trait Hasher { /// writing its contents to this `Hasher`. That way /// `(collection![1, 2, 3], collection![4, 5])` and /// `(collection![1, 2], collection![3, 4, 5])` will provide different - /// sequences of values to the `Hasher` + /// sequences of values to the `Hasher`. /// /// The `impl Hash for [T]` includes a call to this method, so if you're /// hashing a slice (or array or vector) via its `Hash::hash` method, diff --git a/library/core/src/hint.rs b/library/core/src/hint.rs index 616bdd9a97b7c..247e1430de3ed 100644 --- a/library/core/src/hint.rs +++ b/library/core/src/hint.rs @@ -704,7 +704,7 @@ pub const fn likely(b: bool) -> bool { /// // Use outside of a branch condition may still influence a nearby branch /// let cond = unlikely(x != 0); /// if cond { -/// println!("this branch is likely to be taken"); +/// println!("this branch is unlikely to be taken"); /// } /// } /// ``` diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs index 1dbd11426e57e..635917ea6973b 100644 --- a/library/core/src/task/wake.rs +++ b/library/core/src/task/wake.rs @@ -843,9 +843,10 @@ impl LocalWaker { /// Creates a new `LocalWaker` from [`RawWaker`]. /// + /// # Safety + /// /// The behavior of the returned `LocalWaker` is undefined if the contract defined /// in [`RawWaker`]'s and [`RawWakerVTable`]'s documentation is not upheld. - /// Therefore this method is unsafe. #[inline] #[must_use] #[unstable(feature = "local_waker", issue = "118959")] diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index dc6365ea8c622..773049d0ff6c4 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -358,6 +358,7 @@ #![feature(io_error_uncategorized)] #![feature(io_slice_as_bytes)] #![feature(ip)] +#![feature(ipv6_hop_limit)] #![feature(iter_advance_by)] #![feature(iter_next_chunk)] #![feature(maybe_dangling)] diff --git a/library/std/src/net/tcp.rs b/library/std/src/net/tcp.rs index e5c2522a837fb..7f3b00a315862 100644 --- a/library/std/src/net/tcp.rs +++ b/library/std/src/net/tcp.rs @@ -605,6 +605,46 @@ impl TcpStream { self.0.ttl() } + /// Sets the value for the `IPV6_UNICAST_HOPS` option on this socket. + /// + /// This value sets the unicast hop limit field that is used in every packet + /// sent from this socket. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(ipv6_hop_limit)] + /// use std::net::TcpStream; + /// + /// let stream = TcpStream::connect("[::1]:12345") + /// .expect("Couldn't connect to the server..."); + /// stream.set_hop_limit_v6(88).expect("set_hop_limit_v6 call failed"); + /// ``` + #[unstable(feature = "ipv6_hop_limit", issue = "139166")] + pub fn set_hop_limit_v6(&self, limit: u8) -> io::Result<()> { + self.0.set_hop_limit_v6(limit) + } + + /// Gets the value of the `IPV6_UNICAST_HOPS` option on this socket. + /// + /// For more information about this option, see [`TcpStream::set_hop_limit_v6`]. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(ipv6_hop_limit)] + /// use std::net::TcpStream; + /// + /// let stream = TcpStream::connect("[::1]:12345") + /// .expect("Couldn't connect to the server..."); + /// stream.set_hop_limit_v6(88).expect("set_hop_limit_v6 call failed"); + /// assert_eq!(stream.hop_limit_v6().unwrap(), 88); + /// ``` + #[unstable(feature = "ipv6_hop_limit", issue = "139166")] + pub fn hop_limit_v6(&self) -> io::Result { + self.0.hop_limit_v6() + } + /// Gets the value of the `SO_ERROR` option on this socket. /// /// This will retrieve the stored error in the underlying socket, clearing @@ -1032,6 +1072,44 @@ impl TcpListener { self.0.ttl() } + /// Sets the value for the `IPV6_UNICAST_HOPS` option on this socket. + /// + /// This value sets the unicast hop limit field that is used in every packet + /// sent from this socket. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(ipv6_hop_limit)] + /// use std::net::TcpListener; + /// + /// let listener = TcpListener::bind("[::1]:12345").unwrap(); + /// listener.set_hop_limit_v6(88).expect("set_hop_limit_v6 call failed"); + /// ``` + #[unstable(feature = "ipv6_hop_limit", issue = "139166")] + pub fn set_hop_limit_v6(&self, limit: u8) -> io::Result<()> { + self.0.set_hop_limit_v6(limit) + } + + /// Gets the value of the `IPV6_UNICAST_HOPS` option on this socket. + /// + /// For more information about this option, see [`TcpListener::set_hop_limit_v6`]. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(ipv6_hop_limit)] + /// use std::net::TcpListener; + /// + /// let listener = TcpListener::bind("[::1]:12345").unwrap(); + /// listener.set_hop_limit_v6(88).expect("set_hop_limit_v6 call failed"); + /// assert_eq!(listener.hop_limit_v6().unwrap(), 88); + /// ``` + #[unstable(feature = "ipv6_hop_limit", issue = "139166")] + pub fn hop_limit_v6(&self) -> io::Result { + self.0.hop_limit_v6() + } + #[stable(feature = "net2_mutators", since = "1.9.0")] #[deprecated(since = "1.16.0", note = "this option can only be set before the socket is bound")] #[allow(missing_docs)] diff --git a/library/std/src/net/tcp/tests.rs b/library/std/src/net/tcp/tests.rs index 45a512cb9b4c7..58de3d478caa0 100644 --- a/library/std/src/net/tcp/tests.rs +++ b/library/std/src/net/tcp/tests.rs @@ -894,6 +894,23 @@ fn ttl() { assert_eq!(ttl, t!(stream.ttl())); } +#[test] +#[cfg_attr(target_env = "sgx", ignore)] +#[cfg(not(all(target_os = "wasi", any(target_env = "p2", target_env = "p3"))))] +fn hop_limit() { + let hlim = 100; + + let listener = t!(TcpListener::bind(LOCALHOST_IP6)); + + t!(listener.set_hop_limit_v6(hlim)); + assert_eq!(hlim, t!(listener.hop_limit_v6())); + + let stream = t!(TcpStream::connect(t!(listener.local_addr()))); + + t!(stream.set_hop_limit_v6(hlim)); + assert_eq!(hlim, t!(stream.hop_limit_v6())); +} + #[test] #[cfg_attr(target_env = "sgx", ignore)] fn set_nonblocking() { diff --git a/library/std/src/net/udp.rs b/library/std/src/net/udp.rs index 6448c9f2e0091..914c400fb05f1 100644 --- a/library/std/src/net/udp.rs +++ b/library/std/src/net/udp.rs @@ -589,6 +589,82 @@ impl UdpSocket { self.0.ttl() } + /// Sets the value for the `IPV6_UNICAST_HOPS` option on this socket. + /// + /// This value sets the unicast hop limit field that is used in every packet + /// sent from this socket. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(ipv6_hop_limit)] + /// use std::net::UdpSocket; + /// + /// let socket = UdpSocket::bind("[::1]:12345").expect("couldn't bind to address"); + /// socket.set_hop_limit_v6(88).expect("set_hop_limit_v6 call failed"); + /// ``` + #[unstable(feature = "ipv6_hop_limit", issue = "139166")] + pub fn set_hop_limit_v6(&self, limit: u8) -> io::Result<()> { + self.0.set_hop_limit_v6(limit) + } + + /// Gets the value of the `IPV6_UNICAST_HOPS` option on this socket. + /// + /// For more information about this option, see [`UdpSocket::set_hop_limit_v6`]. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(ipv6_hop_limit)] + /// use std::net::UdpSocket; + /// + /// let socket = UdpSocket::bind("[::1]:12345").expect("couldn't bind to address"); + /// socket.set_hop_limit_v6(88).expect("set_hop_limit_v6 call failed"); + /// assert_eq!(socket.hop_limit_v6().unwrap(), 88); + /// ``` + #[unstable(feature = "ipv6_hop_limit", issue = "139166")] + pub fn hop_limit_v6(&self) -> io::Result { + self.0.hop_limit_v6() + } + + /// Sets the value for the `IPV6_MULTICAST_HOPS` option on this socket. + /// + /// This value sets the hop limit field for outgoing multicast packets + /// sent from this socket. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(ipv6_hop_limit)] + /// use std::net::UdpSocket; + /// + /// let socket = UdpSocket::bind("[::1]:12345").expect("couldn't bind to address"); + /// socket.set_multicast_hop_limit_v6(88).expect("set_multicast_hop_limit_v6 call failed"); + /// ``` + #[unstable(feature = "ipv6_hop_limit", issue = "139166")] + pub fn set_multicast_hop_limit_v6(&self, limit: u8) -> io::Result<()> { + self.0.set_multicast_hop_limit_v6(limit) + } + + /// Gets the value of the `IPV6_MULTICAST_HOPS` option on this socket. + /// + /// For more information about this option, see [`UdpSocket::set_multicast_hop_limit_v6`]. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(ipv6_hop_limit)] + /// use std::net::UdpSocket; + /// + /// let socket = UdpSocket::bind("[::1]:12345").expect("couldn't bind to address"); + /// socket.set_multicast_hop_limit_v6(88).expect("set_multicast_hop_limit_v6 call failed"); + /// assert_eq!(socket.multicast_hop_limit_v6().unwrap(), 88); + /// ``` + #[unstable(feature = "ipv6_hop_limit", issue = "139166")] + pub fn multicast_hop_limit_v6(&self) -> io::Result { + self.0.multicast_hop_limit_v6() + } + /// Executes an operation of the `IP_ADD_MEMBERSHIP` type. /// /// This function specifies a new multicast group for this socket to join. diff --git a/library/std/src/net/udp/tests.rs b/library/std/src/net/udp/tests.rs index 38d6dab80f64e..89ec91122c5fb 100644 --- a/library/std/src/net/udp/tests.rs +++ b/library/std/src/net/udp/tests.rs @@ -353,6 +353,17 @@ fn ttl() { assert_eq!(ttl, t!(stream.ttl())); } +#[test] +#[cfg(not(all(target_os = "wasi", any(target_env = "p2", target_env = "p3"))))] +fn hop_limit() { + let hlim = 100; + + let stream = t!(UdpSocket::bind(LOCALHOST_IP6)); + + t!(stream.set_hop_limit_v6(hlim)); + assert_eq!(hlim, t!(stream.hop_limit_v6())); +} + #[test] fn set_nonblocking() { each_ip(&mut |socket, _| { diff --git a/library/std/src/sys/fs/unsupported.rs b/library/std/src/sys/fs/unsupported.rs index f63553a543669..1421dad97272f 100644 --- a/library/std/src/sys/fs/unsupported.rs +++ b/library/std/src/sys/fs/unsupported.rs @@ -29,6 +29,25 @@ pub struct FileType(!); #[derive(Debug)] pub struct DirBuilder {} +// Dummy Drops so that `needs_drop::()` etc. is true independent of platform, +// avoiding a portability hazard. +// The types not listed here are pure data and don’t implement Drop even when real. +impl Drop for File { + fn drop(&mut self) { + self.0 + } +} +impl Drop for ReadDir { + fn drop(&mut self) { + self.0 + } +} +impl Drop for DirEntry { + fn drop(&mut self) { + self.0 + } +} + impl FileAttr { pub fn size(&self) -> u64 { self.0 diff --git a/library/std/src/sys/fs/vexos.rs b/library/std/src/sys/fs/vexos.rs index ec5da582140cc..6529159eb49fc 100644 --- a/library/std/src/sys/fs/vexos.rs +++ b/library/std/src/sys/fs/vexos.rs @@ -479,6 +479,13 @@ impl Drop for File { } } +impl Drop for ReadDir { + fn drop(&mut self) { + // Dummy Drop so that `needs_drop::()` is true independent of platform. + self.0 + } +} + pub fn readdir(_p: &Path) -> io::Result { // While there *is* a userspace function for reading file directories, // the necessary implementation cannot currently be done cleanly, as diff --git a/library/std/src/sys/net/connection/sgx.rs b/library/std/src/sys/net/connection/sgx.rs index acebb8c5bd60c..8771a89568da8 100644 --- a/library/std/src/sys/net/connection/sgx.rs +++ b/library/std/src/sys/net/connection/sgx.rs @@ -9,6 +9,7 @@ use crate::sys::{AsInner, FromInner, IntoInner, TryIntoInner, sgx_ineffective, u use crate::time::Duration; const DEFAULT_FAKE_TTL: u32 = 64; +const DEFAULT_FAKE_HLIM: u8 = 64; #[derive(Debug, Clone)] pub struct Socket { @@ -243,6 +244,14 @@ impl TcpStream { sgx_ineffective(DEFAULT_FAKE_TTL) } + pub fn set_hop_limit_v6(&self, _: u8) -> io::Result<()> { + sgx_ineffective(()) + } + + pub fn hop_limit_v6(&self) -> io::Result { + sgx_ineffective(DEFAULT_FAKE_HLIM) + } + pub fn take_error(&self) -> io::Result> { Ok(None) } @@ -322,6 +331,14 @@ impl TcpListener { sgx_ineffective(DEFAULT_FAKE_TTL) } + pub fn set_hop_limit_v6(&self, _: u8) -> io::Result<()> { + sgx_ineffective(()) + } + + pub fn hop_limit_v6(&self) -> io::Result { + sgx_ineffective(DEFAULT_FAKE_HLIM) + } + pub fn set_only_v6(&self, _: bool) -> io::Result<()> { sgx_ineffective(()) } @@ -461,6 +478,22 @@ impl UdpSocket { self.0 } + pub fn set_hop_limit_v6(&self, _: u8) -> io::Result<()> { + self.0 + } + + pub fn hop_limit_v6(&self) -> io::Result { + self.0 + } + + pub fn set_multicast_hop_limit_v6(&self, _: u8) -> io::Result<()> { + self.0 + } + + pub fn multicast_hop_limit_v6(&self) -> io::Result { + self.0 + } + pub fn take_error(&self) -> io::Result> { self.0 } diff --git a/library/std/src/sys/net/connection/socket/mod.rs b/library/std/src/sys/net/connection/socket/mod.rs index 55db60fde694d..08375078b44ef 100644 --- a/library/std/src/sys/net/connection/socket/mod.rs +++ b/library/std/src/sys/net/connection/socket/mod.rs @@ -524,6 +524,31 @@ impl TcpStream { Ok(raw as u32) } + pub fn set_hop_limit_v6(&self, limit: u8) -> io::Result<()> { + cfg_select! { + all(target_os = "wasi", any(target_env = "p2", target_env = "p3")) => { + let _ = limit; + Err(io::Error::new(ErrorKind::Unsupported, "not supported on this platform")) + } + _ => unsafe { + setsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_UNICAST_HOPS, limit as c_int) + }, + } + } + + pub fn hop_limit_v6(&self) -> io::Result { + cfg_select! { + all(target_os = "wasi", any(target_env = "p2", target_env = "p3")) => { + Err(io::Error::new(ErrorKind::Unsupported, "not supported on this platform")) + } + _ => { + let raw: c_int = + unsafe { getsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_UNICAST_HOPS)? }; + Ok(raw as u8) + } + } + } + pub fn take_error(&self) -> io::Result> { self.inner.take_error() } @@ -652,6 +677,31 @@ impl TcpListener { Ok(raw as u32) } + pub fn set_hop_limit_v6(&self, limit: u8) -> io::Result<()> { + cfg_select! { + all(target_os = "wasi", any(target_env = "p2", target_env = "p3")) => { + let _ = limit; + Err(io::Error::new(ErrorKind::Unsupported, "not supported on this platform")) + } + _ => unsafe { + setsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_UNICAST_HOPS, limit as c_int) + }, + } + } + + pub fn hop_limit_v6(&self) -> io::Result { + cfg_select! { + all(target_os = "wasi", any(target_env = "p2", target_env = "p3")) => { + Err(io::Error::new(ErrorKind::Unsupported, "not supported on this platform")) + } + _ => { + let raw: c_int = + unsafe { getsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_UNICAST_HOPS)? }; + Ok(raw as u8) + } + } + } + pub fn set_only_v6(&self, only_v6: bool) -> io::Result<()> { unsafe { setsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_V6ONLY, only_v6 as c_int) } } @@ -872,6 +922,56 @@ impl UdpSocket { Ok(raw as u32) } + pub fn set_hop_limit_v6(&self, limit: u8) -> io::Result<()> { + cfg_select! { + all(target_os = "wasi", any(target_env = "p2", target_env = "p3")) => { + let _ = limit; + Err(io::Error::new(ErrorKind::Unsupported, "not supported on this platform")) + } + _ => unsafe { + setsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_UNICAST_HOPS, limit as c_int) + }, + } + } + + pub fn hop_limit_v6(&self) -> io::Result { + cfg_select! { + all(target_os = "wasi", any(target_env = "p2", target_env = "p3")) => { + Err(io::Error::new(ErrorKind::Unsupported, "not supported on this platform")) + } + _ => { + let raw: c_int = + unsafe { getsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_UNICAST_HOPS)? }; + Ok(raw as u8) + } + } + } + + pub fn set_multicast_hop_limit_v6(&self, limit: u8) -> io::Result<()> { + cfg_select! { + all(target_os = "wasi", any(target_env = "p2", target_env = "p3")) => { + let _ = limit; + Err(io::Error::new(ErrorKind::Unsupported, "not supported on this platform")) + } + _ => unsafe { + setsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_MULTICAST_HOPS, limit as c_int) + }, + } + } + + pub fn multicast_hop_limit_v6(&self) -> io::Result { + cfg_select! { + all(target_os = "wasi", any(target_env = "p2", target_env = "p3")) => { + Err(io::Error::new(ErrorKind::Unsupported, "not supported on this platform")) + } + _ => { + let raw: c_int = + unsafe { getsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_MULTICAST_HOPS)? }; + Ok(raw as u8) + } + } + } + pub fn take_error(&self) -> io::Result> { self.inner.take_error() } diff --git a/library/std/src/sys/net/connection/socket/windows.rs b/library/std/src/sys/net/connection/socket/windows.rs index e9d5336001fd8..1249ac2808195 100644 --- a/library/std/src/sys/net/connection/socket/windows.rs +++ b/library/std/src/sys/net/connection/socket/windows.rs @@ -29,10 +29,11 @@ pub(super) mod netc { pub use crate::sys::c::{ ADDRESS_FAMILY as sa_family_t, ADDRINFOA as addrinfo, IP_ADD_MEMBERSHIP, IP_DROP_MEMBERSHIP, IP_MULTICAST_LOOP, IP_MULTICAST_TTL, IP_TTL, IPPROTO_IP, IPPROTO_IPV6, - IPV6_ADD_MEMBERSHIP, IPV6_DROP_MEMBERSHIP, IPV6_MULTICAST_LOOP, IPV6_V6ONLY, SO_BROADCAST, - SO_RCVTIMEO, SO_SNDTIMEO, SOCK_DGRAM, SOCK_STREAM, SOCKADDR as sockaddr, - SOCKADDR_STORAGE as sockaddr_storage, SOL_SOCKET, WSAEMSGSIZE as EMSGSIZE, bind, connect, - freeaddrinfo, getpeername, getsockname, getsockopt, listen, setsockopt, + IPV6_ADD_MEMBERSHIP, IPV6_DROP_MEMBERSHIP, IPV6_MULTICAST_HOPS, IPV6_MULTICAST_LOOP, + IPV6_UNICAST_HOPS, IPV6_V6ONLY, SO_BROADCAST, SO_RCVTIMEO, SO_SNDTIMEO, SOCK_DGRAM, + SOCK_STREAM, SOCKADDR as sockaddr, SOCKADDR_STORAGE as sockaddr_storage, SOL_SOCKET, + WSAEMSGSIZE as EMSGSIZE, bind, connect, freeaddrinfo, getpeername, getsockname, getsockopt, + listen, setsockopt, }; #[allow(non_camel_case_types)] diff --git a/library/std/src/sys/net/connection/uefi/mod.rs b/library/std/src/sys/net/connection/uefi/mod.rs index b29b324a1ee9e..0e72f87717568 100644 --- a/library/std/src/sys/net/connection/uefi/mod.rs +++ b/library/std/src/sys/net/connection/uefi/mod.rs @@ -145,6 +145,14 @@ impl TcpStream { self.inner.ttl() } + pub fn set_hop_limit_v6(&self, _: u8) -> io::Result<()> { + unsupported() + } + + pub fn hop_limit_v6(&self) -> io::Result { + unsupported() + } + pub fn take_error(&self) -> io::Result> { unsupported() } @@ -197,6 +205,14 @@ impl TcpListener { self.inner.ttl() } + pub fn set_hop_limit_v6(&self, _: u8) -> io::Result<()> { + unsupported() + } + + pub fn hop_limit_v6(&self) -> io::Result { + unsupported() + } + pub fn set_only_v6(&self, _: bool) -> io::Result<()> { unsupported() } @@ -324,6 +340,22 @@ impl UdpSocket { self.0 } + pub fn set_hop_limit_v6(&self, _: u8) -> io::Result<()> { + self.0 + } + + pub fn hop_limit_v6(&self) -> io::Result { + self.0 + } + + pub fn set_multicast_hop_limit_v6(&self, _: u8) -> io::Result<()> { + self.0 + } + + pub fn multicast_hop_limit_v6(&self) -> io::Result { + self.0 + } + pub fn take_error(&self) -> io::Result> { self.0 } diff --git a/library/std/src/sys/net/connection/unsupported.rs b/library/std/src/sys/net/connection/unsupported.rs index 7a4d3a97b8324..193348a79ae3d 100644 --- a/library/std/src/sys/net/connection/unsupported.rs +++ b/library/std/src/sys/net/connection/unsupported.rs @@ -111,6 +111,14 @@ impl TcpStream { self.0 } + pub fn set_hop_limit_v6(&self, _: u8) -> io::Result<()> { + self.0 + } + + pub fn hop_limit_v6(&self) -> io::Result { + self.0 + } + pub fn take_error(&self) -> io::Result> { self.0 } @@ -153,6 +161,14 @@ impl TcpListener { self.0 } + pub fn set_hop_limit_v6(&self, _: u8) -> io::Result<()> { + self.0 + } + + pub fn hop_limit_v6(&self) -> io::Result { + self.0 + } + pub fn set_only_v6(&self, _: bool) -> io::Result<()> { self.0 } @@ -279,6 +295,22 @@ impl UdpSocket { self.0 } + pub fn set_hop_limit_v6(&self, _: u8) -> io::Result<()> { + self.0 + } + + pub fn hop_limit_v6(&self) -> io::Result { + self.0 + } + + pub fn set_multicast_hop_limit_v6(&self, _: u8) -> io::Result<()> { + self.0 + } + + pub fn multicast_hop_limit_v6(&self) -> io::Result { + self.0 + } + pub fn take_error(&self) -> io::Result> { self.0 } diff --git a/library/std/src/sys/net/connection/wasip1.rs b/library/std/src/sys/net/connection/wasip1.rs index d461ea85f9fea..15d7f9a453141 100644 --- a/library/std/src/sys/net/connection/wasip1.rs +++ b/library/std/src/sys/net/connection/wasip1.rs @@ -169,6 +169,14 @@ impl TcpStream { unsupported() } + pub fn set_hop_limit_v6(&self, _: u8) -> io::Result<()> { + unsupported() + } + + pub fn hop_limit_v6(&self) -> io::Result { + unsupported() + } + pub fn take_error(&self) -> io::Result> { unsupported() } @@ -253,6 +261,14 @@ impl TcpListener { unsupported() } + pub fn set_hop_limit_v6(&self, _: u8) -> io::Result<()> { + unsupported() + } + + pub fn hop_limit_v6(&self) -> io::Result { + unsupported() + } + pub fn set_only_v6(&self, _: bool) -> io::Result<()> { unsupported() } @@ -425,6 +441,22 @@ impl UdpSocket { unsupported() } + pub fn set_hop_limit_v6(&self, _: u8) -> io::Result<()> { + unsupported() + } + + pub fn hop_limit_v6(&self) -> io::Result { + unsupported() + } + + pub fn set_multicast_hop_limit_v6(&self, _: u8) -> io::Result<()> { + unsupported() + } + + pub fn multicast_hop_limit_v6(&self) -> io::Result { + unsupported() + } + pub fn take_error(&self) -> io::Result> { unsupported() } diff --git a/library/std/src/sys/net/connection/xous/tcplistener.rs b/library/std/src/sys/net/connection/xous/tcplistener.rs index f406b4381f29a..e0730b2aac6c8 100644 --- a/library/std/src/sys/net/connection/xous/tcplistener.rs +++ b/library/std/src/sys/net/connection/xous/tcplistener.rs @@ -204,6 +204,14 @@ impl TcpListener { .map(|res| res[0] as _)?) } + pub fn set_hop_limit_v6(&self, hlim: u8) -> io::Result<()> { + unimpl!(); + } + + pub fn hop_limit_v6(&self) -> io::Result { + unimpl!(); + } + pub fn set_only_v6(&self, _: bool) -> io::Result<()> { unimpl!(); } diff --git a/library/std/src/sys/net/connection/xous/tcpstream.rs b/library/std/src/sys/net/connection/xous/tcpstream.rs index 45fe0418a27fa..6f8944ba8f18d 100644 --- a/library/std/src/sys/net/connection/xous/tcpstream.rs +++ b/library/std/src/sys/net/connection/xous/tcpstream.rs @@ -403,6 +403,14 @@ impl TcpStream { .map(|res| res[0] as _)?) } + pub fn set_hop_limit_v6(&self, _: u8) -> io::Result<()> { + unimpl!(); + } + + pub fn hop_limit_v6(&self) -> io::Result { + unimpl!(); + } + pub fn take_error(&self) -> io::Result> { // this call doesn't have a meaning on our platform, but we can at least not panic if it's used. Ok(None) diff --git a/library/std/src/sys/net/connection/xous/udp.rs b/library/std/src/sys/net/connection/xous/udp.rs index 281639488a015..e254bfe1a5e45 100644 --- a/library/std/src/sys/net/connection/xous/udp.rs +++ b/library/std/src/sys/net/connection/xous/udp.rs @@ -385,6 +385,14 @@ impl UdpSocket { .map(|res| res[0] as _)?) } + pub fn set_hop_limit_v6(&self, _: u8) -> io::Result<()> { + unimpl!(); + } + + pub fn hop_limit_v6(&self) -> io::Result { + unimpl!(); + } + pub fn take_error(&self) -> io::Result> { // this call doesn't have a meaning on our platform, but we can at least not panic if it's used. Ok(None) @@ -420,6 +428,14 @@ impl UdpSocket { unimpl!(); } + pub fn set_multicast_hop_limit_v6(&self, _: u8) -> io::Result<()> { + unimpl!(); + } + + pub fn multicast_hop_limit_v6(&self) -> io::Result { + unimpl!(); + } + pub fn set_multicast_loop_v6(&self, _: bool) -> io::Result<()> { unimpl!(); } diff --git a/library/std/src/sys/pal/solid/abi/sockets.rs b/library/std/src/sys/pal/solid/abi/sockets.rs index 80802dd42e248..bedcf1c8e1e76 100644 --- a/library/std/src/sys/pal/solid/abi/sockets.rs +++ b/library/std/src/sys/pal/solid/abi/sockets.rs @@ -119,8 +119,11 @@ pub struct sockaddr_storage { pub ss_family: sa_family_t, pub s2_data1: [c_char; 2usize], pub s2_data2: [u32; 3usize], + pub s2_data3: [u32; 3usize], } +const _: () = assert!(size_of::() >= size_of::()); + #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct addrinfo { diff --git a/library/std/src/sys/pal/windows/c/bindings.txt b/library/std/src/sys/pal/windows/c/bindings.txt index 5d9e9a2d15494..1c7035028e83f 100644 --- a/library/std/src/sys/pal/windows/c/bindings.txt +++ b/library/std/src/sys/pal/windows/c/bindings.txt @@ -2260,7 +2260,9 @@ IPPROTO_UDP IPV6_ADD_MEMBERSHIP IPV6_DROP_MEMBERSHIP IPV6_MREQ +IPV6_MULTICAST_HOPS IPV6_MULTICAST_LOOP +IPV6_UNICAST_HOPS IPV6_V6ONLY IsThreadAFiber KF_FLAG_DONT_VERIFY diff --git a/library/std/src/sys/pal/windows/c/windows_sys.rs b/library/std/src/sys/pal/windows/c/windows_sys.rs index 46cf51b6b40d3..131d410edc9ad 100644 --- a/library/std/src/sys/pal/windows/c/windows_sys.rs +++ b/library/std/src/sys/pal/windows/c/windows_sys.rs @@ -2918,7 +2918,9 @@ impl Default for IPV6_MREQ { unsafe { core::mem::zeroed() } } } +pub const IPV6_MULTICAST_HOPS: i32 = 10; pub const IPV6_MULTICAST_LOOP: i32 = 11; +pub const IPV6_UNICAST_HOPS: i32 = 4; pub const IPV6_V6ONLY: i32 = 27; pub const IP_ADD_MEMBERSHIP: i32 = 12; pub const IP_DROP_MEMBERSHIP: i32 = 13; diff --git a/tests/codegen-llvm/intrinsics/transmute.rs b/tests/codegen-llvm/intrinsics/transmute.rs index b86c6df3267e4..ea9c0bbc2476e 100644 --- a/tests/codegen-llvm/intrinsics/transmute.rs +++ b/tests/codegen-llvm/intrinsics/transmute.rs @@ -119,7 +119,7 @@ pub unsafe fn check_from_uninhabited(x: BigNever) -> u16 { #[no_mangle] pub unsafe fn check_intermediate_passthrough(x: u32) -> i32 { // CHECK: start - // CHECK: %[[TMP:.+]] = add i32 1, %x + // CHECK: %[[TMP:.+]] = add i32 %x, 1 // CHECK: %[[RET:.+]] = add i32 %[[TMP]], 1 // CHECK: ret i32 %[[RET]] unsafe { transmute::(1 + x) + 1 } diff --git a/tests/codegen-llvm/some-abis-do-extend-params-to-32-bits.rs b/tests/codegen-llvm/some-abis-do-extend-params-to-32-bits.rs index 79be3bd5f57b4..fa4f1cc969f89 100644 --- a/tests/codegen-llvm/some-abis-do-extend-params-to-32-bits.rs +++ b/tests/codegen-llvm/some-abis-do-extend-params-to-32-bits.rs @@ -33,14 +33,20 @@ use minicore::*; // The patterns in this file are written in the style of a table to make the // uniformities and distinctions more apparent. // +// NB: to check for **absence** of a return attribute, use a pattern +// `define {{(dso_local )?}}i1 @c_ret_bool()` and not just +// `i1 @c_ret_bool()`. Checking for `zeroext` in the substring +// `i1 @c_ret_bool()` will match `zeroext i1 @c_ret_bool()`, which is the +// opposite of your intention. +// // ZERO/SIGN-EXTENDING TO 32 BITS NON-EXTENDING // ============================== ======================= // x86_64-linux: void @c_arg_bool(i1 zeroext %_a) // x86_64-uefi: void @c_arg_bool(i1 zeroext %_a) // i686: void @c_arg_bool(i1 zeroext %_a) // aarch64-apple: void @c_arg_bool(i1 zeroext %_a) -// aarch64-windows: void @c_arg_bool(i1 %_a) -// aarch64-linux: void @c_arg_bool(i1 %_a) +// aarch64-windows: void @c_arg_bool(i1 %_a) +// aarch64-linux: void @c_arg_bool(i1 %_a) // arm: void @c_arg_bool(i1 zeroext %_a) // riscv: void @c_arg_bool(i1 zeroext %_a) #[no_mangle] @@ -50,8 +56,8 @@ pub extern "C" fn c_arg_bool(_a: bool) {} // x86_64-uefi: void @c_arg_u8(i8 zeroext %_a) // i686: void @c_arg_u8(i8 zeroext %_a) // aarch64-apple: void @c_arg_u8(i8 zeroext %_a) -// aarch64-windows: void @c_arg_u8(i8 %_a) -// aarch64-linux: void @c_arg_u8(i8 %_a) +// aarch64-windows: void @c_arg_u8(i8 %_a) +// aarch64-linux: void @c_arg_u8(i8 %_a) // arm: void @c_arg_u8(i8 zeroext %_a) // riscv: void @c_arg_u8(i8 zeroext %_a) #[no_mangle] @@ -68,25 +74,25 @@ pub extern "C" fn c_arg_u8(_a: u8) {} #[no_mangle] pub extern "C" fn c_arg_u16(_a: u16) {} -// x86_64-linux: void @c_arg_u32(i32 %_a) -// x86_64-uefi: void @c_arg_u32(i32 %_a) -// i686: void @c_arg_u32(i32 %_a) -// aarch64-apple: void @c_arg_u32(i32 %_a) +// x86_64-linux: void @c_arg_u32(i32 %_a) +// x86_64-uefi: void @c_arg_u32(i32 %_a) +// i686: void @c_arg_u32(i32 %_a) +// aarch64-apple: void @c_arg_u32(i32 %_a) // aarch64-windows: void @c_arg_u32(i32 %_a) // aarch64-linux: void @c_arg_u32(i32 %_a) -// arm: void @c_arg_u32(i32 %_a) +// arm: void @c_arg_u32(i32 %_a) // riscv: void @c_arg_u32(i32 signext %_a) #[no_mangle] pub extern "C" fn c_arg_u32(_a: u32) {} -// x86_64-linux: void @c_arg_u64(i64 %_a) -// x86_64-uefi: void @c_arg_u64(i64 %_a) -// i686: void @c_arg_u64(i64 %_a) -// aarch64-apple: void @c_arg_u64(i64 %_a) +// x86_64-linux: void @c_arg_u64(i64 %_a) +// x86_64-uefi: void @c_arg_u64(i64 %_a) +// i686: void @c_arg_u64(i64 %_a) +// aarch64-apple: void @c_arg_u64(i64 %_a) // aarch64-windows: void @c_arg_u64(i64 %_a) // aarch64-linux: void @c_arg_u64(i64 %_a) -// arm: void @c_arg_u64(i64 %_a) -// riscv: void @c_arg_u64(i64 %_a) +// arm: void @c_arg_u64(i64 %_a) +// riscv: void @c_arg_u64(i64 %_a) #[no_mangle] pub extern "C" fn c_arg_u64(_a: u64) {} @@ -94,8 +100,8 @@ pub extern "C" fn c_arg_u64(_a: u64) {} // x86_64-uefi: void @c_arg_i8(i8 signext %_a) // i686: void @c_arg_i8(i8 signext %_a) // aarch64-apple: void @c_arg_i8(i8 signext %_a) -// aarch64-windows: void @c_arg_i8(i8 %_a) -// aarch64-linux: void @c_arg_i8(i8 %_a) +// aarch64-windows: void @c_arg_i8(i8 %_a) +// aarch64-linux: void @c_arg_i8(i8 %_a) // arm: void @c_arg_i8(i8 signext %_a) // riscv: void @c_arg_i8(i8 signext %_a) #[no_mangle] @@ -112,25 +118,25 @@ pub extern "C" fn c_arg_i8(_a: i8) {} #[no_mangle] pub extern "C" fn c_arg_i16(_a: i16) {} -// x86_64-linux: void @c_arg_i32(i32 %_a) -// x86_64-uefi: void @c_arg_i32(i32 %_a) -// i686: void @c_arg_i32(i32 %_a) -// aarch64-apple: void @c_arg_i32(i32 %_a) +// x86_64-linux: void @c_arg_i32(i32 %_a) +// x86_64-uefi: void @c_arg_i32(i32 %_a) +// i686: void @c_arg_i32(i32 %_a) +// aarch64-apple: void @c_arg_i32(i32 %_a) // aarch64-windows: void @c_arg_i32(i32 %_a) // aarch64-linux: void @c_arg_i32(i32 %_a) -// arm: void @c_arg_i32(i32 %_a) +// arm: void @c_arg_i32(i32 %_a) // riscv: void @c_arg_i32(i32 signext %_a) #[no_mangle] pub extern "C" fn c_arg_i32(_a: i32) {} -// x86_64-linux: void @c_arg_i64(i64 %_a) -// x86_64-uefi: void @c_arg_i64(i64 %_a) -// i686: void @c_arg_i64(i64 %_a) -// aarch64-apple: void @c_arg_i64(i64 %_a) +// x86_64-linux: void @c_arg_i64(i64 %_a) +// x86_64-uefi: void @c_arg_i64(i64 %_a) +// i686: void @c_arg_i64(i64 %_a) +// aarch64-apple: void @c_arg_i64(i64 %_a) // aarch64-windows: void @c_arg_i64(i64 %_a) // aarch64-linux: void @c_arg_i64(i64 %_a) -// arm: void @c_arg_i64(i64 %_a) -// riscv: void @c_arg_i64(i64 %_a) +// arm: void @c_arg_i64(i64 %_a) +// riscv: void @c_arg_i64(i64 %_a) #[no_mangle] pub extern "C" fn c_arg_i64(_a: i64) {} @@ -138,8 +144,8 @@ pub extern "C" fn c_arg_i64(_a: i64) {} // x86_64-uefi: zeroext i1 @c_ret_bool() // i686: zeroext i1 @c_ret_bool() // aarch64-apple: zeroext i1 @c_ret_bool() -// aarch64-windows: i1 @c_ret_bool() -// aarch64-linux: i1 @c_ret_bool() +// aarch64-windows: define {{(dso_local )?}}i1 @c_ret_bool() +// aarch64-linux: define {{(dso_local )?}}i1 @c_ret_bool() // arm: zeroext i1 @c_ret_bool() // riscv: zeroext i1 @c_ret_bool() #[no_mangle] @@ -147,12 +153,12 @@ pub extern "C" fn c_ret_bool() -> bool { false } -// x86_64-linux: i8 @c_ret_u8() +// x86_64-linux: define {{(dso_local )?}}i8 @c_ret_u8() // x86_64-uefi: zeroext i8 @c_ret_u8() // i686: zeroext i8 @c_ret_u8() // aarch64-apple: zeroext i8 @c_ret_u8() -// aarch64-windows: i8 @c_ret_u8() -// aarch64-linux: i8 @c_ret_u8() +// aarch64-windows: define {{(dso_local )?}}i8 @c_ret_u8() +// aarch64-linux: define {{(dso_local )?}}i8 @c_ret_u8() // arm: zeroext i8 @c_ret_u8() // riscv: zeroext i8 @c_ret_u8() #[no_mangle] @@ -160,12 +166,12 @@ pub extern "C" fn c_ret_u8() -> u8 { 0 } -// x86_64-linux: i16 @c_ret_u16() +// x86_64-linux: define {{(dso_local )?}}i16 @c_ret_u16() // x86_64-uefi: zeroext i16 @c_ret_u16() // i686: zeroext i16 @c_ret_u16() // aarch64-apple: zeroext i16 @c_ret_u16() -// aarch64-windows: i16 @c_ret_u16() -// aarch64-linux: i16 @c_ret_u16() +// aarch64-windows: define {{(dso_local )?}}i16 @c_ret_u16() +// aarch64-linux: define {{(dso_local )?}}i16 @c_ret_u16() // arm: zeroext i16 @c_ret_u16() // riscv: zeroext i16 @c_ret_u16() #[no_mangle] @@ -173,38 +179,38 @@ pub extern "C" fn c_ret_u16() -> u16 { 0 } -// x86_64-linux: i32 @c_ret_u32() -// x86_64-uefi: i32 @c_ret_u32() -// i686: i32 @c_ret_u32() -// aarch64-apple: i32 @c_ret_u32() -// aarch64-windows: i32 @c_ret_u32() -// aarch64-linux: i32 @c_ret_u32() -// arm: i32 @c_ret_u32() +// x86_64-linux: define {{(dso_local )?}}i32 @c_ret_u32() +// x86_64-uefi: define {{(dso_local )?}}i32 @c_ret_u32() +// i686: define {{(dso_local )?}}i32 @c_ret_u32() +// aarch64-apple: define {{(dso_local )?}}i32 @c_ret_u32() +// aarch64-windows: define {{(dso_local )?}}i32 @c_ret_u32() +// aarch64-linux: define {{(dso_local )?}}i32 @c_ret_u32() +// arm: define {{(dso_local )?}}i32 @c_ret_u32() // riscv: signext i32 @c_ret_u32() #[no_mangle] pub extern "C" fn c_ret_u32() -> u32 { 0 } -// x86_64-linux: i64 @c_ret_u64() -// x86_64-uefi: i64 @c_ret_u64() -// i686: i64 @c_ret_u64() -// aarch64-apple: i64 @c_ret_u64() -// aarch64-windows: i64 @c_ret_u64() -// aarch64-linux: i64 @c_ret_u64() -// arm: i64 @c_ret_u64() -// riscv: i64 @c_ret_u64() +// x86_64-linux: define {{(dso_local )?}}i64 @c_ret_u64() +// x86_64-uefi: define {{(dso_local )?}}i64 @c_ret_u64() +// i686: define {{(dso_local )?}}i64 @c_ret_u64() +// aarch64-apple: define {{(dso_local )?}}i64 @c_ret_u64() +// aarch64-windows: define {{(dso_local )?}}i64 @c_ret_u64() +// aarch64-linux: define {{(dso_local )?}}i64 @c_ret_u64() +// arm: define {{(dso_local )?}}i64 @c_ret_u64() +// riscv: define {{(dso_local )?}}i64 @c_ret_u64() #[no_mangle] pub extern "C" fn c_ret_u64() -> u64 { 0 } -// x86_64-linux: i8 @c_ret_i8() +// x86_64-linux: define {{(dso_local )?}}i8 @c_ret_i8() // x86_64-uefi: signext i8 @c_ret_i8() // i686: signext i8 @c_ret_i8() // aarch64-apple: signext i8 @c_ret_i8() -// aarch64-windows: i8 @c_ret_i8() -// aarch64-linux: i8 @c_ret_i8() +// aarch64-windows: define {{(dso_local )?}}i8 @c_ret_i8() +// aarch64-linux: define {{(dso_local )?}}i8 @c_ret_i8() // arm: signext i8 @c_ret_i8() // riscv: signext i8 @c_ret_i8() #[no_mangle] @@ -212,12 +218,12 @@ pub extern "C" fn c_ret_i8() -> i8 { 0 } -// x86_64-linux: i16 @c_ret_i16() +// x86_64-linux: define {{(dso_local )?}}i16 @c_ret_i16() // x86_64-uefi: signext i16 @c_ret_i16() // i686: signext i16 @c_ret_i16() // aarch64-apple: signext i16 @c_ret_i16() -// aarch64-windows: i16 @c_ret_i16() -// aarch64-linux: i16 @c_ret_i16() +// aarch64-windows: define {{(dso_local )?}}i16 @c_ret_i16() +// aarch64-linux: define {{(dso_local )?}}i16 @c_ret_i16() // arm: signext i16 @c_ret_i16() // riscv: signext i16 @c_ret_i16() #[no_mangle] @@ -225,27 +231,27 @@ pub extern "C" fn c_ret_i16() -> i16 { 0 } -// x86_64-linux: i32 @c_ret_i32() -// x86_64-uefi: i32 @c_ret_i32() -// i686: i32 @c_ret_i32() -// aarch64-apple: i32 @c_ret_i32() -// aarch64-windows: i32 @c_ret_i32() -// aarch64-linux: i32 @c_ret_i32() -// arm: i32 @c_ret_i32() +// x86_64-linux: define {{(dso_local )?}}i32 @c_ret_i32() +// x86_64-uefi: define {{(dso_local )?}}i32 @c_ret_i32() +// i686: define {{(dso_local )?}}i32 @c_ret_i32() +// aarch64-apple: define {{(dso_local )?}}i32 @c_ret_i32() +// aarch64-windows: define {{(dso_local )?}}i32 @c_ret_i32() +// aarch64-linux: define {{(dso_local )?}}i32 @c_ret_i32() +// arm: define {{(dso_local )?}}i32 @c_ret_i32() // riscv: signext i32 @c_ret_i32() #[no_mangle] pub extern "C" fn c_ret_i32() -> i32 { 0 } -// x86_64-linux: i64 @c_ret_i64() -// x86_64-uefi: i64 @c_ret_i64() -// i686: i64 @c_ret_i64() -// aarch64-apple: i64 @c_ret_i64() -// aarch64-windows: i64 @c_ret_i64() -// aarch64-linux: i64 @c_ret_i64() -// arm: i64 @c_ret_i64() -// riscv: i64 @c_ret_i64() +// x86_64-linux: define {{(dso_local )?}}i64 @c_ret_i64() +// x86_64-uefi: define {{(dso_local )?}}i64 @c_ret_i64() +// i686: define {{(dso_local )?}}i64 @c_ret_i64() +// aarch64-apple: define {{(dso_local )?}}i64 @c_ret_i64() +// aarch64-windows: define {{(dso_local )?}}i64 @c_ret_i64() +// aarch64-linux: define {{(dso_local )?}}i64 @c_ret_i64() +// arm: define {{(dso_local )?}}i64 @c_ret_i64() +// riscv: define {{(dso_local )?}}i64 @c_ret_i64() #[no_mangle] pub extern "C" fn c_ret_i64() -> i64 { 0 diff --git a/tests/codegen-llvm/var-names.rs b/tests/codegen-llvm/var-names.rs index 40720e197614e..071ac4db786ce 100644 --- a/tests/codegen-llvm/var-names.rs +++ b/tests/codegen-llvm/var-names.rs @@ -9,7 +9,7 @@ pub fn test(a: u32, b: u32) -> u32 { // CHECK: %c = add i32 %a, %b let d = c; let e = d * a; - // CHECK-NEXT: %e = mul i32 %c, %a + // CHECK-NEXT: %e = mul i32 %a, %c e // CHECK-NEXT: ret i32 %e } diff --git a/tests/mir-opt/gvn.rs b/tests/mir-opt/gvn.rs index 0405a6a8ba39e..2ce475f7401ac 100644 --- a/tests/mir-opt/gvn.rs +++ b/tests/mir-opt/gvn.rs @@ -103,7 +103,7 @@ fn subexpression_elimination(x: u64, y: u64, mut z: u64) { // We can substitute through an immutable reference. // CHECK: [[ref:_.*]] = &_3; // CHECK: [[deref:_.*]] = copy (*[[ref]]); - // CHECK: [[addref:_.*]] = Add(copy [[deref]], copy _1); + // CHECK: [[addref:_.*]] = Add(copy _1, copy [[deref]]); // CHECK: opaque::(copy [[addref]]) // CHECK: [[deref2:_.*]] = copy [[deref]]; // CHECK: [[addref2:_.*]] = copy [[addref]]; @@ -143,7 +143,7 @@ fn subexpression_elimination(x: u64, y: u64, mut z: u64) { // Important: `e` is not `a`! // CHECK: [[ref2:_.*]] = &_3; // CHECK: [[deref2:_.*]] = copy (*[[ref2]]); - // CHECK: [[addref2:_.*]] = Add(copy [[deref2]], copy _1); + // CHECK: [[addref2:_.*]] = Add(copy _1, copy [[deref2]]); // CHECK: opaque::(copy [[addref2]]) // CHECK: [[deref3:_.*]] = copy [[deref2]]; // CHECK: [[addref3:_.*]] = copy [[addref2]]; diff --git a/tests/mir-opt/gvn.subexpression_elimination.GVN.panic-abort.diff b/tests/mir-opt/gvn.subexpression_elimination.GVN.panic-abort.diff index 7a479bc55da75..957d62fd72bd5 100644 --- a/tests/mir-opt/gvn.subexpression_elimination.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.subexpression_elimination.GVN.panic-abort.diff @@ -766,7 +766,7 @@ StorageLive(_130); _130 = copy _1; - _128 = Add(move _129, move _130); -+ _128 = Add(copy _129, copy _1); ++ _128 = Add(copy _1, copy _129); StorageDead(_130); - StorageDead(_129); - _127 = opaque::(move _128) -> [return: bb35, unwind unreachable]; @@ -805,7 +805,7 @@ StorageLive(_139); _139 = copy _1; - _137 = Add(move _138, move _139); -+ _137 = Add(move _138, copy _1); ++ _137 = Add(copy _1, move _138); StorageDead(_139); StorageDead(_138); _136 = opaque::(move _137) -> [return: bb37, unwind unreachable]; @@ -821,7 +821,7 @@ StorageLive(_143); _143 = copy _1; - _141 = Add(move _142, move _143); -+ _141 = Add(move _142, copy _1); ++ _141 = Add(copy _1, move _142); StorageDead(_143); StorageDead(_142); _140 = opaque::(move _141) -> [return: bb38, unwind unreachable]; @@ -840,7 +840,7 @@ StorageLive(_149); _149 = copy _1; - _147 = Add(move _148, move _149); -+ _147 = Add(move _148, copy _1); ++ _147 = Add(copy _1, move _148); StorageDead(_149); StorageDead(_148); _146 = opaque::(move _147) -> [return: bb39, unwind unreachable]; @@ -856,7 +856,7 @@ StorageLive(_153); _153 = copy _1; - _151 = Add(move _152, move _153); -+ _151 = Add(move _152, copy _1); ++ _151 = Add(copy _1, move _152); StorageDead(_153); StorageDead(_152); _150 = opaque::(move _151) -> [return: bb40, unwind unreachable]; @@ -874,7 +874,7 @@ StorageLive(_158); _158 = copy _1; - _156 = Add(move _157, move _158); -+ _156 = Add(move _157, copy _1); ++ _156 = Add(copy _1, move _157); StorageDead(_158); StorageDead(_157); _155 = opaque::(move _156) -> [return: bb41, unwind unreachable]; @@ -890,7 +890,7 @@ StorageLive(_162); _162 = copy _1; - _160 = Add(move _161, move _162); -+ _160 = Add(move _161, copy _1); ++ _160 = Add(copy _1, move _161); StorageDead(_162); StorageDead(_161); _159 = opaque::(move _160) -> [return: bb42, unwind unreachable]; @@ -914,7 +914,7 @@ StorageLive(_167); _167 = copy _1; - _165 = Add(move _166, move _167); -+ _165 = Add(copy _166, copy _1); ++ _165 = Add(copy _1, copy _166); StorageDead(_167); - StorageDead(_166); - _164 = opaque::(move _165) -> [return: bb43, unwind unreachable]; diff --git a/tests/mir-opt/gvn.subexpression_elimination.GVN.panic-unwind.diff b/tests/mir-opt/gvn.subexpression_elimination.GVN.panic-unwind.diff index 3ca5238663c28..c5fcc0aff6981 100644 --- a/tests/mir-opt/gvn.subexpression_elimination.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.subexpression_elimination.GVN.panic-unwind.diff @@ -766,7 +766,7 @@ StorageLive(_130); _130 = copy _1; - _128 = Add(move _129, move _130); -+ _128 = Add(copy _129, copy _1); ++ _128 = Add(copy _1, copy _129); StorageDead(_130); - StorageDead(_129); - _127 = opaque::(move _128) -> [return: bb35, unwind continue]; @@ -805,7 +805,7 @@ StorageLive(_139); _139 = copy _1; - _137 = Add(move _138, move _139); -+ _137 = Add(move _138, copy _1); ++ _137 = Add(copy _1, move _138); StorageDead(_139); StorageDead(_138); _136 = opaque::(move _137) -> [return: bb37, unwind continue]; @@ -821,7 +821,7 @@ StorageLive(_143); _143 = copy _1; - _141 = Add(move _142, move _143); -+ _141 = Add(move _142, copy _1); ++ _141 = Add(copy _1, move _142); StorageDead(_143); StorageDead(_142); _140 = opaque::(move _141) -> [return: bb38, unwind continue]; @@ -840,7 +840,7 @@ StorageLive(_149); _149 = copy _1; - _147 = Add(move _148, move _149); -+ _147 = Add(move _148, copy _1); ++ _147 = Add(copy _1, move _148); StorageDead(_149); StorageDead(_148); _146 = opaque::(move _147) -> [return: bb39, unwind continue]; @@ -856,7 +856,7 @@ StorageLive(_153); _153 = copy _1; - _151 = Add(move _152, move _153); -+ _151 = Add(move _152, copy _1); ++ _151 = Add(copy _1, move _152); StorageDead(_153); StorageDead(_152); _150 = opaque::(move _151) -> [return: bb40, unwind continue]; @@ -874,7 +874,7 @@ StorageLive(_158); _158 = copy _1; - _156 = Add(move _157, move _158); -+ _156 = Add(move _157, copy _1); ++ _156 = Add(copy _1, move _157); StorageDead(_158); StorageDead(_157); _155 = opaque::(move _156) -> [return: bb41, unwind continue]; @@ -890,7 +890,7 @@ StorageLive(_162); _162 = copy _1; - _160 = Add(move _161, move _162); -+ _160 = Add(move _161, copy _1); ++ _160 = Add(copy _1, move _161); StorageDead(_162); StorageDead(_161); _159 = opaque::(move _160) -> [return: bb42, unwind continue]; @@ -914,7 +914,7 @@ StorageLive(_167); _167 = copy _1; - _165 = Add(move _166, move _167); -+ _165 = Add(copy _166, copy _1); ++ _165 = Add(copy _1, copy _166); StorageDead(_167); - StorageDead(_166); - _164 = opaque::(move _165) -> [return: bb43, unwind continue]; diff --git a/tests/mir-opt/gvn_commutative.add_commuted.GVN.diff b/tests/mir-opt/gvn_commutative.add_commuted.GVN.diff new file mode 100644 index 0000000000000..a0b78bfe9f50c --- /dev/null +++ b/tests/mir-opt/gvn_commutative.add_commuted.GVN.diff @@ -0,0 +1,41 @@ +- // MIR for `add_commuted` before GVN ++ // MIR for `add_commuted` after GVN + + fn add_commuted(_1: u32, _2: u32) -> (u32, u32) { + debug a => _1; + debug b => _2; + let mut _0: (u32, u32); + let mut _3: u32; + let mut _4: u32; + let mut _5: u32; + let mut _6: u32; + let mut _7: u32; + let mut _8: u32; + + bb0: { + StorageLive(_3); + StorageLive(_4); + _4 = copy _1; + StorageLive(_5); + _5 = copy _2; +- _3 = Add(move _4, move _5); ++ _3 = Add(copy _1, copy _2); + StorageDead(_5); + StorageDead(_4); + StorageLive(_6); + StorageLive(_7); + _7 = copy _2; + StorageLive(_8); + _8 = copy _1; +- _6 = Add(move _7, move _8); ++ _6 = copy _3; + StorageDead(_8); + StorageDead(_7); +- _0 = (move _3, move _6); ++ _0 = (copy _3, copy _3); + StorageDead(_6); + StorageDead(_3); + return; + } + } + diff --git a/tests/mir-opt/gvn_commutative.add_overflow_commuted.GVN.diff b/tests/mir-opt/gvn_commutative.add_overflow_commuted.GVN.diff new file mode 100644 index 0000000000000..f762ecf7acd4b --- /dev/null +++ b/tests/mir-opt/gvn_commutative.add_overflow_commuted.GVN.diff @@ -0,0 +1,41 @@ +- // MIR for `add_overflow_commuted` before GVN ++ // MIR for `add_overflow_commuted` after GVN + + fn add_overflow_commuted(_1: u32, _2: u32) -> ((u32, bool), (u32, bool)) { + debug a => _1; + debug b => _2; + let mut _0: ((u32, bool), (u32, bool)); + let mut _3: (u32, bool); + let mut _4: u32; + let mut _5: u32; + let mut _6: (u32, bool); + let mut _7: u32; + let mut _8: u32; + + bb0: { + StorageLive(_3); + StorageLive(_4); + _4 = copy _1; + StorageLive(_5); + _5 = copy _2; +- _3 = AddWithOverflow(move _4, move _5); ++ _3 = AddWithOverflow(copy _1, copy _2); + StorageDead(_5); + StorageDead(_4); + StorageLive(_6); + StorageLive(_7); + _7 = copy _2; + StorageLive(_8); + _8 = copy _1; +- _6 = AddWithOverflow(move _7, move _8); ++ _6 = copy _3; + StorageDead(_8); + StorageDead(_7); +- _0 = (move _3, move _6); ++ _0 = (copy _3, copy _3); + StorageDead(_6); + StorageDead(_3); + return; + } + } + diff --git a/tests/mir-opt/gvn_commutative.add_unchecked_commuted.GVN.diff b/tests/mir-opt/gvn_commutative.add_unchecked_commuted.GVN.diff new file mode 100644 index 0000000000000..b29ea823bd147 --- /dev/null +++ b/tests/mir-opt/gvn_commutative.add_unchecked_commuted.GVN.diff @@ -0,0 +1,41 @@ +- // MIR for `add_unchecked_commuted` before GVN ++ // MIR for `add_unchecked_commuted` after GVN + + fn add_unchecked_commuted(_1: u32, _2: u32) -> (u32, u32) { + debug a => _1; + debug b => _2; + let mut _0: (u32, u32); + let mut _3: u32; + let mut _4: u32; + let mut _5: u32; + let mut _6: u32; + let mut _7: u32; + let mut _8: u32; + + bb0: { + StorageLive(_3); + StorageLive(_4); + _4 = copy _1; + StorageLive(_5); + _5 = copy _2; +- _3 = AddUnchecked(move _4, move _5); ++ _3 = AddUnchecked(copy _1, copy _2); + StorageDead(_5); + StorageDead(_4); + StorageLive(_6); + StorageLive(_7); + _7 = copy _2; + StorageLive(_8); + _8 = copy _1; +- _6 = AddUnchecked(move _7, move _8); ++ _6 = copy _3; + StorageDead(_8); + StorageDead(_7); +- _0 = (move _3, move _6); ++ _0 = (copy _3, copy _3); + StorageDead(_6); + StorageDead(_3); + return; + } + } + diff --git a/tests/mir-opt/gvn_commutative.and_commuted.GVN.diff b/tests/mir-opt/gvn_commutative.and_commuted.GVN.diff new file mode 100644 index 0000000000000..b25db7e644169 --- /dev/null +++ b/tests/mir-opt/gvn_commutative.and_commuted.GVN.diff @@ -0,0 +1,41 @@ +- // MIR for `and_commuted` before GVN ++ // MIR for `and_commuted` after GVN + + fn and_commuted(_1: u32, _2: u32) -> (u32, u32) { + debug a => _1; + debug b => _2; + let mut _0: (u32, u32); + let mut _3: u32; + let mut _4: u32; + let mut _5: u32; + let mut _6: u32; + let mut _7: u32; + let mut _8: u32; + + bb0: { + StorageLive(_3); + StorageLive(_4); + _4 = copy _1; + StorageLive(_5); + _5 = copy _2; +- _3 = BitAnd(move _4, move _5); ++ _3 = BitAnd(copy _1, copy _2); + StorageDead(_5); + StorageDead(_4); + StorageLive(_6); + StorageLive(_7); + _7 = copy _2; + StorageLive(_8); + _8 = copy _1; +- _6 = BitAnd(move _7, move _8); ++ _6 = copy _3; + StorageDead(_8); + StorageDead(_7); +- _0 = (move _3, move _6); ++ _0 = (copy _3, copy _3); + StorageDead(_6); + StorageDead(_3); + return; + } + } + diff --git a/tests/mir-opt/gvn_commutative.eq_commuted.GVN.diff b/tests/mir-opt/gvn_commutative.eq_commuted.GVN.diff new file mode 100644 index 0000000000000..2f20ece1c915b --- /dev/null +++ b/tests/mir-opt/gvn_commutative.eq_commuted.GVN.diff @@ -0,0 +1,41 @@ +- // MIR for `eq_commuted` before GVN ++ // MIR for `eq_commuted` after GVN + + fn eq_commuted(_1: u32, _2: u32) -> (bool, bool) { + debug a => _1; + debug b => _2; + let mut _0: (bool, bool); + let mut _3: bool; + let mut _4: u32; + let mut _5: u32; + let mut _6: bool; + let mut _7: u32; + let mut _8: u32; + + bb0: { + StorageLive(_3); + StorageLive(_4); + _4 = copy _1; + StorageLive(_5); + _5 = copy _2; +- _3 = Eq(move _4, move _5); ++ _3 = Eq(copy _1, copy _2); + StorageDead(_5); + StorageDead(_4); + StorageLive(_6); + StorageLive(_7); + _7 = copy _2; + StorageLive(_8); + _8 = copy _1; +- _6 = Eq(move _7, move _8); ++ _6 = copy _3; + StorageDead(_8); + StorageDead(_7); +- _0 = (move _3, move _6); ++ _0 = (copy _3, copy _3); + StorageDead(_6); + StorageDead(_3); + return; + } + } + diff --git a/tests/mir-opt/gvn_commutative.mul_commuted.GVN.diff b/tests/mir-opt/gvn_commutative.mul_commuted.GVN.diff new file mode 100644 index 0000000000000..7b0677be7f890 --- /dev/null +++ b/tests/mir-opt/gvn_commutative.mul_commuted.GVN.diff @@ -0,0 +1,41 @@ +- // MIR for `mul_commuted` before GVN ++ // MIR for `mul_commuted` after GVN + + fn mul_commuted(_1: u32, _2: u32) -> (u32, u32) { + debug a => _1; + debug b => _2; + let mut _0: (u32, u32); + let mut _3: u32; + let mut _4: u32; + let mut _5: u32; + let mut _6: u32; + let mut _7: u32; + let mut _8: u32; + + bb0: { + StorageLive(_3); + StorageLive(_4); + _4 = copy _1; + StorageLive(_5); + _5 = copy _2; +- _3 = Mul(move _4, move _5); ++ _3 = Mul(copy _1, copy _2); + StorageDead(_5); + StorageDead(_4); + StorageLive(_6); + StorageLive(_7); + _7 = copy _2; + StorageLive(_8); + _8 = copy _1; +- _6 = Mul(move _7, move _8); ++ _6 = copy _3; + StorageDead(_8); + StorageDead(_7); +- _0 = (move _3, move _6); ++ _0 = (copy _3, copy _3); + StorageDead(_6); + StorageDead(_3); + return; + } + } + diff --git a/tests/mir-opt/gvn_commutative.mul_overflow_commuted.GVN.diff b/tests/mir-opt/gvn_commutative.mul_overflow_commuted.GVN.diff new file mode 100644 index 0000000000000..3eb9d5d4cd5db --- /dev/null +++ b/tests/mir-opt/gvn_commutative.mul_overflow_commuted.GVN.diff @@ -0,0 +1,41 @@ +- // MIR for `mul_overflow_commuted` before GVN ++ // MIR for `mul_overflow_commuted` after GVN + + fn mul_overflow_commuted(_1: u32, _2: u32) -> ((u32, bool), (u32, bool)) { + debug a => _1; + debug b => _2; + let mut _0: ((u32, bool), (u32, bool)); + let mut _3: (u32, bool); + let mut _4: u32; + let mut _5: u32; + let mut _6: (u32, bool); + let mut _7: u32; + let mut _8: u32; + + bb0: { + StorageLive(_3); + StorageLive(_4); + _4 = copy _1; + StorageLive(_5); + _5 = copy _2; +- _3 = MulWithOverflow(move _4, move _5); ++ _3 = MulWithOverflow(copy _1, copy _2); + StorageDead(_5); + StorageDead(_4); + StorageLive(_6); + StorageLive(_7); + _7 = copy _2; + StorageLive(_8); + _8 = copy _1; +- _6 = MulWithOverflow(move _7, move _8); ++ _6 = copy _3; + StorageDead(_8); + StorageDead(_7); +- _0 = (move _3, move _6); ++ _0 = (copy _3, copy _3); + StorageDead(_6); + StorageDead(_3); + return; + } + } + diff --git a/tests/mir-opt/gvn_commutative.mul_unchecked_commuted.GVN.diff b/tests/mir-opt/gvn_commutative.mul_unchecked_commuted.GVN.diff new file mode 100644 index 0000000000000..ceafeb1323b00 --- /dev/null +++ b/tests/mir-opt/gvn_commutative.mul_unchecked_commuted.GVN.diff @@ -0,0 +1,41 @@ +- // MIR for `mul_unchecked_commuted` before GVN ++ // MIR for `mul_unchecked_commuted` after GVN + + fn mul_unchecked_commuted(_1: u32, _2: u32) -> (u32, u32) { + debug a => _1; + debug b => _2; + let mut _0: (u32, u32); + let mut _3: u32; + let mut _4: u32; + let mut _5: u32; + let mut _6: u32; + let mut _7: u32; + let mut _8: u32; + + bb0: { + StorageLive(_3); + StorageLive(_4); + _4 = copy _1; + StorageLive(_5); + _5 = copy _2; +- _3 = MulUnchecked(move _4, move _5); ++ _3 = MulUnchecked(copy _1, copy _2); + StorageDead(_5); + StorageDead(_4); + StorageLive(_6); + StorageLive(_7); + _7 = copy _2; + StorageLive(_8); + _8 = copy _1; +- _6 = MulUnchecked(move _7, move _8); ++ _6 = copy _3; + StorageDead(_8); + StorageDead(_7); +- _0 = (move _3, move _6); ++ _0 = (copy _3, copy _3); + StorageDead(_6); + StorageDead(_3); + return; + } + } + diff --git a/tests/mir-opt/gvn_commutative.ne_commuted.GVN.diff b/tests/mir-opt/gvn_commutative.ne_commuted.GVN.diff new file mode 100644 index 0000000000000..ef1323f39ee38 --- /dev/null +++ b/tests/mir-opt/gvn_commutative.ne_commuted.GVN.diff @@ -0,0 +1,41 @@ +- // MIR for `ne_commuted` before GVN ++ // MIR for `ne_commuted` after GVN + + fn ne_commuted(_1: u32, _2: u32) -> (bool, bool) { + debug a => _1; + debug b => _2; + let mut _0: (bool, bool); + let mut _3: bool; + let mut _4: u32; + let mut _5: u32; + let mut _6: bool; + let mut _7: u32; + let mut _8: u32; + + bb0: { + StorageLive(_3); + StorageLive(_4); + _4 = copy _1; + StorageLive(_5); + _5 = copy _2; +- _3 = Ne(move _4, move _5); ++ _3 = Ne(copy _1, copy _2); + StorageDead(_5); + StorageDead(_4); + StorageLive(_6); + StorageLive(_7); + _7 = copy _2; + StorageLive(_8); + _8 = copy _1; +- _6 = Ne(move _7, move _8); ++ _6 = copy _3; + StorageDead(_8); + StorageDead(_7); +- _0 = (move _3, move _6); ++ _0 = (copy _3, copy _3); + StorageDead(_6); + StorageDead(_3); + return; + } + } + diff --git a/tests/mir-opt/gvn_commutative.or_commuted.GVN.diff b/tests/mir-opt/gvn_commutative.or_commuted.GVN.diff new file mode 100644 index 0000000000000..090469dce3909 --- /dev/null +++ b/tests/mir-opt/gvn_commutative.or_commuted.GVN.diff @@ -0,0 +1,41 @@ +- // MIR for `or_commuted` before GVN ++ // MIR for `or_commuted` after GVN + + fn or_commuted(_1: u32, _2: u32) -> (u32, u32) { + debug a => _1; + debug b => _2; + let mut _0: (u32, u32); + let mut _3: u32; + let mut _4: u32; + let mut _5: u32; + let mut _6: u32; + let mut _7: u32; + let mut _8: u32; + + bb0: { + StorageLive(_3); + StorageLive(_4); + _4 = copy _1; + StorageLive(_5); + _5 = copy _2; +- _3 = BitOr(move _4, move _5); ++ _3 = BitOr(copy _1, copy _2); + StorageDead(_5); + StorageDead(_4); + StorageLive(_6); + StorageLive(_7); + _7 = copy _2; + StorageLive(_8); + _8 = copy _1; +- _6 = BitOr(move _7, move _8); ++ _6 = copy _3; + StorageDead(_8); + StorageDead(_7); +- _0 = (move _3, move _6); ++ _0 = (copy _3, copy _3); + StorageDead(_6); + StorageDead(_3); + return; + } + } + diff --git a/tests/mir-opt/gvn_commutative.rs b/tests/mir-opt/gvn_commutative.rs new file mode 100644 index 0000000000000..9a38136f6ca0c --- /dev/null +++ b/tests/mir-opt/gvn_commutative.rs @@ -0,0 +1,103 @@ +//@ test-mir-pass: GVN + +#![feature(core_intrinsics)] +#![crate_type = "lib"] + +// EMIT_MIR gvn_commutative.add_commuted.GVN.diff +#[unsafe(no_mangle)] +pub fn add_commuted(a: u32, b: u32) -> (u32, u32) { + // CHECK-LABEL: fn add_commuted( + // CHECK: [[LEFT:_.*]] = Add(copy _1, copy _2); + // CHECK: _0 = (copy [[LEFT]], copy [[LEFT]]); + (a + b, b + a) +} + +// EMIT_MIR gvn_commutative.mul_commuted.GVN.diff +#[unsafe(no_mangle)] +pub fn mul_commuted(a: u32, b: u32) -> (u32, u32) { + // CHECK-LABEL: fn mul_commuted( + // CHECK: [[LEFT:_.*]] = Mul(copy _1, copy _2); + // CHECK: _0 = (copy [[LEFT]], copy [[LEFT]]); + (a * b, b * a) +} + +// EMIT_MIR gvn_commutative.and_commuted.GVN.diff +#[unsafe(no_mangle)] +pub fn and_commuted(a: u32, b: u32) -> (u32, u32) { + // CHECK-LABEL: fn and_commuted( + // CHECK: [[LEFT:_.*]] = BitAnd(copy _1, copy _2); + // CHECK: _0 = (copy [[LEFT]], copy [[LEFT]]); + (a & b, b & a) +} + +// EMIT_MIR gvn_commutative.or_commuted.GVN.diff +#[unsafe(no_mangle)] +pub fn or_commuted(a: u32, b: u32) -> (u32, u32) { + // CHECK-LABEL: fn or_commuted( + // CHECK: [[LEFT:_.*]] = BitOr(copy _1, copy _2); + // CHECK: _0 = (copy [[LEFT]], copy [[LEFT]]); + (a | b, b | a) +} + +// EMIT_MIR gvn_commutative.xor_commuted.GVN.diff +#[unsafe(no_mangle)] +pub fn xor_commuted(a: u32, b: u32) -> (u32, u32) { + // CHECK-LABEL: fn xor_commuted( + // CHECK: [[LEFT:_.*]] = BitXor(copy _1, copy _2); + // CHECK: _0 = (copy [[LEFT]], copy [[LEFT]]); + (a ^ b, b ^ a) +} + +// EMIT_MIR gvn_commutative.eq_commuted.GVN.diff +#[unsafe(no_mangle)] +pub fn eq_commuted(a: u32, b: u32) -> (bool, bool) { + // CHECK-LABEL: fn eq_commuted( + // CHECK: [[LEFT:_.*]] = Eq(copy _1, copy _2); + // CHECK: _0 = (copy [[LEFT]], copy [[LEFT]]); + (a == b, b == a) +} + +// EMIT_MIR gvn_commutative.ne_commuted.GVN.diff +#[unsafe(no_mangle)] +pub fn ne_commuted(a: u32, b: u32) -> (bool, bool) { + // CHECK-LABEL: fn ne_commuted( + // CHECK: [[LEFT:_.*]] = Ne(copy _1, copy _2); + // CHECK: _0 = (copy [[LEFT]], copy [[LEFT]]); + (a != b, b != a) +} + +// EMIT_MIR gvn_commutative.add_unchecked_commuted.GVN.diff +#[unsafe(no_mangle)] +pub fn add_unchecked_commuted(a: u32, b: u32) -> (u32, u32) { + // CHECK-LABEL: fn add_unchecked_commuted( + // CHECK: [[LEFT:_.*]] = AddUnchecked(copy _1, copy _2); + // CHECK: _0 = (copy [[LEFT]], copy [[LEFT]]); + unsafe { (core::intrinsics::unchecked_add(a, b), core::intrinsics::unchecked_add(b, a)) } +} + +// EMIT_MIR gvn_commutative.mul_unchecked_commuted.GVN.diff +#[unsafe(no_mangle)] +pub fn mul_unchecked_commuted(a: u32, b: u32) -> (u32, u32) { + // CHECK-LABEL: fn mul_unchecked_commuted( + // CHECK: [[LEFT:_.*]] = MulUnchecked(copy _1, copy _2); + // CHECK: _0 = (copy [[LEFT]], copy [[LEFT]]); + unsafe { (core::intrinsics::unchecked_mul(a, b), core::intrinsics::unchecked_mul(b, a)) } +} + +// EMIT_MIR gvn_commutative.add_overflow_commuted.GVN.diff +#[unsafe(no_mangle)] +pub fn add_overflow_commuted(a: u32, b: u32) -> ((u32, bool), (u32, bool)) { + // CHECK-LABEL: fn add_overflow_commuted( + // CHECK: [[LEFT:_.*]] = AddWithOverflow(copy _1, copy _2); + // CHECK: _0 = (copy [[LEFT]], copy [[LEFT]]); + (core::intrinsics::add_with_overflow(a, b), core::intrinsics::add_with_overflow(b, a)) +} + +// EMIT_MIR gvn_commutative.mul_overflow_commuted.GVN.diff +#[unsafe(no_mangle)] +pub fn mul_overflow_commuted(a: u32, b: u32) -> ((u32, bool), (u32, bool)) { + // CHECK-LABEL: fn mul_overflow_commuted( + // CHECK: [[LEFT:_.*]] = MulWithOverflow(copy _1, copy _2); + // CHECK: _0 = (copy [[LEFT]], copy [[LEFT]]); + (core::intrinsics::mul_with_overflow(a, b), core::intrinsics::mul_with_overflow(b, a)) +} diff --git a/tests/mir-opt/gvn_commutative.xor_commuted.GVN.diff b/tests/mir-opt/gvn_commutative.xor_commuted.GVN.diff new file mode 100644 index 0000000000000..e6e61679ff538 --- /dev/null +++ b/tests/mir-opt/gvn_commutative.xor_commuted.GVN.diff @@ -0,0 +1,41 @@ +- // MIR for `xor_commuted` before GVN ++ // MIR for `xor_commuted` after GVN + + fn xor_commuted(_1: u32, _2: u32) -> (u32, u32) { + debug a => _1; + debug b => _2; + let mut _0: (u32, u32); + let mut _3: u32; + let mut _4: u32; + let mut _5: u32; + let mut _6: u32; + let mut _7: u32; + let mut _8: u32; + + bb0: { + StorageLive(_3); + StorageLive(_4); + _4 = copy _1; + StorageLive(_5); + _5 = copy _2; +- _3 = BitXor(move _4, move _5); ++ _3 = BitXor(copy _1, copy _2); + StorageDead(_5); + StorageDead(_4); + StorageLive(_6); + StorageLive(_7); + _7 = copy _2; + StorageLive(_8); + _8 = copy _1; +- _6 = BitXor(move _7, move _8); ++ _6 = copy _3; + StorageDead(_8); + StorageDead(_7); +- _0 = (move _3, move _6); ++ _0 = (copy _3, copy _3); + StorageDead(_6); + StorageDead(_3); + return; + } + } + diff --git a/tests/mir-opt/if_condition_int.dont_remove_comparison.SimplifyComparisonIntegral.diff b/tests/mir-opt/if_condition_int.dont_remove_comparison.SimplifyComparisonIntegral.diff index ada818c6d4767..1402756281206 100644 --- a/tests/mir-opt/if_condition_int.dont_remove_comparison.SimplifyComparisonIntegral.diff +++ b/tests/mir-opt/if_condition_int.dont_remove_comparison.SimplifyComparisonIntegral.diff @@ -30,7 +30,7 @@ _7 = copy _2; _6 = copy _2 as i32 (IntToInt); StorageDead(_7); - _0 = Add(const 100_i32, move _6); + _0 = Add(move _6, const 100_i32); StorageDead(_6); goto -> bb3; } @@ -41,7 +41,7 @@ _5 = copy _2; _4 = copy _2 as i32 (IntToInt); StorageDead(_5); - _0 = Add(const 10_i32, move _4); + _0 = Add(move _4, const 10_i32); StorageDead(_4); goto -> bb3; } diff --git a/tests/mir-opt/if_condition_int.rs b/tests/mir-opt/if_condition_int.rs index 3d8f637b00408..ce824e3372edb 100644 --- a/tests/mir-opt/if_condition_int.rs +++ b/tests/mir-opt/if_condition_int.rs @@ -92,10 +92,10 @@ fn dont_remove_comparison(a: i8) -> i32 { // CHECK: switchInt(copy _1) -> [17: [[BB1:bb.*]], otherwise: [[BB2:bb.*]]]; // CHECK: [[BB1]]: // CHECK: [[cast_1:_.*]] = copy [[b]] as i32 (IntToInt); - // CHECK: _0 = Add(const 100_i32, move [[cast_1]]); + // CHECK: _0 = Add(move [[cast_1]], const 100_i32); // CHECK: [[BB2]]: // CHECK: [[cast_2:_.*]] = copy [[b]] as i32 (IntToInt); - // CHECK: _0 = Add(const 10_i32, move [[cast_2]]); + // CHECK: _0 = Add(move [[cast_2]], const 10_i32); let b = a == 17; match b { false => 10 + b as i32, diff --git a/tests/mir-opt/inline/inline_shims.drop.Inline.panic-abort.diff b/tests/mir-opt/inline/inline_shims.drop.Inline.panic-abort.diff index a7cf6a7733083..437745be8bc90 100644 --- a/tests/mir-opt/inline/inline_shims.drop.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/inline_shims.drop.Inline.panic-abort.diff @@ -121,7 +121,7 @@ + } + + bb4: { -+ _16 = Eq(copy _14, copy _11); ++ _16 = Eq(copy _11, copy _14); + switchInt(move _16) -> [0: bb3, otherwise: bb2]; + } + diff --git a/tests/mir-opt/pre-codegen/deref_nested_borrows.src.GVN.panic-abort.diff b/tests/mir-opt/pre-codegen/deref_nested_borrows.src.GVN.panic-abort.diff index 9450bd51bdb83..0026d03323e32 100644 --- a/tests/mir-opt/pre-codegen/deref_nested_borrows.src.GVN.panic-abort.diff +++ b/tests/mir-opt/pre-codegen/deref_nested_borrows.src.GVN.panic-abort.diff @@ -28,7 +28,7 @@ StorageLive(_5); _5 = copy _2; - _0 = Eq(move _4, move _5); -+ _0 = Eq(move _4, copy _2); ++ _0 = Eq(copy _2, move _4); StorageDead(_5); StorageDead(_4); StorageDead(_2); diff --git a/tests/mir-opt/pre-codegen/deref_nested_borrows.src.GVN.panic-unwind.diff b/tests/mir-opt/pre-codegen/deref_nested_borrows.src.GVN.panic-unwind.diff index 100e1a8504427..04e1211bde445 100644 --- a/tests/mir-opt/pre-codegen/deref_nested_borrows.src.GVN.panic-unwind.diff +++ b/tests/mir-opt/pre-codegen/deref_nested_borrows.src.GVN.panic-unwind.diff @@ -28,7 +28,7 @@ StorageLive(_5); _5 = copy _2; - _0 = Eq(move _4, move _5); -+ _0 = Eq(move _4, copy _2); ++ _0 = Eq(copy _2, move _4); StorageDead(_5); StorageDead(_4); StorageDead(_2); diff --git a/tests/mir-opt/pre-codegen/deref_nested_borrows.src.runtime-optimized.after.panic-abort.mir b/tests/mir-opt/pre-codegen/deref_nested_borrows.src.runtime-optimized.after.panic-abort.mir index 1385663e271d1..0719a51cef557 100644 --- a/tests/mir-opt/pre-codegen/deref_nested_borrows.src.runtime-optimized.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/deref_nested_borrows.src.runtime-optimized.after.panic-abort.mir @@ -23,7 +23,7 @@ fn src(_1: &&u8) -> bool { StorageLive(_6); _5 = no_retag copy (*_1); _6 = copy (*_5); - _0 = Eq(move _6, copy _3); + _0 = Eq(copy _3, move _6); StorageDead(_6); StorageDead(_3); return; diff --git a/tests/mir-opt/pre-codegen/deref_nested_borrows.src.runtime-optimized.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/deref_nested_borrows.src.runtime-optimized.after.panic-unwind.mir index ef192696afdbb..10e82641e58d2 100644 --- a/tests/mir-opt/pre-codegen/deref_nested_borrows.src.runtime-optimized.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/deref_nested_borrows.src.runtime-optimized.after.panic-unwind.mir @@ -23,7 +23,7 @@ fn src(_1: &&u8) -> bool { StorageLive(_6); _5 = no_retag copy (*_1); _6 = copy (*_5); - _0 = Eq(move _6, copy _3); + _0 = Eq(copy _3, move _6); StorageDead(_6); StorageDead(_3); return; 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() {} diff --git a/tests/ui/borrowck/wrong-loop-explain-borrow-error-issue-164169.rs b/tests/ui/borrowck/wrong-loop-explain-borrow-error-issue-164169.rs new file mode 100644 index 0000000000000..82599a84df661 --- /dev/null +++ b/tests/ui/borrowck/wrong-loop-explain-borrow-error-issue-164169.rs @@ -0,0 +1,31 @@ +//@ check-fail +//@ forbid-output: backend2.push( +use std::path::PathBuf; + +type Test = Option<(PathBuf, Vec)>; + +fn test1(backend: &mut Vec) -> Result<(), String> { + let mut backend2 = Vec::new(); + for b in backend { + backend2.push(match b { + None => None, + Some((file, bytes)) => Some((file.as_path(), bytes)), + }); + } + + loop { + test2(&mut backend2)?; //~ ERROR E0499 + } +} + +fn test2<'a, P, C>(disks: &'a mut [Option<(P, &'a mut Vec)>]) -> Result { + todo!() +} + +fn test3<'a, P, C>(disks: &'a mut [Option<(P, &'a mut Vec)>]) -> Result { + loop { + test2(disks)?; //~ ERROR E0499 + } +} + +fn main() {} diff --git a/tests/ui/borrowck/wrong-loop-explain-borrow-error-issue-164169.stderr b/tests/ui/borrowck/wrong-loop-explain-borrow-error-issue-164169.stderr new file mode 100644 index 0000000000000..92026d3aedec8 --- /dev/null +++ b/tests/ui/borrowck/wrong-loop-explain-borrow-error-issue-164169.stderr @@ -0,0 +1,24 @@ +error[E0499]: cannot borrow `backend2` as mutable more than once at a time + --> $DIR/wrong-loop-explain-borrow-error-issue-164169.rs:17:15 + | +LL | test2(&mut backend2)?; + | ^^^^^^^^^^^^^ + | | + | `backend2` was mutably borrowed here in the previous iteration of the loop + | first borrow used here, in later iteration of loop + +error[E0499]: cannot borrow `*disks` as mutable more than once at a time + --> $DIR/wrong-loop-explain-borrow-error-issue-164169.rs:27:15 + | +LL | fn test3<'a, P, C>(disks: &'a mut [Option<(P, &'a mut Vec)>]) -> Result { + | -- lifetime `'a` defined here +LL | loop { +LL | test2(disks)?; + | ------^^^^^- + | | | + | | `*disks` was mutably borrowed here in the previous iteration of the loop + | argument requires that `*disks` is borrowed for `'a` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/feature-gates/feature-gate-large-assignments.rs b/tests/ui/feature-gates/feature-gate-large-assignments.rs index 3c284ca3cafbd..dc37b8735410b 100644 --- a/tests/ui/feature-gates/feature-gate-large-assignments.rs +++ b/tests/ui/feature-gates/feature-gate-large-assignments.rs @@ -1,5 +1,6 @@ // check that `move_size_limit` is feature-gated #![move_size_limit = "42"] //~ ERROR the `move_size_limit` attribute is an experimental feature +//~^ ERROR the `move_size_limit` attribute is an experimental feature fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-large-assignments.stderr b/tests/ui/feature-gates/feature-gate-large-assignments.stderr index 350afcc0d63ad..6ec13a4f5342e 100644 --- a/tests/ui/feature-gates/feature-gate-large-assignments.stderr +++ b/tests/ui/feature-gates/feature-gate-large-assignments.stderr @@ -8,6 +8,17 @@ LL | #![move_size_limit = "42"] = help: add `#![feature(large_assignments)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 1 previous error +error[E0658]: the `move_size_limit` attribute is an experimental feature + --> $DIR/feature-gate-large-assignments.rs:3:4 + | +LL | #![move_size_limit = "42"] + | ^^^^^^^^^^^^^^^ + | + = note: see issue #83518 for more information + = help: add `#![feature(large_assignments)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-pattern-complexity-limit.rs b/tests/ui/feature-gates/feature-gate-pattern-complexity-limit.rs index 972312a497fa2..5a04749132ce2 100644 --- a/tests/ui/feature-gates/feature-gate-pattern-complexity-limit.rs +++ b/tests/ui/feature-gates/feature-gate-pattern-complexity-limit.rs @@ -2,7 +2,11 @@ #![pattern_complexity_limit = "42"] //~^ ERROR: use of an internal attribute [E0658] +//~| ERROR: use of an internal attribute [E0658] //~| NOTE the `pattern_complexity_limit` attribute is an internal implementation detail that will never be stable //~| NOTE: the `pattern_complexity_limit` attribute is used for rustc unit tests +//~| NOTE the `pattern_complexity_limit` attribute is an internal implementation detail that will never be stable +//~| NOTE: the `pattern_complexity_limit` attribute is used for rustc unit tests +//~| NOTE: duplicate diagnostic fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-pattern-complexity-limit.stderr b/tests/ui/feature-gates/feature-gate-pattern-complexity-limit.stderr index 7faf38d842e7f..82c57be8ec4e4 100644 --- a/tests/ui/feature-gates/feature-gate-pattern-complexity-limit.stderr +++ b/tests/ui/feature-gates/feature-gate-pattern-complexity-limit.stderr @@ -8,6 +8,17 @@ LL | #![pattern_complexity_limit = "42"] = note: the `pattern_complexity_limit` attribute is an internal implementation detail that will never be stable = note: the `pattern_complexity_limit` attribute is used for rustc unit tests -error: aborting due to 1 previous error +error[E0658]: use of an internal attribute + --> $DIR/feature-gate-pattern-complexity-limit.rs:3:4 + | +LL | #![pattern_complexity_limit = "42"] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable + = note: the `pattern_complexity_limit` attribute is an internal implementation detail that will never be stable + = note: the `pattern_complexity_limit` attribute is used for rustc unit tests + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0658`.