Auto merge of #118732 - matthiaskrgr:rollup-ub9pgjm, r=matthiaskrgr
Rollup of 8 pull requests Successful merges: - #118505 (Elaborate on ip_addr bit conversion endianness) - #118581 (OnceLock: Add note about drop and statics) - #118677 ([rustdoc] Fix display of features) - #118690 (coverage: Avoid unnecessary macros in unit tests) - #118693 (Tell MirUsedCollector that the pointer alignment checks calls its panic symbol) - #118695 (coverage: Merge refined spans in a separate final pass) - #118709 (fix jobserver GLOBAL_CLIENT_CHECKED uninitialized before use) - #118722 (rustdoc: remove unused parameter `reversed` from onEach(Lazy)) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
8043f62258
20 changed files with 216 additions and 194 deletions
|
@ -795,10 +795,6 @@ dependencies = [
|
|||
"rustc-demangle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "coverage_test_macros"
|
||||
version = "0.0.0"
|
||||
|
||||
[[package]]
|
||||
name = "cpufeatures"
|
||||
version = "0.2.8"
|
||||
|
@ -4266,7 +4262,6 @@ dependencies = [
|
|||
name = "rustc_mir_transform"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"coverage_test_macros",
|
||||
"either",
|
||||
"itertools",
|
||||
"rustc_arena",
|
||||
|
|
|
@ -52,7 +52,7 @@ fn default_client() -> Client {
|
|||
|
||||
static GLOBAL_CLIENT_CHECKED: OnceLock<Client> = OnceLock::new();
|
||||
|
||||
pub fn check(report_warning: impl FnOnce(&'static str)) {
|
||||
pub fn initialize_checked(report_warning: impl FnOnce(&'static str)) {
|
||||
let client_checked = match &*GLOBAL_CLIENT {
|
||||
Ok(client) => client.clone(),
|
||||
Err(e) => {
|
||||
|
|
|
@ -316,6 +316,10 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
|
|||
// Set parallel mode before thread pool creation, which will create `Lock`s.
|
||||
rustc_data_structures::sync::set_dyn_thread_safe_mode(config.opts.unstable_opts.threads > 1);
|
||||
|
||||
// Check jobserver before run_in_thread_pool_with_globals, which call jobserver::acquire_thread
|
||||
let early_handler = EarlyErrorHandler::new(config.opts.error_format);
|
||||
early_handler.initialize_checked_jobserver();
|
||||
|
||||
util::run_in_thread_pool_with_globals(
|
||||
config.opts.edition,
|
||||
config.opts.unstable_opts.threads,
|
||||
|
|
|
@ -27,6 +27,8 @@ use std::sync::Arc;
|
|||
|
||||
fn mk_session(matches: getopts::Matches) -> (Session, Cfg) {
|
||||
let mut early_handler = EarlyErrorHandler::new(ErrorOutputType::default());
|
||||
early_handler.initialize_checked_jobserver();
|
||||
|
||||
let registry = registry::Registry::new(&[]);
|
||||
let sessopts = build_session_options(&mut early_handler, &matches);
|
||||
let temps_dir = sessopts.unstable_opts.temps_dir.as_deref().map(PathBuf::from);
|
||||
|
|
|
@ -27,8 +27,3 @@ rustc_trait_selection = { path = "../rustc_trait_selection" }
|
|||
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
|
||||
tracing = "0.1"
|
||||
# tidy-alphabetical-end
|
||||
|
||||
[dev-dependencies]
|
||||
# tidy-alphabetical-start
|
||||
coverage_test_macros = { path = "src/coverage/test_macros" }
|
||||
# tidy-alphabetical-end
|
||||
|
|
|
@ -89,10 +89,10 @@ impl CoverageSpan {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn merge_from(&mut self, mut other: CoverageSpan) {
|
||||
debug_assert!(self.is_mergeable(&other));
|
||||
pub fn merge_from(&mut self, other: &Self) {
|
||||
debug_assert!(self.is_mergeable(other));
|
||||
self.span = self.span.to(other.span);
|
||||
self.merged_spans.append(&mut other.merged_spans);
|
||||
self.merged_spans.extend_from_slice(&other.merged_spans);
|
||||
}
|
||||
|
||||
pub fn cutoff_statements_at(&mut self, cutoff_pos: BytePos) {
|
||||
|
@ -267,7 +267,7 @@ impl<'a> CoverageSpansGenerator<'a> {
|
|||
if curr.is_mergeable(prev) {
|
||||
debug!(" same bcb (and neither is a closure), merge with prev={prev:?}");
|
||||
let prev = self.take_prev();
|
||||
self.curr_mut().merge_from(prev);
|
||||
self.curr_mut().merge_from(&prev);
|
||||
self.maybe_push_macro_name_span();
|
||||
// Note that curr.span may now differ from curr_original_span
|
||||
} else if prev.span.hi() <= curr.span.lo() {
|
||||
|
@ -275,7 +275,7 @@ impl<'a> CoverageSpansGenerator<'a> {
|
|||
" different bcbs and disjoint spans, so keep curr for next iter, and add prev={prev:?}",
|
||||
);
|
||||
let prev = self.take_prev();
|
||||
self.push_refined_span(prev);
|
||||
self.refined_spans.push(prev);
|
||||
self.maybe_push_macro_name_span();
|
||||
} else if prev.is_closure {
|
||||
// drop any equal or overlapping span (`curr`) and keep `prev` to test again in the
|
||||
|
@ -322,11 +322,10 @@ impl<'a> CoverageSpansGenerator<'a> {
|
|||
let prev = self.take_prev();
|
||||
debug!(" AT END, adding last prev={prev:?}");
|
||||
|
||||
// Take `pending_dups` so that we can drain it while calling self methods.
|
||||
// It is never used as a field after this point.
|
||||
for dup in std::mem::take(&mut self.pending_dups) {
|
||||
// Drain any remaining dups into the output.
|
||||
for dup in self.pending_dups.drain(..) {
|
||||
debug!(" ...adding at least one pending dup={:?}", dup);
|
||||
self.push_refined_span(dup);
|
||||
self.refined_spans.push(dup);
|
||||
}
|
||||
|
||||
// Async functions wrap a closure that implements the body to be executed. The enclosing
|
||||
|
@ -343,9 +342,20 @@ impl<'a> CoverageSpansGenerator<'a> {
|
|||
};
|
||||
|
||||
if !body_ends_with_closure {
|
||||
self.push_refined_span(prev);
|
||||
self.refined_spans.push(prev);
|
||||
}
|
||||
|
||||
// Do one last merge pass, to simplify the output.
|
||||
self.refined_spans.dedup_by(|b, a| {
|
||||
if a.is_mergeable(b) {
|
||||
debug!(?a, ?b, "merging list-adjacent refined spans");
|
||||
a.merge_from(b);
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
});
|
||||
|
||||
// Remove `CoverageSpan`s derived from closures, originally added to ensure the coverage
|
||||
// regions for the current function leave room for the closure's own coverage regions
|
||||
// (injected separately, from the closure's own MIR).
|
||||
|
@ -353,18 +363,6 @@ impl<'a> CoverageSpansGenerator<'a> {
|
|||
self.refined_spans
|
||||
}
|
||||
|
||||
fn push_refined_span(&mut self, covspan: CoverageSpan) {
|
||||
if let Some(last) = self.refined_spans.last_mut()
|
||||
&& last.is_mergeable(&covspan)
|
||||
{
|
||||
// Instead of pushing the new span, merge it with the last refined span.
|
||||
debug!(?last, ?covspan, "merging new refined span with last refined span");
|
||||
last.merge_from(covspan);
|
||||
} else {
|
||||
self.refined_spans.push(covspan);
|
||||
}
|
||||
}
|
||||
|
||||
/// If `curr` is part of a new macro expansion, carve out and push a separate
|
||||
/// span that ends just after the macro name and its subsequent `!`.
|
||||
fn maybe_push_macro_name_span(&mut self) {
|
||||
|
@ -397,7 +395,7 @@ impl<'a> CoverageSpansGenerator<'a> {
|
|||
" and curr starts a new macro expansion, so add a new span just for \
|
||||
the macro `{visible_macro}!`, new span={macro_name_cov:?}",
|
||||
);
|
||||
self.push_refined_span(macro_name_cov);
|
||||
self.refined_spans.push(macro_name_cov);
|
||||
}
|
||||
|
||||
fn curr(&self) -> &CoverageSpan {
|
||||
|
@ -454,19 +452,14 @@ impl<'a> CoverageSpansGenerator<'a> {
|
|||
previous iteration, or prev started a new disjoint span"
|
||||
);
|
||||
if last_dup.span.hi() <= self.curr().span.lo() {
|
||||
// Temporarily steal `pending_dups` into a local, so that we can
|
||||
// drain it while calling other self methods.
|
||||
let mut pending_dups = std::mem::take(&mut self.pending_dups);
|
||||
for dup in pending_dups.drain(..) {
|
||||
for dup in self.pending_dups.drain(..) {
|
||||
debug!(" ...adding at least one pending={:?}", dup);
|
||||
self.push_refined_span(dup);
|
||||
self.refined_spans.push(dup);
|
||||
}
|
||||
// The list of dups is now empty, but we can recycle its capacity.
|
||||
assert!(pending_dups.is_empty() && self.pending_dups.is_empty());
|
||||
self.pending_dups = pending_dups;
|
||||
} else {
|
||||
self.pending_dups.clear();
|
||||
}
|
||||
assert!(self.pending_dups.is_empty());
|
||||
}
|
||||
|
||||
/// Advance `prev` to `curr` (if any), and `curr` to the next `CoverageSpan` in sorted order.
|
||||
|
@ -513,22 +506,18 @@ impl<'a> CoverageSpansGenerator<'a> {
|
|||
let has_pre_closure_span = prev.span.lo() < right_cutoff;
|
||||
let has_post_closure_span = prev.span.hi() > right_cutoff;
|
||||
|
||||
// Temporarily steal `pending_dups` into a local, so that we can
|
||||
// mutate and/or drain it while calling other self methods.
|
||||
let mut pending_dups = std::mem::take(&mut self.pending_dups);
|
||||
|
||||
if has_pre_closure_span {
|
||||
let mut pre_closure = self.prev().clone();
|
||||
pre_closure.span = pre_closure.span.with_hi(left_cutoff);
|
||||
debug!(" prev overlaps a closure. Adding span for pre_closure={:?}", pre_closure);
|
||||
if !pending_dups.is_empty() {
|
||||
for mut dup in pending_dups.iter().cloned() {
|
||||
dup.span = dup.span.with_hi(left_cutoff);
|
||||
debug!(" ...and at least one pre_closure dup={:?}", dup);
|
||||
self.push_refined_span(dup);
|
||||
}
|
||||
|
||||
for mut dup in self.pending_dups.iter().cloned() {
|
||||
dup.span = dup.span.with_hi(left_cutoff);
|
||||
debug!(" ...and at least one pre_closure dup={:?}", dup);
|
||||
self.refined_spans.push(dup);
|
||||
}
|
||||
self.push_refined_span(pre_closure);
|
||||
|
||||
self.refined_spans.push(pre_closure);
|
||||
}
|
||||
|
||||
if has_post_closure_span {
|
||||
|
@ -537,19 +526,17 @@ impl<'a> CoverageSpansGenerator<'a> {
|
|||
// about how the `CoverageSpan`s are ordered.)
|
||||
self.prev_mut().span = self.prev().span.with_lo(right_cutoff);
|
||||
debug!(" Mutated prev.span to start after the closure. prev={:?}", self.prev());
|
||||
for dup in pending_dups.iter_mut() {
|
||||
|
||||
for dup in &mut self.pending_dups {
|
||||
debug!(" ...and at least one overlapping dup={:?}", dup);
|
||||
dup.span = dup.span.with_lo(right_cutoff);
|
||||
}
|
||||
let closure_covspan = self.take_curr(); // Prevent this curr from becoming prev.
|
||||
self.push_refined_span(closure_covspan); // since self.prev() was already updated
|
||||
} else {
|
||||
pending_dups.clear();
|
||||
}
|
||||
|
||||
// Restore the modified post-closure spans, or the empty vector's capacity.
|
||||
assert!(self.pending_dups.is_empty());
|
||||
self.pending_dups = pending_dups;
|
||||
let closure_covspan = self.take_curr(); // Prevent this curr from becoming prev.
|
||||
self.refined_spans.push(closure_covspan); // since self.prev() was already updated
|
||||
} else {
|
||||
self.pending_dups.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/// Called if `curr.span` equals `prev_original_span` (and potentially equal to all
|
||||
|
@ -645,7 +632,7 @@ impl<'a> CoverageSpansGenerator<'a> {
|
|||
} else {
|
||||
debug!(" ... adding modified prev={:?}", self.prev());
|
||||
let prev = self.take_prev();
|
||||
self.push_refined_span(prev);
|
||||
self.refined_spans.push(prev);
|
||||
}
|
||||
} else {
|
||||
// with `pending_dups`, `prev` cannot have any statements that don't overlap
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
[package]
|
||||
name = "coverage_test_macros"
|
||||
version = "0.0.0"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
proc-macro = true
|
|
@ -1,6 +0,0 @@
|
|||
use proc_macro::TokenStream;
|
||||
|
||||
#[proc_macro]
|
||||
pub fn let_bcb(item: TokenStream) -> TokenStream {
|
||||
format!("let bcb{item} = graph::BasicCoverageBlock::from_usize({item});").parse().unwrap()
|
||||
}
|
|
@ -27,8 +27,6 @@
|
|||
use super::counters;
|
||||
use super::graph::{self, BasicCoverageBlock};
|
||||
|
||||
use coverage_test_macros::let_bcb;
|
||||
|
||||
use itertools::Itertools;
|
||||
use rustc_data_structures::graph::WithNumNodes;
|
||||
use rustc_data_structures::graph::WithSuccessors;
|
||||
|
@ -37,6 +35,10 @@ use rustc_middle::mir::*;
|
|||
use rustc_middle::ty;
|
||||
use rustc_span::{self, BytePos, Pos, Span, DUMMY_SP};
|
||||
|
||||
fn bcb(index: u32) -> BasicCoverageBlock {
|
||||
BasicCoverageBlock::from_u32(index)
|
||||
}
|
||||
|
||||
// All `TEMP_BLOCK` targets should be replaced before calling `to_body() -> mir::Body`.
|
||||
const TEMP_BLOCK: BasicBlock = BasicBlock::MAX;
|
||||
|
||||
|
@ -300,12 +302,15 @@ fn goto_switchint<'a>() -> Body<'a> {
|
|||
mir_body
|
||||
}
|
||||
|
||||
macro_rules! assert_successors {
|
||||
($basic_coverage_blocks:ident, $i:ident, [$($successor:ident),*]) => {
|
||||
let mut successors = $basic_coverage_blocks.successors[$i].clone();
|
||||
successors.sort_unstable();
|
||||
assert_eq!(successors, vec![$($successor),*]);
|
||||
}
|
||||
#[track_caller]
|
||||
fn assert_successors(
|
||||
basic_coverage_blocks: &graph::CoverageGraph,
|
||||
bcb: BasicCoverageBlock,
|
||||
expected_successors: &[BasicCoverageBlock],
|
||||
) {
|
||||
let mut successors = basic_coverage_blocks.successors[bcb].clone();
|
||||
successors.sort_unstable();
|
||||
assert_eq!(successors, expected_successors);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -334,13 +339,9 @@ fn test_covgraph_goto_switchint() {
|
|||
basic_coverage_blocks.iter_enumerated().collect::<Vec<_>>()
|
||||
);
|
||||
|
||||
let_bcb!(0);
|
||||
let_bcb!(1);
|
||||
let_bcb!(2);
|
||||
|
||||
assert_successors!(basic_coverage_blocks, bcb0, [bcb1, bcb2]);
|
||||
assert_successors!(basic_coverage_blocks, bcb1, []);
|
||||
assert_successors!(basic_coverage_blocks, bcb2, []);
|
||||
assert_successors(&basic_coverage_blocks, bcb(0), &[bcb(1), bcb(2)]);
|
||||
assert_successors(&basic_coverage_blocks, bcb(1), &[]);
|
||||
assert_successors(&basic_coverage_blocks, bcb(2), &[]);
|
||||
}
|
||||
|
||||
/// Create a mock `Body` with a loop.
|
||||
|
@ -418,15 +419,10 @@ fn test_covgraph_switchint_then_loop_else_return() {
|
|||
basic_coverage_blocks.iter_enumerated().collect::<Vec<_>>()
|
||||
);
|
||||
|
||||
let_bcb!(0);
|
||||
let_bcb!(1);
|
||||
let_bcb!(2);
|
||||
let_bcb!(3);
|
||||
|
||||
assert_successors!(basic_coverage_blocks, bcb0, [bcb1]);
|
||||
assert_successors!(basic_coverage_blocks, bcb1, [bcb2, bcb3]);
|
||||
assert_successors!(basic_coverage_blocks, bcb2, []);
|
||||
assert_successors!(basic_coverage_blocks, bcb3, [bcb1]);
|
||||
assert_successors(&basic_coverage_blocks, bcb(0), &[bcb(1)]);
|
||||
assert_successors(&basic_coverage_blocks, bcb(1), &[bcb(2), bcb(3)]);
|
||||
assert_successors(&basic_coverage_blocks, bcb(2), &[]);
|
||||
assert_successors(&basic_coverage_blocks, bcb(3), &[bcb(1)]);
|
||||
}
|
||||
|
||||
/// Create a mock `Body` with nested loops.
|
||||
|
@ -546,21 +542,13 @@ fn test_covgraph_switchint_loop_then_inner_loop_else_break() {
|
|||
basic_coverage_blocks.iter_enumerated().collect::<Vec<_>>()
|
||||
);
|
||||
|
||||
let_bcb!(0);
|
||||
let_bcb!(1);
|
||||
let_bcb!(2);
|
||||
let_bcb!(3);
|
||||
let_bcb!(4);
|
||||
let_bcb!(5);
|
||||
let_bcb!(6);
|
||||
|
||||
assert_successors!(basic_coverage_blocks, bcb0, [bcb1]);
|
||||
assert_successors!(basic_coverage_blocks, bcb1, [bcb2, bcb3]);
|
||||
assert_successors!(basic_coverage_blocks, bcb2, []);
|
||||
assert_successors!(basic_coverage_blocks, bcb3, [bcb4]);
|
||||
assert_successors!(basic_coverage_blocks, bcb4, [bcb5, bcb6]);
|
||||
assert_successors!(basic_coverage_blocks, bcb5, [bcb1]);
|
||||
assert_successors!(basic_coverage_blocks, bcb6, [bcb4]);
|
||||
assert_successors(&basic_coverage_blocks, bcb(0), &[bcb(1)]);
|
||||
assert_successors(&basic_coverage_blocks, bcb(1), &[bcb(2), bcb(3)]);
|
||||
assert_successors(&basic_coverage_blocks, bcb(2), &[]);
|
||||
assert_successors(&basic_coverage_blocks, bcb(3), &[bcb(4)]);
|
||||
assert_successors(&basic_coverage_blocks, bcb(4), &[bcb(5), bcb(6)]);
|
||||
assert_successors(&basic_coverage_blocks, bcb(5), &[bcb(1)]);
|
||||
assert_successors(&basic_coverage_blocks, bcb(6), &[bcb(4)]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -595,10 +583,7 @@ fn test_find_loop_backedges_one() {
|
|||
backedges
|
||||
);
|
||||
|
||||
let_bcb!(1);
|
||||
let_bcb!(3);
|
||||
|
||||
assert_eq!(backedges[bcb1], vec![bcb3]);
|
||||
assert_eq!(backedges[bcb(1)], &[bcb(3)]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -613,13 +598,8 @@ fn test_find_loop_backedges_two() {
|
|||
backedges
|
||||
);
|
||||
|
||||
let_bcb!(1);
|
||||
let_bcb!(4);
|
||||
let_bcb!(5);
|
||||
let_bcb!(6);
|
||||
|
||||
assert_eq!(backedges[bcb1], vec![bcb5]);
|
||||
assert_eq!(backedges[bcb4], vec![bcb6]);
|
||||
assert_eq!(backedges[bcb(1)], &[bcb(5)]);
|
||||
assert_eq!(backedges[bcb(4)], &[bcb(6)]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -632,13 +612,11 @@ fn test_traverse_coverage_with_loops() {
|
|||
traversed_in_order.push(bcb);
|
||||
}
|
||||
|
||||
let_bcb!(6);
|
||||
|
||||
// bcb0 is visited first. Then bcb1 starts the first loop, and all remaining nodes, *except*
|
||||
// bcb6 are inside the first loop.
|
||||
assert_eq!(
|
||||
*traversed_in_order.last().expect("should have elements"),
|
||||
bcb6,
|
||||
bcb(6),
|
||||
"bcb6 should not be visited until all nodes inside the first loop have been visited"
|
||||
);
|
||||
}
|
||||
|
@ -656,20 +634,18 @@ fn test_make_bcb_counters() {
|
|||
coverage_counters.make_bcb_counters(&basic_coverage_blocks, bcb_has_coverage_spans);
|
||||
assert_eq!(coverage_counters.num_expressions(), 0);
|
||||
|
||||
let_bcb!(1);
|
||||
assert_eq!(
|
||||
0, // bcb1 has a `Counter` with id = 0
|
||||
match coverage_counters.bcb_counter(bcb1).expect("should have a counter") {
|
||||
match coverage_counters.bcb_counter(bcb(1)).expect("should have a counter") {
|
||||
counters::BcbCounter::Counter { id, .. } => id,
|
||||
_ => panic!("expected a Counter"),
|
||||
}
|
||||
.as_u32()
|
||||
);
|
||||
|
||||
let_bcb!(2);
|
||||
assert_eq!(
|
||||
1, // bcb2 has a `Counter` with id = 1
|
||||
match coverage_counters.bcb_counter(bcb2).expect("should have a counter") {
|
||||
match coverage_counters.bcb_counter(bcb(2)).expect("should have a counter") {
|
||||
counters::BcbCounter::Counter { id, .. } => id,
|
||||
_ => panic!("expected a Counter"),
|
||||
}
|
||||
|
|
|
@ -844,6 +844,9 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
|
|||
mir::TerminatorKind::Assert { ref msg, .. } => {
|
||||
let lang_item = match &**msg {
|
||||
mir::AssertKind::BoundsCheck { .. } => LangItem::PanicBoundsCheck,
|
||||
mir::AssertKind::MisalignedPointerDereference { .. } => {
|
||||
LangItem::PanicMisalignedPointerDereference
|
||||
}
|
||||
_ => LangItem::Panic,
|
||||
};
|
||||
push_mono_lang_item(self, lang_item);
|
||||
|
|
|
@ -1474,17 +1474,6 @@ pub fn build_session(
|
|||
let asm_arch =
|
||||
if target_cfg.allow_asm { InlineAsmArch::from_str(&target_cfg.arch).ok() } else { None };
|
||||
|
||||
// Check jobserver before getting `jobserver::client`.
|
||||
jobserver::check(|err| {
|
||||
#[allow(rustc::untranslatable_diagnostic)]
|
||||
#[allow(rustc::diagnostic_outside_of_impl)]
|
||||
parse_sess
|
||||
.span_diagnostic
|
||||
.struct_warn(err)
|
||||
.note("the build environment is likely misconfigured")
|
||||
.emit()
|
||||
});
|
||||
|
||||
let sess = Session {
|
||||
target: target_cfg,
|
||||
host,
|
||||
|
@ -1792,6 +1781,18 @@ impl EarlyErrorHandler {
|
|||
pub fn early_warn(&self, msg: impl Into<DiagnosticMessage>) {
|
||||
self.handler.struct_warn(msg).emit()
|
||||
}
|
||||
|
||||
pub fn initialize_checked_jobserver(&self) {
|
||||
// initialize jobserver before getting `jobserver::client` and `build_session`.
|
||||
jobserver::initialize_checked(|err| {
|
||||
#[allow(rustc::untranslatable_diagnostic)]
|
||||
#[allow(rustc::diagnostic_outside_of_impl)]
|
||||
self.handler
|
||||
.struct_warn(err)
|
||||
.note("the build environment is likely misconfigured")
|
||||
.emit()
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fn mk_emitter(output: ErrorOutputType) -> Box<DynEmitter> {
|
||||
|
|
|
@ -468,7 +468,13 @@ impl Ipv4Addr {
|
|||
#[unstable(feature = "ip_bits", issue = "113744")]
|
||||
pub const BITS: u32 = 32;
|
||||
|
||||
/// Converts an IPv4 address into host byte order `u32`.
|
||||
/// Converts an IPv4 address into a `u32` representation using native byte order.
|
||||
///
|
||||
/// Although IPv4 addresses are big-endian, the `u32` value will use the target platform's
|
||||
/// native byte order. That is, the `u32` value is an integer representation of the IPv4
|
||||
/// address and not an integer interpretation of the IPv4 address's big-endian bitstring. This
|
||||
/// means that the `u32` value masked with `0xffffff00` will set the last octet in the address
|
||||
/// to 0, regardless of the target platform's endianness.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -479,6 +485,16 @@ impl Ipv4Addr {
|
|||
/// let addr = Ipv4Addr::new(0x12, 0x34, 0x56, 0x78);
|
||||
/// assert_eq!(0x12345678, addr.to_bits());
|
||||
/// ```
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(ip_bits)]
|
||||
/// use std::net::Ipv4Addr;
|
||||
///
|
||||
/// let addr = Ipv4Addr::new(0x12, 0x34, 0x56, 0x78);
|
||||
/// let addr_bits = addr.to_bits() & 0xffffff00;
|
||||
/// assert_eq!(Ipv4Addr::new(0x12, 0x34, 0x56, 0x00), Ipv4Addr::from_bits(addr_bits));
|
||||
///
|
||||
/// ```
|
||||
#[rustc_const_unstable(feature = "ip_bits", issue = "113744")]
|
||||
#[unstable(feature = "ip_bits", issue = "113744")]
|
||||
#[must_use]
|
||||
|
@ -487,7 +503,9 @@ impl Ipv4Addr {
|
|||
u32::from_be_bytes(self.octets)
|
||||
}
|
||||
|
||||
/// Converts a host byte order `u32` into an IPv4 address.
|
||||
/// Converts a native byte order `u32` into an IPv4 address.
|
||||
///
|
||||
/// See [`Ipv4Addr::to_bits`] for an explanation on endianness.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -1224,7 +1242,13 @@ impl Ipv6Addr {
|
|||
#[unstable(feature = "ip_bits", issue = "113744")]
|
||||
pub const BITS: u32 = 128;
|
||||
|
||||
/// Converts an IPv6 address into host byte order `u128`.
|
||||
/// Converts an IPv6 address into a `u128` representation using native byte order.
|
||||
///
|
||||
/// Although IPv6 addresses are big-endian, the `u128` value will use the target platform's
|
||||
/// native byte order. That is, the `u128` value is an integer representation of the IPv6
|
||||
/// address and not an integer interpretation of the IPv6 address's big-endian bitstring. This
|
||||
/// means that the `u128` value masked with `0xffffffffffffffffffffffffffff0000_u128` will set
|
||||
/// the last segment in the address to 0, regardless of the target platform's endianness.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -1238,6 +1262,24 @@ impl Ipv6Addr {
|
|||
/// );
|
||||
/// assert_eq!(0x102030405060708090A0B0C0D0E0F00D_u128, u128::from(addr));
|
||||
/// ```
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(ip_bits)]
|
||||
/// use std::net::Ipv6Addr;
|
||||
///
|
||||
/// let addr = Ipv6Addr::new(
|
||||
/// 0x1020, 0x3040, 0x5060, 0x7080,
|
||||
/// 0x90A0, 0xB0C0, 0xD0E0, 0xF00D,
|
||||
/// );
|
||||
/// let addr_bits = addr.to_bits() & 0xffffffffffffffffffffffffffff0000_u128;
|
||||
/// assert_eq!(
|
||||
/// Ipv6Addr::new(
|
||||
/// 0x1020, 0x3040, 0x5060, 0x7080,
|
||||
/// 0x90A0, 0xB0C0, 0xD0E0, 0x0000,
|
||||
/// ),
|
||||
/// Ipv6Addr::from_bits(addr_bits));
|
||||
///
|
||||
/// ```
|
||||
#[rustc_const_unstable(feature = "ip_bits", issue = "113744")]
|
||||
#[unstable(feature = "ip_bits", issue = "113744")]
|
||||
#[must_use]
|
||||
|
@ -1246,7 +1288,9 @@ impl Ipv6Addr {
|
|||
u128::from_be_bytes(self.octets)
|
||||
}
|
||||
|
||||
/// Converts a host byte order `u128` into an IPv6 address.
|
||||
/// Converts a native byte order `u128` into an IPv6 address.
|
||||
///
|
||||
/// See [`Ipv6Addr::to_bits`] for an explanation on endianness.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
|
|
@ -17,25 +17,36 @@ use crate::sync::Once;
|
|||
/// ‘lazy static’ or ‘memoizing’):
|
||||
///
|
||||
/// ```
|
||||
/// use std::collections::HashMap;
|
||||
/// use std::sync::OnceLock;
|
||||
///
|
||||
/// fn hash_map() -> &'static HashMap<u32, char> {
|
||||
/// static HASHMAP: OnceLock<HashMap<u32, char>> = OnceLock::new();
|
||||
/// HASHMAP.get_or_init(|| {
|
||||
/// let mut m = HashMap::new();
|
||||
/// m.insert(0, 'a');
|
||||
/// m.insert(1, 'b');
|
||||
/// m.insert(2, 'c');
|
||||
/// m
|
||||
/// })
|
||||
/// struct DeepThought {
|
||||
/// answer: String,
|
||||
/// }
|
||||
///
|
||||
/// // The `HashMap` is built, stored in the `OnceLock`, and returned.
|
||||
/// let _ = hash_map();
|
||||
/// impl DeepThought {
|
||||
/// # fn great_question() -> String {
|
||||
/// # "42".to_string()
|
||||
/// # }
|
||||
/// #
|
||||
/// fn new() -> Self {
|
||||
/// Self {
|
||||
/// // M3 Ultra takes about 16 million years in --release config
|
||||
/// answer: Self::great_question(),
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// // The `HashMap` is retrieved from the `OnceLock` and returned.
|
||||
/// let _ = hash_map();
|
||||
/// fn computation() -> &'static DeepThought {
|
||||
/// // n.b. static items do not call [`Drop`] on program termination, so if
|
||||
/// // [`DeepThought`] impls Drop, that will not be used for this instance.
|
||||
/// static COMPUTATION: OnceLock<DeepThought> = OnceLock::new();
|
||||
/// COMPUTATION.get_or_init(|| DeepThought::new())
|
||||
/// }
|
||||
///
|
||||
/// // The `DeepThought` is built, stored in the `OnceLock`, and returned.
|
||||
/// let _ = computation().answer;
|
||||
/// // The `DeepThought` is retrieved from the `OnceLock` and returned.
|
||||
/// let _ = computation().answer;
|
||||
/// ```
|
||||
///
|
||||
/// Writing to a `OnceLock` from a separate thread:
|
||||
|
|
|
@ -1081,15 +1081,9 @@ so that we can apply CSS-filters to change the arrow color in themes */
|
|||
}
|
||||
|
||||
.item-info .stab {
|
||||
/* This min-height is needed to unify the height of the stab elements because some of them
|
||||
have emojis.
|
||||
*/
|
||||
min-height: 36px;
|
||||
display: flex;
|
||||
display: block;
|
||||
padding: 3px;
|
||||
margin-bottom: 5px;
|
||||
align-items: center;
|
||||
vertical-align: text-bottom;
|
||||
}
|
||||
.item-name .stab {
|
||||
margin-left: 0.3125em;
|
||||
|
@ -1112,17 +1106,26 @@ so that we can apply CSS-filters to change the arrow color in themes */
|
|||
color: var(--stab-code-color);
|
||||
}
|
||||
|
||||
.stab .emoji {
|
||||
.stab .emoji, .item-info .stab::before {
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
.stab .emoji {
|
||||
margin-right: 0.3rem;
|
||||
}
|
||||
.item-info .stab::before {
|
||||
/* ensure badges with emoji and without it have same height */
|
||||
content: "\0";
|
||||
width: 0;
|
||||
display: inline-block;
|
||||
color: transparent;
|
||||
}
|
||||
|
||||
/* Black one-pixel outline around emoji shapes */
|
||||
.emoji {
|
||||
text-shadow:
|
||||
1px 0 0 black,
|
||||
-1px 0 0 black,
|
||||
0 1px 0 black,
|
||||
0 1px 0 black,
|
||||
0 -1px 0 black;
|
||||
}
|
||||
|
||||
|
|
|
@ -51,22 +51,11 @@ function removeClass(elem, className) {
|
|||
* Run a callback for every element of an Array.
|
||||
* @param {Array<?>} arr - The array to iterate over
|
||||
* @param {function(?)} func - The callback
|
||||
* @param {boolean} [reversed] - Whether to iterate in reverse
|
||||
*/
|
||||
function onEach(arr, func, reversed) {
|
||||
if (arr && arr.length > 0) {
|
||||
if (reversed) {
|
||||
for (let i = arr.length - 1; i >= 0; --i) {
|
||||
if (func(arr[i])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (const elem of arr) {
|
||||
if (func(elem)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
function onEach(arr, func) {
|
||||
for (const elem of arr) {
|
||||
if (func(elem)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
@ -80,14 +69,12 @@ function onEach(arr, func, reversed) {
|
|||
* https://developer.mozilla.org/en-US/docs/Web/API/NodeList
|
||||
* @param {NodeList<?>|HTMLCollection<?>} lazyArray - An array to iterate over
|
||||
* @param {function(?)} func - The callback
|
||||
* @param {boolean} [reversed] - Whether to iterate in reverse
|
||||
*/
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
function onEachLazy(lazyArray, func, reversed) {
|
||||
function onEachLazy(lazyArray, func) {
|
||||
return onEach(
|
||||
Array.prototype.slice.call(lazyArray),
|
||||
func,
|
||||
reversed);
|
||||
func);
|
||||
}
|
||||
|
||||
function updateLocalStorage(name, value) {
|
||||
|
|
|
@ -4,5 +4,3 @@ warning: failed to connect to jobserver from environment variable `MAKEFLAGS="--
|
|||
|
||||
error: no input filename given
|
||||
|
||||
warning: 1 warning emitted
|
||||
|
||||
|
|
|
@ -2,5 +2,3 @@ warning: failed to connect to jobserver from environment variable `MAKEFLAGS="--
|
|||
|
|
||||
= note: the build environment is likely misconfigured
|
||||
|
||||
warning: 1 warning emitted
|
||||
|
||||
|
|
|
@ -8,7 +8,22 @@ assert-size: (".item-info", {"width": 840})
|
|||
assert-size: (".item-info .stab", {"width": 289})
|
||||
assert-position: (".item-info .stab", {"x": 245})
|
||||
|
||||
// We check that the display of the feature elements is not broken. It serves as regression
|
||||
// test for <https://github.com/rust-lang/rust/issues/118615>.
|
||||
set-window-size: (850, 800)
|
||||
store-position: (
|
||||
"//*[@class='stab portability']//code[text()='Win32_System']",
|
||||
{"x": first_line_x, "y": first_line_y},
|
||||
)
|
||||
store-position: (
|
||||
"//*[@class='stab portability']//code[text()='Win32_System_Diagnostics']",
|
||||
{"x": second_line_x, "y": second_line_y},
|
||||
)
|
||||
assert: |first_line_x| != |second_line_x| && |first_line_x| == 516 && |second_line_x| == 272
|
||||
assert: |first_line_y| != |second_line_y| && |first_line_y| == 688 && |second_line_y| == 711
|
||||
|
||||
// Now we ensure that they're not rendered on the same line.
|
||||
set-window-size: (1100, 800)
|
||||
go-to: "file://" + |DOC_PATH| + "/lib2/trait.Trait.html"
|
||||
// We first ensure that there are two item info on the trait.
|
||||
assert-count: ("#main-content > .item-info .stab", 2)
|
||||
|
|
|
@ -6,6 +6,13 @@ edition = "2018"
|
|||
[lib]
|
||||
path = "lib.rs"
|
||||
|
||||
[features]
|
||||
Win32 = ["Win32_System"]
|
||||
Win32_System = ["Win32_System_Diagnostics"]
|
||||
Win32_System_Diagnostics = ["Win32_System_Diagnostics_Debug"]
|
||||
Win32_System_Diagnostics_Debug = []
|
||||
default = ["Win32"]
|
||||
|
||||
[dependencies]
|
||||
implementors = { path = "./implementors" }
|
||||
http = { path = "./http" }
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
// ignore-tidy-linelength
|
||||
|
||||
#![feature(doc_cfg)]
|
||||
#![feature(doc_auto_cfg)]
|
||||
|
||||
pub mod another_folder;
|
||||
pub mod another_mod;
|
||||
|
@ -28,6 +29,14 @@ impl Foo {
|
|||
/// Some documentation
|
||||
/// # A Heading
|
||||
pub fn a_method(&self) {}
|
||||
|
||||
#[cfg(all(
|
||||
feature = "Win32",
|
||||
feature = "Win32_System",
|
||||
feature = "Win32_System_Diagnostics",
|
||||
feature = "Win32_System_Diagnostics_Debug"
|
||||
))]
|
||||
pub fn lot_of_features() {}
|
||||
}
|
||||
|
||||
#[doc(cfg(feature = "foo-method"))]
|
||||
|
|
Loading…
Add table
Reference in a new issue