mirror of https://github.com/rust-lang/rust.git
Auto merge of #129978 - matthiaskrgr:rollup-a7ryoox, r=matthiaskrgr
Rollup of 10 pull requests Successful merges: - #101339 (enable -Zrandomize-layout in debug CI builds ) - #120736 (rustdoc: add header map to the table of contents) - #127021 (Add target support for RTEMS Arm) - #128928 (CI: rfl: add more tools and steps) - #129584 (warn the user if the upstream master branch is old) - #129664 (Arbitrary self types v2: pointers feature gate.) - #129752 (Make supertrait and implied predicates queries defaulted) - #129918 (Update docs of `missing_abi` lint) - #129919 (Stabilize `waker_getters`) - #129925 (remove deprecated option `rust.split-debuginfo`) Failed merges: - #129789 (rustdoc: use strategic boxing to shrink `clean::Item`) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
eb33b43bab
|
@ -3569,6 +3569,7 @@ dependencies = [
|
|||
"rustc_hir_pretty",
|
||||
"rustc_hir_typeck",
|
||||
"rustc_incremental",
|
||||
"rustc_index",
|
||||
"rustc_infer",
|
||||
"rustc_interface",
|
||||
"rustc_lint",
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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`
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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,
|
||||
|
@ -1704,20 +1724,44 @@ fn check_method_receiver<'tcx>(
|
|||
)
|
||||
.with_help(fluent::hir_analysis_invalid_receiver_ty_help)
|
||||
.emit()
|
||||
} else {
|
||||
// Report error; would not have worked with `arbitrary_self_types`.
|
||||
tcx.dcx().emit_err(errors::InvalidReceiverTy { span, receiver_ty })
|
||||
});
|
||||
}
|
||||
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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -20,4 +20,5 @@ nightly = [
|
|||
"dep:rustc_macros",
|
||||
"rustc_index_macros/nightly",
|
||||
]
|
||||
rustc_randomized_layouts = []
|
||||
# tidy-alphabetical-end
|
||||
|
|
|
@ -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>());
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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 }
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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>>>>,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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!(
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -407,6 +407,7 @@ symbols! {
|
|||
append_const_msg,
|
||||
arbitrary_enum_discriminant,
|
||||
arbitrary_self_types,
|
||||
arbitrary_self_types_pointers,
|
||||
args,
|
||||
arith_offset,
|
||||
arm,
|
||||
|
|
|
@ -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),
|
||||
|
||||
|
|
|
@ -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()
|
||||
},
|
||||
}
|
||||
}
|
|
@ -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.
|
||||
#
|
||||
|
|
|
@ -52,4 +52,5 @@ check-cfg = [
|
|||
'cfg(no_global_oom_handling)',
|
||||
'cfg(no_rc)',
|
||||
'cfg(no_sync)',
|
||||
'cfg(randomized_layouts)',
|
||||
]
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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")]
|
||||
|
|
|
@ -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)]
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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"))',
|
||||
]
|
||||
|
|
|
@ -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",
|
||||
))] {
|
||||
|
|
|
@ -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"))',
|
||||
]
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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")]
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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;
|
|
@ -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;
|
|
@ -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")]
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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",
|
||||
)))]
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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)",
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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"))',
|
||||
]
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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"])
|
||||
}
|
||||
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.",
|
||||
},
|
||||
];
|
||||
|
|
|
@ -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/
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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).
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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(),
|
||||
};
|
||||
|
|
|
@ -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()
|
||||
{
|
||||
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,7 +300,8 @@ fn sidebar_trait<'a>(
|
|||
foreign_impls.sort();
|
||||
}
|
||||
|
||||
let mut blocks: Vec<LinkBlock<'_>> = [
|
||||
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),
|
||||
|
@ -233,9 +311,9 @@ fn sidebar_trait<'a>(
|
|||
("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);
|
||||
.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,33 +420,6 @@ 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()) {
|
||||
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,
|
||||
);
|
||||
}
|
||||
|
||||
let (synthetic, concrete): (Vec<&Impl>, Vec<&Impl>) =
|
||||
v.iter().partition::<Vec<_>, _>(|i| i.inner_impl().kind.is_auto());
|
||||
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"),
|
||||
|
@ -381,8 +428,30 @@ fn sidebar_assoc_items<'a>(
|
|||
),
|
||||
LinkBlock::new(Link::new("implementations", "Methods"), "method", methods),
|
||||
];
|
||||
blocks.append(&mut deref_methods);
|
||||
blocks.extend([concrete, synthetic, blanket]);
|
||||
|
||||
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 blocks, impl_, v, &mut derefs, &mut used_links);
|
||||
}
|
||||
|
||||
let (synthetic, concrete): (Vec<&Impl>, Vec<&Impl>) =
|
||||
v.iter().partition::<Vec<_>, _>(|i| i.inner_impl().kind.is_auto());
|
||||
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,
|
||||
&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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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"];
|
||||
|
||||
|
@ -198,6 +217,16 @@
|
|||
"js_name": "hide-sidebar",
|
||||
"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",
|
||||
|
|
|
@ -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") {
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>");
|
||||
|
|
|
@ -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),*)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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(())
|
||||
}
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -134,6 +134,11 @@ pub(super) fn handle_needs(
|
|||
condition: config.target_cfg().relocation_model == "pic",
|
||||
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")),
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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"]
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
//@ compile-flags: -O
|
||||
//@ needs-deterministic-layouts
|
||||
#![crate_type = "lib"]
|
||||
#![feature(exact_size_is_empty)]
|
||||
|
||||
|
|
|
@ -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"]
|
||||
|
|
|
@ -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 {}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"})
|
|
@ -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"})
|
||||
|
|
|
@ -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 {}
|
|
@ -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'
|
|
@ -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,
|
||||
}
|
|
@ -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'
|
|
@ -1 +1 @@
|
|||
<ul class="block variant"><li><a href="#variant.Shown">Shown</a></li></ul>
|
||||
<ul class="block variant"><li><a href="#variant.Shown" title="Shown">Shown</a></li></ul>
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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() {}
|
|
@ -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`.
|
|
@ -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`)
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue