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 928783d

Browse files
committedDec 11, 2021
Auto merge of #91799 - matthiaskrgr:rollup-b38xx6i, r=matthiaskrgr
Rollup of 6 pull requests Successful merges: - #83174 (Suggest using a temporary variable to fix borrowck errors) - #89734 (Point at capture points for non-`'static` reference crossing a `yield` point) - #90270 (Make `Borrow` and `BorrowMut` impls `const`) - #90741 (Const `Option::cloned`) - #91548 (Add spin_loop hint for RISC-V architecture) - #91721 (Minor improvements to `future::join!`'s implementation) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
2 parents b8dc6aa + ed81098 commit 928783d

File tree

56 files changed

+949
-201
lines changed

Some content is hidden

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

56 files changed

+949
-201
lines changed
 

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,7 @@ fn try_extract_error_from_fulfill_cx<'tcx>(
368368
error_region,
369369
cause.clone(),
370370
placeholder_region,
371+
vec![],
371372
),
372373
),
373374
(Some(error_region), _) => NiceRegionError::new(

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

Lines changed: 87 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,18 @@ use rustc_span::symbol::sym;
1515
use rustc_span::{BytePos, MultiSpan, Span, DUMMY_SP};
1616
use rustc_trait_selection::infer::InferCtxtExt;
1717

18+
use crate::borrow_set::TwoPhaseActivation;
1819
use crate::borrowck_errors;
1920

21+
use crate::diagnostics::find_all_local_uses;
2022
use crate::{
2123
borrow_set::BorrowData, diagnostics::Instance, prefixes::IsPrefixOf,
2224
InitializationRequiringAction, MirBorrowckCtxt, PrefixSet, WriteKind,
2325
};
2426

2527
use super::{
26-
explain_borrow::BorrowExplanation, FnSelfUseKind, IncludingDowncast, RegionName,
27-
RegionNameSource, UseSpans,
28+
explain_borrow::{BorrowExplanation, LaterUseKind},
29+
FnSelfUseKind, IncludingDowncast, RegionName, RegionNameSource, UseSpans,
2830
};
2931

3032
#[derive(Debug)]
@@ -768,9 +770,92 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
768770
Some((issued_span, span)),
769771
);
770772

773+
self.suggest_using_local_if_applicable(
774+
&mut err,
775+
location,
776+
(place, span),
777+
gen_borrow_kind,
778+
issued_borrow,
779+
explanation,
780+
);
781+
771782
err
772783
}
773784

785+
#[instrument(level = "debug", skip(self, err))]
786+
fn suggest_using_local_if_applicable(
787+
&self,
788+
err: &mut DiagnosticBuilder<'_>,
789+
location: Location,
790+
(place, span): (Place<'tcx>, Span),
791+
gen_borrow_kind: BorrowKind,
792+
issued_borrow: &BorrowData<'tcx>,
793+
explanation: BorrowExplanation,
794+
) {
795+
let used_in_call =
796+
matches!(explanation, BorrowExplanation::UsedLater(LaterUseKind::Call, _call_span, _));
797+
if !used_in_call {
798+
debug!("not later used in call");
799+
return;
800+
}
801+
802+
let outer_call_loc =
803+
if let TwoPhaseActivation::ActivatedAt(loc) = issued_borrow.activation_location {
804+
loc
805+
} else {
806+
issued_borrow.reserve_location
807+
};
808+
let outer_call_stmt = self.body.stmt_at(outer_call_loc);
809+
810+
let inner_param_location = location;
811+
let Some(inner_param_stmt) = self.body.stmt_at(inner_param_location).left() else {
812+
debug!("`inner_param_location` {:?} is not for a statement", inner_param_location);
813+
return;
814+
};
815+
let Some(&inner_param) = inner_param_stmt.kind.as_assign().map(|(p, _)| p) else {
816+
debug!(
817+
"`inner_param_location` {:?} is not for an assignment: {:?}",
818+
inner_param_location, inner_param_stmt
819+
);
820+
return;
821+
};
822+
let inner_param_uses = find_all_local_uses::find(self.body, inner_param.local);
823+
let Some((inner_call_loc,inner_call_term)) = inner_param_uses.into_iter().find_map(|loc| {
824+
let Either::Right(term) = self.body.stmt_at(loc) else {
825+
debug!("{:?} is a statement, so it can't be a call", loc);
826+
return None;
827+
};
828+
let TerminatorKind::Call { args, .. } = &term.kind else {
829+
debug!("not a call: {:?}", term);
830+
return None;
831+
};
832+
debug!("checking call args for uses of inner_param: {:?}", args);
833+
if args.contains(&Operand::Move(inner_param)) {
834+
Some((loc,term))
835+
} else {
836+
None
837+
}
838+
}) else {
839+
debug!("no uses of inner_param found as a by-move call arg");
840+
return;
841+
};
842+
debug!("===> outer_call_loc = {:?}, inner_call_loc = {:?}", outer_call_loc, inner_call_loc);
843+
844+
let inner_call_span = inner_call_term.source_info.span;
845+
let outer_call_span = outer_call_stmt.either(|s| s.source_info, |t| t.source_info).span;
846+
if outer_call_span == inner_call_span || !outer_call_span.contains(inner_call_span) {
847+
// FIXME: This stops the suggestion in some cases where it should be emitted.
848+
// Fix the spans for those cases so it's emitted correctly.
849+
debug!(
850+
"outer span {:?} does not strictly contain inner span {:?}",
851+
outer_call_span, inner_call_span
852+
);
853+
return;
854+
}
855+
err.span_help(inner_call_span, "try adding a local storing this argument...");
856+
err.span_help(outer_call_span, "...and then using that local as the argument to this call");
857+
}
858+
774859
fn suggest_split_at_mut_if_applicable(
775860
&self,
776861
err: &mut DiagnosticBuilder<'_>,

0 commit comments

Comments
 (0)
Please sign in to comment.