diff options
106 files changed, 1549 insertions, 284 deletions
diff --git a/Cargo.lock b/Cargo.lock index ce78d921244..d6714199682 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3569,6 +3569,7 @@ dependencies = [ "rustc_hir_pretty", "rustc_hir_typeck", "rustc_incremental", + "rustc_index", "rustc_infer", "rustc_interface", "rustc_lint", diff --git a/compiler/rustc/Cargo.toml b/compiler/rustc/Cargo.toml index 5008069542f..a2fc9d5c408 100644 --- a/compiler/rustc/Cargo.toml +++ b/compiler/rustc/Cargo.toml @@ -30,5 +30,6 @@ features = ['unprefixed_malloc_on_supported_platforms'] jemalloc = ['dep:jemalloc-sys'] llvm = ['rustc_driver_impl/llvm'] max_level_info = ['rustc_driver_impl/max_level_info'] +rustc_randomized_layouts = ['rustc_driver_impl/rustc_randomized_layouts'] rustc_use_parallel_compiler = ['rustc_driver_impl/rustc_use_parallel_compiler'] # tidy-alphabetical-end diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs index 5160b4ed0a2..7432768be4a 100644 --- a/compiler/rustc_abi/src/layout.rs +++ b/compiler/rustc_abi/src/layout.rs @@ -968,8 +968,8 @@ fn univariant< let mut align = if pack.is_some() { dl.i8_align } else { dl.aggregate_align }; let mut max_repr_align = repr.align; let mut inverse_memory_index: IndexVec<u32, FieldIdx> = fields.indices().collect(); - let optimize = !repr.inhibit_struct_field_reordering(); - if optimize && fields.len() > 1 { + let optimize_field_order = !repr.inhibit_struct_field_reordering(); + if optimize_field_order && fields.len() > 1 { let end = if let StructKind::MaybeUnsized = kind { fields.len() - 1 } else { fields.len() }; let optimizing = &mut inverse_memory_index.raw[..end]; let fields_excluding_tail = &fields.raw[..end]; @@ -1176,7 +1176,7 @@ fn univariant< // If field 5 has offset 0, offsets[0] is 5, and memory_index[5] should be 0. // Field 5 would be the first element, so memory_index is i: // Note: if we didn't optimize, it's already right. - let memory_index = if optimize { + let memory_index = if optimize_field_order { inverse_memory_index.invert_bijective_mapping() } else { debug_assert!(inverse_memory_index.iter().copied().eq(fields.indices())); @@ -1189,6 +1189,9 @@ fn univariant< } let mut layout_of_single_non_zst_field = None; let mut abi = Abi::Aggregate { sized }; + + let optimize_abi = !repr.inhibit_newtype_abi_optimization(); + // Try to make this a Scalar/ScalarPair. if sized && size.bytes() > 0 { // We skip *all* ZST here and later check if we are good in terms of alignment. @@ -1205,7 +1208,7 @@ fn univariant< match field.abi { // For plain scalars, or vectors of them, we can't unpack // newtypes for `#[repr(C)]`, as that affects C ABIs. - Abi::Scalar(_) | Abi::Vector { .. } if optimize => { + Abi::Scalar(_) | Abi::Vector { .. } if optimize_abi => { abi = field.abi; } // But scalar pairs are Rust-specific and get diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index df29b3d54f0..be42bc84932 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -43,14 +43,17 @@ bitflags! { const IS_SIMD = 1 << 1; const IS_TRANSPARENT = 1 << 2; // Internal only for now. If true, don't reorder fields. + // On its own it does not prevent ABI optimizations. const IS_LINEAR = 1 << 3; - // If true, the type's layout can be randomized using - // the seed stored in `ReprOptions.field_shuffle_seed` + // If true, the type's crate has opted into layout randomization. + // Other flags can still inhibit reordering and thus randomization. + // The seed stored in `ReprOptions.field_shuffle_seed`. const RANDOMIZE_LAYOUT = 1 << 4; // Any of these flags being set prevent field reordering optimisation. - const IS_UNOPTIMISABLE = ReprFlags::IS_C.bits() + const FIELD_ORDER_UNOPTIMIZABLE = ReprFlags::IS_C.bits() | ReprFlags::IS_SIMD.bits() | ReprFlags::IS_LINEAR.bits(); + const ABI_UNOPTIMIZABLE = ReprFlags::IS_C.bits() | ReprFlags::IS_SIMD.bits(); } } @@ -139,10 +142,14 @@ impl ReprOptions { self.c() || self.int.is_some() } + pub fn inhibit_newtype_abi_optimization(&self) -> bool { + self.flags.intersects(ReprFlags::ABI_UNOPTIMIZABLE) + } + /// Returns `true` if this `#[repr()]` guarantees a fixed field order, /// e.g. `repr(C)` or `repr(<int>)`. pub fn inhibit_struct_field_reordering(&self) -> bool { - self.flags.intersects(ReprFlags::IS_UNOPTIMISABLE) || self.int.is_some() + self.flags.intersects(ReprFlags::FIELD_ORDER_UNOPTIMIZABLE) || self.int.is_some() } /// Returns `true` if this type is valid for reordering and `-Z randomize-layout` diff --git a/compiler/rustc_driver_impl/Cargo.toml b/compiler/rustc_driver_impl/Cargo.toml index 91cbffcd707..6d6d3f35a4b 100644 --- a/compiler/rustc_driver_impl/Cargo.toml +++ b/compiler/rustc_driver_impl/Cargo.toml @@ -23,6 +23,7 @@ rustc_hir_analysis = { path = "../rustc_hir_analysis" } rustc_hir_pretty = { path = "../rustc_hir_pretty" } rustc_hir_typeck = { path = "../rustc_hir_typeck" } rustc_incremental = { path = "../rustc_incremental" } +rustc_index = { path = "../rustc_index" } rustc_infer = { path = "../rustc_infer" } rustc_interface = { path = "../rustc_interface" } rustc_lint = { path = "../rustc_lint" } @@ -72,6 +73,10 @@ ctrlc = "3.4.4" # tidy-alphabetical-start llvm = ['rustc_interface/llvm'] max_level_info = ['rustc_log/max_level_info'] +rustc_randomized_layouts = [ + 'rustc_index/rustc_randomized_layouts', + 'rustc_middle/rustc_randomized_layouts' +] rustc_use_parallel_compiler = [ 'rustc_data_structures/rustc_use_parallel_compiler', 'rustc_interface/rustc_use_parallel_compiler', diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index cd6adbda039..fba65883550 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -349,8 +349,10 @@ declare_features! ( (unstable, adt_const_params, "1.56.0", Some(95174)), /// Allows defining an `#[alloc_error_handler]`. (unstable, alloc_error_handler, "1.29.0", Some(51540)), - /// Allows trait methods with arbitrary self types. + /// Allows inherent and trait methods with arbitrary self types. (unstable, arbitrary_self_types, "1.23.0", Some(44874)), + /// Allows inherent and trait methods with arbitrary self types that are raw pointers. + (unstable, arbitrary_self_types_pointers, "CURRENT_RUSTC_VERSION", Some(44874)), /// Enables experimental inline assembly support for additional architectures. (unstable, asm_experimental_arch, "1.58.0", Some(93335)), /// Allows using `label` operands in inline assembly. diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index f83eac7cd6c..3627faf8dfc 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -1652,6 +1652,13 @@ fn check_fn_or_method<'tcx>( } } +/// The `arbitrary_self_types_pointers` feature implies `arbitrary_self_types`. +#[derive(Clone, Copy, PartialEq)] +enum ArbitrarySelfTypesLevel { + Basic, // just arbitrary_self_types + WithPointers, // both arbitrary_self_types and arbitrary_self_types_pointers +} + #[instrument(level = "debug", skip(wfcx))] fn check_method_receiver<'tcx>( wfcx: &WfCheckingCtxt<'_, 'tcx>, @@ -1684,14 +1691,27 @@ fn check_method_receiver<'tcx>( return Ok(()); } - if tcx.features().arbitrary_self_types { - if !receiver_is_valid(wfcx, span, receiver_ty, self_ty, true) { - // Report error; `arbitrary_self_types` was enabled. - return Err(tcx.dcx().emit_err(errors::InvalidReceiverTy { span, receiver_ty })); - } + let arbitrary_self_types_level = if tcx.features().arbitrary_self_types_pointers { + Some(ArbitrarySelfTypesLevel::WithPointers) + } else if tcx.features().arbitrary_self_types { + Some(ArbitrarySelfTypesLevel::Basic) } else { - if !receiver_is_valid(wfcx, span, receiver_ty, self_ty, false) { - return Err(if receiver_is_valid(wfcx, span, receiver_ty, self_ty, true) { + None + }; + + if !receiver_is_valid(wfcx, span, receiver_ty, self_ty, arbitrary_self_types_level) { + return Err(match arbitrary_self_types_level { + // Wherever possible, emit a message advising folks that the features + // `arbitrary_self_types` or `arbitrary_self_types_pointers` might + // have helped. + None if receiver_is_valid( + wfcx, + span, + receiver_ty, + self_ty, + Some(ArbitrarySelfTypesLevel::Basic), + ) => + { // Report error; would have worked with `arbitrary_self_types`. feature_err( &tcx.sess, @@ -1699,25 +1719,49 @@ fn check_method_receiver<'tcx>( span, format!( "`{receiver_ty}` cannot be used as the type of `self` without \ - the `arbitrary_self_types` feature", + the `arbitrary_self_types` feature", ), ) .with_help(fluent::hir_analysis_invalid_receiver_ty_help) .emit() - } else { - // Report error; would not have worked with `arbitrary_self_types`. + } + None | Some(ArbitrarySelfTypesLevel::Basic) + if receiver_is_valid( + wfcx, + span, + receiver_ty, + self_ty, + Some(ArbitrarySelfTypesLevel::WithPointers), + ) => + { + // Report error; would have worked with `arbitrary_self_types_pointers`. + feature_err( + &tcx.sess, + sym::arbitrary_self_types_pointers, + span, + format!( + "`{receiver_ty}` cannot be used as the type of `self` without \ + the `arbitrary_self_types_pointers` feature", + ), + ) + .with_help(fluent::hir_analysis_invalid_receiver_ty_help) + .emit() + } + _ => + // Report error; would not have worked with `arbitrary_self_types[_pointers]`. + { tcx.dcx().emit_err(errors::InvalidReceiverTy { span, receiver_ty }) - }); - } + } + }); } Ok(()) } /// Returns whether `receiver_ty` would be considered a valid receiver type for `self_ty`. If /// `arbitrary_self_types` is enabled, `receiver_ty` must transitively deref to `self_ty`, possibly -/// through a `*const/mut T` raw pointer. If the feature is not enabled, the requirements are more -/// strict: `receiver_ty` must implement `Receiver` and directly implement -/// `Deref<Target = self_ty>`. +/// through a `*const/mut T` raw pointer if `arbitrary_self_types_pointers` is also enabled. +/// If neither feature is enabled, the requirements are more strict: `receiver_ty` must implement +/// `Receiver` and directly implement `Deref<Target = self_ty>`. /// /// N.B., there are cases this function returns `true` but causes an error to be emitted, /// particularly when `receiver_ty` derefs to a type that is the same as `self_ty` but has the @@ -1727,7 +1771,7 @@ fn receiver_is_valid<'tcx>( span: Span, receiver_ty: Ty<'tcx>, self_ty: Ty<'tcx>, - arbitrary_self_types_enabled: bool, + arbitrary_self_types_enabled: Option<ArbitrarySelfTypesLevel>, ) -> bool { let infcx = wfcx.infcx; let tcx = wfcx.tcx(); @@ -1745,8 +1789,8 @@ fn receiver_is_valid<'tcx>( let mut autoderef = Autoderef::new(infcx, wfcx.param_env, wfcx.body_def_id, span, receiver_ty); - // The `arbitrary_self_types` feature allows raw pointer receivers like `self: *const Self`. - if arbitrary_self_types_enabled { + // The `arbitrary_self_types_pointers` feature allows raw pointer receivers like `self: *const Self`. + if arbitrary_self_types_enabled == Some(ArbitrarySelfTypesLevel::WithPointers) { autoderef = autoderef.include_raw_pointers(); } @@ -1772,7 +1816,7 @@ fn receiver_is_valid<'tcx>( // Without `feature(arbitrary_self_types)`, we require that each step in the // deref chain implement `receiver`. - if !arbitrary_self_types_enabled { + if arbitrary_self_types_enabled.is_none() { if !receiver_is_implemented( wfcx, receiver_trait_def_id, diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 0cf5403b3c0..2fdba8446bd 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -403,7 +403,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { mode, })); } else if bad_ty.reached_raw_pointer - && !self.tcx.features().arbitrary_self_types + && !self.tcx.features().arbitrary_self_types_pointers && !self.tcx.sess.at_least_rust_2018() { // this case used to be allowed by the compiler, diff --git a/compiler/rustc_index/Cargo.toml b/compiler/rustc_index/Cargo.toml index 92ea3f278dc..f7d18f84e34 100644 --- a/compiler/rustc_index/Cargo.toml +++ b/compiler/rustc_index/Cargo.toml @@ -20,4 +20,5 @@ nightly = [ "dep:rustc_macros", "rustc_index_macros/nightly", ] +rustc_randomized_layouts = [] # tidy-alphabetical-end diff --git a/compiler/rustc_index/src/lib.rs b/compiler/rustc_index/src/lib.rs index f773b5b46ad..52f354b8eca 100644 --- a/compiler/rustc_index/src/lib.rs +++ b/compiler/rustc_index/src/lib.rs @@ -33,8 +33,19 @@ pub use vec::IndexVec; /// /// </div> #[macro_export] +#[cfg(not(feature = "rustc_randomized_layouts"))] macro_rules! static_assert_size { ($ty:ty, $size:expr) => { const _: [(); $size] = [(); ::std::mem::size_of::<$ty>()]; }; } + +#[macro_export] +#[cfg(feature = "rustc_randomized_layouts")] +macro_rules! static_assert_size { + ($ty:ty, $size:expr) => { + // no effect other than using the statements. + // struct sizes are not deterministic under randomized layouts + const _: (usize, usize) = ($size, ::std::mem::size_of::<$ty>()); + }; +} diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 7063f488209..25d33126754 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -3706,7 +3706,7 @@ declare_lint_pass!(UnusedDocComment => [UNUSED_DOC_COMMENTS]); declare_lint! { /// The `missing_abi` lint detects cases where the ABI is omitted from - /// extern declarations. + /// `extern` declarations. /// /// ### Example /// @@ -3720,10 +3720,12 @@ declare_lint! { /// /// ### Explanation /// - /// Historically, Rust implicitly selected C as the ABI for extern - /// declarations. We expect to add new ABIs, like `C-unwind`, in the future, - /// though this has not yet happened, and especially with their addition - /// seeing the ABI easily will make code review easier. + /// For historic reasons, Rust implicitly selects `C` as the default ABI for + /// `extern` declarations. [Other ABIs] like `C-unwind` and `system` have + /// been added since then, and especially with their addition seeing the ABI + /// easily makes code review easier. + /// + /// [Other ABIs]: https://doc.rust-lang.org/reference/items/external-blocks.html#abi pub MISSING_ABI, Allow, "No declared ABI for extern declaration" diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 1264510a831..53da07aeaa6 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -247,8 +247,8 @@ provide! { tcx, def_id, other, cdata, explicit_predicates_of => { table } generics_of => { table } inferred_outlives_of => { table_defaulted_array } - explicit_super_predicates_of => { table } - explicit_implied_predicates_of => { table } + explicit_super_predicates_of => { table_defaulted_array } + explicit_implied_predicates_of => { table_defaulted_array } type_of => { table } type_alias_is_lazy => { table_direct } variances_of => { table } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 88256c4db04..c55583b39a6 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1443,9 +1443,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } if let DefKind::Trait = def_kind { record!(self.tables.trait_def[def_id] <- self.tcx.trait_def(def_id)); - record_array!(self.tables.explicit_super_predicates_of[def_id] <- + record_defaulted_array!(self.tables.explicit_super_predicates_of[def_id] <- self.tcx.explicit_super_predicates_of(def_id).skip_binder()); - record_array!(self.tables.explicit_implied_predicates_of[def_id] <- + record_defaulted_array!(self.tables.explicit_implied_predicates_of[def_id] <- self.tcx.explicit_implied_predicates_of(def_id).skip_binder()); let module_children = self.tcx.module_children_local(local_id); @@ -1454,9 +1454,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } if let DefKind::TraitAlias = def_kind { record!(self.tables.trait_def[def_id] <- self.tcx.trait_def(def_id)); - record_array!(self.tables.explicit_super_predicates_of[def_id] <- + record_defaulted_array!(self.tables.explicit_super_predicates_of[def_id] <- self.tcx.explicit_super_predicates_of(def_id).skip_binder()); - record_array!(self.tables.explicit_implied_predicates_of[def_id] <- + record_defaulted_array!(self.tables.explicit_implied_predicates_of[def_id] <- self.tcx.explicit_implied_predicates_of(def_id).skip_binder()); } if let DefKind::Trait | DefKind::Impl { .. } = def_kind { diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index a84923130c3..8180a507a51 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -390,6 +390,8 @@ define_tables! { explicit_item_bounds: Table<DefIndex, LazyArray<(ty::Clause<'static>, Span)>>, explicit_item_super_predicates: Table<DefIndex, LazyArray<(ty::Clause<'static>, Span)>>, inferred_outlives_of: Table<DefIndex, LazyArray<(ty::Clause<'static>, Span)>>, + explicit_super_predicates_of: Table<DefIndex, LazyArray<(ty::Clause<'static>, Span)>>, + explicit_implied_predicates_of: Table<DefIndex, LazyArray<(ty::Clause<'static>, Span)>>, inherent_impls: Table<DefIndex, LazyArray<DefIndex>>, associated_types_for_impl_traits_in_associated_fn: Table<DefIndex, LazyArray<DefId>>, associated_type_for_effects: Table<DefIndex, Option<LazyValue<DefId>>>, @@ -419,10 +421,6 @@ define_tables! { lookup_deprecation_entry: Table<DefIndex, LazyValue<attr::Deprecation>>, explicit_predicates_of: Table<DefIndex, LazyValue<ty::GenericPredicates<'static>>>, generics_of: Table<DefIndex, LazyValue<ty::Generics>>, - explicit_super_predicates_of: Table<DefIndex, LazyArray<(ty::Clause<'static>, Span)>>, - // As an optimization, we only store this for trait aliases, - // since it's identical to explicit_super_predicates_of for traits. - explicit_implied_predicates_of: Table<DefIndex, LazyArray<(ty::Clause<'static>, Span)>>, type_of: Table<DefIndex, LazyValue<ty::EarlyBinder<'static, Ty<'static>>>>, variances_of: Table<DefIndex, LazyArray<ty::Variance>>, fn_sig: Table<DefIndex, LazyValue<ty::EarlyBinder<'static, ty::PolyFnSig<'static>>>>, diff --git a/compiler/rustc_middle/Cargo.toml b/compiler/rustc_middle/Cargo.toml index 69e3b703cce..b23589afb58 100644 --- a/compiler/rustc_middle/Cargo.toml +++ b/compiler/rustc_middle/Cargo.toml @@ -40,5 +40,6 @@ tracing = "0.1" [features] # tidy-alphabetical-start +rustc_randomized_layouts = [] rustc_use_parallel_compiler = ["dep:rustc-rayon-core"] # tidy-alphabetical-end diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs index c9bd702cce3..0320a91d142 100644 --- a/compiler/rustc_middle/src/query/plumbing.rs +++ b/compiler/rustc_middle/src/query/plumbing.rs @@ -337,6 +337,7 @@ macro_rules! define_callbacks { // Ensure that values grow no larger than 64 bytes by accident. // Increase this limit if necessary, but do try to keep the size low if possible #[cfg(target_pointer_width = "64")] + #[cfg(not(feature = "rustc_randomized_layouts"))] const _: () = { if mem::size_of::<Value<'static>>() > 64 { panic!("{}", concat!( diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index cd94c0afad0..ee70a6346d9 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -35,6 +35,7 @@ use rustc_data_structures::tagged_ptr::CopyTaggedPtr; use rustc_errors::{Diag, ErrorGuaranteed, StashKey}; use rustc_hir::def::{CtorKind, CtorOf, DefKind, DocLinkResMap, LifetimeRes, Res}; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LocalDefIdMap}; +use rustc_hir::LangItem; use rustc_index::IndexVec; use rustc_macros::{ extension, Decodable, Encodable, HashStable, TyDecodable, TyEncodable, TypeFoldable, @@ -1570,8 +1571,15 @@ impl<'tcx> TyCtxt<'tcx> { flags.insert(ReprFlags::RANDOMIZE_LAYOUT); } + // box is special, on the one hand the compiler assumes an ordered layout, with the pointer + // always at offset zero. On the other hand we want scalar abi optimizations. + let is_box = self.is_lang_item(did.to_def_id(), LangItem::OwnedBox); + // This is here instead of layout because the choice must make it into metadata. - if !self.consider_optimizing(|| format!("Reorder fields of {:?}", self.def_path_str(did))) { + if is_box + || !self + .consider_optimizing(|| format!("Reorder fields of {:?}", self.def_path_str(did))) + { flags.insert(ReprFlags::IS_LINEAR); } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 34765209605..36b31d10c4d 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -407,6 +407,7 @@ symbols! { append_const_msg, arbitrary_enum_discriminant, arbitrary_self_types, + arbitrary_self_types_pointers, args, arith_offset, arm, diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index e6b00c84254..6abd8a0d6b7 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -1695,6 +1695,8 @@ supported_targets! { ("armv7r-none-eabihf", armv7r_none_eabihf), ("armv8r-none-eabihf", armv8r_none_eabihf), + ("armv7-rtems-eabihf", armv7_rtems_eabihf), + ("x86_64-pc-solaris", x86_64_pc_solaris), ("sparcv9-sun-solaris", sparcv9_sun_solaris), diff --git a/compiler/rustc_target/src/spec/targets/armv7_rtems_eabihf.rs b/compiler/rustc_target/src/spec/targets/armv7_rtems_eabihf.rs new file mode 100644 index 00000000000..1edecac095f --- /dev/null +++ b/compiler/rustc_target/src/spec/targets/armv7_rtems_eabihf.rs @@ -0,0 +1,35 @@ +use crate::spec::{cvs, Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions}; + +pub(crate) fn target() -> Target { + Target { + llvm_target: "armv7-unknown-none-eabihf".into(), + metadata: crate::spec::TargetMetadata { + description: Some("Armv7 RTEMS (Requires RTEMS toolchain and kernel".into()), + tier: Some(3), + host_tools: Some(false), + std: Some(true), + }, + pointer_width: 32, + data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(), + arch: "arm".into(), + + options: TargetOptions { + os: "rtems".into(), + families: cvs!["unix"], + abi: "eabihf".into(), + linker_flavor: LinkerFlavor::Gnu(Cc::Yes, Lld::No), + linker: None, + relocation_model: RelocModel::Static, + panic_strategy: PanicStrategy::Abort, + features: "+thumb2,+neon,+vfp3".into(), + max_atomic_width: Some(64), + emit_debug_gdb_scripts: false, + // GCC defaults to 8 for arm-none here. + c_enum_min_bits: Some(8), + eh_frame_header: false, + no_default_libraries: false, + env: "newlib".into(), + ..Default::default() + }, + } +} diff --git a/config.example.toml b/config.example.toml index b967d5d9fe8..13f76933b16 100644 --- a/config.example.toml +++ b/config.example.toml @@ -519,6 +519,9 @@ # are disabled statically" because `max_level_info` is enabled, set this value to `true`. #debug-logging = rust.debug-assertions (boolean) +# Whether or not to build rustc, tools and the libraries with randomized type layout +#randomize-layout = false + # Whether or not overflow checks are enabled for the compiler and standard # library. # diff --git a/library/alloc/Cargo.toml b/library/alloc/Cargo.toml index 4365bcc4ad0..1bd4434d4f7 100644 --- a/library/alloc/Cargo.toml +++ b/library/alloc/Cargo.toml @@ -52,4 +52,5 @@ check-cfg = [ 'cfg(no_global_oom_handling)', 'cfg(no_rc)', 'cfg(no_sync)', + 'cfg(randomized_layouts)', ] diff --git a/library/alloc/src/collections/btree/node/tests.rs b/library/alloc/src/collections/btree/node/tests.rs index d230749d712..4d2fa0f0941 100644 --- a/library/alloc/src/collections/btree/node/tests.rs +++ b/library/alloc/src/collections/btree/node/tests.rs @@ -90,7 +90,7 @@ fn test_partial_eq() { #[test] #[cfg(target_arch = "x86_64")] -#[cfg_attr(miri, ignore)] // We'd like to run Miri with layout randomization +#[cfg_attr(any(miri, randomized_layouts), ignore)] // We'd like to run Miri with layout randomization fn test_sizes() { assert_eq!(core::mem::size_of::<LeafNode<(), ()>>(), 16); assert_eq!(core::mem::size_of::<LeafNode<i64, i64>>(), 16 + CAPACITY * 2 * 8); diff --git a/library/core/Cargo.toml b/library/core/Cargo.toml index cace4582b48..94f343d0670 100644 --- a/library/core/Cargo.toml +++ b/library/core/Cargo.toml @@ -43,6 +43,8 @@ check-cfg = [ 'cfg(bootstrap)', 'cfg(no_fp_fmt_parse)', 'cfg(stdarch_intel_sde)', + # #[cfg(bootstrap)] rtems + 'cfg(target_os, values("rtems"))', # core use #[path] imports to portable-simd `core_simd` crate # and to stdarch `core_arch` crate which messes-up with Cargo list # of declared features, we therefor expect any feature cfg diff --git a/library/core/src/ffi/mod.rs b/library/core/src/ffi/mod.rs index ec1f9052a15..dc107c5d22c 100644 --- a/library/core/src/ffi/mod.rs +++ b/library/core/src/ffi/mod.rs @@ -110,7 +110,7 @@ mod c_char_definition { all(target_os = "android", any(target_arch = "aarch64", target_arch = "arm")), all(target_os = "l4re", target_arch = "x86_64"), all( - any(target_os = "freebsd", target_os = "openbsd"), + any(target_os = "freebsd", target_os = "openbsd", target_os = "rtems"), any( target_arch = "aarch64", target_arch = "arm", diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs index 7e5c1574f53..6924b3c13ec 100644 --- a/library/core/src/task/wake.rs +++ b/library/core/src/task/wake.rs @@ -60,22 +60,6 @@ impl RawWaker { RawWaker { data, vtable } } - /// Gets the `data` pointer used to create this `RawWaker`. - #[inline] - #[must_use] - #[unstable(feature = "waker_getters", issue = "96992")] - pub fn data(&self) -> *const () { - self.data - } - - /// Gets the `vtable` pointer used to create this `RawWaker`. - #[inline] - #[must_use] - #[unstable(feature = "waker_getters", issue = "96992")] - pub fn vtable(&self) -> &'static RawWakerVTable { - self.vtable - } - #[unstable(feature = "noop_waker", issue = "98286")] const NOOP: RawWaker = { const VTABLE: RawWakerVTable = RawWakerVTable::new( @@ -509,6 +493,37 @@ impl Waker { a_data == b_data && ptr::eq(a_vtable, b_vtable) } + /// Creates a new `Waker` from the provided `data` pointer and `vtable`. + /// + /// The `data` pointer can be used to store arbitrary data as required + /// by the executor. This could be e.g. a type-erased pointer to an `Arc` + /// that is associated with the task. + /// The value of this pointer will get passed to all functions that are part + /// of the `vtable` as the first parameter. + /// + /// It is important to consider that the `data` pointer must point to a + /// thread safe type such as an `Arc`. + /// + /// The `vtable` customizes the behavior of a `Waker`. For each operation + /// on the `Waker`, the associated function in the `vtable` will be called. + /// + /// # Safety + /// + /// The behavior of the returned `Waker` is undefined if the contract defined + /// in [`RawWakerVTable`]'s documentation is not upheld. + /// + /// (Authors wishing to avoid unsafe code may implement the [`Wake`] trait instead, at the + /// cost of a required heap allocation.) + /// + /// [`Wake`]: ../../alloc/task/trait.Wake.html + #[inline] + #[must_use] + #[stable(feature = "waker_getters", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "waker_getters", since = "CURRENT_RUSTC_VERSION")] + pub const unsafe fn new(data: *const (), vtable: &'static RawWakerVTable) -> Self { + Waker { waker: RawWaker { data, vtable } } + } + /// Creates a new `Waker` from [`RawWaker`]. /// /// # Safety @@ -565,12 +580,20 @@ impl Waker { WAKER } - /// Gets a reference to the underlying [`RawWaker`]. + /// Gets the `data` pointer used to create this `Waker`. #[inline] #[must_use] - #[unstable(feature = "waker_getters", issue = "96992")] - pub fn as_raw(&self) -> &RawWaker { - &self.waker + #[stable(feature = "waker_getters", since = "CURRENT_RUSTC_VERSION")] + pub fn data(&self) -> *const () { + self.waker.data + } + + /// Gets the `vtable` pointer used to create this `Waker`. + #[inline] + #[must_use] + #[stable(feature = "waker_getters", since = "CURRENT_RUSTC_VERSION")] + pub fn vtable(&self) -> &'static RawWakerVTable { + self.waker.vtable } } @@ -778,6 +801,30 @@ impl LocalWaker { a_data == b_data && ptr::eq(a_vtable, b_vtable) } + /// Creates a new `LocalWaker` from the provided `data` pointer and `vtable`. + /// + /// The `data` pointer can be used to store arbitrary data as required + /// by the executor. This could be e.g. a type-erased pointer to an `Arc` + /// that is associated with the task. + /// The value of this pointer will get passed to all functions that are part + /// of the `vtable` as the first parameter. + /// + /// The `vtable` customizes the behavior of a `LocalWaker`. For each + /// operation on the `LocalWaker`, the associated function in the `vtable` + /// will be called. + /// + /// # Safety + /// + /// The behavior of the returned `Waker` is undefined if the contract defined + /// in [`RawWakerVTable`]'s documentation is not upheld. + /// + #[inline] + #[must_use] + #[unstable(feature = "local_waker", issue = "118959")] + pub const unsafe fn new(data: *const (), vtable: &'static RawWakerVTable) -> Self { + LocalWaker { waker: RawWaker { data, vtable } } + } + /// Creates a new `LocalWaker` from [`RawWaker`]. /// /// The behavior of the returned `LocalWaker` is undefined if the contract defined @@ -831,12 +878,20 @@ impl LocalWaker { WAKER } - /// Gets a reference to the underlying [`RawWaker`]. + /// Gets the `data` pointer used to create this `LocalWaker`. #[inline] #[must_use] - #[unstable(feature = "waker_getters", issue = "96992")] - pub fn as_raw(&self) -> &RawWaker { - &self.waker + #[unstable(feature = "local_waker", issue = "118959")] + pub fn data(&self) -> *const () { + self.waker.data + } + + /// Gets the `vtable` pointer used to create this `LocalWaker`. + #[inline] + #[must_use] + #[unstable(feature = "local_waker", issue = "118959")] + pub fn vtable(&self) -> &'static RawWakerVTable { + self.waker.vtable } } #[unstable(feature = "local_waker", issue = "118959")] diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index c205f028dd3..96fc621494f 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -112,7 +112,6 @@ #![feature(unsize)] #![feature(unsized_tuple_coercion)] #![feature(unwrap_infallible)] -#![feature(waker_getters)] // tidy-alphabetical-end #![allow(internal_features)] #![deny(fuzzy_provenance_casts)] diff --git a/library/core/tests/waker.rs b/library/core/tests/waker.rs index 361e900e695..8f6bf0565fc 100644 --- a/library/core/tests/waker.rs +++ b/library/core/tests/waker.rs @@ -4,14 +4,13 @@ use std::task::{RawWaker, RawWakerVTable, Waker}; #[test] fn test_waker_getters() { let raw_waker = RawWaker::new(ptr::without_provenance_mut(42usize), &WAKER_VTABLE); - assert_eq!(raw_waker.data() as usize, 42); - assert!(ptr::eq(raw_waker.vtable(), &WAKER_VTABLE)); - let waker = unsafe { Waker::from_raw(raw_waker) }; + assert_eq!(waker.data() as usize, 42); + assert!(ptr::eq(waker.vtable(), &WAKER_VTABLE)); + let waker2 = waker.clone(); - let raw_waker2 = waker2.as_raw(); - assert_eq!(raw_waker2.data() as usize, 43); - assert!(ptr::eq(raw_waker2.vtable(), &WAKER_VTABLE)); + assert_eq!(waker2.data() as usize, 43); + assert!(ptr::eq(waker2.vtable(), &WAKER_VTABLE)); } static WAKER_VTABLE: RawWakerVTable = RawWakerVTable::new( diff --git a/library/panic_unwind/Cargo.toml b/library/panic_unwind/Cargo.toml index f830808d196..6d1f9764efb 100644 --- a/library/panic_unwind/Cargo.toml +++ b/library/panic_unwind/Cargo.toml @@ -20,3 +20,10 @@ cfg-if = { version = "1.0", features = ['rustc-dep-of-std'] } [target.'cfg(not(all(windows, target_env = "msvc")))'.dependencies] libc = { version = "0.2", default-features = false } + +[lints.rust.unexpected_cfgs] +level = "warn" +check-cfg = [ + # #[cfg(bootstrap)] rtems + 'cfg(target_os, values("rtems"))', +] diff --git a/library/panic_unwind/src/lib.rs b/library/panic_unwind/src/lib.rs index 2d174f4b1a4..4552fb68d26 100644 --- a/library/panic_unwind/src/lib.rs +++ b/library/panic_unwind/src/lib.rs @@ -48,7 +48,7 @@ cfg_if::cfg_if! { target_os = "psp", target_os = "xous", target_os = "solid_asp3", - all(target_family = "unix", not(target_os = "espidf")), + all(target_family = "unix", not(any(target_os = "espidf", target_os = "rtems"))), all(target_vendor = "fortanix", target_env = "sgx"), target_family = "wasm", ))] { diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index 82cfd603a21..e20fe9feff1 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -146,4 +146,6 @@ check-cfg = [ # and to the `backtrace` crate which messes-up with Cargo list # of declared features, we therefor expect any feature cfg 'cfg(feature, values(any()))', + # #[cfg(bootstrap)] rtems + 'cfg(target_os, values("rtems"))', ] diff --git a/library/std/build.rs b/library/std/build.rs index 72254cafc85..ba1eece46f3 100644 --- a/library/std/build.rs +++ b/library/std/build.rs @@ -53,6 +53,7 @@ fn main() { || target_os == "uefi" || target_os == "teeos" || target_os == "zkvm" + || target_os == "rtems" // See src/bootstrap/src/core/build_steps/synthetic_targets.rs || env::var("RUSTC_BOOTSTRAP_SYNTHETIC_TARGET").is_ok() diff --git a/library/std/src/os/mod.rs b/library/std/src/os/mod.rs index 020a8b324f4..a2496baa63f 100644 --- a/library/std/src/os/mod.rs +++ b/library/std/src/os/mod.rs @@ -143,6 +143,8 @@ pub mod nto; pub mod openbsd; #[cfg(target_os = "redox")] pub mod redox; +#[cfg(target_os = "rtems")] +pub mod rtems; #[cfg(target_os = "solaris")] pub mod solaris; #[cfg(target_os = "solid_asp3")] diff --git a/library/std/src/os/rtems/fs.rs b/library/std/src/os/rtems/fs.rs new file mode 100644 index 00000000000..bec0d41e42d --- /dev/null +++ b/library/std/src/os/rtems/fs.rs @@ -0,0 +1,374 @@ +#![stable(feature = "metadata_ext", since = "1.1.0")] + +use crate::fs::Metadata; +use crate::sys_common::AsInner; + +/// OS-specific extensions to [`fs::Metadata`]. +/// +/// [`fs::Metadata`]: crate::fs::Metadata +#[stable(feature = "metadata_ext", since = "1.1.0")] +pub trait MetadataExt { + /// Returns the device ID on which this file resides. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::rtems::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_dev()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_dev(&self) -> u64; + + /// Returns the inode number. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::rtems::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_ino()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_ino(&self) -> u64; + + /// Returns the file type and mode. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::rtems::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_mode()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_mode(&self) -> u32; + + /// Returns the number of hard links to file. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::rtems::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_nlink()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_nlink(&self) -> u64; + + /// Returns the user ID of the file owner. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::rtems::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_uid()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_uid(&self) -> u32; + + /// Returns the group ID of the file owner. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::rtems::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_gid()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_gid(&self) -> u32; + + /// Returns the device ID that this file represents. Only relevant for special file. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::rtems::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_rdev()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_rdev(&self) -> u64; + + /// Returns the size of the file (if it is a regular file or a symbolic link) in bytes. + /// + /// The size of a symbolic link is the length of the pathname it contains, + /// without a terminating null byte. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::rtems::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_size()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_size(&self) -> u64; + + /// Returns the last access time of the file, in seconds since Unix Epoch. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::rtems::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_atime()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_atime(&self) -> i64; + + /// Returns the last access time of the file, in nanoseconds since [`st_atime`]. + /// + /// [`st_atime`]: Self::st_atime + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::rtems::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_atime_nsec()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_atime_nsec(&self) -> i64; + + /// Returns the last modification time of the file, in seconds since Unix Epoch. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::rtems::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_mtime()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_mtime(&self) -> i64; + + /// Returns the last modification time of the file, in nanoseconds since [`st_mtime`]. + /// + /// [`st_mtime`]: Self::st_mtime + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::rtems::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_mtime_nsec()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_mtime_nsec(&self) -> i64; + + /// Returns the last status change time of the file, in seconds since Unix Epoch. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::rtems::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_ctime()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_ctime(&self) -> i64; + + /// Returns the last status change time of the file, in nanoseconds since [`st_ctime`]. + /// + /// [`st_ctime`]: Self::st_ctime + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::rtems::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_ctime_nsec()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_ctime_nsec(&self) -> i64; + + /// Returns the "preferred" block size for efficient filesystem I/O. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::rtems::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_blksize()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_blksize(&self) -> u64; + + /// Returns the number of blocks allocated to the file, 512-byte units. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::rtems::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_blocks()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_blocks(&self) -> u64; +} + +#[stable(feature = "metadata_ext", since = "1.1.0")] +impl MetadataExt for Metadata { + fn st_dev(&self) -> u64 { + self.as_inner().as_inner().st_dev as u64 + } + + fn st_ino(&self) -> u64 { + self.as_inner().as_inner().st_ino as u64 + } + + fn st_mode(&self) -> u32 { + self.as_inner().as_inner().st_mode as u32 + } + + fn st_nlink(&self) -> u64 { + self.as_inner().as_inner().st_nlink as u64 + } + + fn st_uid(&self) -> u32 { + self.as_inner().as_inner().st_uid as u32 + } + + fn st_gid(&self) -> u32 { + self.as_inner().as_inner().st_gid as u32 + } + + fn st_rdev(&self) -> u64 { + self.as_inner().as_inner().st_rdev as u64 + } + + fn st_size(&self) -> u64 { + self.as_inner().as_inner().st_size as u64 + } + + fn st_atime(&self) -> i64 { + self.as_inner().as_inner().st_atime as i64 + } + + fn st_atime_nsec(&self) -> i64 { + 0 + } + + fn st_mtime(&self) -> i64 { + self.as_inner().as_inner().st_mtime as i64 + } + + fn st_mtime_nsec(&self) -> i64 { + 0 + } + + fn st_ctime(&self) -> i64 { + self.as_inner().as_inner().st_ctime as i64 + } + + fn st_ctime_nsec(&self) -> i64 { + 0 + } + + fn st_blksize(&self) -> u64 { + self.as_inner().as_inner().st_blksize as u64 + } + + fn st_blocks(&self) -> u64 { + self.as_inner().as_inner().st_blocks as u64 + } +} diff --git a/library/std/src/os/rtems/mod.rs b/library/std/src/os/rtems/mod.rs new file mode 100644 index 00000000000..7275bfd1765 --- /dev/null +++ b/library/std/src/os/rtems/mod.rs @@ -0,0 +1,4 @@ +#![stable(feature = "raw_ext", since = "1.1.0")] +#![forbid(unsafe_op_in_unsafe_fn)] +pub mod fs; +pub(crate) mod raw; diff --git a/library/std/src/os/rtems/raw.rs b/library/std/src/os/rtems/raw.rs new file mode 100644 index 00000000000..113079cf4ab --- /dev/null +++ b/library/std/src/os/rtems/raw.rs @@ -0,0 +1,33 @@ +//! rtems raw type definitions + +#![stable(feature = "raw_ext", since = "1.1.0")] +#![deprecated( + since = "1.8.0", + note = "these type aliases are no longer supported by \ + the standard library, the `libc` crate on \ + crates.io should be used instead for the correct \ + definitions" +)] +#![allow(deprecated)] + +#[stable(feature = "pthread_t", since = "1.8.0")] +pub type pthread_t = libc::pthread_t; + +#[stable(feature = "raw_ext", since = "1.1.0")] +pub type blkcnt_t = libc::blkcnt_t; + +#[stable(feature = "raw_ext", since = "1.1.0")] +pub type blksize_t = libc::blksize_t; +#[stable(feature = "raw_ext", since = "1.1.0")] +pub type dev_t = libc::dev_t; +#[stable(feature = "raw_ext", since = "1.1.0")] +pub type ino_t = libc::ino_t; +#[stable(feature = "raw_ext", since = "1.1.0")] +pub type mode_t = libc::mode_t; +#[stable(feature = "raw_ext", since = "1.1.0")] +pub type nlink_t = libc::nlink_t; +#[stable(feature = "raw_ext", since = "1.1.0")] +pub type off_t = libc::off_t; + +#[stable(feature = "raw_ext", since = "1.1.0")] +pub type time_t = libc::time_t; diff --git a/library/std/src/os/unix/mod.rs b/library/std/src/os/unix/mod.rs index c6581b9c4c8..7d2f0bd4efe 100644 --- a/library/std/src/os/unix/mod.rs +++ b/library/std/src/os/unix/mod.rs @@ -73,6 +73,8 @@ mod platform { pub use crate::os::openbsd::*; #[cfg(target_os = "redox")] pub use crate::os::redox::*; + #[cfg(target_os = "rtems")] + pub use crate::os::rtems::*; #[cfg(target_os = "solaris")] pub use crate::os::solaris::*; #[cfg(target_os = "vita")] diff --git a/library/std/src/sys/pal/unix/args.rs b/library/std/src/sys/pal/unix/args.rs index 9a37e1a0346..a943e3a581a 100644 --- a/library/std/src/sys/pal/unix/args.rs +++ b/library/std/src/sys/pal/unix/args.rs @@ -112,6 +112,7 @@ impl DoubleEndedIterator for Args { target_os = "aix", target_os = "nto", target_os = "hurd", + target_os = "rtems", ))] mod imp { use crate::ffi::c_char; diff --git a/library/std/src/sys/pal/unix/env.rs b/library/std/src/sys/pal/unix/env.rs index fb1f868644d..b2d399b8791 100644 --- a/library/std/src/sys/pal/unix/env.rs +++ b/library/std/src/sys/pal/unix/env.rs @@ -240,6 +240,17 @@ pub mod os { pub const EXE_EXTENSION: &str = ""; } +#[cfg(target_os = "rtems")] +pub mod os { + pub const FAMILY: &str = "unix"; + pub const OS: &str = "rtems"; + pub const DLL_PREFIX: &str = "lib"; + pub const DLL_SUFFIX: &str = ".so"; + pub const DLL_EXTENSION: &str = "so"; + pub const EXE_SUFFIX: &str = ""; + pub const EXE_EXTENSION: &str = ""; +} + #[cfg(target_os = "vxworks")] pub mod os { pub const FAMILY: &str = "unix"; diff --git a/library/std/src/sys/pal/unix/fs.rs b/library/std/src/sys/pal/unix/fs.rs index 7fa147c9754..4ec577a0a01 100644 --- a/library/std/src/sys/pal/unix/fs.rs +++ b/library/std/src/sys/pal/unix/fs.rs @@ -478,6 +478,7 @@ impl FileAttr { target_os = "horizon", target_os = "vita", target_os = "hurd", + target_os = "rtems", )))] pub fn modified(&self) -> io::Result<SystemTime> { #[cfg(target_pointer_width = "32")] @@ -490,7 +491,12 @@ impl FileAttr { SystemTime::new(self.stat.st_mtime as i64, self.stat.st_mtime_nsec as i64) } - #[cfg(any(target_os = "vxworks", target_os = "espidf", target_os = "vita"))] + #[cfg(any( + target_os = "vxworks", + target_os = "espidf", + target_os = "vita", + target_os = "rtems", + ))] pub fn modified(&self) -> io::Result<SystemTime> { SystemTime::new(self.stat.st_mtime as i64, 0) } @@ -506,6 +512,7 @@ impl FileAttr { target_os = "horizon", target_os = "vita", target_os = "hurd", + target_os = "rtems", )))] pub fn accessed(&self) -> io::Result<SystemTime> { #[cfg(target_pointer_width = "32")] @@ -518,7 +525,12 @@ impl FileAttr { SystemTime::new(self.stat.st_atime as i64, self.stat.st_atime_nsec as i64) } - #[cfg(any(target_os = "vxworks", target_os = "espidf", target_os = "vita"))] + #[cfg(any( + target_os = "vxworks", + target_os = "espidf", + target_os = "vita", + target_os = "rtems" + ))] pub fn accessed(&self) -> io::Result<SystemTime> { SystemTime::new(self.stat.st_atime as i64, 0) } @@ -853,6 +865,7 @@ impl Drop for Dir { target_os = "fuchsia", target_os = "horizon", target_os = "vxworks", + target_os = "rtems", )))] { let fd = unsafe { libc::dirfd(self.0) }; @@ -970,6 +983,7 @@ impl DirEntry { target_os = "aix", target_os = "nto", target_os = "hurd", + target_os = "rtems", target_vendor = "apple", ))] pub fn ino(&self) -> u64 { diff --git a/library/std/src/sys/pal/unix/mod.rs b/library/std/src/sys/pal/unix/mod.rs index ba2f58f9c10..e8428eccb16 100644 --- a/library/std/src/sys/pal/unix/mod.rs +++ b/library/std/src/sys/pal/unix/mod.rs @@ -79,6 +79,7 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) { target_os = "l4re", target_os = "horizon", target_os = "vita", + target_os = "rtems", // The poll on Darwin doesn't set POLLNVAL for closed fds. target_vendor = "apple", )))] diff --git a/library/std/src/sys/pal/unix/os.rs b/library/std/src/sys/pal/unix/os.rs index a785b97ac8d..503f8915256 100644 --- a/library/std/src/sys/pal/unix/os.rs +++ b/library/std/src/sys/pal/unix/os.rs @@ -31,7 +31,7 @@ cfg_if::cfg_if! { } extern "C" { - #[cfg(not(any(target_os = "dragonfly", target_os = "vxworks")))] + #[cfg(not(any(target_os = "dragonfly", target_os = "vxworks", target_os = "rtems")))] #[cfg_attr( any( target_os = "linux", @@ -61,13 +61,14 @@ extern "C" { } /// Returns the platform-specific value of errno -#[cfg(not(any(target_os = "dragonfly", target_os = "vxworks")))] +#[cfg(not(any(target_os = "dragonfly", target_os = "vxworks", target_os = "rtems")))] pub fn errno() -> i32 { unsafe { (*errno_location()) as i32 } } /// Sets the platform-specific value of errno -#[cfg(all(not(target_os = "dragonfly"), not(target_os = "vxworks")))] // needed for readdir and syscall! +// needed for readdir and syscall! +#[cfg(all(not(target_os = "dragonfly"), not(target_os = "vxworks"), not(target_os = "rtems")))] #[allow(dead_code)] // but not all target cfgs actually end up using it pub fn set_errno(e: i32) { unsafe { *errno_location() = e as c_int } @@ -78,6 +79,16 @@ pub fn errno() -> i32 { unsafe { libc::errnoGet() } } +#[cfg(target_os = "rtems")] +pub fn errno() -> i32 { + extern "C" { + #[thread_local] + static _tls_errno: c_int; + } + + unsafe { _tls_errno as i32 } +} + #[cfg(target_os = "dragonfly")] pub fn errno() -> i32 { extern "C" { @@ -472,7 +483,7 @@ pub fn current_exe() -> io::Result<PathBuf> { } } -#[cfg(target_os = "redox")] +#[cfg(any(target_os = "redox", target_os = "rtems"))] pub fn current_exe() -> io::Result<PathBuf> { crate::fs::read_to_string("sys:exe").map(PathBuf::from) } diff --git a/library/std/src/sys/pal/unix/process/process_unix.rs b/library/std/src/sys/pal/unix/process/process_unix.rs index 9d091f033e0..4bb22f36709 100644 --- a/library/std/src/sys/pal/unix/process/process_unix.rs +++ b/library/std/src/sys/pal/unix/process/process_unix.rs @@ -1089,13 +1089,13 @@ fn signal_string(signal: i32) -> &'static str { libc::SIGURG => " (SIGURG)", #[cfg(not(target_os = "l4re"))] libc::SIGXCPU => " (SIGXCPU)", - #[cfg(not(target_os = "l4re"))] + #[cfg(not(any(target_os = "l4re", target_os = "rtems")))] libc::SIGXFSZ => " (SIGXFSZ)", - #[cfg(not(target_os = "l4re"))] + #[cfg(not(any(target_os = "l4re", target_os = "rtems")))] libc::SIGVTALRM => " (SIGVTALRM)", #[cfg(not(target_os = "l4re"))] libc::SIGPROF => " (SIGPROF)", - #[cfg(not(target_os = "l4re"))] + #[cfg(not(any(target_os = "l4re", target_os = "rtems")))] libc::SIGWINCH => " (SIGWINCH)", #[cfg(not(any(target_os = "haiku", target_os = "l4re")))] libc::SIGIO => " (SIGIO)", diff --git a/library/std/src/sys/personality/mod.rs b/library/std/src/sys/personality/mod.rs index 1a6ea1dafcb..68085d026c4 100644 --- a/library/std/src/sys/personality/mod.rs +++ b/library/std/src/sys/personality/mod.rs @@ -31,7 +31,7 @@ cfg_if::cfg_if! { target_os = "psp", target_os = "xous", target_os = "solid_asp3", - all(target_family = "unix", not(target_os = "espidf"), not(target_os = "l4re")), + all(target_family = "unix", not(target_os = "espidf"), not(target_os = "l4re"), not(target_os = "rtems")), all(target_vendor = "fortanix", target_env = "sgx"), ))] { mod gcc; diff --git a/library/unwind/Cargo.toml b/library/unwind/Cargo.toml index bbd1db8dfa5..590de31a678 100644 --- a/library/unwind/Cargo.toml +++ b/library/unwind/Cargo.toml @@ -34,3 +34,10 @@ llvm-libunwind = [] # If crt-static is enabled, static link to `libunwind.a` provided by system # If crt-static is disabled, dynamic link to `libunwind.so` provided by system system-llvm-libunwind = [] + +[lints.rust.unexpected_cfgs] +level = "warn" +check-cfg = [ + # #[cfg(bootstrap)] rtems + 'cfg(target_os, values("rtems"))', +] diff --git a/library/unwind/src/lib.rs b/library/unwind/src/lib.rs index 250af912e07..26ed00bfbd5 100644 --- a/library/unwind/src/lib.rs +++ b/library/unwind/src/lib.rs @@ -22,6 +22,7 @@ cfg_if::cfg_if! { target_os = "l4re", target_os = "none", target_os = "espidf", + target_os = "rtems", ))] { // These "unix" family members do not have unwinder. } else if #[cfg(any( diff --git a/src/bootstrap/src/core/build_steps/format.rs b/src/bootstrap/src/core/build_steps/format.rs index 8c52df78ab6..91fbc57429a 100644 --- a/src/bootstrap/src/core/build_steps/format.rs +++ b/src/bootstrap/src/core/build_steps/format.rs @@ -93,7 +93,6 @@ fn get_modified_rs_files(build: &Builder<'_>) -> Result<Option<Vec<String>>, Str if !verify_rustfmt_version(build) { return Ok(None); } - get_git_modified_files(&build.config.git_config(), Some(&build.config.src), &["rs"]) } diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 84a6b26a491..a8e12540473 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -1810,6 +1810,9 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the if builder.config.rust_optimize_tests { cmd.arg("--optimize-tests"); } + if builder.config.rust_randomize_layout { + cmd.arg("--rust-randomized-layout"); + } if builder.config.cmd.only_modified() { cmd.arg("--only-modified"); } diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs index d7398b76cc9..304fe8da2bf 100644 --- a/src/bootstrap/src/core/builder.rs +++ b/src/bootstrap/src/core/builder.rs @@ -1618,6 +1618,15 @@ impl<'a> Builder<'a> { rustflags.arg("-Csymbol-mangling-version=legacy"); } + // FIXME: the following components don't build with `-Zrandomize-layout` yet: + // - wasm-component-ld, due to the `wast`crate + // - rust-analyzer, due to the rowan crate + // so we exclude entire categories of steps here due to lack of fine-grained control over + // rustflags. + if self.config.rust_randomize_layout && mode != Mode::ToolStd && mode != Mode::ToolRustc { + rustflags.arg("-Zrandomize-layout"); + } + // Enable compile-time checking of `cfg` names, values and Cargo `features`. // // Note: `std`, `alloc` and `core` imports some dependencies by #[path] (like @@ -2193,6 +2202,9 @@ impl<'a> Builder<'a> { rustflags.arg("-Zvalidate-mir"); rustflags.arg(&format!("-Zmir-opt-level={mir_opt_level}")); } + if self.config.rust_randomize_layout { + rustflags.arg("--cfg=randomized_layouts"); + } // Always enable inlining MIR when building the standard library. // Without this flag, MIR inlining is disabled when incremental compilation is enabled. // That causes some mir-opt tests which inline functions from the standard library to diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index fba80b92f45..f7cc9ee7219 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -268,7 +268,6 @@ pub struct Config { pub rust_debuginfo_level_std: DebuginfoLevel, pub rust_debuginfo_level_tools: DebuginfoLevel, pub rust_debuginfo_level_tests: DebuginfoLevel, - pub rust_split_debuginfo_for_build_triple: Option<SplitDebuginfo>, // FIXME: Deprecated field. Remove in Q3'24. pub rust_rpath: bool, pub rust_strip: bool, pub rust_frame_pointers: bool, @@ -280,6 +279,7 @@ pub struct Config { pub rust_codegen_backends: Vec<String>, pub rust_verify_llvm_ir: bool, pub rust_thin_lto_import_instr_limit: Option<u32>, + pub rust_randomize_layout: bool, pub rust_remap_debuginfo: bool, pub rust_new_symbol_mangling: Option<bool>, pub rust_profile_use: Option<String>, @@ -1090,6 +1090,7 @@ define_config! { codegen_units: Option<u32> = "codegen-units", codegen_units_std: Option<u32> = "codegen-units-std", debug_assertions: Option<bool> = "debug-assertions", + randomize_layout: Option<bool> = "randomize-layout", debug_assertions_std: Option<bool> = "debug-assertions-std", overflow_checks: Option<bool> = "overflow-checks", overflow_checks_std: Option<bool> = "overflow-checks-std", @@ -1099,7 +1100,6 @@ define_config! { debuginfo_level_std: Option<DebuginfoLevel> = "debuginfo-level-std", debuginfo_level_tools: Option<DebuginfoLevel> = "debuginfo-level-tools", debuginfo_level_tests: Option<DebuginfoLevel> = "debuginfo-level-tests", - split_debuginfo: Option<String> = "split-debuginfo", backtrace: Option<bool> = "backtrace", incremental: Option<bool> = "incremental", parallel_compiler: Option<bool> = "parallel-compiler", @@ -1181,6 +1181,7 @@ impl Config { backtrace: true, rust_optimize: RustOptimize::Bool(true), rust_optimize_tests: true, + rust_randomize_layout: false, submodules: None, docs: true, docs_minification: true, @@ -1636,10 +1637,10 @@ impl Config { debuginfo_level_std: debuginfo_level_std_toml, debuginfo_level_tools: debuginfo_level_tools_toml, debuginfo_level_tests: debuginfo_level_tests_toml, - split_debuginfo, backtrace, incremental, parallel_compiler, + randomize_layout, default_linker, channel, description, @@ -1695,18 +1696,6 @@ impl Config { debuginfo_level_tests = debuginfo_level_tests_toml; lld_enabled = lld_enabled_toml; - config.rust_split_debuginfo_for_build_triple = split_debuginfo - .as_deref() - .map(SplitDebuginfo::from_str) - .map(|v| v.expect("invalid value for rust.split-debuginfo")); - - if config.rust_split_debuginfo_for_build_triple.is_some() { - println!( - "WARNING: specifying `rust.split-debuginfo` is deprecated, use `target.{}.split-debuginfo` instead", - config.build - ); - } - optimize = optimize_toml; omit_git_hash = omit_git_hash_toml; config.rust_new_symbol_mangling = new_symbol_mangling; @@ -1729,6 +1718,7 @@ impl Config { set(&mut config.lld_mode, lld_mode); set(&mut config.llvm_bitcode_linker_enabled, llvm_bitcode_linker); + config.rust_randomize_layout = randomize_layout.unwrap_or_default(); config.llvm_tools_enabled = llvm_tools.unwrap_or(true); config.rustc_parallel = parallel_compiler.unwrap_or(config.channel == "dev" || config.channel == "nightly"); @@ -2504,9 +2494,6 @@ impl Config { self.target_config .get(&target) .and_then(|t| t.split_debuginfo) - .or_else(|| { - if self.build == target { self.rust_split_debuginfo_for_build_triple } else { None } - }) .unwrap_or_else(|| SplitDebuginfo::default_for_platform(target)) } @@ -2900,6 +2887,7 @@ fn check_incompatible_options_for_ci_rustc( let Rust { // Following options are the CI rustc incompatible ones. optimize, + randomize_layout, debug_logging, debuginfo_level_rustc, llvm_tools, @@ -2927,7 +2915,6 @@ fn check_incompatible_options_for_ci_rustc( debuginfo_level_std: _, debuginfo_level_tools: _, debuginfo_level_tests: _, - split_debuginfo: _, backtrace: _, parallel_compiler: _, musl_root: _, @@ -2964,6 +2951,7 @@ fn check_incompatible_options_for_ci_rustc( // otherwise, we just print a warning with `warn` macro. err!(current_rust_config.optimize, optimize); + err!(current_rust_config.randomize_layout, randomize_layout); err!(current_rust_config.debug_logging, debug_logging); err!(current_rust_config.debuginfo_level_rustc, debuginfo_level_rustc); err!(current_rust_config.rpath, rpath); diff --git a/src/bootstrap/src/core/sanity.rs b/src/bootstrap/src/core/sanity.rs index 60ec57d0d44..dbc712adadf 100644 --- a/src/bootstrap/src/core/sanity.rs +++ b/src/bootstrap/src/core/sanity.rs @@ -13,6 +13,8 @@ use std::ffi::{OsStr, OsString}; use std::path::PathBuf; use std::{env, fs}; +use build_helper::git::warn_old_master_branch; + #[cfg(not(feature = "bootstrap-self-test"))] use crate::builder::Builder; use crate::builder::Kind; @@ -34,6 +36,7 @@ pub struct Finder { // Targets can be removed from this list once they are present in the stage0 compiler (usually by updating the beta compiler of the bootstrap). const STAGE0_MISSING_TARGETS: &[&str] = &[ // just a dummy comment so the list doesn't get onelined + "armv7-rtems-eabihf", ]; /// Minimum version threshold for libstdc++ required when using prebuilt LLVM @@ -374,4 +377,14 @@ $ pacman -R cmake && pacman -S mingw-w64-x86_64-cmake if let Some(ref s) = build.config.ccache { cmd_finder.must_have(s); } + + // this warning is useless in CI, + // and CI probably won't have the right branches anyway. + if !build_helper::ci::CiEnv::is_ci() { + if let Err(e) = warn_old_master_branch(&build.config.git_config(), &build.config.src) + .map_err(|e| e.to_string()) + { + eprintln!("unable to check if upstream branch is old: {e}"); + } + } } diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index 82b640f5423..5751c398f30 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -678,6 +678,9 @@ impl Build { if self.config.rustc_parallel { features.push("rustc_use_parallel_compiler"); } + if self.config.rust_randomize_layout { + features.push("rustc_randomized_layouts"); + } // If debug logging is on, then we want the default for tracing: // https://github.com/tokio-rs/tracing/blob/3dd5c03d907afdf2c39444a29931833335171554/tracing/src/level_filters.rs#L26 diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs index 3ab14aade9f..3fec2d953d9 100644 --- a/src/bootstrap/src/utils/change_tracker.rs +++ b/src/bootstrap/src/utils/change_tracker.rs @@ -240,4 +240,9 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[ severity: ChangeSeverity::Info, summary: "New option `build.cargo-clippy` added for supporting the use of custom/external clippy.", }, + ChangeInfo { + change_id: 129925, + severity: ChangeSeverity::Warning, + summary: "Removed `rust.split-debuginfo` as it was deprecated long time ago.", + }, ]; diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-17/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-17/Dockerfile index 275acb47c33..3acc2ceb135 100644 --- a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-17/Dockerfile +++ b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-17/Dockerfile @@ -50,6 +50,7 @@ ENV RUST_CONFIGURE_ARGS \ --build=x86_64-unknown-linux-gnu \ --llvm-root=/usr/lib/llvm-17 \ --enable-llvm-link-shared \ + --set rust.randomize-layout=true \ --set rust.thin-lto-import-instr-limit=10 COPY host-x86_64/dist-x86_64-linux/shared.sh /scripts/ diff --git a/src/ci/docker/scripts/rfl-build.sh b/src/ci/docker/scripts/rfl-build.sh index 389abb2fdd3..8011e07e92e 100755 --- a/src/ci/docker/scripts/rfl-build.sh +++ b/src/ci/docker/scripts/rfl-build.sh @@ -4,8 +4,8 @@ set -euo pipefail LINUX_VERSION=4c7864e81d8bbd51036dacf92fb0a400e13aaeee -# Build rustc, rustdoc and cargo -../x.py build --stage 1 library rustdoc +# Build rustc, rustdoc, cargo, clippy-driver and rustfmt +../x.py build --stage 2 library rustdoc clippy rustfmt ../x.py build --stage 0 cargo # Install rustup so that we can use the built toolchain easily, and also @@ -16,7 +16,7 @@ sh rustup.sh -y --default-toolchain none source /cargo/env BUILD_DIR=$(realpath ./build) -rustup toolchain link local "${BUILD_DIR}"/x86_64-unknown-linux-gnu/stage1 +rustup toolchain link local "${BUILD_DIR}"/x86_64-unknown-linux-gnu/stage2 rustup default local mkdir -p rfl @@ -62,11 +62,47 @@ make -C linux LLVM=1 -j$(($(nproc) + 1)) \ defconfig \ rfl-for-rust-ci.config -make -C linux LLVM=1 -j$(($(nproc) + 1)) \ - samples/rust/rust_minimal.o \ - samples/rust/rust_print.o \ - drivers/net/phy/ax88796b_rust.o \ +BUILD_TARGETS=" + samples/rust/rust_minimal.o + samples/rust/rust_print.o + drivers/net/phy/ax88796b_rust.o rust/doctests_kernel_generated.o +" + +# Build a few Rust targets +# +# This does not include building the C side of the kernel nor linking, +# which can find other issues, but it is much faster. +# +# This includes transforming `rustdoc` tests into KUnit ones thanks to +# `CONFIG_RUST_KERNEL_DOCTESTS=y` above (which, for the moment, uses the +# unstable `--test-builder` and `--no-run`). +make -C linux LLVM=1 -j$(($(nproc) + 1)) \ + $BUILD_TARGETS +# Generate documentation make -C linux LLVM=1 -j$(($(nproc) + 1)) \ rustdoc + +# Build macro expanded source (`-Zunpretty=expanded`) +# +# This target also formats the macro expanded code, thus it is also +# intended to catch ICEs with formatting `-Zunpretty=expanded` output +# like https://github.com/rust-lang/rustfmt/issues/6105. +make -C linux LLVM=1 -j$(($(nproc) + 1)) \ + samples/rust/rust_minimal.rsi + +# Re-build with Clippy enabled +# +# This should not introduce Clippy errors, since `CONFIG_WERROR` is not +# set (thus no `-Dwarnings`) and the kernel uses `-W` for all Clippy +# lints, including `clippy::all`. However, it could catch ICEs. +make -C linux LLVM=1 -j$(($(nproc) + 1)) CLIPPY=1 \ + $BUILD_TARGETS + +# Format the code +# +# This returns successfully even if there were changes, i.e. it is not +# a check. +make -C linux LLVM=1 -j$(($(nproc) + 1)) \ + rustfmt diff --git a/src/doc/not_found.md b/src/doc/not_found.md index f0794fc0be3..9552759d2b8 100644 --- a/src/doc/not_found.md +++ b/src/doc/not_found.md @@ -2,7 +2,7 @@ <!-- Completely hide the TOC and the section numbers --> <style type="text/css"> -#TOC { display: none; } +#rustdoc-toc { display: none; } .header-section-number { display: none; } li {list-style-type: none; } #search-input { diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index b3a74a7716b..3e199539694 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -40,6 +40,7 @@ - [thumbv8m.base-none-eabi](./platform-support/thumbv8m.base-none-eabi.md) - [thumbv8m.main-none-eabi\*](./platform-support/thumbv8m.main-none-eabi.md) - [armv6k-nintendo-3ds](platform-support/armv6k-nintendo-3ds.md) + - [armv7-rtems-eabihf](platform-support/armv7-rtems-eabihf.md) - [armv7-sony-vita-newlibeabihf](platform-support/armv7-sony-vita-newlibeabihf.md) - [armv7-unknown-linux-uclibceabi](platform-support/armv7-unknown-linux-uclibceabi.md) - [armv7-unknown-linux-uclibceabihf](platform-support/armv7-unknown-linux-uclibceabihf.md) diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index a2641b22753..319dc9a7c08 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -280,6 +280,7 @@ target | std | host | notes `armv6-unknown-freebsd` | ✓ | ✓ | Armv6 FreeBSD [`armv6-unknown-netbsd-eabihf`](platform-support/netbsd.md) | ✓ | ✓ | Armv6 NetBSD w/hard-float [`armv6k-nintendo-3ds`](platform-support/armv6k-nintendo-3ds.md) | ? | | Armv6k Nintendo 3DS, Horizon (Requires devkitARM toolchain) +[`armv7-rtems-eabihf`](platform-support/armv7-rtems-eabihf.md) | ? | | RTEMS OS for ARM BSPs [`armv7-sony-vita-newlibeabihf`](platform-support/armv7-sony-vita-newlibeabihf.md) | ✓ | | Armv7-A Cortex-A9 Sony PlayStation Vita (requires VITASDK toolchain) [`armv7-unknown-linux-uclibceabi`](platform-support/armv7-unknown-linux-uclibceabi.md) | ✓ | ✓ | Armv7-A Linux with uClibc, softfloat [`armv7-unknown-linux-uclibceabihf`](platform-support/armv7-unknown-linux-uclibceabihf.md) | ✓ | ? | Armv7-A Linux with uClibc, hardfloat diff --git a/src/doc/rustc/src/platform-support/armv7-rtems-eabihf.md b/src/doc/rustc/src/platform-support/armv7-rtems-eabihf.md new file mode 100644 index 00000000000..2791c21ee45 --- /dev/null +++ b/src/doc/rustc/src/platform-support/armv7-rtems-eabihf.md @@ -0,0 +1,52 @@ +# `armv7-rtems-eabihf` + +**Tier: 3** + +ARM targets for the [RTEMS realtime operating system](https://www.rtems.org) using the RTEMS gcc cross-compiler for linking against the libraries of a specified Board Support Package (BSP). + +## Target maintainers + +- [@thesummer](https://github.com/thesummer) + +## Requirements + +The target does not support host tools. Only cross-compilation is possible. +The cross-compiler toolchain can be obtained by following the installation instructions +of the [RTEMS Documentation](https://docs.rtems.org/branches/master/user/index.html). Additionally to the cross-compiler also a compiled BSP +for a board fitting the architecture needs to be available on the host. +Currently tested has been the BSP `xilinx_zynq_a9_qemu` of RTEMS 6. + +`std` support is available, but not yet fully tested. Do NOT use in flight software! + +The target follows the EABI calling convention for `extern "C"`. + +The resulting binaries are in ELF format. + +## Building the target + +The target can be built by the standard compiler of Rust. + +## Building Rust programs + +Rust does not yet ship pre-compiled artifacts for this target. To compile for +this target, you will either need to build Rust with the target enabled (see +"Building the target" above), or build your own copy of `core` by using +`build-std` or similar. + +In order to build an RTEMS executable it is also necessary to have a basic RTEMS configuration (in C) compiled to link against as this configures the operating system. +An example can be found at this [`rtems-sys`](https://github.com/thesummer/rtems-sys) crate which could be added as an dependency to your application. + +## Testing + +The resulting binaries run fine on an emulated target (possibly also on a real Zedboard or similar). +For example, on qemu the following command can execute the binary: +```sh +qemu-system-arm -no-reboot -serial null -serial mon:stdio -net none -nographic -M xilinx-zynq-a9 -m 512M -kernel <binary file> +``` + +While basic execution of the unit test harness seems to work. However, running the Rust testsuite on the (emulated) hardware has not yet been tested. + +## Cross-compilation toolchains and C code + +Compatible C-code can be built with the RTEMS cross-compiler toolchain `arm-rtems6-gcc`. +For more information how to build the toolchain, RTEMS itself and RTEMS applications please have a look at the [RTEMS Documentation](https://docs.rtems.org/branches/master/user/index.html). diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 58fcfc4ed8d..5666b229078 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -512,9 +512,6 @@ impl Item { pub(crate) fn is_mod(&self) -> bool { self.type_() == ItemType::Module } - pub(crate) fn is_trait(&self) -> bool { - self.type_() == ItemType::Trait - } pub(crate) fn is_struct(&self) -> bool { self.type_() == ItemType::Struct } @@ -542,9 +539,6 @@ impl Item { pub(crate) fn is_ty_method(&self) -> bool { self.type_() == ItemType::TyMethod } - pub(crate) fn is_type_alias(&self) -> bool { - self.type_() == ItemType::TypeAlias - } pub(crate) fn is_primitive(&self) -> bool { self.type_() == ItemType::Primitive } diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index e37c24c1438..6f4665db6f1 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -51,12 +51,12 @@ use tracing::{debug, trace}; use crate::clean::RenderedLink; use crate::doctest; use crate::doctest::GlobalTestOptions; -use crate::html::escape::Escape; +use crate::html::escape::{Escape, EscapeBodyText}; use crate::html::format::Buffer; use crate::html::highlight; use crate::html::length_limit::HtmlWithLimit; use crate::html::render::small_url_encode; -use crate::html::toc::TocBuilder; +use crate::html::toc::{Toc, TocBuilder}; #[cfg(test)] mod tests; @@ -102,6 +102,7 @@ pub struct Markdown<'a> { /// A struct like `Markdown` that renders the markdown with a table of contents. pub(crate) struct MarkdownWithToc<'a> { pub(crate) content: &'a str, + pub(crate) links: &'a [RenderedLink], pub(crate) ids: &'a mut IdMap, pub(crate) error_codes: ErrorCodes, pub(crate) edition: Edition, @@ -533,9 +534,11 @@ impl<'a, 'b, 'ids, I: Iterator<Item = SpannedEvent<'a>>> Iterator let id = self.id_map.derive(id); if let Some(ref mut builder) = self.toc { + let mut text_header = String::new(); + plain_text_from_events(self.buf.iter().map(|(ev, _)| ev.clone()), &mut text_header); let mut html_header = String::new(); - html::push_html(&mut html_header, self.buf.iter().map(|(ev, _)| ev.clone())); - let sec = builder.push(level as u32, html_header, id.clone()); + html_text_from_events(self.buf.iter().map(|(ev, _)| ev.clone()), &mut html_header); + let sec = builder.push(level as u32, text_header, html_header, id.clone()); self.buf.push_front((Event::Html(format!("{sec} ").into()), 0..0)); } @@ -1412,10 +1415,23 @@ impl Markdown<'_> { } impl MarkdownWithToc<'_> { - pub(crate) fn into_string(self) -> String { - let MarkdownWithToc { content: md, ids, error_codes: codes, edition, playground } = self; + pub(crate) fn into_parts(self) -> (Toc, String) { + let MarkdownWithToc { content: md, links, ids, error_codes: codes, edition, playground } = + self; - let p = Parser::new_ext(md, main_body_opts()).into_offset_iter(); + // This is actually common enough to special-case + if md.is_empty() { + return (Toc { entries: Vec::new() }, String::new()); + } + let mut replacer = |broken_link: BrokenLink<'_>| { + links + .iter() + .find(|link| &*link.original_text == &*broken_link.reference) + .map(|link| (link.href.as_str().into(), link.tooltip.as_str().into())) + }; + + let p = Parser::new_with_broken_link_callback(md, main_body_opts(), Some(&mut replacer)); + let p = p.into_offset_iter(); let mut s = String::with_capacity(md.len() * 3 / 2); @@ -1429,7 +1445,11 @@ impl MarkdownWithToc<'_> { html::push_html(&mut s, p); } - format!("<nav id=\"TOC\">{toc}</nav>{s}", toc = toc.into_toc().print()) + (toc.into_toc(), s) + } + pub(crate) fn into_string(self) -> String { + let (toc, s) = self.into_parts(); + format!("<nav id=\"rustdoc\">{toc}</nav>{s}", toc = toc.print()) } } @@ -1608,7 +1628,16 @@ pub(crate) fn plain_text_summary(md: &str, link_names: &[RenderedLink]) -> Strin let p = Parser::new_with_broken_link_callback(md, summary_opts(), Some(&mut replacer)); - for event in p { + plain_text_from_events(p, &mut s); + + s +} + +pub(crate) fn plain_text_from_events<'a>( + events: impl Iterator<Item = pulldown_cmark::Event<'a>>, + s: &mut String, +) { + for event in events { match &event { Event::Text(text) => s.push_str(text), Event::Code(code) => { @@ -1623,8 +1652,29 @@ pub(crate) fn plain_text_summary(md: &str, link_names: &[RenderedLink]) -> Strin _ => (), } } +} - s +pub(crate) fn html_text_from_events<'a>( + events: impl Iterator<Item = pulldown_cmark::Event<'a>>, + s: &mut String, +) { + for event in events { + match &event { + Event::Text(text) => { + write!(s, "{}", EscapeBodyText(text)).expect("string alloc infallible") + } + Event::Code(code) => { + s.push_str("<code>"); + write!(s, "{}", EscapeBodyText(code)).expect("string alloc infallible"); + s.push_str("</code>"); + } + Event::HardBreak | Event::SoftBreak => s.push(' '), + Event::Start(Tag::CodeBlock(..)) => break, + Event::End(TagEnd::Paragraph) => break, + Event::End(TagEnd::Heading(..)) => break, + _ => (), + } + } } #[derive(Debug)] @@ -1975,7 +2025,8 @@ fn init_id_map() -> FxHashMap<Cow<'static, str>, usize> { map.insert("default-settings".into(), 1); map.insert("sidebar-vars".into(), 1); map.insert("copy-path".into(), 1); - map.insert("TOC".into(), 1); + map.insert("rustdoc-toc".into(), 1); + map.insert("rustdoc-modnav".into(), 1); // This is the list of IDs used by rustdoc sections (but still generated by // rustdoc). map.insert("fields".into(), 1); diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs index 19386fe5e69..9fe43e428f2 100644 --- a/src/librustdoc/html/render/context.rs +++ b/src/librustdoc/html/render/context.rs @@ -15,7 +15,7 @@ use rustc_span::{sym, FileName, Symbol}; use tracing::info; use super::print_item::{full_path, item_path, print_item}; -use super::sidebar::{print_sidebar, sidebar_module_like, Sidebar}; +use super::sidebar::{print_sidebar, sidebar_module_like, ModuleLike, Sidebar}; use super::write_shared::write_shared; use super::{collect_spans_and_sources, scrape_examples_help, AllTypes, LinkFromSrc, StylePath}; use crate::clean::types::ExternalLocation; @@ -617,12 +617,14 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { let all = shared.all.replace(AllTypes::new()); let mut sidebar = Buffer::html(); - let blocks = sidebar_module_like(all.item_sections()); + // all.html is not customizable, so a blank id map is fine + let blocks = sidebar_module_like(all.item_sections(), &mut IdMap::new(), ModuleLike::Crate); let bar = Sidebar { title_prefix: "", title: "", is_crate: false, is_mod: false, + parent_is_crate: false, blocks: vec![blocks], path: String::new(), }; diff --git a/src/librustdoc/html/render/sidebar.rs b/src/librustdoc/html/render/sidebar.rs index 5b9c93ef74a..c75c28ef0a3 100644 --- a/src/librustdoc/html/render/sidebar.rs +++ b/src/librustdoc/html/render/sidebar.rs @@ -13,7 +13,24 @@ use crate::clean; use crate::formats::item_type::ItemType; use crate::formats::Impl; use crate::html::format::Buffer; -use crate::html::markdown::IdMap; +use crate::html::markdown::{IdMap, MarkdownWithToc}; + +#[derive(Clone, Copy)] +pub(crate) enum ModuleLike { + Module, + Crate, +} + +impl ModuleLike { + pub(crate) fn is_crate(self) -> bool { + matches!(self, ModuleLike::Crate) + } +} +impl<'a> From<&'a clean::Item> for ModuleLike { + fn from(it: &'a clean::Item) -> ModuleLike { + if it.is_crate() { ModuleLike::Crate } else { ModuleLike::Module } + } +} #[derive(Template)] #[template(path = "sidebar.html")] @@ -21,6 +38,7 @@ pub(super) struct Sidebar<'a> { pub(super) title_prefix: &'static str, pub(super) title: &'a str, pub(super) is_crate: bool, + pub(super) parent_is_crate: bool, pub(super) is_mod: bool, pub(super) blocks: Vec<LinkBlock<'a>>, pub(super) path: String, @@ -63,15 +81,19 @@ impl<'a> LinkBlock<'a> { /// A link to an item. Content should not be escaped. #[derive(PartialOrd, Ord, PartialEq, Eq, Hash, Clone)] pub(crate) struct Link<'a> { - /// The content for the anchor tag + /// The content for the anchor tag and title attr name: Cow<'a, str>, + /// The content for the anchor tag (if different from name) + name_html: Option<Cow<'a, str>>, /// The id of an anchor within the page (without a `#` prefix) href: Cow<'a, str>, + /// Nested list of links (used only in top-toc) + children: Vec<Link<'a>>, } impl<'a> Link<'a> { pub fn new(href: impl Into<Cow<'a, str>>, name: impl Into<Cow<'a, str>>) -> Self { - Self { href: href.into(), name: name.into() } + Self { href: href.into(), name: name.into(), children: vec![], name_html: None } } pub fn empty() -> Link<'static> { Link::new("", "") @@ -95,17 +117,21 @@ pub(crate) mod filters { } pub(super) fn print_sidebar(cx: &Context<'_>, it: &clean::Item, buffer: &mut Buffer) { - let blocks: Vec<LinkBlock<'_>> = match *it.kind { - clean::StructItem(ref s) => sidebar_struct(cx, it, s), - clean::TraitItem(ref t) => sidebar_trait(cx, it, t), - clean::PrimitiveItem(_) => sidebar_primitive(cx, it), - clean::UnionItem(ref u) => sidebar_union(cx, it, u), - clean::EnumItem(ref e) => sidebar_enum(cx, it, e), - clean::TypeAliasItem(ref t) => sidebar_type_alias(cx, it, t), - clean::ModuleItem(ref m) => vec![sidebar_module(&m.items)], - clean::ForeignTypeItem => sidebar_foreign_type(cx, it), - _ => vec![], - }; + let mut ids = IdMap::new(); + let mut blocks: Vec<LinkBlock<'_>> = docblock_toc(cx, it, &mut ids).into_iter().collect(); + match *it.kind { + clean::StructItem(ref s) => sidebar_struct(cx, it, s, &mut blocks), + clean::TraitItem(ref t) => sidebar_trait(cx, it, t, &mut blocks), + clean::PrimitiveItem(_) => sidebar_primitive(cx, it, &mut blocks), + clean::UnionItem(ref u) => sidebar_union(cx, it, u, &mut blocks), + clean::EnumItem(ref e) => sidebar_enum(cx, it, e, &mut blocks), + clean::TypeAliasItem(ref t) => sidebar_type_alias(cx, it, t, &mut blocks), + clean::ModuleItem(ref m) => { + blocks.push(sidebar_module(&m.items, &mut ids, ModuleLike::from(it))) + } + clean::ForeignTypeItem => sidebar_foreign_type(cx, it, &mut blocks), + _ => {} + } // The sidebar is designed to display sibling functions, modules and // other miscellaneous information. since there are lots of sibling // items (and that causes quadratic growth in large modules), @@ -113,15 +139,9 @@ pub(super) fn print_sidebar(cx: &Context<'_>, it: &clean::Item, buffer: &mut Buf // still, we don't move everything into JS because we want to preserve // as much HTML as possible in order to allow non-JS-enabled browsers // to navigate the documentation (though slightly inefficiently). - let (title_prefix, title) = if it.is_struct() - || it.is_trait() - || it.is_primitive() - || it.is_union() - || it.is_enum() - // crate title is displayed as part of logo lockup - || (it.is_mod() && !it.is_crate()) - || it.is_type_alias() - { + // + // crate title is displayed as part of logo lockup + let (title_prefix, title) = if !blocks.is_empty() && !it.is_crate() { ( match *it.kind { clean::ModuleItem(..) => "Module ", @@ -146,8 +166,15 @@ pub(super) fn print_sidebar(cx: &Context<'_>, it: &clean::Item, buffer: &mut Buf } else { "".into() }; - let sidebar = - Sidebar { title_prefix, title, is_mod: it.is_mod(), is_crate: it.is_crate(), blocks, path }; + let sidebar = Sidebar { + title_prefix, + title, + is_mod: it.is_mod(), + is_crate: it.is_crate(), + parent_is_crate: sidebar_path.len() == 1, + blocks, + path, + }; sidebar.render_into(buffer).unwrap(); } @@ -163,30 +190,80 @@ fn get_struct_fields_name<'a>(fields: &'a [clean::Item]) -> Vec<Link<'a>> { fields } +fn docblock_toc<'a>( + cx: &'a Context<'_>, + it: &'a clean::Item, + ids: &mut IdMap, +) -> Option<LinkBlock<'a>> { + let (toc, _) = MarkdownWithToc { + content: &it.doc_value(), + links: &it.links(cx), + ids, + error_codes: cx.shared.codes, + edition: cx.shared.edition(), + playground: &cx.shared.playground, + } + .into_parts(); + let links: Vec<Link<'_>> = toc + .entries + .into_iter() + .map(|entry| { + Link { + name_html: if entry.html == entry.name { None } else { Some(entry.html.into()) }, + name: entry.name.into(), + href: entry.id.into(), + children: entry + .children + .entries + .into_iter() + .map(|entry| Link { + name_html: if entry.html == entry.name { + None + } else { + Some(entry.html.into()) + }, + name: entry.name.into(), + href: entry.id.into(), + // Only a single level of nesting is shown here. + // Going the full six could break the layout, + // so we have to cut it off somewhere. + children: vec![], + }) + .collect(), + } + }) + .collect(); + if links.is_empty() { + None + } else { + Some(LinkBlock::new(Link::new("", "Sections"), "top-toc", links)) + } +} + fn sidebar_struct<'a>( cx: &'a Context<'_>, it: &'a clean::Item, s: &'a clean::Struct, -) -> Vec<LinkBlock<'a>> { + items: &mut Vec<LinkBlock<'a>>, +) { let fields = get_struct_fields_name(&s.fields); let field_name = match s.ctor_kind { Some(CtorKind::Fn) => Some("Tuple Fields"), None => Some("Fields"), _ => None, }; - let mut items = vec![]; if let Some(name) = field_name { items.push(LinkBlock::new(Link::new("fields", name), "structfield", fields)); } - sidebar_assoc_items(cx, it, &mut items); - items + sidebar_assoc_items(cx, it, items); } fn sidebar_trait<'a>( cx: &'a Context<'_>, it: &'a clean::Item, t: &'a clean::Trait, -) -> Vec<LinkBlock<'a>> { + blocks: &mut Vec<LinkBlock<'a>>, +) { fn filter_items<'a>( items: &'a [clean::Item], filt: impl Fn(&clean::Item) -> bool, @@ -223,19 +300,20 @@ fn sidebar_trait<'a>( foreign_impls.sort(); } - let mut blocks: Vec<LinkBlock<'_>> = [ - ("required-associated-types", "Required Associated Types", req_assoc), - ("provided-associated-types", "Provided Associated Types", prov_assoc), - ("required-associated-consts", "Required Associated Constants", req_assoc_const), - ("provided-associated-consts", "Provided Associated Constants", prov_assoc_const), - ("required-methods", "Required Methods", req_method), - ("provided-methods", "Provided Methods", prov_method), - ("foreign-impls", "Implementations on Foreign Types", foreign_impls), - ] - .into_iter() - .map(|(id, title, items)| LinkBlock::new(Link::new(id, title), "", items)) - .collect(); - sidebar_assoc_items(cx, it, &mut blocks); + blocks.extend( + [ + ("required-associated-types", "Required Associated Types", req_assoc), + ("provided-associated-types", "Provided Associated Types", prov_assoc), + ("required-associated-consts", "Required Associated Constants", req_assoc_const), + ("provided-associated-consts", "Provided Associated Constants", prov_assoc_const), + ("required-methods", "Required Methods", req_method), + ("provided-methods", "Provided Methods", prov_method), + ("foreign-impls", "Implementations on Foreign Types", foreign_impls), + ] + .into_iter() + .map(|(id, title, items)| LinkBlock::new(Link::new(id, title), "", items)), + ); + sidebar_assoc_items(cx, it, blocks); if !t.is_object_safe(cx.tcx()) { blocks.push(LinkBlock::forced( @@ -251,20 +329,17 @@ fn sidebar_trait<'a>( "impl-auto", )); } - blocks } -fn sidebar_primitive<'a>(cx: &'a Context<'_>, it: &'a clean::Item) -> Vec<LinkBlock<'a>> { +fn sidebar_primitive<'a>(cx: &'a Context<'_>, it: &'a clean::Item, items: &mut Vec<LinkBlock<'a>>) { if it.name.map(|n| n.as_str() != "reference").unwrap_or(false) { - let mut items = vec![]; - sidebar_assoc_items(cx, it, &mut items); - items + sidebar_assoc_items(cx, it, items); } else { let shared = Rc::clone(&cx.shared); let (concrete, synthetic, blanket_impl) = super::get_filtered_impls_for_reference(&shared, it); - sidebar_render_assoc_items(cx, &mut IdMap::new(), concrete, synthetic, blanket_impl).into() + sidebar_render_assoc_items(cx, &mut IdMap::new(), concrete, synthetic, blanket_impl, items); } } @@ -272,8 +347,8 @@ fn sidebar_type_alias<'a>( cx: &'a Context<'_>, it: &'a clean::Item, t: &'a clean::TypeAlias, -) -> Vec<LinkBlock<'a>> { - let mut items = vec![]; + items: &mut Vec<LinkBlock<'a>>, +) { if let Some(inner_type) = &t.inner_type { items.push(LinkBlock::forced(Link::new("aliased-type", "Aliased type"), "type")); match inner_type { @@ -295,19 +370,18 @@ fn sidebar_type_alias<'a>( } } } - sidebar_assoc_items(cx, it, &mut items); - items + sidebar_assoc_items(cx, it, items); } fn sidebar_union<'a>( cx: &'a Context<'_>, it: &'a clean::Item, u: &'a clean::Union, -) -> Vec<LinkBlock<'a>> { + items: &mut Vec<LinkBlock<'a>>, +) { let fields = get_struct_fields_name(&u.fields); - let mut items = vec![LinkBlock::new(Link::new("fields", "Fields"), "structfield", fields)]; - sidebar_assoc_items(cx, it, &mut items); - items + items.push(LinkBlock::new(Link::new("fields", "Fields"), "structfield", fields)); + sidebar_assoc_items(cx, it, items); } /// Adds trait implementations into the blocks of links @@ -346,21 +420,22 @@ fn sidebar_assoc_items<'a>( methods.sort(); } - let mut deref_methods = Vec::new(); - let [concrete, synthetic, blanket] = if v.iter().any(|i| i.inner_impl().trait_.is_some()) { + let mut blocks = vec![ + LinkBlock::new( + Link::new("implementations", "Associated Constants"), + "associatedconstant", + assoc_consts, + ), + LinkBlock::new(Link::new("implementations", "Methods"), "method", methods), + ]; + + if v.iter().any(|i| i.inner_impl().trait_.is_some()) { if let Some(impl_) = v.iter().find(|i| i.trait_did() == cx.tcx().lang_items().deref_trait()) { let mut derefs = DefIdSet::default(); derefs.insert(did); - sidebar_deref_methods( - cx, - &mut deref_methods, - impl_, - v, - &mut derefs, - &mut used_links, - ); + sidebar_deref_methods(cx, &mut blocks, impl_, v, &mut derefs, &mut used_links); } let (synthetic, concrete): (Vec<&Impl>, Vec<&Impl>) = @@ -368,21 +443,15 @@ fn sidebar_assoc_items<'a>( let (blanket_impl, concrete): (Vec<&Impl>, Vec<&Impl>) = concrete.into_iter().partition::<Vec<_>, _>(|i| i.inner_impl().kind.is_blanket()); - sidebar_render_assoc_items(cx, &mut id_map, concrete, synthetic, blanket_impl) - } else { - std::array::from_fn(|_| LinkBlock::new(Link::empty(), "", vec![])) - }; - - let mut blocks = vec![ - LinkBlock::new( - Link::new("implementations", "Associated Constants"), - "associatedconstant", - assoc_consts, - ), - LinkBlock::new(Link::new("implementations", "Methods"), "method", methods), - ]; - blocks.append(&mut deref_methods); - blocks.extend([concrete, synthetic, blanket]); + sidebar_render_assoc_items( + cx, + &mut id_map, + concrete, + synthetic, + blanket_impl, + &mut blocks, + ); + } links.append(&mut blocks); } } @@ -472,7 +541,8 @@ fn sidebar_enum<'a>( cx: &'a Context<'_>, it: &'a clean::Item, e: &'a clean::Enum, -) -> Vec<LinkBlock<'a>> { + items: &mut Vec<LinkBlock<'a>>, +) { let mut variants = e .variants() .filter_map(|v| v.name) @@ -480,24 +550,37 @@ fn sidebar_enum<'a>( .collect::<Vec<_>>(); variants.sort_unstable(); - let mut items = vec![LinkBlock::new(Link::new("variants", "Variants"), "variant", variants)]; - sidebar_assoc_items(cx, it, &mut items); - items + items.push(LinkBlock::new(Link::new("variants", "Variants"), "variant", variants)); + sidebar_assoc_items(cx, it, items); } pub(crate) fn sidebar_module_like( item_sections_in_use: FxHashSet<ItemSection>, + ids: &mut IdMap, + module_like: ModuleLike, ) -> LinkBlock<'static> { - let item_sections = ItemSection::ALL + let item_sections: Vec<Link<'_>> = ItemSection::ALL .iter() .copied() .filter(|sec| item_sections_in_use.contains(sec)) - .map(|sec| Link::new(sec.id(), sec.name())) + .map(|sec| Link::new(ids.derive(sec.id()), sec.name())) .collect(); - LinkBlock::new(Link::empty(), "", item_sections) + let header = if let Some(first_section) = item_sections.get(0) { + Link::new( + first_section.href.to_owned(), + if module_like.is_crate() { "Crate Items" } else { "Module Items" }, + ) + } else { + Link::empty() + }; + LinkBlock::new(header, "", item_sections) } -fn sidebar_module(items: &[clean::Item]) -> LinkBlock<'static> { +fn sidebar_module( + items: &[clean::Item], + ids: &mut IdMap, + module_like: ModuleLike, +) -> LinkBlock<'static> { let item_sections_in_use: FxHashSet<_> = items .iter() .filter(|it| { @@ -518,13 +601,15 @@ fn sidebar_module(items: &[clean::Item]) -> LinkBlock<'static> { .map(|it| item_ty_to_section(it.type_())) .collect(); - sidebar_module_like(item_sections_in_use) + sidebar_module_like(item_sections_in_use, ids, module_like) } -fn sidebar_foreign_type<'a>(cx: &'a Context<'_>, it: &'a clean::Item) -> Vec<LinkBlock<'a>> { - let mut items = vec![]; - sidebar_assoc_items(cx, it, &mut items); - items +fn sidebar_foreign_type<'a>( + cx: &'a Context<'_>, + it: &'a clean::Item, + items: &mut Vec<LinkBlock<'a>>, +) { + sidebar_assoc_items(cx, it, items); } /// Renders the trait implementations for this type @@ -534,7 +619,8 @@ fn sidebar_render_assoc_items( concrete: Vec<&Impl>, synthetic: Vec<&Impl>, blanket_impl: Vec<&Impl>, -) -> [LinkBlock<'static>; 3] { + items: &mut Vec<LinkBlock<'_>>, +) { let format_impls = |impls: Vec<&Impl>, id_map: &mut IdMap| { let mut links = FxHashSet::default(); @@ -559,7 +645,7 @@ fn sidebar_render_assoc_items( let concrete = format_impls(concrete, id_map); let synthetic = format_impls(synthetic, id_map); let blanket = format_impls(blanket_impl, id_map); - [ + items.extend([ LinkBlock::new( Link::new("trait-implementations", "Trait Implementations"), "trait-implementation", @@ -575,7 +661,7 @@ fn sidebar_render_assoc_items( "blanket-implementation", blanket, ), - ] + ]); } fn get_next_url(used_links: &mut FxHashSet<String>, url: String) -> String { diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 1e483062289..271de1b1ccf 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -568,12 +568,16 @@ img { width: 48px; } -ul.block, .block li { +ul.block, .block li, .block ul { padding: 0; margin: 0; list-style: none; } +.block ul a { + padding-left: 1rem; +} + .sidebar-elems a, .sidebar > h2 a { display: block; @@ -585,6 +589,14 @@ ul.block, .block li { background-clip: border-box; } +.hide-toc #rustdoc-toc, .hide-toc .in-crate { + display: none; +} + +.hide-modnav #rustdoc-modnav { + display: none; +} + .sidebar h2 { text-wrap: balance; overflow-wrap: anywhere; diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index c3e219f2c87..0291b6ed6f5 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -499,7 +499,7 @@ function preLoadCss(cssUrl) { if (!window.SIDEBAR_ITEMS) { return; } - const sidebar = document.getElementsByClassName("sidebar-elems")[0]; + const sidebar = document.getElementById("rustdoc-modnav"); /** * Append to the sidebar a "block" of links - a heading along with a list (`<ul>`) of items. @@ -885,7 +885,7 @@ function preLoadCss(cssUrl) { if (!window.ALL_CRATES) { return; } - const sidebarElems = document.getElementsByClassName("sidebar-elems")[0]; + const sidebarElems = document.getElementById("rustdoc-modnav"); if (!sidebarElems) { return; } diff --git a/src/librustdoc/html/static/js/settings.js b/src/librustdoc/html/static/js/settings.js index 2b42fbebb80..c52a19ef987 100644 --- a/src/librustdoc/html/static/js/settings.js +++ b/src/librustdoc/html/static/js/settings.js @@ -36,6 +36,20 @@ removeClass(document.documentElement, "hide-sidebar"); } break; + case "hide-toc": + if (value === true) { + addClass(document.documentElement, "hide-toc"); + } else { + removeClass(document.documentElement, "hide-toc"); + } + break; + case "hide-modnav": + if (value === true) { + addClass(document.documentElement, "hide-modnav"); + } else { + removeClass(document.documentElement, "hide-modnav"); + } + break; } } @@ -102,6 +116,11 @@ let output = ""; for (const setting of settings) { + if (setting === "hr") { + output += "<hr>"; + continue; + } + const js_data_name = setting["js_name"]; const setting_name = setting["name"]; @@ -199,6 +218,16 @@ "default": false, }, { + "name": "Hide table of contents", + "js_name": "hide-toc", + "default": false, + }, + { + "name": "Hide module navigation", + "js_name": "hide-modnav", + "default": false, + }, + { "name": "Disable keyboard shortcuts", "js_name": "disable-shortcuts", "default": false, diff --git a/src/librustdoc/html/static/js/storage.js b/src/librustdoc/html/static/js/storage.js index 4a27ca92fff..d75fb7a7fb5 100644 --- a/src/librustdoc/html/static/js/storage.js +++ b/src/librustdoc/html/static/js/storage.js @@ -196,16 +196,21 @@ updateTheme(); // This needs to be done here because this JS is render-blocking, // so that the sidebar doesn't "jump" after appearing on screen. // The user interaction to change this is set up in main.js. +// +// At this point in page load, `document.body` is not available yet. +// Set a class on the `<html>` element instead. if (getSettingValue("source-sidebar-show") === "true") { - // At this point in page load, `document.body` is not available yet. - // Set a class on the `<html>` element instead. addClass(document.documentElement, "src-sidebar-expanded"); } if (getSettingValue("hide-sidebar") === "true") { - // At this point in page load, `document.body` is not available yet. - // Set a class on the `<html>` element instead. addClass(document.documentElement, "hide-sidebar"); } +if (getSettingValue("hide-toc") === "true") { + addClass(document.documentElement, "hide-toc"); +} +if (getSettingValue("hide-modnav") === "true") { + addClass(document.documentElement, "hide-modnav"); +} function updateSidebarWidth() { const desktopSidebarWidth = getSettingValue("desktop-sidebar-width"); if (desktopSidebarWidth && desktopSidebarWidth !== "null") { diff --git a/src/librustdoc/html/templates/sidebar.html b/src/librustdoc/html/templates/sidebar.html index 0990c2716b8..fccf65cbefc 100644 --- a/src/librustdoc/html/templates/sidebar.html +++ b/src/librustdoc/html/templates/sidebar.html @@ -1,8 +1,3 @@ -{% if !title.is_empty() %} - <h2 class="location"> {# #} - <a href="#">{{title_prefix}}{{title|wrapped|safe}}</a> {# #} - </h2> -{% endif %} <div class="sidebar-elems"> {% if is_crate %} <ul class="block"> {# #} @@ -11,18 +6,46 @@ {% endif %} {% if self.should_render_blocks() %} - <section> + <section id="rustdoc-toc"> + {% if !title.is_empty() %} + <h2 class="location"> {# #} + <a href="#">{{title_prefix}}{{title|wrapped|safe}}</a> {# #} + </h2> + {% endif %} {% for block in blocks %} {% if block.should_render() %} {% if !block.heading.name.is_empty() %} - <h3><a href="#{{block.heading.href|safe}}"> {# #} - {{block.heading.name|wrapped|safe}} {# #} - </a></h3> {# #} + <h3> {# #} + <a href="#{{block.heading.href|safe}}">{{block.heading.name|wrapped|safe}}</a> {# #} + </h3> {% endif %} {% if !block.links.is_empty() %} <ul class="block{% if !block.class.is_empty() +%} {{+block.class}}{% endif %}"> {% for link in block.links %} - <li><a href="#{{link.href|safe}}">{{link.name}}</a></li> + <li> {# #} + <a href="#{{link.href|safe}}" title="{{link.name}}"> + {% match link.name_html %} + {% when Some with (html) %} + {{html|safe}} + {% else %} + {{link.name}} + {% endmatch %} + </a> {# #} + {% if !link.children.is_empty() %} + <ul> + {% for child in link.children %} + <li><a href="#{{child.href|safe}}" title="{{child.name}}"> + {% match child.name_html %} + {% when Some with (html) %} + {{html|safe}} + {% else %} + {{child.name}} + {% endmatch %} + </a></li> + {% endfor %} + </ul> + {% endif %} + </li> {% endfor %} </ul> {% endif %} @@ -30,7 +53,11 @@ {% endfor %} </section> {% endif %} + <div id="rustdoc-modnav"> {% if !path.is_empty() %} - <h2><a href="{% if is_mod %}../{% endif %}index.html">In {{+ path|wrapped|safe}}</a></h2> + <h2{% if parent_is_crate +%} class="in-crate"{% endif %}> {# #} + <a href="{% if is_mod %}../{% endif %}index.html">In {{+ path|wrapped|safe}}</a> {# #} + </h2> {% endif %} + </div> {# #} </div> diff --git a/src/librustdoc/html/toc.rs b/src/librustdoc/html/toc.rs index a12c2a6a16c..7fdce41a634 100644 --- a/src/librustdoc/html/toc.rs +++ b/src/librustdoc/html/toc.rs @@ -1,4 +1,5 @@ //! Table-of-contents creation. +use crate::html::escape::Escape; /// A (recursive) table of contents #[derive(Debug, PartialEq)] @@ -16,7 +17,7 @@ pub(crate) struct Toc { /// ### A /// ## B /// ``` - entries: Vec<TocEntry>, + pub(crate) entries: Vec<TocEntry>, } impl Toc { @@ -27,11 +28,16 @@ impl Toc { #[derive(Debug, PartialEq)] pub(crate) struct TocEntry { - level: u32, - sec_number: String, - name: String, - id: String, - children: Toc, + pub(crate) level: u32, + pub(crate) sec_number: String, + // name is a plain text header that works in a `title` tag + // html includes `<code>` tags + // the tooltip is used so that, when a toc is truncated, + // you can mouse over it to see the whole thing + pub(crate) name: String, + pub(crate) html: String, + pub(crate) id: String, + pub(crate) children: Toc, } /// Progressive construction of a table of contents. @@ -115,7 +121,7 @@ impl TocBuilder { /// Push a level `level` heading into the appropriate place in the /// hierarchy, returning a string containing the section number in /// `<num>.<num>.<num>` format. - pub(crate) fn push(&mut self, level: u32, name: String, id: String) -> &str { + pub(crate) fn push(&mut self, level: u32, name: String, html: String, id: String) -> &str { assert!(level >= 1); // collapse all previous sections into their parents until we @@ -149,6 +155,7 @@ impl TocBuilder { self.chain.push(TocEntry { level, name, + html, sec_number, id, children: Toc { entries: Vec::new() }, @@ -170,10 +177,11 @@ impl Toc { // recursively format this table of contents let _ = write!( v, - "\n<li><a href=\"#{id}\">{num} {name}</a>", + "\n<li><a href=\"#{id}\" title=\"{name}\">{num} {html}</a>", id = entry.id, num = entry.sec_number, - name = entry.name + name = Escape(&entry.name), + html = &entry.html, ); entry.children.print_inner(&mut *v); v.push_str("</li>"); diff --git a/src/librustdoc/html/toc/tests.rs b/src/librustdoc/html/toc/tests.rs index 014f346862b..81aca737baf 100644 --- a/src/librustdoc/html/toc/tests.rs +++ b/src/librustdoc/html/toc/tests.rs @@ -9,7 +9,10 @@ fn builder_smoke() { // there's been no macro mistake. macro_rules! push { ($level: expr, $name: expr) => { - assert_eq!(builder.push($level, $name.to_string(), "".to_string()), $name); + assert_eq!( + builder.push($level, $name.to_string(), $name.to_string(), "".to_string()), + $name + ); }; } push!(2, "0.1"); @@ -48,6 +51,7 @@ fn builder_smoke() { TocEntry { level: $level, name: $name.to_string(), + html: $name.to_string(), sec_number: $name.to_string(), id: "".to_string(), children: toc!($($sub),*) diff --git a/src/librustdoc/markdown.rs b/src/librustdoc/markdown.rs index a98f81d011e..581ebbbe58d 100644 --- a/src/librustdoc/markdown.rs +++ b/src/librustdoc/markdown.rs @@ -72,6 +72,7 @@ pub(crate) fn render<P: AsRef<Path>>( let text = if !options.markdown_no_toc { MarkdownWithToc { content: text, + links: &[], ids: &mut ids, error_codes, edition, diff --git a/src/tools/build_helper/src/git.rs b/src/tools/build_helper/src/git.rs index da84569c778..cc48a8964a3 100644 --- a/src/tools/build_helper/src/git.rs +++ b/src/tools/build_helper/src/git.rs @@ -159,3 +159,37 @@ pub fn get_git_untracked_files( .collect(); Ok(Some(files)) } + +/// Print a warning if the branch returned from `updated_master_branch` is old +/// +/// For certain configurations of git repository, this remote will not be +/// updated when running `git pull`. +/// +/// This can result in formatting thousands of files instead of a dozen, +/// so we should warn the user something is wrong. +pub fn warn_old_master_branch( + config: &GitConfig<'_>, + git_dir: &Path, +) -> Result<(), Box<dyn std::error::Error>> { + use std::time::Duration; + const WARN_AFTER: Duration = Duration::from_secs(60 * 60 * 24 * 10); + let updated_master = updated_master_branch(config, Some(git_dir))?; + let branch_path = git_dir.join(".git/refs/remotes").join(&updated_master); + match std::fs::metadata(branch_path) { + Ok(meta) => { + if meta.modified()?.elapsed()? > WARN_AFTER { + eprintln!("warning: {updated_master} has not been updated in 10 days"); + } else { + return Ok(()); + } + } + Err(err) => { + eprintln!("warning: unable to check if {updated_master} is old due to error: {err}") + } + } + eprintln!( + "warning: {updated_master} is used to determine if files have been modified\n\ + warning: if it is not updated, this may cause files to be needlessly reformatted" + ); + Ok(()) +} diff --git a/src/tools/compiletest/src/command-list.rs b/src/tools/compiletest/src/command-list.rs index a559d6f81a2..865aa76ddb0 100644 --- a/src/tools/compiletest/src/command-list.rs +++ b/src/tools/compiletest/src/command-list.rs @@ -136,6 +136,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "min-llvm-version", "min-system-llvm-version", "needs-asm-support", + "needs-deterministic-layouts", "needs-dlltool", "needs-dynamic-linking", "needs-force-clang-based-tests", diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 5831f7c3cf2..773d795f75a 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -274,6 +274,9 @@ pub struct Config { /// Flags to pass to the compiler when building for the target pub target_rustcflags: Vec<String>, + /// Whether the compiler and stdlib has been built with randomized struct layouts + pub rust_randomized_layout: bool, + /// Whether tests should be optimized by default. Individual test-suites and test files may /// override this setting. pub optimize_tests: bool, diff --git a/src/tools/compiletest/src/header/needs.rs b/src/tools/compiletest/src/header/needs.rs index 72b1b9c6d48..e903f60ceb3 100644 --- a/src/tools/compiletest/src/header/needs.rs +++ b/src/tools/compiletest/src/header/needs.rs @@ -135,6 +135,11 @@ pub(super) fn handle_needs( ignore_reason: "ignored on targets without PIC relocation model", }, Need { + name: "needs-deterministic-layouts", + condition: !config.rust_randomized_layout, + ignore_reason: "ignored when randomizing layouts", + }, + Need { name: "needs-wasmtime", condition: config.runner.as_ref().is_some_and(|r| r.contains("wasmtime")), ignore_reason: "ignored when wasmtime runner is not available", diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs index 7018362af54..5402e69bc66 100644 --- a/src/tools/compiletest/src/lib.rs +++ b/src/tools/compiletest/src/lib.rs @@ -99,6 +99,11 @@ pub fn parse_config(args: Vec<String>) -> Config { ) .optmulti("", "host-rustcflags", "flags to pass to rustc for host", "FLAGS") .optmulti("", "target-rustcflags", "flags to pass to rustc for target", "FLAGS") + .optflag( + "", + "rust-randomized-layout", + "set this when rustc/stdlib were compiled with randomized layouts", + ) .optflag("", "optimize-tests", "run tests with optimizations enabled") .optflag("", "verbose", "run tests verbosely, showing all output") .optflag( @@ -286,6 +291,7 @@ pub fn parse_config(args: Vec<String>) -> Config { host_rustcflags: matches.opt_strs("host-rustcflags"), target_rustcflags: matches.opt_strs("target-rustcflags"), optimize_tests: matches.opt_present("optimize-tests"), + rust_randomized_layout: matches.opt_present("rust-randomized-layout"), target, host: opt_str2(matches.opt_str("host")), cdb, diff --git a/src/tools/miri/tests/pass/dyn-arbitrary-self.rs b/src/tools/miri/tests/pass/dyn-arbitrary-self.rs index 6be13b155f4..dc2b9e4491b 100644 --- a/src/tools/miri/tests/pass/dyn-arbitrary-self.rs +++ b/src/tools/miri/tests/pass/dyn-arbitrary-self.rs @@ -1,6 +1,6 @@ //@revisions: stack tree //@[tree]compile-flags: -Zmiri-tree-borrows -#![feature(arbitrary_self_types, unsize, coerce_unsized, dispatch_from_dyn)] +#![feature(arbitrary_self_types_pointers, unsize, coerce_unsized, dispatch_from_dyn)] #![feature(rustc_attrs)] fn pin_box_dyn() { diff --git a/tests/assembly/targets/targets-elf.rs b/tests/assembly/targets/targets-elf.rs index b0c5eec1fe4..c8610e03939 100644 --- a/tests/assembly/targets/targets-elf.rs +++ b/tests/assembly/targets/targets-elf.rs @@ -129,6 +129,9 @@ //@ revisions: armv7_linux_androideabi //@ [armv7_linux_androideabi] compile-flags: --target armv7-linux-androideabi //@ [armv7_linux_androideabi] needs-llvm-components: arm +//@ revisions: armv7_rtems_eabihf +//@ [armv7_rtems_eabihf] compile-flags: --target armv7-rtems-eabihf +//@ [armv7_rtems_eabihf] needs-llvm-components: arm //@ revisions: armv7_sony_vita_newlibeabihf //@ [armv7_sony_vita_newlibeabihf] compile-flags: --target armv7-sony-vita-newlibeabihf //@ [armv7_sony_vita_newlibeabihf] needs-llvm-components: arm diff --git a/tests/codegen/issues/issue-86106.rs b/tests/codegen/issues/issue-86106.rs index e8164c5c380..8d1ce116d26 100644 --- a/tests/codegen/issues/issue-86106.rs +++ b/tests/codegen/issues/issue-86106.rs @@ -1,5 +1,6 @@ //@ only-64bit llvm appears to use stores instead of memset on 32bit //@ compile-flags: -C opt-level=3 -Z merge-functions=disabled +//@ needs-deterministic-layouts // The below two functions ensure that both `String::new()` and `"".to_string()` // produce the identical code. diff --git a/tests/codegen/mem-replace-big-type.rs b/tests/codegen/mem-replace-big-type.rs index d5eadda4469..e62f1a953df 100644 --- a/tests/codegen/mem-replace-big-type.rs +++ b/tests/codegen/mem-replace-big-type.rs @@ -5,6 +5,7 @@ //@ compile-flags: -C no-prepopulate-passes -Zinline-mir=no //@ ignore-debug: precondition checks in ptr::read make them a bad candidate for MIR inlining +//@ needs-deterministic-layouts #![crate_type = "lib"] diff --git a/tests/codegen/slice-iter-nonnull.rs b/tests/codegen/slice-iter-nonnull.rs index c960688b00c..eda807d3682 100644 --- a/tests/codegen/slice-iter-nonnull.rs +++ b/tests/codegen/slice-iter-nonnull.rs @@ -1,4 +1,5 @@ //@ compile-flags: -O +//@ needs-deterministic-layouts #![crate_type = "lib"] #![feature(exact_size_is_empty)] diff --git a/tests/codegen/vecdeque-drain.rs b/tests/codegen/vecdeque-drain.rs index 31fcf035f11..fca1ed367e6 100644 --- a/tests/codegen/vecdeque-drain.rs +++ b/tests/codegen/vecdeque-drain.rs @@ -1,6 +1,7 @@ // Check that draining at the front or back doesn't copy memory. //@ compile-flags: -O +//@ needs-deterministic-layouts //@ ignore-debug: FIXME: checks for call detect scoped noalias metadata #![crate_type = "lib"] diff --git a/tests/mir-opt/building/receiver_ptr_mutability.rs b/tests/mir-opt/building/receiver_ptr_mutability.rs index 4bb3b4cade5..1ddb8b71a5a 100644 --- a/tests/mir-opt/building/receiver_ptr_mutability.rs +++ b/tests/mir-opt/building/receiver_ptr_mutability.rs @@ -1,7 +1,7 @@ // skip-filecheck // EMIT_MIR receiver_ptr_mutability.main.built.after.mir -#![feature(arbitrary_self_types)] +#![feature(arbitrary_self_types_pointers)] struct Test {} diff --git a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.rs b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.rs index c92424f2983..08347f71b42 100644 --- a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.rs +++ b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.rs @@ -1,3 +1,4 @@ +//@needs-deterministic-layouts // Verify that we do not ICE when printing an invalid constant. // EMIT_MIR_FOR_EACH_BIT_WIDTH // EMIT_MIR_FOR_EACH_PANIC_STRATEGY diff --git a/tests/rustdoc-gui/sidebar-modnav-position.goml b/tests/rustdoc-gui/sidebar-modnav-position.goml new file mode 100644 index 00000000000..eb86d118ab2 --- /dev/null +++ b/tests/rustdoc-gui/sidebar-modnav-position.goml @@ -0,0 +1,44 @@ +// Verifies that, when TOC is hidden, modnav is always in exactly the same spot +// This is driven by a reasonably common use case: +// +// - There are three or more items that might meet my needs. +// - I open the first one, decide it's not what I want, switch to the second one using the sidebar. +// - The second one also doesn't meet my needs, so I switch to the third. +// - The third also doesn't meet my needs, so... +// +// because the sibling module nav is in exactly the same place every time, +// it's very easy to find and switch between pages that way. + +go-to: "file://" + |DOC_PATH| + "/test_docs/enum.WhoLetTheDogOut.html" +show-text: true +set-local-storage: {"rustdoc-hide-toc": "true"} + +define-function: ( + "check-positions", + [url], + block { + go-to: "file://" + |DOC_PATH| + |url| + // Checking results colors. + assert-position: ("#rustdoc-modnav > h2", {"x": |h2_x|, "y": |h2_y|}) + assert-position: ( + "#rustdoc-modnav > ul:first-of-type > li:first-of-type", + {"x": |x|, "y": |y|} + ) + }, +) + +// First, at test_docs root +go-to: "file://" + |DOC_PATH| + "/test_docs/enum.WhoLetTheDogOut.html" +store-position: ("#rustdoc-modnav > h2", {"x": h2_x, "y": h2_y}) +store-position: ("#rustdoc-modnav > ul:first-of-type > li:first-of-type", {"x": x, "y": y}) +call-function: ("check-positions", {"url": "/test_docs/enum.WhoLetTheDogOut.html"}) +call-function: ("check-positions", {"url": "/test_docs/struct.StructWithPublicUndocumentedFields.html"}) +call-function: ("check-positions", {"url": "/test_docs/codeblock_sub/index.html"}) + +// Now in a submodule +go-to: "file://" + |DOC_PATH| + "/test_docs/fields/struct.Struct.html" +store-position: ("#rustdoc-modnav > h2", {"x": h2_x, "y": h2_y}) +store-position: ("#rustdoc-modnav > ul:first-of-type > li:first-of-type", {"x": x, "y": y}) +call-function: ("check-positions", {"url": "/test_docs/fields/struct.Struct.html"}) +call-function: ("check-positions", {"url": "/test_docs/fields/union.Union.html"}) +call-function: ("check-positions", {"url": "/test_docs/fields/enum.Enum.html"}) diff --git a/tests/rustdoc-gui/sidebar.goml b/tests/rustdoc-gui/sidebar.goml index e499c159c6c..7794cdbe9e2 100644 --- a/tests/rustdoc-gui/sidebar.goml +++ b/tests/rustdoc-gui/sidebar.goml @@ -118,7 +118,7 @@ assert-false: ".sidebar-elems > .crate" go-to: "./module/index.html" assert-property: (".sidebar", {"clientWidth": "200"}) assert-text: (".sidebar > .sidebar-crate > h2 > a", "lib2") -assert-text: (".sidebar > .location", "Module module") +assert-text: (".sidebar .location", "Module module") assert-count: (".sidebar .location", 1) assert-text: (".sidebar-elems ul.block > li.current > a", "module") // Module page requires three headings: @@ -126,8 +126,8 @@ assert-text: (".sidebar-elems ul.block > li.current > a", "module") // - Module name, followed by TOC for module headings // - "In crate [name]" parent pointer, followed by sibling navigation assert-count: (".sidebar h2", 3) -assert-text: (".sidebar > .sidebar-elems > h2", "In crate lib2") -assert-property: (".sidebar > .sidebar-elems > h2 > a", { +assert-text: (".sidebar > .sidebar-elems > #rustdoc-modnav > h2", "In crate lib2") +assert-property: (".sidebar > .sidebar-elems > #rustdoc-modnav > h2 > a", { "href": "/lib2/index.html", }, ENDS_WITH) // We check that we don't have the crate list. @@ -136,9 +136,9 @@ assert-false: ".sidebar-elems > .crate" go-to: "./sub_module/sub_sub_module/index.html" assert-property: (".sidebar", {"clientWidth": "200"}) assert-text: (".sidebar > .sidebar-crate > h2 > a", "lib2") -assert-text: (".sidebar > .location", "Module sub_sub_module") -assert-text: (".sidebar > .sidebar-elems > h2", "In lib2::module::sub_module") -assert-property: (".sidebar > .sidebar-elems > h2 > a", { +assert-text: (".sidebar .location", "Module sub_sub_module") +assert-text: (".sidebar > .sidebar-elems > #rustdoc-modnav > h2", "In lib2::module::sub_module") +assert-property: (".sidebar > .sidebar-elems > #rustdoc-modnav > h2 > a", { "href": "/module/sub_module/index.html", }, ENDS_WITH) assert-text: (".sidebar-elems ul.block > li.current > a", "sub_sub_module") @@ -198,3 +198,36 @@ assert-position-false: (".sidebar-crate > h2 > a", {"x": -3}) // when line-wrapped, see that it becomes flush-left again drag-and-drop: ((205, 100), (108, 100)) assert-position: (".sidebar-crate > h2 > a", {"x": -3}) + +// Configuration option to show TOC in sidebar. +set-local-storage: {"rustdoc-hide-toc": "true"} +go-to: "file://" + |DOC_PATH| + "/test_docs/enum.WhoLetTheDogOut.html" +assert-css: ("#rustdoc-toc", {"display": "none"}) +assert-css: (".sidebar .in-crate", {"display": "none"}) +set-local-storage: {"rustdoc-hide-toc": "false"} +go-to: "file://" + |DOC_PATH| + "/test_docs/enum.WhoLetTheDogOut.html" +assert-css: ("#rustdoc-toc", {"display": "block"}) +assert-css: (".sidebar .in-crate", {"display": "block"}) + +set-local-storage: {"rustdoc-hide-modnav": "true"} +go-to: "file://" + |DOC_PATH| + "/test_docs/enum.WhoLetTheDogOut.html" +assert-css: ("#rustdoc-modnav", {"display": "none"}) +set-local-storage: {"rustdoc-hide-modnav": "false"} +go-to: "file://" + |DOC_PATH| + "/test_docs/enum.WhoLetTheDogOut.html" +assert-css: ("#rustdoc-modnav", {"display": "block"}) + +set-local-storage: {"rustdoc-hide-toc": "true"} +go-to: "file://" + |DOC_PATH| + "/test_docs/index.html" +assert-css: ("#rustdoc-toc", {"display": "none"}) +assert-false: ".sidebar .in-crate" +set-local-storage: {"rustdoc-hide-toc": "false"} +go-to: "file://" + |DOC_PATH| + "/test_docs/index.html" +assert-css: ("#rustdoc-toc", {"display": "block"}) +assert-false: ".sidebar .in-crate" + +set-local-storage: {"rustdoc-hide-modnav": "true"} +go-to: "file://" + |DOC_PATH| + "/test_docs/index.html" +assert-css: ("#rustdoc-modnav", {"display": "none"}) +set-local-storage: {"rustdoc-hide-modnav": "false"} +go-to: "file://" + |DOC_PATH| + "/test_docs/index.html" +assert-css: ("#rustdoc-modnav", {"display": "block"}) diff --git a/tests/rustdoc/sidebar/module.rs b/tests/rustdoc/sidebar/module.rs new file mode 100644 index 00000000000..b5bcb9f232c --- /dev/null +++ b/tests/rustdoc/sidebar/module.rs @@ -0,0 +1,16 @@ +#![crate_name = "foo"] + +//@ has 'foo/index.html' +//@ has - '//section[@id="rustdoc-toc"]/h3' 'Crate Items' + +//@ has 'foo/bar/index.html' +//@ has - '//section[@id="rustdoc-toc"]/h3' 'Module Items' +pub mod bar { + //@ has 'foo/bar/struct.Baz.html' + //@ !has - '//section[@id="rustdoc-toc"]/h3' 'Module Items' + pub struct Baz; +} + +//@ has 'foo/baz/index.html' +//@ !has - '//section[@id="rustdoc-toc"]/h3' 'Module Items' +pub mod baz {} diff --git a/tests/rustdoc/sidebar-all-page.rs b/tests/rustdoc/sidebar/sidebar-all-page.rs index 1f97a414048..1f97a414048 100644 --- a/tests/rustdoc/sidebar-all-page.rs +++ b/tests/rustdoc/sidebar/sidebar-all-page.rs diff --git a/tests/rustdoc/sidebar-items.rs b/tests/rustdoc/sidebar/sidebar-items.rs index f3812143a7d..f3812143a7d 100644 --- a/tests/rustdoc/sidebar-items.rs +++ b/tests/rustdoc/sidebar/sidebar-items.rs diff --git a/tests/rustdoc/sidebar-link-generation.rs b/tests/rustdoc/sidebar/sidebar-link-generation.rs index ee868ec75d3..ee868ec75d3 100644 --- a/tests/rustdoc/sidebar-link-generation.rs +++ b/tests/rustdoc/sidebar/sidebar-link-generation.rs diff --git a/tests/rustdoc/sidebar-links-to-foreign-impl.rs b/tests/rustdoc/sidebar/sidebar-links-to-foreign-impl.rs index 7c039eeb39f..7c039eeb39f 100644 --- a/tests/rustdoc/sidebar-links-to-foreign-impl.rs +++ b/tests/rustdoc/sidebar/sidebar-links-to-foreign-impl.rs diff --git a/tests/rustdoc/sidebar/top-toc-html.rs b/tests/rustdoc/sidebar/top-toc-html.rs new file mode 100644 index 00000000000..0f603960434 --- /dev/null +++ b/tests/rustdoc/sidebar/top-toc-html.rs @@ -0,0 +1,23 @@ +// ignore-tidy-linelength + +#![crate_name = "foo"] +#![feature(lazy_type_alias)] +#![allow(incomplete_features)] + +//! # Basic [link](https://example.com), *emphasis*, **_very emphasis_** and `code` +//! +//! This test case covers TOC entries with rich text inside. +//! Rustdoc normally supports headers with links, but for the +//! TOC, that would break the layout. +//! +//! For consistency, emphasis is also filtered out. + +//@ has foo/index.html +// User header +//@ has - '//section[@id="rustdoc-toc"]/h3' 'Sections' +//@ has - '//section[@id="rustdoc-toc"]/ul[@class="block top-toc"]/li/a[@href="#basic-link-emphasis-very-emphasis-and-code"]/@title' 'Basic link, emphasis, very emphasis and `code`' +//@ has - '//section[@id="rustdoc-toc"]/ul[@class="block top-toc"]/li/a[@href="#basic-link-emphasis-very-emphasis-and-code"]' 'Basic link, emphasis, very emphasis and code' +//@ count - '//section[@id="rustdoc-toc"]/ul[@class="block top-toc"]/li/a[@href="#basic-link-emphasis-very-emphasis-and-code"]/em' 0 +//@ count - '//section[@id="rustdoc-toc"]/ul[@class="block top-toc"]/li/a[@href="#basic-link-emphasis-very-emphasis-and-code"]/a' 0 +//@ count - '//section[@id="rustdoc-toc"]/ul[@class="block top-toc"]/li/a[@href="#basic-link-emphasis-very-emphasis-and-code"]/code' 1 +//@ has - '//section[@id="rustdoc-toc"]/ul[@class="block top-toc"]/li/a[@href="#basic-link-emphasis-very-emphasis-and-code"]/code' 'code' diff --git a/tests/rustdoc/sidebar/top-toc-idmap.rs b/tests/rustdoc/sidebar/top-toc-idmap.rs new file mode 100644 index 00000000000..af07cb4179b --- /dev/null +++ b/tests/rustdoc/sidebar/top-toc-idmap.rs @@ -0,0 +1,44 @@ +#![crate_name = "foo"] +#![feature(lazy_type_alias)] +#![allow(incomplete_features)] + +//! # Structs +//! +//! This header has the same name as a built-in header, +//! and we need to make sure they're disambiguated with +//! suffixes. +//! +//! Module-like headers get derived from the internal ID map, +//! so the *internal* one gets a suffix here. To make sure it +//! works right, the one in the `top-toc` needs to match the one +//! in the `top-doc`, and the one that's not in the `top-doc` +//! needs to match the one that isn't in the `top-toc`. + +//@ has foo/index.html +// User header +//@ has - '//section[@id="rustdoc-toc"]/ul[@class="block top-toc"]/li/a[@href="#structs"]' 'Structs' +//@ has - '//details[@class="toggle top-doc"]/div[@class="docblock"]/h2[@id="structs"]' 'Structs' +// Built-in header +//@ has - '//section[@id="rustdoc-toc"]/ul[@class="block"]/li/a[@href="#structs-1"]' 'Structs' +//@ has - '//section[@id="main-content"]/h2[@id="structs-1"]' 'Structs' + +/// # Fields +/// ## Fields +/// ### Fields +/// +/// The difference between struct-like headers and module-like headers +/// is strange, but not actually a problem as long as we're consistent. + +//@ has foo/struct.MyStruct.html +// User header +//@ has - '//section[@id="rustdoc-toc"]/ul[@class="block top-toc"]/li/a[@href="#fields-1"]' 'Fields' +//@ has - '//details[@class="toggle top-doc"]/div[@class="docblock"]/h2[@id="fields-1"]' 'Fields' +// Only one level of nesting +//@ count - '//section[@id="rustdoc-toc"]/ul[@class="block top-toc"]//a' 2 +// Built-in header +//@ has - '//section[@id="rustdoc-toc"]/h3/a[@href="#fields"]' 'Fields' +//@ has - '//section[@id="main-content"]/h2[@id="fields"]' 'Fields' + +pub struct MyStruct { + pub fields: i32, +} diff --git a/tests/rustdoc/sidebar/top-toc-nil.rs b/tests/rustdoc/sidebar/top-toc-nil.rs new file mode 100644 index 00000000000..d72d41abf88 --- /dev/null +++ b/tests/rustdoc/sidebar/top-toc-nil.rs @@ -0,0 +1,7 @@ +#![crate_name = "foo"] + +//! This test case covers missing top TOC entries. + +//@ has foo/index.html +// User header +//@ !has - '//section[@id="rustdoc-toc"]/ul[@class="block top-toc"]' 'Basic link and emphasis' diff --git a/tests/rustdoc/strip-enum-variant.no-not-shown.html b/tests/rustdoc/strip-enum-variant.no-not-shown.html index e072335297d..d7a36cc631a 100644 --- a/tests/rustdoc/strip-enum-variant.no-not-shown.html +++ b/tests/rustdoc/strip-enum-variant.no-not-shown.html @@ -1 +1 @@ -<ul class="block variant"><li><a href="#variant.Shown">Shown</a></li></ul> \ No newline at end of file +<ul class="block variant"><li><a href="#variant.Shown" title="Shown">Shown</a></li></ul> \ No newline at end of file diff --git a/tests/ui/cast/ptr-to-trait-obj-different-regions-lt-ext.rs b/tests/ui/cast/ptr-to-trait-obj-different-regions-lt-ext.rs index 96345de01c9..be2b89aab08 100644 --- a/tests/ui/cast/ptr-to-trait-obj-different-regions-lt-ext.rs +++ b/tests/ui/cast/ptr-to-trait-obj-different-regions-lt-ext.rs @@ -2,7 +2,7 @@ // // issue: <https://github.com/rust-lang/rust/issues/120217> -#![feature(arbitrary_self_types)] +#![feature(arbitrary_self_types_pointers)] trait Static<'a> { fn proof(self: *const Self, s: &'a str) -> &'static str; diff --git a/tests/ui/check-cfg/well-known-values.stderr b/tests/ui/check-cfg/well-known-values.stderr index 0530e1c34c9..144a67025b3 100644 --- a/tests/ui/check-cfg/well-known-values.stderr +++ b/tests/ui/check-cfg/well-known-values.stderr @@ -210,7 +210,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` LL | target_os = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_os` are: `aix`, `android`, `cuda`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `macos`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `psp`, `redox`, `solaris`, `solid_asp3`, `teeos`, `trusty`, `tvos`, `uefi`, `unknown`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, and `zkvm` + = note: expected values for `target_os` are: `aix`, `android`, `cuda`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `macos`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `psp`, `redox`, `rtems`, `solaris`, `solid_asp3`, `teeos`, `trusty`, `tvos`, `uefi`, `unknown`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, and `zkvm` = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` @@ -294,7 +294,7 @@ LL | #[cfg(target_os = "linuz")] // testing that we suggest `linux` | | | help: there is a expected value with a similar name: `"linux"` | - = note: expected values for `target_os` are: `aix`, `android`, `cuda`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `macos`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `psp`, `redox`, `solaris`, `solid_asp3`, `teeos`, `trusty`, `tvos`, `uefi`, `unknown`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, and `zkvm` + = note: expected values for `target_os` are: `aix`, `android`, `cuda`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `macos`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `psp`, `redox`, `rtems`, `solaris`, `solid_asp3`, `teeos`, `trusty`, `tvos`, `uefi`, `unknown`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, and `zkvm` = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: 30 warnings emitted diff --git a/tests/ui/feature-gates/feature-gate-arbitrary-self-types-pointers.rs b/tests/ui/feature-gates/feature-gate-arbitrary-self-types-pointers.rs new file mode 100644 index 00000000000..79ceb05662b --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-arbitrary-self-types-pointers.rs @@ -0,0 +1,15 @@ +trait Foo { + fn foo(self: *const Self); //~ ERROR `*const Self` cannot be used as the type of `self` +} + +struct Bar; + +impl Foo for Bar { + fn foo(self: *const Self) {} //~ ERROR `*const Bar` cannot be used as the type of `self` +} + +impl Bar { + fn bar(self: *mut Self) {} //~ ERROR `*mut Bar` cannot be used as the type of `self` +} + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-arbitrary-self-types-pointers.stderr b/tests/ui/feature-gates/feature-gate-arbitrary-self-types-pointers.stderr new file mode 100644 index 00000000000..3bb93cf2ea0 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-arbitrary-self-types-pointers.stderr @@ -0,0 +1,36 @@ +error[E0658]: `*const Bar` cannot be used as the type of `self` without the `arbitrary_self_types_pointers` feature + --> $DIR/feature-gate-arbitrary-self-types-pointers.rs:8:18 + | +LL | fn foo(self: *const Self) {} + | ^^^^^^^^^^^ + | + = note: see issue #44874 <https://github.com/rust-lang/rust/issues/44874> for more information + = help: add `#![feature(arbitrary_self_types_pointers)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`) + +error[E0658]: `*mut Bar` cannot be used as the type of `self` without the `arbitrary_self_types_pointers` feature + --> $DIR/feature-gate-arbitrary-self-types-pointers.rs:12:18 + | +LL | fn bar(self: *mut Self) {} + | ^^^^^^^^^ + | + = note: see issue #44874 <https://github.com/rust-lang/rust/issues/44874> for more information + = help: add `#![feature(arbitrary_self_types_pointers)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`) + +error[E0658]: `*const Self` cannot be used as the type of `self` without the `arbitrary_self_types_pointers` feature + --> $DIR/feature-gate-arbitrary-self-types-pointers.rs:2:18 + | +LL | fn foo(self: *const Self); + | ^^^^^^^^^^^ + | + = note: see issue #44874 <https://github.com/rust-lang/rust/issues/44874> for more information + = help: add `#![feature(arbitrary_self_types_pointers)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`) + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-arbitrary_self_types-raw-pointer.stderr b/tests/ui/feature-gates/feature-gate-arbitrary_self_types-raw-pointer.stderr index 711025ff93b..856e0595331 100644 --- a/tests/ui/feature-gates/feature-gate-arbitrary_self_types-raw-pointer.stderr +++ b/tests/ui/feature-gates/feature-gate-arbitrary_self_types-raw-pointer.stderr @@ -1,33 +1,33 @@ -error[E0658]: `*const Foo` cannot be used as the type of `self` without the `arbitrary_self_types` feature +error[E0658]: `*const Foo` cannot be used as the type of `self` without the `arbitrary_self_types_pointers` feature --> $DIR/feature-gate-arbitrary_self_types-raw-pointer.rs:4:18 | LL | fn foo(self: *const Self) {} | ^^^^^^^^^^^ | = note: see issue #44874 <https://github.com/rust-lang/rust/issues/44874> for more information - = help: add `#![feature(arbitrary_self_types)]` to the crate attributes to enable + = help: add `#![feature(arbitrary_self_types_pointers)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`) -error[E0658]: `*const ()` cannot be used as the type of `self` without the `arbitrary_self_types` feature +error[E0658]: `*const ()` cannot be used as the type of `self` without the `arbitrary_self_types_pointers` feature --> $DIR/feature-gate-arbitrary_self_types-raw-pointer.rs:14:18 | LL | fn bar(self: *const Self) {} | ^^^^^^^^^^^ | = note: see issue #44874 <https://github.com/rust-lang/rust/issues/44874> for more information - = help: add `#![feature(arbitrary_self_types)]` to the crate attributes to enable + = help: add `#![feature(arbitrary_self_types_pointers)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`) -error[E0658]: `*const Self` cannot be used as the type of `self` without the `arbitrary_self_types` feature +error[E0658]: `*const Self` cannot be used as the type of `self` without the `arbitrary_self_types_pointers` feature --> $DIR/feature-gate-arbitrary_self_types-raw-pointer.rs:9:18 | LL | fn bar(self: *const Self); | ^^^^^^^^^^^ | = note: see issue #44874 <https://github.com/rust-lang/rust/issues/44874> for more information - = help: add `#![feature(arbitrary_self_types)]` to the crate attributes to enable + = help: add `#![feature(arbitrary_self_types_pointers)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`) diff --git a/tests/ui/inference/auxiliary/inference_unstable_iterator.rs b/tests/ui/inference/auxiliary/inference_unstable_iterator.rs index 04bc0b1a8ac..8ba6fc89f16 100644 --- a/tests/ui/inference/auxiliary/inference_unstable_iterator.rs +++ b/tests/ui/inference/auxiliary/inference_unstable_iterator.rs @@ -1,5 +1,5 @@ #![feature(staged_api)] -#![feature(arbitrary_self_types)] +#![feature(arbitrary_self_types_pointers)] #![stable(feature = "ipu_iterator", since = "1.0.0")] diff --git a/tests/ui/inference/auxiliary/inference_unstable_itertools.rs b/tests/ui/inference/auxiliary/inference_unstable_itertools.rs index fa1efbcfefc..32ca3a45119 100644 --- a/tests/ui/inference/auxiliary/inference_unstable_itertools.rs +++ b/tests/ui/inference/auxiliary/inference_unstable_itertools.rs @@ -1,4 +1,4 @@ -#![feature(arbitrary_self_types)] +#![feature(arbitrary_self_types_pointers)] pub trait IpuItertools { fn ipu_flatten(&self) -> u32 { diff --git a/tests/ui/self/arbitrary_self_types_raw_pointer_struct.rs b/tests/ui/self/arbitrary_self_types_raw_pointer_struct.rs index 1f45d91847f..7f76ed7fd2a 100644 --- a/tests/ui/self/arbitrary_self_types_raw_pointer_struct.rs +++ b/tests/ui/self/arbitrary_self_types_raw_pointer_struct.rs @@ -1,5 +1,5 @@ //@ run-pass -#![feature(arbitrary_self_types)] +#![feature(arbitrary_self_types_pointers)] use std::rc::Rc; diff --git a/tests/ui/self/arbitrary_self_types_raw_pointer_trait.rs b/tests/ui/self/arbitrary_self_types_raw_pointer_trait.rs index 43f596659b9..6f34c9281b0 100644 --- a/tests/ui/self/arbitrary_self_types_raw_pointer_trait.rs +++ b/tests/ui/self/arbitrary_self_types_raw_pointer_trait.rs @@ -1,5 +1,5 @@ //@ run-pass -#![feature(arbitrary_self_types)] +#![feature(arbitrary_self_types_pointers)] use std::ptr; diff --git a/tests/ui/stats/hir-stats.rs b/tests/ui/stats/hir-stats.rs index 249413d80e8..7c5da8cf554 100644 --- a/tests/ui/stats/hir-stats.rs +++ b/tests/ui/stats/hir-stats.rs @@ -1,12 +1,15 @@ //@ check-pass //@ compile-flags: -Zhir-stats //@ only-x86_64 +// layout randomization affects the hir stat output +//@ needs-deterministic-layouts // Type layouts sometimes change. When that happens, until the next bootstrap // bump occurs, stage1 and stage2 will give different outputs for this test. // Add an `ignore-stage1` comment marker to work around that problem during // that time. + // The aim here is to include at least one of every different type of top-level // AST/HIR node reported by `-Zhir-stats`. diff --git a/tests/ui/structs-enums/type-sizes.rs b/tests/ui/structs-enums/type-sizes.rs index 9c933a9ef1c..5ca9c8678b7 100644 --- a/tests/ui/structs-enums/type-sizes.rs +++ b/tests/ui/structs-enums/type-sizes.rs @@ -1,4 +1,5 @@ //@ run-pass +//@ needs-deterministic-layouts #![allow(non_camel_case_types)] #![allow(dead_code)] |
