Skip to content

Commit 23078c8

Browse files
committed
Auto merge of #158094 - JonathanBrouwer:rollup-n0CyzLh, r=JonathanBrouwer
Rollup of 6 pull requests Successful merges: - #158026 (`RegionValues`: disable unnecessary range check) - #156795 (Handle generic reborrow in expression-use adjustment walking) - #157694 (Enhance documentation on wake call memory ordering) - #158034 (Fix reborrow source expression visits) - #158074 (Document transient connection errors from TcpListener::accept) - #158086 (renovate: Loosen dashboard approval and adopt recommended config)
2 parents c55fad5 + 701e622 commit 23078c8

12 files changed

Lines changed: 200 additions & 40 deletions

File tree

.github/renovate.json5

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,25 @@
11
{
22
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
33
"extends": [
4+
"config:recommended",
5+
// Open a PR to migrate the config when Renovate deprecates syntax
6+
":configMigration",
7+
// Refresh lock files on the first day of each month
8+
// (still gated by dashboard approval for now)
9+
":maintainLockFilesMonthly",
410
// Pin GitHub Actions to their commit SHA digests, resolving floating tags
511
// (e.g. `v4`) to the full SemVer version (e.g. `v4.1.2`)
612
"helpers:pinGitHubActionDigestsToSemver"
713
],
8-
// Let Renovatebot keep an opened issue that tracks our dependencies
9-
"dependencyDashboard": true,
1014
// Require manual approval from the Dependency Dashboard before opening PRs
1115
"dependencyDashboardApproval": true,
16+
"packageRules": [
17+
{
18+
// No dashboard approval necessary for GitHub Actions updates
19+
"matchManagers": ["github-actions"],
20+
"dependencyDashboardApproval": false
21+
}
22+
],
1223
// Don't manage dependencies inside subtrees. They are updated upstream and
1324
// synced in. See `src/doc/rustc-dev-guide/src/external-repos.md` for the list.
1425
"ignorePaths": [

compiler/rustc_borrowck/src/region_infer/values.rs

Lines changed: 20 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use rustc_middle::bug;
99
use rustc_middle::mir::{BasicBlock, Location};
1010
use rustc_middle::ty::{self, RegionVid};
1111
use rustc_mir_dataflow::points::{DenseLocationMap, PointIndex};
12-
use tracing::debug;
12+
use tracing::{debug, instrument};
1313

1414
use crate::BorrowIndex;
1515
use crate::polonius::LiveLoans;
@@ -116,37 +116,43 @@ impl LivenessValues {
116116
/// Records `region` as being live at the given `location`.
117117
pub(crate) fn add_location(&mut self, region: RegionVid, location: Location) {
118118
let point = self.location_map.point_from_location(location);
119+
// This is a debug assert despite being cheap because it drops
120+
// the current `point_in_range()` uses to 0 when debugging is off.
121+
debug_assert!(
122+
self.location_map.point_in_range(point),
123+
"Tried inserting region {region:?} whose location {location:?} does not belong to this body!"
124+
);
119125
debug!("LivenessValues::add_location(region={:?}, location={:?})", region, location);
120126
match &mut self.live_regions {
121127
LiveRegions::AtPoints(points) => {
122128
points.insert(region, point);
123129
}
124130

125-
LiveRegions::InBody(live_regions) if self.location_map.point_in_range(point) => {
131+
LiveRegions::InBody(live_regions) => {
126132
live_regions.insert(region);
127133
}
128-
129-
LiveRegions::InBody(_) => (),
130134
};
131135
}
132136

133137
/// Records `region` as being live at all the given `points`.
134138
pub(crate) fn add_points(&mut self, region: RegionVid, points: &IntervalSet<PointIndex>) {
139+
debug_assert!(
140+
points.iter().all(|point| self.location_map.point_in_range(point)),
141+
"Tried inserting region {region:?} with some points not belonging to this body!"
142+
);
135143
debug!("LivenessValues::add_points(region={:?}, points={:?})", region, points);
136144
match &mut self.live_regions {
137145
LiveRegions::AtPoints(these_points) => {
138146
these_points.union_row(region, points);
139147
}
140-
LiveRegions::InBody(live_regions)
141-
if points.iter().any(|point| self.location_map.point_in_range(point)) =>
142-
{
148+
LiveRegions::InBody(live_regions) => {
143149
live_regions.insert(region);
144150
}
145-
LiveRegions::InBody(_) => (),
146151
};
147152
}
148153

149154
/// Records `region` as being live at all the control-flow points.
155+
#[instrument(skip(self))]
150156
pub(crate) fn add_all_points(&mut self, region: RegionVid) {
151157
match &mut self.live_regions {
152158
LiveRegions::AtPoints(points) => points.insert_all_into_row(region),
@@ -172,10 +178,7 @@ impl LivenessValues {
172178

173179
/// Returns an iterator of all the points where `region` is live.
174180
fn live_points(&self, region: RegionVid) -> impl Iterator<Item = PointIndex> {
175-
self.point_liveness(region)
176-
.into_iter()
177-
.flat_map(|set| set.iter())
178-
.take_while(|&p| self.location_map.point_in_range(p))
181+
self.point_liveness(region).into_iter().flat_map(|set| set.iter())
179182
}
180183

181184
/// For debugging purposes, returns a pretty-printed string of the points where the `region` is
@@ -343,11 +346,10 @@ impl<'tcx, N: Idx> RegionValues<'tcx, N> {
343346

344347
/// Returns the locations contained within a given region `r`.
345348
pub(crate) fn locations_outlived_by(&self, r: N) -> impl Iterator<Item = Location> {
346-
self.points.row(r).into_iter().flat_map(move |set| {
347-
set.iter()
348-
.take_while(move |&p| self.location_map.point_in_range(p))
349-
.map(move |p| self.location_map.to_location(p))
350-
})
349+
self.points
350+
.row(r)
351+
.into_iter()
352+
.flat_map(move |set| set.iter().map(move |p| self.location_map.to_location(p)))
351353
}
352354

353355
/// Returns just the universal regions that are contained in a given region's value.
@@ -413,11 +415,7 @@ pub(crate) fn pretty_print_points(
413415
points: impl IntoIterator<Item = PointIndex>,
414416
) -> String {
415417
pretty_print_region_elements(
416-
points
417-
.into_iter()
418-
.take_while(|&p| location_map.point_in_range(p))
419-
.map(|p| location_map.to_location(p))
420-
.map(RegionElement::Location),
418+
points.into_iter().map(|p| location_map.to_location(p)).map(RegionElement::Location),
421419
)
422420
}
423421

compiler/rustc_hir_typeck/src/expr_use_visitor.rs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -727,7 +727,8 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
727727
let typeck_results = self.cx.typeck_results();
728728
let adjustments = typeck_results.expr_adjustments(expr);
729729
let mut place_with_id = self.cat_expr_unadjusted(expr)?;
730-
for adjustment in adjustments {
730+
for (adjustment_index, adjustment) in adjustments.iter().enumerate() {
731+
let is_last_adjustment = adjustment_index + 1 == adjustments.len();
731732
debug!("walk_adjustment expr={:?} adj={:?}", expr, adjustment);
732733
match adjustment.kind {
733734
adjustment::Adjust::NeverToAny | adjustment::Adjust::Pointer(_) => {
@@ -752,13 +753,13 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
752753
self.walk_autoref(expr, &place_with_id, autoref);
753754
}
754755

755-
adjustment::Adjust::GenericReborrow(_reborrow) => {
756-
// To build an expression as a place expression, it needs to be a field
757-
// projection or deref at the outmost layer. So it is field projection or deref
758-
// on an adjusted value. But this means that adjustment is applied on a
759-
// subexpression that is not the final operand/rvalue for function call or
760-
// assignment. This is a contradiction.
761-
unreachable!("Reborrow trait usage during adjustment walk");
756+
adjustment::Adjust::GenericReborrow(mutability) if is_last_adjustment => {
757+
let bk = ty::BorrowKind::from_mutbl(mutability);
758+
self.delegate.borrow_mut().borrow(&place_with_id, place_with_id.hir_id, bk);
759+
}
760+
761+
adjustment::Adjust::GenericReborrow(_) => {
762+
span_bug!(expr.span, "generic reborrow adjustment must be terminal");
762763
}
763764
}
764765
place_with_id = self.cat_expr_adjusted(expr, place_with_id, adjustment)?;

compiler/rustc_middle/src/thir/visit.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,9 @@ pub fn walk_expr<'thir, 'tcx: 'thir, V: Visitor<'thir, 'tcx>>(
187187
}
188188
ThreadLocalRef(_) => {}
189189
Yield { value } => visitor.visit_expr(&visitor.thir()[value]),
190-
Reborrow { .. } => {}
190+
Reborrow { source, mutability: _, target: _ } => {
191+
visitor.visit_expr(&visitor.thir()[source])
192+
}
191193
}
192194
}
193195

compiler/rustc_mir_dataflow/src/points.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ impl DenseLocationMap {
3131
for (bb, bb_data) in body.basic_blocks.iter_enumerated() {
3232
basic_blocks.extend((0..=bb_data.statements.len()).map(|_| bb));
3333
}
34-
34+
// Invariant: no block is preceded by more than all statements.
35+
debug_assert!(*statements_before_block.iter().max().unwrap() < num_points);
3536
Self { statements_before_block, basic_blocks, num_points }
3637
}
3738

@@ -42,10 +43,14 @@ impl DenseLocationMap {
4243
}
4344

4445
/// Converts a `Location` into a `PointIndex`. O(1).
46+
/// [[`Self::point_in_range()`]] guaranteed for the returned index.
4547
#[inline]
4648
pub fn point_from_location(&self, location: Location) -> PointIndex {
4749
let Location { block, statement_index } = location;
4850
let start_index = self.statements_before_block[block];
51+
// Note the invariant in [`Self::new()`]; if the indexing
52+
// operation above did not panic then this holds by construction.
53+
debug_assert!(start_index < self.num_points);
4954
PointIndex::new(start_index + statement_index)
5055
}
5156

library/alloc/src/task.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@ use crate::sync::Arc;
3737
/// link ../../std/task/struct.Waker.html#impl-From%3CArc%3CW,+Global%3E%3E-for-Waker
3838
/// without getting a link-checking error in CI. -->
3939
///
40+
/// # Memory Ordering
41+
///
42+
/// To avoid missed wakeups, all executors must adhere to the requirement described for [`Waker::wake`].
43+
///
4044
/// # Examples
4145
///
4246
/// A basic `block_on` function that takes a future and runs it to completion on

library/core/src/task/wake.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -418,15 +418,16 @@ unsafe impl Sync for Waker {}
418418
impl Waker {
419419
/// Wakes up the task associated with this `Waker`.
420420
///
421-
/// As long as the executor keeps running and the task is not finished, it is
422-
/// guaranteed that each invocation of [`wake()`](Self::wake) (or
421+
/// As long as the executor keeps running and the task is not finished,
422+
/// it is guaranteed that each invocation of [`wake()`](Self::wake) (or
423423
/// [`wake_by_ref()`](Self::wake_by_ref)) will be followed by at least one
424-
/// [`poll()`] of the task to which this `Waker` belongs. This makes
425-
/// it possible to temporarily yield to other tasks while running potentially
426-
/// unbounded processing loops.
424+
/// [`poll()`] of the task to which this `Waker` belongs, such that the call to
425+
/// [`wake()`](Self::wake) (or [`wake_by_ref()`](Self::wake_by_ref)) _happens-before_
426+
/// the beginning of the invocation of [`poll()`]. This makes it possible to temporarily
427+
/// yield to other tasks while running potentially unbounded processing loops.
427428
///
428429
/// Note that the above implies that multiple wake-ups may be coalesced into a
429-
/// single [`poll()`] invocation by the runtime.
430+
/// single [`poll()`] invocation by the executor.
430431
///
431432
/// Also note that yielding to competing tasks is not guaranteed: it is the
432433
/// executor’s choice which task to run and the executor may choose to run the

library/std/src/net/tcp.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -876,6 +876,29 @@ impl TcpListener {
876876
/// is established. When established, the corresponding [`TcpStream`] and the
877877
/// remote peer's address will be returned.
878878
///
879+
/// # Errors
880+
///
881+
/// Some errors this function returns do not indicate a problem with the
882+
/// listener itself, and a program serving a long-lived listener will
883+
/// usually want to handle them and keep accepting connections rather than
884+
/// treat them as fatal. These include, but are not limited to:
885+
///
886+
/// - An error specific to a single incoming connection that failed before
887+
/// it could be accepted, such as one aborted by the peer
888+
/// ([`ConnectionAborted`]). A later call may succeed immediately.
889+
/// - An error from reaching the per-process or system-wide open file
890+
/// descriptor limit. The call can be retried once other file descriptors
891+
/// have been closed, typically after a short delay.
892+
/// - An error from failing to allocate memory while accepting a connection
893+
/// ([`OutOfMemory`]).
894+
///
895+
/// Which errors can occur is platform-specific. On Unix, [`Interrupted`]
896+
/// errors are retried internally rather than being returned.
897+
///
898+
/// [`ConnectionAborted`]: io::ErrorKind::ConnectionAborted
899+
/// [`OutOfMemory`]: io::ErrorKind::OutOfMemory
900+
/// [`Interrupted`]: io::ErrorKind::Interrupted
901+
///
879902
/// # Examples
880903
///
881904
/// ```no_run
@@ -902,6 +925,11 @@ impl TcpListener {
902925
/// the peer's [`SocketAddr`] structure. Iterating over it is equivalent to
903926
/// calling [`TcpListener::accept`] in a loop.
904927
///
928+
/// # Errors
929+
///
930+
/// Each connection yielded by the iterator can fail for the same reasons as
931+
/// [`TcpListener::accept`]; see its documentation for details.
932+
///
905933
/// # Examples
906934
///
907935
/// ```no_run
@@ -937,6 +965,11 @@ impl TcpListener {
937965
/// the peer's [`SocketAddr`] structure. Iterating over it is equivalent to
938966
/// calling [`TcpListener::accept`] in a loop.
939967
///
968+
/// # Errors
969+
///
970+
/// Each connection yielded by the iterator can fail for the same reasons as
971+
/// [`TcpListener::accept`]; see its documentation for details.
972+
///
940973
/// # Examples
941974
///
942975
/// ```no_run
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
//@ check-pass
2+
3+
#![feature(reborrow)]
4+
5+
use std::marker::{CoerceShared, Reborrow};
6+
7+
#[allow(unused)]
8+
struct CustomMut<'a, T>(&'a mut T);
9+
impl<'a, T> Reborrow for CustomMut<'a, T> {}
10+
impl<'a, T> CoerceShared<CustomRef<'a, T>> for CustomMut<'a, T> {}
11+
12+
#[allow(unused)]
13+
struct CustomRef<'a, T>(&'a T);
14+
impl<'a, T> Clone for CustomRef<'a, T> {
15+
fn clone(&self) -> Self {
16+
Self(self.0)
17+
}
18+
}
19+
impl<'a, T> Copy for CustomRef<'a, T> {}
20+
21+
fn takes_mut(_: CustomMut<'_, ()>) {}
22+
fn takes_shared(_: CustomRef<'_, ()>) {}
23+
24+
fn main() {
25+
let a = CustomMut(&mut ());
26+
27+
let mut f = || {
28+
takes_mut(a);
29+
takes_shared(a);
30+
};
31+
32+
f();
33+
f();
34+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
//@ check-pass
2+
3+
#![feature(reborrow)]
4+
5+
use std::marker::{CoerceShared, Reborrow};
6+
7+
#[allow(unused)]
8+
struct CustomMut<'a, T>(&'a mut T);
9+
impl<'a, T> Reborrow for CustomMut<'a, T> {}
10+
impl<'a, T> CoerceShared<CustomRef<'a, T>> for CustomMut<'a, T> {}
11+
12+
#[allow(unused)]
13+
struct CustomRef<'a, T>(&'a T);
14+
impl<'a, T> Clone for CustomRef<'a, T> {
15+
fn clone(&self) -> Self {
16+
Self(self.0)
17+
}
18+
}
19+
impl<'a, T> Copy for CustomRef<'a, T> {}
20+
21+
fn takes_mut(_: CustomMut<'_, ()>) {}
22+
fn takes_shared(_: CustomRef<'_, ()>) {}
23+
24+
fn main() {
25+
let a = CustomMut(&mut ());
26+
27+
takes_mut(a);
28+
takes_mut(a);
29+
30+
takes_shared(a);
31+
takes_shared(a);
32+
}

0 commit comments

Comments
 (0)