Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit a11eb4f

Browse files
committedJan 13, 2023
Auto merge of #106822 - matthiaskrgr:rollup-46bi4pi, r=matthiaskrgr
Rollup of 10 pull requests Successful merges: - #104645 (Add log-backtrace option to show backtraces along with logging) - #106465 (Bump `IMPLIED_BOUNDS_ENTAILMENT` to Deny + ReportNow) - #106489 (Fix linker detection for linker (drivers) with a version postfix (e.g. clang-12 instead of clang)) - #106585 (When suggesting writing a fully qualified path probe for appropriate types) - #106641 (Provide help on closures capturing self causing borrow checker errors) - #106678 (Warn when using panic-strategy abort for proc-macro crates) - #106701 (Fix `mpsc::SyncSender` spinning behavior) - #106793 (Normalize test output more thoroughly) - #106797 (riscv: Fix ELF header flags) - #106813 (Remove redundant session field) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
2 parents 0b90256 + f709382 commit a11eb4f

File tree

58 files changed

+1011
-165
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+1011
-165
lines changed
 

‎Cargo.lock

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4273,6 +4273,7 @@ version = "0.0.0"
42734273
dependencies = [
42744274
"rustc_span",
42754275
"tracing",
4276+
"tracing-core",
42764277
"tracing-subscriber",
42774278
"tracing-tree",
42784279
]

‎compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs

Lines changed: 144 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use rustc_errors::{
66
struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan,
77
};
88
use rustc_hir as hir;
9+
use rustc_hir::def::Res;
910
use rustc_hir::intravisit::{walk_block, walk_expr, Visitor};
1011
use rustc_hir::{AsyncGeneratorKind, GeneratorKind, LangItem};
1112
use rustc_infer::infer::TyCtxtInferExt;
@@ -20,7 +21,7 @@ use rustc_middle::ty::{self, suggest_constraining_type_params, PredicateKind, Ty
2021
use rustc_mir_dataflow::move_paths::{InitKind, MoveOutIndex, MovePathIndex};
2122
use rustc_span::def_id::LocalDefId;
2223
use rustc_span::hygiene::DesugaringKind;
23-
use rustc_span::symbol::sym;
24+
use rustc_span::symbol::{kw, sym};
2425
use rustc_span::{BytePos, Span, Symbol};
2526
use rustc_trait_selection::infer::InferCtxtExt;
2627

@@ -29,6 +30,7 @@ use crate::borrowck_errors;
2930

3031
use crate::diagnostics::conflict_errors::StorageDeadOrDrop::LocalStorageDead;
3132
use crate::diagnostics::find_all_local_uses;
33+
use crate::diagnostics::mutability_errors::mut_borrow_of_mutable_ref;
3234
use crate::{
3335
borrow_set::BorrowData, diagnostics::Instance, prefixes::IsPrefixOf,
3436
InitializationRequiringAction, MirBorrowckCtxt, PrefixSet, WriteKind,
@@ -356,7 +358,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
356358
if let Some(hir::Node::Item(hir::Item {
357359
kind: hir::ItemKind::Fn(_, _, body_id),
358360
..
359-
})) = hir.find(hir.local_def_id_to_hir_id(self.mir_def_id()))
361+
})) = hir.find(self.mir_hir_id())
360362
&& let Some(hir::Node::Expr(expr)) = hir.find(body_id.hir_id)
361363
{
362364
let place = &self.move_data.move_paths[mpi].place;
@@ -948,7 +950,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
948950
}
949951
(BorrowKind::Mut { .. }, BorrowKind::Shared) => {
950952
first_borrow_desc = "immutable ";
951-
self.cannot_reborrow_already_borrowed(
953+
let mut err = self.cannot_reborrow_already_borrowed(
952954
span,
953955
&desc_place,
954956
&msg_place,
@@ -958,7 +960,13 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
958960
"immutable",
959961
&msg_borrow,
960962
None,
961-
)
963+
);
964+
self.suggest_binding_for_closure_capture_self(
965+
&mut err,
966+
issued_borrow.borrowed_place,
967+
&issued_spans,
968+
);
969+
err
962970
}
963971

964972
(BorrowKind::Mut { .. }, BorrowKind::Mut { .. }) => {
@@ -1240,6 +1248,138 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
12401248
}
12411249
}
12421250

