Skip to content

Commit a4d2b17

Browse files
committed
Auto merge of rust-lang#121407 - matthiaskrgr:rollup-gf2ohp5, r=matthiaskrgr
Rollup of 6 pull requests Successful merges: - rust-lang#119636 (os::net: expanding TcpStreamExt for Linux with `tcp_deferaccept`.) - rust-lang#121261 (coverage: Remove `pending_dups` from the span refiner) - rust-lang#121336 (triagebot: add queue notifications) - rust-lang#121391 (never patterns: Fix liveness analysis in the presence of never patterns) - rust-lang#121399 (Solaris linker does not support --strip-debug) - rust-lang#121406 (Add a couple tests) Failed merges: - rust-lang#121206 (Top level error handling) r? `@ghost` `@rustbot` modify labels: rollup
2 parents f8131a4 + d3d0ae7 commit a4d2b17

File tree

15 files changed

+225
-184
lines changed

15 files changed

+225
-184
lines changed

compiler/rustc_codegen_ssa/src/back/linker.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -626,7 +626,7 @@ impl<'a> Linker for GccLinker<'a> {
626626
// it does support --strip-all as a compatibility alias for -s.
627627
// The --strip-debug case is handled by running an external
628628
// `strip` utility as a separate step after linking.
629-
if self.sess.target.os != "illumos" {
629+
if !self.sess.target.is_like_solaris {
630630
self.linker_arg("--strip-debug");
631631
}
632632
}

compiler/rustc_hir/src/pat_util.rs

+9-2
Original file line numberDiff line numberDiff line change
@@ -71,14 +71,21 @@ impl hir::Pat<'_> {
7171
/// Call `f` on every "binding" in a pattern, e.g., on `a` in
7272
/// `match foo() { Some(a) => (), None => () }`.
7373
///
74-
/// When encountering an or-pattern `p_0 | ... | p_n` only `p_0` will be visited.
74+
/// When encountering an or-pattern `p_0 | ... | p_n` only the first non-never pattern will be
75+
/// visited. If they're all never patterns we visit nothing, which is ok since a never pattern
76+
/// cannot have bindings.
7577
pub fn each_binding_or_first(
7678
&self,
7779
f: &mut impl FnMut(hir::BindingAnnotation, HirId, Span, Ident),
7880
) {
7981
self.walk(|p| match &p.kind {
8082
PatKind::Or(ps) => {
81-
ps[0].each_binding_or_first(f);
83+
for p in *ps {
84+
if !p.is_never_pattern() {
85+
p.each_binding_or_first(f);
86+
break;
87+
}
88+
}
8289
false
8390
}
8491
PatKind::Binding(bm, _, ident, _) => {

compiler/rustc_mir_transform/src/coverage/spans.rs

+16-164
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ pub(super) fn generate_coverage_spans(
6161
hir_info,
6262
basic_coverage_blocks,
6363
);
64-
let coverage_spans = SpansRefiner::refine_sorted_spans(basic_coverage_blocks, sorted_spans);
64+
let coverage_spans = SpansRefiner::refine_sorted_spans(sorted_spans);
6565
mappings.extend(coverage_spans.into_iter().map(|RefinedCovspan { bcb, span, .. }| {
6666
// Each span produced by the generator represents an ordinary code region.
6767
BcbMapping { kind: BcbMappingKind::Code(bcb), span }
@@ -88,8 +88,6 @@ pub(super) fn generate_coverage_spans(
8888

8989
#[derive(Debug)]
9090
struct CurrCovspan {
91-
/// This is used as the basis for [`PrevCovspan::original_span`], so it must
92-
/// not be modified.
9391
span: Span,
9492
bcb: BasicCoverageBlock,
9593
is_closure: bool,
@@ -102,7 +100,7 @@ impl CurrCovspan {
102100

103101
fn into_prev(self) -> PrevCovspan {
104102
let Self { span, bcb, is_closure } = self;
105-
PrevCovspan { original_span: span, span, bcb, merged_spans: vec![span], is_closure }
103+
PrevCovspan { span, bcb, merged_spans: vec![span], is_closure }
106104
}
107105

108106
fn into_refined(self) -> RefinedCovspan {
@@ -115,7 +113,6 @@ impl CurrCovspan {
115113

116114
#[derive(Debug)]
117115
struct PrevCovspan {
118-
original_span: Span,
119116
span: Span,
120117
bcb: BasicCoverageBlock,
121118
/// List of all the original spans from MIR that have been merged into this
@@ -135,42 +132,17 @@ impl PrevCovspan {
135132
self.merged_spans.push(other.span);
136133
}
137134

138-
fn cutoff_statements_at(&mut self, cutoff_pos: BytePos) {
135+
fn cutoff_statements_at(mut self, cutoff_pos: BytePos) -> Option<RefinedCovspan> {
139136
self.merged_spans.retain(|span| span.hi() <= cutoff_pos);
140137
if let Some(max_hi) = self.merged_spans.iter().map(|span| span.hi()).max() {
141138
self.span = self.span.with_hi(max_hi);
142139
}
143-
}
144-
145-
fn into_dup(self) -> DuplicateCovspan {
146-
let Self { original_span, span, bcb, merged_spans: _, is_closure } = self;
147-
// Only unmodified spans end up in `pending_dups`.
148-
debug_assert_eq!(original_span, span);
149-
DuplicateCovspan { span, bcb, is_closure }
150-
}
151-
152-
fn refined_copy(&self) -> RefinedCovspan {
153-
let &Self { original_span: _, span, bcb, merged_spans: _, is_closure } = self;
154-
RefinedCovspan { span, bcb, is_closure }
155-
}
156140

157-
fn into_refined(self) -> RefinedCovspan {
158-
self.refined_copy()
141+
if self.merged_spans.is_empty() { None } else { Some(self.into_refined()) }
159142
}
160-
}
161-
162-
#[derive(Debug)]
163-
struct DuplicateCovspan {
164-
span: Span,
165-
bcb: BasicCoverageBlock,
166-
is_closure: bool,
167-
}
168143

169-
impl DuplicateCovspan {
170-
/// Returns a copy of this covspan, as a [`RefinedCovspan`].
171-
/// Should only be called in places that would otherwise clone this covspan.
172144
fn refined_copy(&self) -> RefinedCovspan {
173-
let &Self { span, bcb, is_closure } = self;
145+
let &Self { span, bcb, merged_spans: _, is_closure } = self;
174146
RefinedCovspan { span, bcb, is_closure }
175147
}
176148

@@ -205,10 +177,7 @@ impl RefinedCovspan {
205177
/// * Merge spans that represent continuous (both in source code and control flow), non-branching
206178
/// execution
207179
/// * Carve out (leave uncovered) any span that will be counted by another MIR (notably, closures)
208-
struct SpansRefiner<'a> {
209-
/// The BasicCoverageBlock Control Flow Graph (BCB CFG).
210-
basic_coverage_blocks: &'a CoverageGraph,
211-
180+
struct SpansRefiner {
212181
/// The initial set of coverage spans, sorted by `Span` (`lo` and `hi`) and by relative
213182
/// dominance between the `BasicCoverageBlock`s of equal `Span`s.
214183
sorted_spans_iter: std::vec::IntoIter<SpanFromMir>,
@@ -223,36 +192,22 @@ struct SpansRefiner<'a> {
223192
/// If that `curr` was discarded, `prev` retains its value from the previous iteration.
224193
some_prev: Option<PrevCovspan>,
225194

226-
/// One or more coverage spans with the same `Span` but different `BasicCoverageBlock`s, and
227-
/// no `BasicCoverageBlock` in this list dominates another `BasicCoverageBlock` in the list.
228-
/// If a new `curr` span also fits this criteria (compared to an existing list of
229-
/// `pending_dups`), that `curr` moves to `prev` before possibly being added to
230-
/// the `pending_dups` list, on the next iteration. As a result, if `prev` and `pending_dups`
231-
/// have the same `Span`, the criteria for `pending_dups` holds for `prev` as well: a `prev`
232-
/// with a matching `Span` does not dominate any `pending_dup` and no `pending_dup` dominates a
233-
/// `prev` with a matching `Span`)
234-
pending_dups: Vec<DuplicateCovspan>,
235-
236195
/// The final coverage spans to add to the coverage map. A `Counter` or `Expression`
237196
/// will also be injected into the MIR for each BCB that has associated spans.
238197
refined_spans: Vec<RefinedCovspan>,
239198
}
240199

241-
impl<'a> SpansRefiner<'a> {
200+
impl SpansRefiner {
242201
/// Takes the initial list of (sorted) spans extracted from MIR, and "refines"
243202
/// them by merging compatible adjacent spans, removing redundant spans,
244203
/// and carving holes in spans when they overlap in unwanted ways.
245-
fn refine_sorted_spans(
246-
basic_coverage_blocks: &'a CoverageGraph,
247-
sorted_spans: Vec<SpanFromMir>,
248-
) -> Vec<RefinedCovspan> {
204+
fn refine_sorted_spans(sorted_spans: Vec<SpanFromMir>) -> Vec<RefinedCovspan> {
205+
let sorted_spans_len = sorted_spans.len();
249206
let this = Self {
250-
basic_coverage_blocks,
251207
sorted_spans_iter: sorted_spans.into_iter(),
252208
some_curr: None,
253209
some_prev: None,
254-
pending_dups: Vec::new(),
255-
refined_spans: Vec::with_capacity(basic_coverage_blocks.num_nodes() * 2),
210+
refined_spans: Vec::with_capacity(sorted_spans_len),
256211
};
257212

258213
this.to_refined_spans()
@@ -292,21 +247,11 @@ impl<'a> SpansRefiner<'a> {
292247
self.take_curr(); // Discards curr.
293248
} else if curr.is_closure {
294249
self.carve_out_span_for_closure();
295-
} else if prev.original_span == prev.span && prev.span == curr.span {
296-
// Prev and curr have the same span, and prev's span hasn't
297-
// been modified by other spans.
298-
self.update_pending_dups();
299250
} else {
300251
self.cutoff_prev_at_overlapping_curr();
301252
}
302253
}
303254

304-
// Drain any remaining dups into the output.
305-
for dup in self.pending_dups.drain(..) {
306-
debug!(" ...adding at least one pending dup={:?}", dup);
307-
self.refined_spans.push(dup.into_refined());
308-
}
309-
310255
// There is usually a final span remaining in `prev` after the loop ends,
311256
// so add it to the output as well.
312257
if let Some(prev) = self.some_prev.take() {
@@ -359,36 +304,6 @@ impl<'a> SpansRefiner<'a> {
359304
self.some_prev.take().unwrap_or_else(|| bug!("some_prev is None (take_prev)"))
360305
}
361306

362-
/// If there are `pending_dups` but `prev` is not a matching dup (`prev.span` doesn't match the
363-
/// `pending_dups` spans), then one of the following two things happened during the previous
364-
/// iteration:
365-
/// * the previous `curr` span (which is now `prev`) was not a duplicate of the pending_dups
366-
/// (in which case there should be at least two spans in `pending_dups`); or
367-
/// * the `span` of `prev` was modified by `curr_mut().merge_from(prev)` (in which case
368-
/// `pending_dups` could have as few as one span)
369-
/// In either case, no more spans will match the span of `pending_dups`, so
370-
/// add the `pending_dups` if they don't overlap `curr`, and clear the list.
371-
fn maybe_flush_pending_dups(&mut self) {
372-
let Some(last_dup) = self.pending_dups.last() else { return };
373-
if last_dup.span == self.prev().span {
374-
return;
375-
}
376-
377-
debug!(
378-
" SAME spans, but pending_dups are NOT THE SAME, so BCBs matched on \
379-
previous iteration, or prev started a new disjoint span"
380-
);
381-
if last_dup.span.hi() <= self.curr().span.lo() {
382-
for dup in self.pending_dups.drain(..) {
383-
debug!(" ...adding at least one pending={:?}", dup);
384-
self.refined_spans.push(dup.into_refined());
385-
}
386-
} else {
387-
self.pending_dups.clear();
388-
}
389-
assert!(self.pending_dups.is_empty());
390-
}
391-
392307
/// Advance `prev` to `curr` (if any), and `curr` to the next coverage span in sorted order.
393308
fn next_coverage_span(&mut self) -> bool {
394309
if let Some(curr) = self.some_curr.take() {
@@ -408,7 +323,6 @@ impl<'a> SpansRefiner<'a> {
408323
);
409324
} else {
410325
self.some_curr = Some(CurrCovspan::new(curr.span, curr.bcb, curr.is_closure));
411-
self.maybe_flush_pending_dups();
412326
return true;
413327
}
414328
}
@@ -433,13 +347,6 @@ impl<'a> SpansRefiner<'a> {
433347
let mut pre_closure = self.prev().refined_copy();
434348
pre_closure.span = pre_closure.span.with_hi(left_cutoff);
435349
debug!(" prev overlaps a closure. Adding span for pre_closure={:?}", pre_closure);
436-
437-
for mut dup in self.pending_dups.iter().map(DuplicateCovspan::refined_copy) {
438-
dup.span = dup.span.with_hi(left_cutoff);
439-
debug!(" ...and at least one pre_closure dup={:?}", dup);
440-
self.refined_spans.push(dup);
441-
}
442-
443350
self.refined_spans.push(pre_closure);
444351
}
445352

@@ -448,58 +355,9 @@ impl<'a> SpansRefiner<'a> {
448355
self.prev_mut().span = self.prev().span.with_lo(right_cutoff);
449356
debug!(" Mutated prev.span to start after the closure. prev={:?}", self.prev());
450357

451-
for dup in &mut self.pending_dups {
452-
debug!(" ...and at least one overlapping dup={:?}", dup);
453-
dup.span = dup.span.with_lo(right_cutoff);
454-
}
455-
456358
// Prevent this curr from becoming prev.
457359
let closure_covspan = self.take_curr().into_refined();
458360
self.refined_spans.push(closure_covspan); // since self.prev() was already updated
459-
} else {
460-
self.pending_dups.clear();
461-
}
462-
}
463-
464-
/// Called if `curr.span` equals `prev.original_span` (and potentially equal to all
465-
/// `pending_dups` spans, if any). Keep in mind, `prev.span()` may have been changed.
466-
/// If prev.span() was merged into other spans (with matching BCB, for instance),
467-
/// `prev.span.hi()` will be greater than (further right of) `prev.original_span.hi()`.
468-
/// If prev.span() was split off to the right of a closure, prev.span().lo() will be
469-
/// greater than prev.original_span.lo(). The actual span of `prev.original_span` is
470-
/// not as important as knowing that `prev()` **used to have the same span** as `curr()`,
471-
/// which means their sort order is still meaningful for determining the dominator
472-
/// relationship.
473-
///
474-
/// When two coverage spans have the same `Span`, dominated spans can be discarded; but if
475-
/// neither coverage span dominates the other, both (or possibly more than two) are held,
476-
/// until their disposition is determined. In this latter case, the `prev` dup is moved into
477-
/// `pending_dups` so the new `curr` dup can be moved to `prev` for the next iteration.
478-
fn update_pending_dups(&mut self) {
479-
let prev_bcb = self.prev().bcb;
480-
let curr_bcb = self.curr().bcb;
481-
482-
// Equal coverage spans are ordered by dominators before dominated (if any), so it should be
483-
// impossible for `curr` to dominate any previous coverage span.
484-
debug_assert!(!self.basic_coverage_blocks.dominates(curr_bcb, prev_bcb));
485-
486-
// `prev` is a duplicate of `curr`, so add it to the list of pending dups.
487-
// If it dominates `curr`, it will be removed by the subsequent discard step.
488-
let prev = self.take_prev().into_dup();
489-
debug!(?prev, "adding prev to pending dups");
490-
self.pending_dups.push(prev);
491-
492-
let initial_pending_count = self.pending_dups.len();
493-
if initial_pending_count > 0 {
494-
self.pending_dups
495-
.retain(|dup| !self.basic_coverage_blocks.dominates(dup.bcb, curr_bcb));
496-
497-
let n_discarded = initial_pending_count - self.pending_dups.len();
498-
if n_discarded > 0 {
499-
debug!(
500-
" discarded {n_discarded} of {initial_pending_count} pending_dups that dominated curr",
501-
);
502-
}
503361
}
504362
}
505363

@@ -516,19 +374,13 @@ impl<'a> SpansRefiner<'a> {
516374
if it has statements that end before curr; prev={:?}",
517375
self.prev()
518376
);
519-
if self.pending_dups.is_empty() {
520-
let curr_span = self.curr().span;
521-
self.prev_mut().cutoff_statements_at(curr_span.lo());
522-
if self.prev().merged_spans.is_empty() {
523-
debug!(" ... no non-overlapping statements to add");
524-
} else {
525-
debug!(" ... adding modified prev={:?}", self.prev());
526-
let prev = self.take_prev().into_refined();
527-
self.refined_spans.push(prev);
528-
}
377+
378+
let curr_span = self.curr().span;
379+
if let Some(prev) = self.take_prev().cutoff_statements_at(curr_span.lo()) {
380+
debug!("after cutoff, adding {prev:?}");
381+
self.refined_spans.push(prev);
529382
} else {
530-
// with `pending_dups`, `prev` cannot have any statements that don't overlap
531-
self.pending_dups.clear();
383+
debug!("prev was eliminated by cutoff");
532384
}
533385
}
534386
}

compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs

+10-5
Original file line numberDiff line numberDiff line change
@@ -52,14 +52,19 @@ pub(super) fn mir_to_initial_sorted_coverage_spans(
5252
// - Span A extends further left, or
5353
// - Both have the same start and span A extends further right
5454
.then_with(|| Ord::cmp(&a.span.hi(), &b.span.hi()).reverse())
55-
// If both spans are equal, sort the BCBs in dominator order,
56-
// so that dominating BCBs come before other BCBs they dominate.
57-
.then_with(|| basic_coverage_blocks.cmp_in_dominator_order(a.bcb, b.bcb))
58-
// If two spans are otherwise identical, put closure spans first,
59-
// as this seems to be what the refinement step expects.
55+
// If two spans have the same lo & hi, put closure spans first,
56+
// as they take precedence over non-closure spans.
6057
.then_with(|| Ord::cmp(&a.is_closure, &b.is_closure).reverse())
58+
// After deduplication, we want to keep only the most-dominated BCB.
59+
.then_with(|| basic_coverage_blocks.cmp_in_dominator_order(a.bcb, b.bcb).reverse())
6160
});
6261

62+
// Among covspans with the same span, keep only one. Closure spans take
63+
// precedence, otherwise keep the one with the most-dominated BCB.
64+
// (Ideally we should try to preserve _all_ non-dominating BCBs, but that
65+
// requires a lot more complexity in the span refiner, for little benefit.)
66+
initial_spans.dedup_by(|b, a| a.span.source_equal(b.span));
67+
6368
initial_spans
6469
}
6570

compiler/rustc_passes/src/liveness.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -526,8 +526,8 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
526526
}
527527

528528
fn define_bindings_in_pat(&mut self, pat: &hir::Pat<'_>, mut succ: LiveNode) -> LiveNode {
529-
// In an or-pattern, only consider the first pattern; any later patterns
530-
// must have the same bindings, and we also consider the first pattern
529+
// In an or-pattern, only consider the first non-never pattern; any later patterns
530+
// must have the same bindings, and we also consider that pattern
531531
// to be the "authoritative" set of ids.
532532
pat.each_binding_or_first(&mut |_, hir_id, pat_sp, ident| {
533533
let ln = self.live_node(hir_id, pat_sp);

0 commit comments

Comments
 (0)