Skip to content

Commit f6a28c2

Browse files
committed
Sort all borrowck errors within a single typeck owner together
1 parent 8b9ee86 commit f6a28c2

21 files changed

Lines changed: 351 additions & 388 deletions

compiler/rustc_borrowck/src/diagnostics/mod.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,13 @@ use tracing::debug;
3434

3535
use super::MirBorrowckCtxt;
3636
use super::borrow_set::BorrowData;
37+
use crate::LocalMutationIsAllowed;
3738
use crate::constraints::OutlivesConstraint;
3839
use crate::nll::ConstraintDescription;
3940
use crate::session_diagnostics::{
4041
CaptureArgLabel, CaptureReasonLabel, CaptureReasonNote, CaptureReasonSuggest, CaptureVarCause,
4142
CaptureVarKind, CaptureVarPathUseCause, OnClosureNote,
4243
};
43-
use crate::{BorrowCheckRootCtxt, LocalMutationIsAllowed};
4444

4545
mod find_all_local_uses;
4646
mod find_use;
@@ -120,7 +120,7 @@ impl<'diag, 'tcx> BorrowckDiagnosticsBuffer<'diag, 'tcx> {
120120
self.buffered_diags.push(BufferedDiag::Error(diag));
121121
}
122122

123-
pub(crate) fn emit_errors(&mut self, root_cx: &mut BorrowCheckRootCtxt<'diag, 'tcx>) {
123+
pub(crate) fn emit_errors(&mut self) {
124124
// Buffer any move errors that we collected and de-duplicated.
125125
for (_, (_, diag)) in std::mem::take(&mut self.buffered_move_errors) {
126126
// We have already set tainted for this error, so just buffer it.
@@ -136,7 +136,12 @@ impl<'diag, 'tcx> BorrowckDiagnosticsBuffer<'diag, 'tcx> {
136136
if !self.buffered_diags.is_empty() {
137137
self.buffered_diags.sort_by_key(|buffered_diag| buffered_diag.sort_span());
138138
for buffered_diag in self.buffered_diags.drain(..) {
139-
root_cx.buffer_error(buffered_diag);
139+
match buffered_diag {
140+
BufferedDiag::Error(diag) => {
141+
diag.emit();
142+
}
143+
BufferedDiag::NonError(diag) => diag.emit(),
144+
}
140145
}
141146
}
142147
}

compiler/rustc_borrowck/src/lib.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -394,8 +394,9 @@ fn borrowck_collect_region_constraints<'tcx>(
394394
/// Using the region constraints computed by [borrowck_collect_region_constraints]
395395
/// and the additional constraints from [BorrowCheckRootCtxt::handle_opaque_type_uses],
396396
/// compute the region graph and actually check for any borrowck errors.
397-
fn borrowck_check_region_constraints<'tcx>(
398-
root_cx: &mut BorrowCheckRootCtxt<'_, 'tcx>,
397+
fn borrowck_check_region_constraints<'diag, 'tcx>(
398+
root_cx: &mut BorrowCheckRootCtxt<'diag, 'tcx>,
399+
diags_buffer: &mut BorrowckDiagnosticsBuffer<'diag, 'tcx>,
399400
CollectRegionConstraintsResult {
400401
infcx,
401402
body_owned,
@@ -462,7 +463,6 @@ fn borrowck_check_region_constraints<'tcx>(
462463
let movable_coroutine = body.coroutine.is_some()
463464
&& tcx.coroutine_movability(def.to_def_id()) == hir::Movability::Movable;
464465

465-
let diags_buffer = &mut BorrowckDiagnosticsBuffer::default();
466466
// While promoteds should mostly be correct by construction, we need to check them for
467467
// invalid moves to detect moving out of arrays:`struct S; fn main() { &([S][0]); }`.
468468
for promoted_body in &promoted {
@@ -579,8 +579,6 @@ fn borrowck_check_region_constraints<'tcx>(
579579
used_mut_upvars: mbcx.used_mut_upvars,
580580
};
581581

582-
diags_buffer.emit_errors(root_cx);
583-
584582
if let Some(guar) = infcx.tainted_by_errors() {
585583
root_cx.set_tainted_by_errors(guar);
586584
}

compiler/rustc_borrowck/src/root_cx.rs

Lines changed: 12 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use rustc_span::ErrorGuaranteed;
1212
use smallvec::SmallVec;
1313

1414
use crate::consumers::BorrowckConsumer;
15-
use crate::diagnostics::BufferedDiag;
15+
use crate::diagnostics::BorrowckDiagnosticsBuffer;
1616
use crate::nll::compute_closure_requirements_modulo_opaques;
1717
use crate::region_infer::opaque_types::{
1818
UnexpectedHiddenRegion, apply_definition_site_hidden_types, clone_and_resolve_opaque_types,
@@ -46,7 +46,6 @@ pub(super) struct BorrowCheckRootCtxt<'diag, 'tcx: 'diag> {
4646
/// This should be `None` during normal compilation. See [`crate::consumers`] for more
4747
/// information on how this is used.
4848
pub consumer: Option<BorrowckConsumer<'tcx>>,
49-
errors: Vec<BufferedDiag<'diag>>,
5049
}
5150

5251
impl<'diag, 'tcx> BorrowCheckRootCtxt<'diag, 'tcx> {
@@ -65,7 +64,6 @@ impl<'diag, 'tcx> BorrowCheckRootCtxt<'diag, 'tcx> {
6564
propagated_borrowck_results: Default::default(),
6665
tainted_by_errors,
6766
consumer,
68-
errors: Default::default(),
6967
}
7068
}
7169

@@ -89,10 +87,9 @@ impl<'diag, 'tcx> BorrowCheckRootCtxt<'diag, 'tcx> {
8987
}
9088

9189
pub(super) fn finalize(
92-
mut self,
90+
self,
9391
) -> Result<&'tcx FxIndexMap<LocalDefId, ty::DefinitionSiteHiddenType<'tcx>>, ErrorGuaranteed>
9492
{
95-
self.emit_errors();
9693
if let Some(guar) = self.tainted_by_errors.get() {
9794
Err(guar)
9895
} else {
@@ -168,7 +165,10 @@ impl<'diag, 'tcx> BorrowCheckRootCtxt<'diag, 'tcx> {
168165
/// which don't depend on opaque types. In this case they get removed from
169166
/// `collect_region_constraints_results` and the final result gets put into
170167
/// `propagated_borrowck_results`.
171-
fn apply_closure_requirements_modulo_opaques(&mut self) {
168+
fn apply_closure_requirements_modulo_opaques(
169+
&mut self,
170+
diags_buffer: &mut BorrowckDiagnosticsBuffer<'diag, 'tcx>,
171+
) {
172172
let mut closure_requirements_modulo_opaques = FxHashMap::default();
173173
// We need to `mem::take` both `self.collect_region_constraints_results` and
174174
// `input.deferred_closure_requirements` as we otherwise can't iterate over
@@ -226,7 +226,7 @@ impl<'diag, 'tcx> BorrowCheckRootCtxt<'diag, 'tcx> {
226226
self.collect_region_constraints_results.insert(def_id, input);
227227
} else {
228228
assert!(input.deferred_closure_requirements.is_empty());
229-
let result = borrowck_check_region_constraints(self, input);
229+
let result = borrowck_check_region_constraints(self, diags_buffer, input);
230230
self.propagated_borrowck_results.insert(def_id, result);
231231
}
232232
}
@@ -281,14 +281,16 @@ impl<'diag, 'tcx> BorrowCheckRootCtxt<'diag, 'tcx> {
281281
self.collect_region_constraints_results.insert(def_id, result);
282282
}
283283

284+
let diags_buffer = &mut BorrowckDiagnosticsBuffer::default();
285+
284286
// We now apply the closure requirements of nested bodies modulo
285287
// opaques. In case a body does not depend on opaque types, we
286288
// eagerly check its region constraints and use the final closure
287289
// requirements.
288290
//
289291
// We eagerly finish borrowck for bodies which don't depend on
290292
// opaques.
291-
self.apply_closure_requirements_modulo_opaques();
293+
self.apply_closure_requirements_modulo_opaques(diags_buffer);
292294

293295
// We handle opaque type uses for all bodies together.
294296
self.handle_opaque_type_uses();
@@ -314,32 +316,9 @@ impl<'diag, 'tcx> BorrowCheckRootCtxt<'diag, 'tcx> {
314316
);
315317
}
316318

317-
let result = borrowck_check_region_constraints(self, input);
319+
let result = borrowck_check_region_constraints(self, diags_buffer, input);
318320
self.propagated_borrowck_results.insert(def_id, result);
319321
}
320-
}
321-
322-
pub(crate) fn buffer_error(&mut self, buffered_diag: BufferedDiag<'_>) {
323-
match buffered_diag {
324-
BufferedDiag::Error(diag) => {
325-
let diag = diag.with_dcx(self.dcx());
326-
self.errors.push(BufferedDiag::Error(diag));
327-
}
328-
BufferedDiag::NonError(diag) => {
329-
let diag = diag.with_dcx(self.dcx());
330-
self.errors.push(BufferedDiag::NonError(diag));
331-
}
332-
}
333-
}
334-
335-
pub(crate) fn emit_errors(&mut self) {
336-
for buffered_diag in self.errors.drain(..) {
337-
match buffered_diag {
338-
BufferedDiag::Error(diag) => {
339-
diag.emit();
340-
}
341-
BufferedDiag::NonError(diag) => diag.emit(),
342-
}
343-
}
322+
diags_buffer.emit_errors();
344323
}
345324
}

tests/ui/async-await/issue-74072-lifetime-name-annotations.stderr

Lines changed: 44 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,23 @@ LL | *x += 1;
1010
LL | y
1111
| - returning this value requires that `*x` is borrowed for `'1`
1212

13-
error[E0506]: cannot assign to `*x` because it is borrowed
14-
--> $DIR/issue-74072-lifetime-name-annotations.rs:17:9
13+
error[E0716]: temporary value dropped while borrowed
14+
--> $DIR/issue-74072-lifetime-name-annotations.rs:13:5
1515
|
16-
LL | (async move || {
17-
| - return type of async closure is &'1 i32
18-
...
19-
LL | let y = &*x;
20-
| --- `*x` is borrowed here
21-
LL | *x += 1;
22-
| ^^^^^^^ `*x` is assigned to here but it was already borrowed
23-
LL | y
24-
| - returning this value requires that `*x` is borrowed for `'1`
16+
LL | pub fn async_closure(x: &mut i32) -> impl Future<Output=&i32> {
17+
| - let's call the lifetime of this reference `'1`
18+
LL | // (async move || {
19+
LL | ||
20+
LL | ||
21+
LL | || let y = &*x;
22+
LL | || *x += 1;
23+
LL | || y
24+
LL | || })()
25+
| ||______^_- argument requires that borrow lasts for `'1`
26+
| |_______|
27+
| creates a temporary value which is freed while still in use
28+
LL | }
29+
| - temporary value is freed at the end of this statement
2530

2631
error: lifetime may not live long enough
2732
--> $DIR/issue-74072-lifetime-name-annotations.rs:13:20
@@ -41,12 +46,25 @@ LL | | })()
4146
|
4247
= note: closure implements `AsyncFnMut`, so references to captured variables can't escape the closure
4348

49+
error[E0506]: cannot assign to `*x` because it is borrowed
50+
--> $DIR/issue-74072-lifetime-name-annotations.rs:17:9
51+
|
52+
LL | (async move || {
53+
| - return type of async closure is &'1 i32
54+
...
55+
LL | let y = &*x;
56+
| --- `*x` is borrowed here
57+
LL | *x += 1;
58+
| ^^^^^^^ `*x` is assigned to here but it was already borrowed
59+
LL | y
60+
| - returning this value requires that `*x` is borrowed for `'1`
61+
4462
error[E0716]: temporary value dropped while borrowed
45-
--> $DIR/issue-74072-lifetime-name-annotations.rs:13:5
63+
--> $DIR/issue-74072-lifetime-name-annotations.rs:23:5
4664
|
47-
LL | pub fn async_closure(x: &mut i32) -> impl Future<Output=&i32> {
48-
| - let's call the lifetime of this reference `'1`
49-
LL | // (async move || {
65+
LL | pub fn async_closure_explicit_return_type(x: &mut i32) -> impl Future<Output=&i32> {
66+
| - let's call the lifetime of this reference `'1`
67+
LL | // (async move || -> &i32 {
5068
LL | ||
5169
LL | ||
5270
LL | || let y = &*x;
@@ -59,19 +77,6 @@ LL | || })()
5977
LL | }
6078
| - temporary value is freed at the end of this statement
6179

62-
error[E0506]: cannot assign to `*x` because it is borrowed
63-
--> $DIR/issue-74072-lifetime-name-annotations.rs:27:9
64-
|
65-
LL | (async move || -> &i32 {
66-
| - return type of async closure is &'1 i32
67-
...
68-
LL | let y = &*x;
69-
| --- `*x` is borrowed here
70-
LL | *x += 1;
71-
| ^^^^^^^ `*x` is assigned to here but it was already borrowed
72-
LL | y
73-
| - returning this value requires that `*x` is borrowed for `'1`
74-
7580
error: lifetime may not live long enough
7681
--> $DIR/issue-74072-lifetime-name-annotations.rs:23:28
7782
|
@@ -90,23 +95,18 @@ LL | | })()
9095
|
9196
= note: closure implements `AsyncFnMut`, so references to captured variables can't escape the closure
9297

93-
error[E0716]: temporary value dropped while borrowed
94-
--> $DIR/issue-74072-lifetime-name-annotations.rs:23:5
98+
error[E0506]: cannot assign to `*x` because it is borrowed
99+
--> $DIR/issue-74072-lifetime-name-annotations.rs:27:9
95100
|
96-
LL | pub fn async_closure_explicit_return_type(x: &mut i32) -> impl Future<Output=&i32> {
97-
| - let's call the lifetime of this reference `'1`
98-
LL | // (async move || -> &i32 {
99-
LL | ||
100-
LL | ||
101-
LL | || let y = &*x;
102-
LL | || *x += 1;
103-
LL | || y
104-
LL | || })()
105-
| ||______^_- argument requires that borrow lasts for `'1`
106-
| |_______|
107-
| creates a temporary value which is freed while still in use
108-
LL | }
109-
| - temporary value is freed at the end of this statement
101+
LL | (async move || -> &i32 {
102+
| - return type of async closure is &'1 i32
103+
...
104+
LL | let y = &*x;
105+
| --- `*x` is borrowed here
106+
LL | *x += 1;
107+
| ^^^^^^^ `*x` is assigned to here but it was already borrowed
108+
LL | y
109+
| - returning this value requires that `*x` is borrowed for `'1`
110110

111111
error[E0506]: cannot assign to `*x` because it is borrowed
112112
--> $DIR/issue-74072-lifetime-name-annotations.rs:35:9

tests/ui/async-await/issues/issue-62097.stderr

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,17 @@
1+
error[E0521]: borrowed data escapes outside of method
2+
--> $DIR/issue-62097.rs:13:9
3+
|
4+
LL | pub async fn run_dummy_fn(&self) {
5+
| -----
6+
| |
7+
| `self` is a reference that is only valid in the method body
8+
| let's call the lifetime of this reference `'1`
9+
LL | foo(|| self.bar()).await;
10+
| ^^^^^^^^^^^^^^^^^^
11+
| |
12+
| `self` escapes the method body here
13+
| argument requires that `'1` must outlive `'static`
14+
115
error[E0373]: closure may outlive the current function, but it borrows `self`, which is owned by the current function
216
--> $DIR/issue-62097.rs:13:13
317
|
@@ -16,20 +30,6 @@ help: to force the closure to take ownership of `self` (and any other referenced
1630
LL | foo(move || self.bar()).await;
1731
| ++++
1832

19-
error[E0521]: borrowed data escapes outside of method
20-
--> $DIR/issue-62097.rs:13:9
21-
|
22-
LL | pub async fn run_dummy_fn(&self) {
23-
| -----
24-
| |
25-
| `self` is a reference that is only valid in the method body
26-
| let's call the lifetime of this reference `'1`
27-
LL | foo(|| self.bar()).await;
28-
| ^^^^^^^^^^^^^^^^^^
29-
| |
30-
| `self` escapes the method body here
31-
| argument requires that `'1` must outlive `'static`
32-
3333
error: aborting due to 2 previous errors
3434

3535
Some errors have detailed explanations: E0373, E0521.

tests/ui/borrowck/borrowck-closures-mut-of-imm.stderr

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,6 @@ error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference
44
LL | let mut c1 = || set(&mut *x);
55
| ^^^^^^^ cannot borrow as mutable
66

7-
error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference
8-
--> $DIR/borrowck-closures-mut-of-imm.rs:12:25
9-
|
10-
LL | let mut c2 = || set(&mut *x);
11-
| ^^^^^^^ cannot borrow as mutable
12-
137
error[E0524]: two closures require unique access to `x` at the same time
148
--> $DIR/borrowck-closures-mut-of-imm.rs:12:18
159
|
@@ -26,6 +20,12 @@ LL | let mut c2 = || set(&mut *x);
2620
LL | c2(); c1();
2721
| -- first borrow later used here
2822

23+
error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference
24+
--> $DIR/borrowck-closures-mut-of-imm.rs:12:25
25+
|
26+
LL | let mut c2 = || set(&mut *x);
27+
| ^^^^^^^ cannot borrow as mutable
28+
2929
error: aborting due to 3 previous errors
3030

3131
Some errors have detailed explanations: E0524, E0596.

0 commit comments

Comments
 (0)