1251+
fn suggest_binding_for_closure_capture_self(
1252+
&self,
1253+
err: &mut Diagnostic,
1254+
borrowed_place: Place<'tcx>,
1255+
issued_spans: &UseSpans<'tcx>,
1256+
) {
1257+
let UseSpans::ClosureUse { capture_kind_span, .. } = issued_spans else { return };
1258+
let hir = self.infcx.tcx.hir();
1259+
1260+
// check whether the borrowed place is capturing `self` by mut reference
1261+
let local = borrowed_place.local;
1262+
let Some(_) = self
1263+
.body
1264+
.local_decls
1265+
.get(local)
1266+
.map(|l| mut_borrow_of_mutable_ref(l, self.local_names[local])) else { return };
1267+
1268+
struct ExpressionFinder<'hir> {
1269+
capture_span: Span,
1270+
closure_change_spans: Vec<Span>,
1271+
closure_arg_span: Option<Span>,
1272+
in_closure: bool,
1273+
suggest_arg: String,
1274+
hir: rustc_middle::hir::map::Map<'hir>,
1275+
closure_local_id: Option<hir::HirId>,
1276+
closure_call_changes: Vec<(Span, String)>,
1277+
}
1278+
impl<'hir> Visitor<'hir> for ExpressionFinder<'hir> {
1279+
fn visit_expr(&mut self, e: &'hir hir::Expr<'hir>) {
1280+
if e.span.contains(self.capture_span) {
1281+
if let hir::ExprKind::Closure(&hir::Closure {
1282+
movability: None,
1283+
body,
1284+
fn_arg_span,
1285+
fn_decl: hir::FnDecl{ inputs, .. },
1286+
..
1287+
}) = e.kind &&
1288+
let Some(hir::Node::Expr(body )) = self.hir.find(body.hir_id) {
1289+
self.suggest_arg = "this: &Self".to_string();
1290+
if inputs.len() > 0 {
1291+
self.suggest_arg.push_str(", ");
1292+
}
1293+
self.in_closure = true;
1294+
self.closure_arg_span = fn_arg_span;
1295+
self.visit_expr(body);
1296+
self.in_closure = false;
1297+
}
1298+
}
1299+
if let hir::Expr { kind: hir::ExprKind::Path(path), .. } = e {
1300+
if let hir::QPath::Resolved(_, hir::Path { segments: [seg], ..}) = path &&
1301+
seg.ident.name == kw::SelfLower && self.in_closure {
1302+
self.closure_change_spans.push(e.span);
1303+
}
1304+
}
1305+
hir::intravisit::walk_expr(self, e);
1306+
}
1307+
1308+
fn visit_local(&mut self, local: &'hir hir::Local<'hir>) {
1309+
if let hir::Pat { kind: hir::PatKind::Binding(_, hir_id, _ident, _), .. } = local.pat &&
1310+
let Some(init) = local.init
1311+
{
1312+
if let hir::Expr { kind: hir::ExprKind::Closure(&hir::Closure {
1313+
movability: None,
1314+
..
1315+
}), .. } = init &&
1316+
init.span.contains(self.capture_span) {
1317+
self.closure_local_id = Some(*hir_id);
1318+
}
1319+
}
1320+
hir::intravisit::walk_local(self, local);
1321+
}
1322+
1323+
fn visit_stmt(&mut self, s: &'hir hir::Stmt<'hir>) {
1324+
if let hir::StmtKind::Semi(e) = s.kind &&
1325+
let hir::ExprKind::Call(hir::Expr { kind: hir::ExprKind::Path(path), ..}, args) = e.kind &&
1326+
let hir::QPath::Resolved(_, hir::Path { segments: [seg], ..}) = path &&
1327+
let Res::Local(hir_id) = seg.res &&
1328+
Some(hir_id) == self.closure_local_id {
1329+
let (span, arg_str) = if args.len() > 0 {
1330+
(args[0].span.shrink_to_lo(), "self, ".to_string())
1331+
} else {
1332+
let span = e.span.trim_start(seg.ident.span).unwrap_or(e.span);
1333+
(span, "(self)".to_string())
1334+
};
1335+
self.closure_call_changes.push((span, arg_str));
1336+
}
1337+
hir::intravisit::walk_stmt(self, s);
1338+
}
1339+
}
1340+
1341+
if let Some(hir::Node::ImplItem(
1342+
hir::ImplItem { kind: hir::ImplItemKind::Fn(_fn_sig, body_id), .. }
1343+
)) = hir.find(self.mir_hir_id()) &&
1344+
let Some(hir::Node::Expr(expr)) = hir.find(body_id.hir_id) {
1345+
let mut finder = ExpressionFinder {
1346+
capture_span: *capture_kind_span,
1347+
closure_change_spans: vec![],
1348+
closure_arg_span: None,
1349+
in_closure: false,
1350+
suggest_arg: String::new(),
1351+
closure_local_id: None,
1352+
closure_call_changes: vec![],
1353+
hir,
1354+
};
1355+
finder.visit_expr(expr);
1356+
1357+
if finder.closure_change_spans.is_empty() || finder.closure_call_changes.is_empty() {
1358+
return;
1359+
}
1360+
1361+
let mut sugg = vec![];
1362+
let sm = self.infcx.tcx.sess.source_map();
1363+
1364+
if let Some(span) = finder.closure_arg_span {
1365+
sugg.push((sm.next_point(span.shrink_to_lo()).shrink_to_hi(), finder.suggest_arg));
1366+
}
1367+
for span in finder.closure_change_spans {
1368+
sugg.push((span, "this".to_string()));
1369+
}
1370+
1371+
for (span, suggest) in finder.closure_call_changes {
1372+
sugg.push((span, suggest));
1373+
}
1374+
1375+
err.multipart_suggestion_verbose(
1376+
"try explicitly pass `&Self` into the Closure as an argument",
1377+
sugg,
1378+
Applicability::MachineApplicable,
1379+
);
1380+
}
1381+
}
1382+
12431383
/// Returns the description of the root place for a conflicting borrow and the full
12441384
/// descriptions of the places that caused the conflict.
12451385
///

0 commit comments

Comments
 (0)
Please sign in to comment.