Auto merge of #110061 - WaffleLapkin:duality_of_myself_and_this, r=cjgillot
Add suggestion to use closure argument instead of a capture on borrowck error Fixes #109271 r? `@compiler-errors` This should probably be refined a bit, but opening a PR so that I don't forget anything.
This commit is contained in:
commit
b9fd498fa7
24 changed files with 425 additions and 83 deletions
|
@ -469,6 +469,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rustc_lint_diagnostics]
|
#[rustc_lint_diagnostics]
|
||||||
|
#[track_caller]
|
||||||
pub(crate) fn struct_span_err_with_code<S: Into<MultiSpan>>(
|
pub(crate) fn struct_span_err_with_code<S: Into<MultiSpan>>(
|
||||||
&self,
|
&self,
|
||||||
sp: S,
|
sp: S,
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
use std::iter;
|
||||||
|
|
||||||
use either::Either;
|
use either::Either;
|
||||||
use rustc_data_structures::captures::Captures;
|
use rustc_data_structures::captures::Captures;
|
||||||
use rustc_data_structures::fx::FxIndexSet;
|
use rustc_data_structures::fx::FxIndexSet;
|
||||||
|
@ -10,27 +12,26 @@ use rustc_hir::intravisit::{walk_block, walk_expr, Visitor};
|
||||||
use rustc_hir::{AsyncGeneratorKind, GeneratorKind, LangItem};
|
use rustc_hir::{AsyncGeneratorKind, GeneratorKind, LangItem};
|
||||||
use rustc_infer::infer::TyCtxtInferExt;
|
use rustc_infer::infer::TyCtxtInferExt;
|
||||||
use rustc_infer::traits::ObligationCause;
|
use rustc_infer::traits::ObligationCause;
|
||||||
|
use rustc_middle::hir::nested_filter::OnlyBodies;
|
||||||
use rustc_middle::mir::tcx::PlaceTy;
|
use rustc_middle::mir::tcx::PlaceTy;
|
||||||
use rustc_middle::mir::{
|
use rustc_middle::mir::{
|
||||||
self, AggregateKind, BindingForm, BorrowKind, ClearCrossCrate, ConstraintCategory,
|
self, AggregateKind, BindingForm, BorrowKind, ClearCrossCrate, ConstraintCategory,
|
||||||
FakeReadCause, LocalDecl, LocalInfo, LocalKind, Location, Operand, Place, PlaceRef,
|
FakeReadCause, LocalDecl, LocalInfo, LocalKind, Location, Operand, Place, PlaceRef,
|
||||||
ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind, VarBindingForm,
|
ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind, VarBindingForm,
|
||||||
};
|
};
|
||||||
use rustc_middle::ty::{self, suggest_constraining_type_params, PredicateKind, Ty};
|
use rustc_middle::ty::{self, suggest_constraining_type_params, PredicateKind, Ty, TypeckResults};
|
||||||
use rustc_middle::util::CallKind;
|
use rustc_middle::util::CallKind;
|
||||||
use rustc_mir_dataflow::move_paths::{InitKind, MoveOutIndex, MovePathIndex};
|
use rustc_mir_dataflow::move_paths::{InitKind, MoveOutIndex, MovePathIndex};
|
||||||
use rustc_span::def_id::LocalDefId;
|
use rustc_span::def_id::LocalDefId;
|
||||||
use rustc_span::hygiene::DesugaringKind;
|
use rustc_span::hygiene::DesugaringKind;
|
||||||
use rustc_span::symbol::{kw, sym};
|
use rustc_span::symbol::{kw, sym, Ident};
|
||||||
use rustc_span::{BytePos, Span, Symbol};
|
use rustc_span::{BytePos, Span, Symbol};
|
||||||
use rustc_trait_selection::infer::InferCtxtExt;
|
use rustc_trait_selection::infer::InferCtxtExt;
|
||||||
use rustc_trait_selection::traits::ObligationCtxt;
|
use rustc_trait_selection::traits::ObligationCtxt;
|
||||||
|
|
||||||
use crate::borrow_set::TwoPhaseActivation;
|
use crate::borrow_set::TwoPhaseActivation;
|
||||||
use crate::borrowck_errors;
|
use crate::borrowck_errors;
|
||||||
|
|
||||||
use crate::diagnostics::conflict_errors::StorageDeadOrDrop::LocalStorageDead;
|
use crate::diagnostics::conflict_errors::StorageDeadOrDrop::LocalStorageDead;
|
||||||
use crate::diagnostics::mutability_errors::mut_borrow_of_mutable_ref;
|
|
||||||
use crate::diagnostics::{find_all_local_uses, CapturedMessageOpt};
|
use crate::diagnostics::{find_all_local_uses, CapturedMessageOpt};
|
||||||
use crate::{
|
use crate::{
|
||||||
borrow_set::BorrowData, diagnostics::Instance, prefixes::IsPrefixOf,
|
borrow_set::BorrowData, diagnostics::Instance, prefixes::IsPrefixOf,
|
||||||
|
@ -959,7 +960,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||||
&msg_borrow,
|
&msg_borrow,
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
self.suggest_binding_for_closure_capture_self(
|
self.suggest_binding_for_closure_capture_self(&mut err, &issued_spans);
|
||||||
|
self.suggest_using_closure_argument_instead_of_capture(
|
||||||
&mut err,
|
&mut err,
|
||||||
issued_borrow.borrowed_place,
|
issued_borrow.borrowed_place,
|
||||||
&issued_spans,
|
&issued_spans,
|
||||||
|
@ -982,6 +984,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||||
place,
|
place,
|
||||||
issued_borrow.borrowed_place,
|
issued_borrow.borrowed_place,
|
||||||
);
|
);
|
||||||
|
self.suggest_using_closure_argument_instead_of_capture(
|
||||||
|
&mut err,
|
||||||
|
issued_borrow.borrowed_place,
|
||||||
|
&issued_spans,
|
||||||
|
);
|
||||||
err
|
err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1268,23 +1275,162 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn suggest_binding_for_closure_capture_self(
|
/// Suggest using closure argument instead of capture.
|
||||||
|
///
|
||||||
|
/// For example:
|
||||||
|
/// ```ignore (illustrative)
|
||||||
|
/// struct S;
|
||||||
|
///
|
||||||
|
/// impl S {
|
||||||
|
/// fn call(&mut self, f: impl Fn(&mut Self)) { /* ... */ }
|
||||||
|
/// fn x(&self) {}
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// let mut v = S;
|
||||||
|
/// v.call(|this: &mut S| v.x());
|
||||||
|
/// // ^\ ^-- help: try using the closure argument: `this`
|
||||||
|
/// // *-- error: cannot borrow `v` as mutable because it is also borrowed as immutable
|
||||||
|
/// ```
|
||||||
|
fn suggest_using_closure_argument_instead_of_capture(
|
||||||
&self,
|
&self,
|
||||||
err: &mut Diagnostic,
|
err: &mut Diagnostic,
|
||||||
borrowed_place: Place<'tcx>,
|
borrowed_place: Place<'tcx>,
|
||||||
issued_spans: &UseSpans<'tcx>,
|
issued_spans: &UseSpans<'tcx>,
|
||||||
|
) {
|
||||||
|
let &UseSpans::ClosureUse { capture_kind_span, .. } = issued_spans else { return };
|
||||||
|
let tcx = self.infcx.tcx;
|
||||||
|
let hir = tcx.hir();
|
||||||
|
|
||||||
|
// Get the type of the local that we are trying to borrow
|
||||||
|
let local = borrowed_place.local;
|
||||||
|
let local_ty = self.body.local_decls[local].ty;
|
||||||
|
|
||||||
|
// Get the body the error happens in
|
||||||
|
let Some(body_id) = hir.get(self.mir_hir_id()).body_id() else { return };
|
||||||
|
|
||||||
|
let body_expr = hir.body(body_id).value;
|
||||||
|
|
||||||
|
struct ClosureFinder<'hir> {
|
||||||
|
hir: rustc_middle::hir::map::Map<'hir>,
|
||||||
|
borrow_span: Span,
|
||||||
|
res: Option<(&'hir hir::Expr<'hir>, &'hir hir::Closure<'hir>)>,
|
||||||
|
/// The path expression with the `borrow_span` span
|
||||||
|
error_path: Option<(&'hir hir::Expr<'hir>, &'hir hir::QPath<'hir>)>,
|
||||||
|
}
|
||||||
|
impl<'hir> Visitor<'hir> for ClosureFinder<'hir> {
|
||||||
|
type NestedFilter = OnlyBodies;
|
||||||
|
|
||||||
|
fn nested_visit_map(&mut self) -> Self::Map {
|
||||||
|
self.hir
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_expr(&mut self, ex: &'hir hir::Expr<'hir>) {
|
||||||
|
if let hir::ExprKind::Path(qpath) = &ex.kind
|
||||||
|
&& ex.span == self.borrow_span
|
||||||
|
{
|
||||||
|
self.error_path = Some((ex, qpath));
|
||||||
|
}
|
||||||
|
|
||||||
|
if let hir::ExprKind::Closure(closure) = ex.kind
|
||||||
|
&& ex.span.contains(self.borrow_span)
|
||||||
|
// To support cases like `|| { v.call(|this| v.get()) }`
|
||||||
|
// FIXME: actually support such cases (need to figure out how to move from the capture place to original local)
|
||||||
|
&& self.res.as_ref().map_or(true, |(prev_res, _)| prev_res.span.contains(ex.span))
|
||||||
|
{
|
||||||
|
self.res = Some((ex, closure));
|
||||||
|
}
|
||||||
|
|
||||||
|
hir::intravisit::walk_expr(self, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the closure that most tightly wraps `capture_kind_span`
|
||||||
|
let mut finder =
|
||||||
|
ClosureFinder { hir, borrow_span: capture_kind_span, res: None, error_path: None };
|
||||||
|
finder.visit_expr(body_expr);
|
||||||
|
let Some((closure_expr, closure)) = finder.res else { return };
|
||||||
|
|
||||||
|
let typeck_results: &TypeckResults<'_> =
|
||||||
|
tcx.typeck_opt_const_arg(self.body.source.with_opt_param().as_local().unwrap());
|
||||||
|
|
||||||
|
// Check that the parent of the closure is a method call,
|
||||||
|
// with receiver matching with local's type (modulo refs)
|
||||||
|
let parent = hir.parent_id(closure_expr.hir_id);
|
||||||
|
if let hir::Node::Expr(parent) = hir.get(parent) {
|
||||||
|
if let hir::ExprKind::MethodCall(_, recv, ..) = parent.kind {
|
||||||
|
let recv_ty = typeck_results.expr_ty(recv);
|
||||||
|
|
||||||
|
if recv_ty.peel_refs() != local_ty {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get closure's arguments
|
||||||
|
let ty::Closure(_, substs) = typeck_results.expr_ty(closure_expr).kind() else { unreachable!() };
|
||||||
|
let sig = substs.as_closure().sig();
|
||||||
|
let tupled_params =
|
||||||
|
tcx.erase_late_bound_regions(sig.inputs().iter().next().unwrap().map_bound(|&b| b));
|
||||||
|
let ty::Tuple(params) = tupled_params.kind() else { return };
|
||||||
|
|
||||||
|
// Find the first argument with a matching type, get its name
|
||||||
|
let Some((_, this_name)) = params
|
||||||
|
.iter()
|
||||||
|
.zip(hir.body_param_names(closure.body))
|
||||||
|
.find(|(param_ty, name)|{
|
||||||
|
// FIXME: also support deref for stuff like `Rc` arguments
|
||||||
|
param_ty.peel_refs() == local_ty && name != &Ident::empty()
|
||||||
|
})
|
||||||
|
else { return };
|
||||||
|
|
||||||
|
let spans;
|
||||||
|
if let Some((_path_expr, qpath)) = finder.error_path
|
||||||
|
&& let hir::QPath::Resolved(_, path) = qpath
|
||||||
|
&& let hir::def::Res::Local(local_id) = path.res
|
||||||
|
{
|
||||||
|
// Find all references to the problematic variable in this closure body
|
||||||
|
|
||||||
|
struct VariableUseFinder {
|
||||||
|
local_id: hir::HirId,
|
||||||
|
spans: Vec<Span>,
|
||||||
|
}
|
||||||
|
impl<'hir> Visitor<'hir> for VariableUseFinder {
|
||||||
|
fn visit_expr(&mut self, ex: &'hir hir::Expr<'hir>) {
|
||||||
|
if let hir::ExprKind::Path(qpath) = &ex.kind
|
||||||
|
&& let hir::QPath::Resolved(_, path) = qpath
|
||||||
|
&& let hir::def::Res::Local(local_id) = path.res
|
||||||
|
&& local_id == self.local_id
|
||||||
|
{
|
||||||
|
self.spans.push(ex.span);
|
||||||
|
}
|
||||||
|
|
||||||
|
hir::intravisit::walk_expr(self, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut finder = VariableUseFinder { local_id, spans: Vec::new() };
|
||||||
|
finder.visit_expr(hir.body(closure.body).value);
|
||||||
|
|
||||||
|
spans = finder.spans;
|
||||||
|
} else {
|
||||||
|
spans = vec![capture_kind_span];
|
||||||
|
}
|
||||||
|
|
||||||
|
err.multipart_suggestion(
|
||||||
|
"try using the closure argument",
|
||||||
|
iter::zip(spans, iter::repeat(this_name.to_string())).collect(),
|
||||||
|
Applicability::MaybeIncorrect,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn suggest_binding_for_closure_capture_self(
|
||||||
|
&self,
|
||||||
|
err: &mut Diagnostic,
|
||||||
|
issued_spans: &UseSpans<'tcx>,
|
||||||
) {
|
) {
|
||||||
let UseSpans::ClosureUse { capture_kind_span, .. } = issued_spans else { return };
|
let UseSpans::ClosureUse { capture_kind_span, .. } = issued_spans else { return };
|
||||||
let hir = self.infcx.tcx.hir();
|
let hir = self.infcx.tcx.hir();
|
||||||
|
|
||||||
// check whether the borrowed place is capturing `self` by mut reference
|
|
||||||
let local = borrowed_place.local;
|
|
||||||
let Some(_) = self
|
|
||||||
.body
|
|
||||||
.local_decls
|
|
||||||
.get(local)
|
|
||||||
.map(|l| mut_borrow_of_mutable_ref(l, self.local_names[local])) else { return };
|
|
||||||
|
|
||||||
struct ExpressionFinder<'hir> {
|
struct ExpressionFinder<'hir> {
|
||||||
capture_span: Span,
|
capture_span: Span,
|
||||||
closure_change_spans: Vec<Span>,
|
closure_change_spans: Vec<Span>,
|
||||||
|
|
|
@ -3529,12 +3529,20 @@ impl<'hir> OwnerNode<'hir> {
|
||||||
|
|
||||||
pub fn body_id(&self) -> Option<BodyId> {
|
pub fn body_id(&self) -> Option<BodyId> {
|
||||||
match self {
|
match self {
|
||||||
OwnerNode::TraitItem(TraitItem {
|
OwnerNode::Item(Item {
|
||||||
kind: TraitItemKind::Fn(_, TraitFn::Provided(body_id)),
|
kind:
|
||||||
|
ItemKind::Static(_, _, body) | ItemKind::Const(_, body) | ItemKind::Fn(_, _, body),
|
||||||
..
|
..
|
||||||
})
|
})
|
||||||
| OwnerNode::ImplItem(ImplItem { kind: ImplItemKind::Fn(_, body_id), .. })
|
| OwnerNode::TraitItem(TraitItem {
|
||||||
| OwnerNode::Item(Item { kind: ItemKind::Fn(.., body_id), .. }) => Some(*body_id),
|
kind:
|
||||||
|
TraitItemKind::Fn(_, TraitFn::Provided(body)) | TraitItemKind::Const(_, Some(body)),
|
||||||
|
..
|
||||||
|
})
|
||||||
|
| OwnerNode::ImplItem(ImplItem {
|
||||||
|
kind: ImplItemKind::Fn(_, body) | ImplItemKind::Const(_, body),
|
||||||
|
..
|
||||||
|
}) => Some(*body),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3729,12 +3737,27 @@ impl<'hir> Node<'hir> {
|
||||||
|
|
||||||
pub fn body_id(&self) -> Option<BodyId> {
|
pub fn body_id(&self) -> Option<BodyId> {
|
||||||
match self {
|
match self {
|
||||||
Node::TraitItem(TraitItem {
|
Node::Item(Item {
|
||||||
kind: TraitItemKind::Fn(_, TraitFn::Provided(body_id)),
|
kind:
|
||||||
|
ItemKind::Static(_, _, body) | ItemKind::Const(_, body) | ItemKind::Fn(_, _, body),
|
||||||
..
|
..
|
||||||
})
|
})
|
||||||
| Node::ImplItem(ImplItem { kind: ImplItemKind::Fn(_, body_id), .. })
|
| Node::TraitItem(TraitItem {
|
||||||
| Node::Item(Item { kind: ItemKind::Fn(.., body_id), .. }) => Some(*body_id),
|
kind:
|
||||||
|
TraitItemKind::Fn(_, TraitFn::Provided(body)) | TraitItemKind::Const(_, Some(body)),
|
||||||
|
..
|
||||||
|
})
|
||||||
|
| Node::ImplItem(ImplItem {
|
||||||
|
kind: ImplItemKind::Fn(_, body) | ImplItemKind::Const(_, body),
|
||||||
|
..
|
||||||
|
})
|
||||||
|
| Node::Expr(Expr {
|
||||||
|
kind:
|
||||||
|
ExprKind::ConstBlock(AnonConst { body, .. })
|
||||||
|
| ExprKind::Closure(Closure { body, .. })
|
||||||
|
| ExprKind::Repeat(_, ArrayLen::Body(AnonConst { body, .. })),
|
||||||
|
..
|
||||||
|
}) => Some(*body),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ error[E0597]: `bar` does not live long enough
|
||||||
LL | let x = {
|
LL | let x = {
|
||||||
| - borrow later stored here
|
| - borrow later stored here
|
||||||
LL | let bar = 22;
|
LL | let bar = 22;
|
||||||
|
| --- binding `bar` declared here
|
||||||
LL | Foo::new(&bar).await
|
LL | Foo::new(&bar).await
|
||||||
| ^^^^ borrowed value does not live long enough
|
| ^^^^ borrowed value does not live long enough
|
||||||
LL |
|
LL |
|
||||||
|
|
|
@ -13,6 +13,7 @@ error[E0597]: `bar` does not live long enough
|
||||||
LL | let x = {
|
LL | let x = {
|
||||||
| - borrow later stored here
|
| - borrow later stored here
|
||||||
LL | let bar = 22;
|
LL | let bar = 22;
|
||||||
|
| --- binding `bar` declared here
|
||||||
LL | Foo::new(&bar).await
|
LL | Foo::new(&bar).await
|
||||||
| ^^^^ borrowed value does not live long enough
|
| ^^^^ borrowed value does not live long enough
|
||||||
LL |
|
LL |
|
||||||
|
|
39
tests/ui/borrowck/issue-109271-pass-self-into-closure.fixed
Normal file
39
tests/ui/borrowck/issue-109271-pass-self-into-closure.fixed
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
// run-rustfix
|
||||||
|
#![allow(unused)]
|
||||||
|
struct S;
|
||||||
|
|
||||||
|
impl S {
|
||||||
|
fn call(&mut self, f: impl FnOnce((), &mut Self)) {
|
||||||
|
// change state or something ...
|
||||||
|
f((), self);
|
||||||
|
// change state or something ...
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get(&self) {}
|
||||||
|
fn set(&mut self) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let mut v = S;
|
||||||
|
|
||||||
|
v.call(|(), this: &mut S| this.get());
|
||||||
|
//~^ error: cannot borrow `v` as mutable because it is also borrowed as immutable
|
||||||
|
v.call(|(), this: &mut S| this.set());
|
||||||
|
//~^ error: cannot borrow `v` as mutable more than once at a time
|
||||||
|
//~| error: cannot borrow `v` as mutable more than once at a time
|
||||||
|
|
||||||
|
v.call(|(), this: &mut S| {
|
||||||
|
//~^ error: cannot borrow `v` as mutable more than once at a time
|
||||||
|
//~| error: cannot borrow `v` as mutable more than once at a time
|
||||||
|
|
||||||
|
_ = this;
|
||||||
|
this.set();
|
||||||
|
this.get();
|
||||||
|
S::get(&this);
|
||||||
|
|
||||||
|
use std::ops::Add;
|
||||||
|
let v = 0u32;
|
||||||
|
_ = v + v;
|
||||||
|
_ = v.add(3);
|
||||||
|
});
|
||||||
|
}
|
39
tests/ui/borrowck/issue-109271-pass-self-into-closure.rs
Normal file
39
tests/ui/borrowck/issue-109271-pass-self-into-closure.rs
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
// run-rustfix
|
||||||
|
#![allow(unused)]
|
||||||
|
struct S;
|
||||||
|
|
||||||
|
impl S {
|
||||||
|
fn call(&mut self, f: impl FnOnce((), &mut Self)) {
|
||||||
|
// change state or something ...
|
||||||
|
f((), self);
|
||||||
|
// change state or something ...
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get(&self) {}
|
||||||
|
fn set(&mut self) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let mut v = S;
|
||||||
|
|
||||||
|
v.call(|(), this: &mut S| v.get());
|
||||||
|
//~^ error: cannot borrow `v` as mutable because it is also borrowed as immutable
|
||||||
|
v.call(|(), this: &mut S| v.set());
|
||||||
|
//~^ error: cannot borrow `v` as mutable more than once at a time
|
||||||
|
//~| error: cannot borrow `v` as mutable more than once at a time
|
||||||
|
|
||||||
|
v.call(|(), this: &mut S| {
|
||||||
|
//~^ error: cannot borrow `v` as mutable more than once at a time
|
||||||
|
//~| error: cannot borrow `v` as mutable more than once at a time
|
||||||
|
|
||||||
|
_ = v;
|
||||||
|
v.set();
|
||||||
|
v.get();
|
||||||
|
S::get(&v);
|
||||||
|
|
||||||
|
use std::ops::Add;
|
||||||
|
let v = 0u32;
|
||||||
|
_ = v + v;
|
||||||
|
_ = v.add(3);
|
||||||
|
});
|
||||||
|
}
|
85
tests/ui/borrowck/issue-109271-pass-self-into-closure.stderr
Normal file
85
tests/ui/borrowck/issue-109271-pass-self-into-closure.stderr
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable
|
||||||
|
--> $DIR/issue-109271-pass-self-into-closure.rs:19:5
|
||||||
|
|
|
||||||
|
LL | v.call(|(), this: &mut S| v.get());
|
||||||
|
| ^^----^------------------^-^^^^^^^
|
||||||
|
| | | | |
|
||||||
|
| | | | first borrow occurs due to use of `v` in closure
|
||||||
|
| | | | help: try using the closure argument: `this`
|
||||||
|
| | | immutable borrow occurs here
|
||||||
|
| | immutable borrow later used by call
|
||||||
|
| mutable borrow occurs here
|
||||||
|
|
||||||
|
error[E0499]: cannot borrow `v` as mutable more than once at a time
|
||||||
|
--> $DIR/issue-109271-pass-self-into-closure.rs:21:5
|
||||||
|
|
|
||||||
|
LL | v.call(|(), this: &mut S| v.set());
|
||||||
|
| ^^----^------------------^-^^^^^^^
|
||||||
|
| | | | |
|
||||||
|
| | | | first borrow occurs due to use of `v` in closure
|
||||||
|
| | | | help: try using the closure argument: `this`
|
||||||
|
| | | first mutable borrow occurs here
|
||||||
|
| | first borrow later used by call
|
||||||
|
| second mutable borrow occurs here
|
||||||
|
|
||||||
|
error[E0499]: cannot borrow `v` as mutable more than once at a time
|
||||||
|
--> $DIR/issue-109271-pass-self-into-closure.rs:21:12
|
||||||
|
|
|
||||||
|
LL | v.call(|(), this: &mut S| v.set());
|
||||||
|
| -------^^^^^^^^^^^^^^^^^^---------
|
||||||
|
| | | | |
|
||||||
|
| | | | second borrow occurs due to use of `v` in closure
|
||||||
|
| | | second mutable borrow occurs here
|
||||||
|
| | first borrow later used by call
|
||||||
|
| first mutable borrow occurs here
|
||||||
|
|
||||||
|
error[E0499]: cannot borrow `v` as mutable more than once at a time
|
||||||
|
--> $DIR/issue-109271-pass-self-into-closure.rs:25:5
|
||||||
|
|
|
||||||
|
LL | v.call(|(), this: &mut S| {
|
||||||
|
| ^ ---- ------------------ first mutable borrow occurs here
|
||||||
|
| | |
|
||||||
|
| _____| first borrow later used by call
|
||||||
|
| |
|
||||||
|
LL | |
|
||||||
|
LL | |
|
||||||
|
LL | |
|
||||||
|
LL | | _ = v;
|
||||||
|
LL | | v.set();
|
||||||
|
| | - first borrow occurs due to use of `v` in closure
|
||||||
|
... |
|
||||||
|
LL | | _ = v.add(3);
|
||||||
|
LL | | });
|
||||||
|
| |______^ second mutable borrow occurs here
|
||||||
|
|
|
||||||
|
help: try using the closure argument
|
||||||
|
|
|
||||||
|
LL ~ _ = this;
|
||||||
|
LL ~ this.set();
|
||||||
|
LL ~ this.get();
|
||||||
|
LL ~ S::get(&this);
|
||||||
|
|
|
||||||
|
|
||||||
|
error[E0499]: cannot borrow `v` as mutable more than once at a time
|
||||||
|
--> $DIR/issue-109271-pass-self-into-closure.rs:25:12
|
||||||
|
|
|
||||||
|
LL | v.call(|(), this: &mut S| {
|
||||||
|
| - ---- ^^^^^^^^^^^^^^^^^^ second mutable borrow occurs here
|
||||||
|
| | |
|
||||||
|
| _____| first borrow later used by call
|
||||||
|
| |
|
||||||
|
LL | |
|
||||||
|
LL | |
|
||||||
|
LL | |
|
||||||
|
LL | | _ = v;
|
||||||
|
LL | | v.set();
|
||||||
|
| | - second borrow occurs due to use of `v` in closure
|
||||||
|
... |
|
||||||
|
LL | | _ = v.add(3);
|
||||||
|
LL | | });
|
||||||
|
| |______- first mutable borrow occurs here
|
||||||
|
|
||||||
|
error: aborting due to 5 previous errors
|
||||||
|
|
||||||
|
Some errors have detailed explanations: E0499, E0502.
|
||||||
|
For more information about an error, try `rustc --explain E0499`.
|
|
@ -4,6 +4,8 @@ error[E0597]: `x` does not live long enough
|
||||||
LL | impl<'a, T: 'static> Generic<'a, T> {
|
LL | impl<'a, T: 'static> Generic<'a, T> {
|
||||||
| -- lifetime `'a` defined here
|
| -- lifetime `'a` defined here
|
||||||
...
|
...
|
||||||
|
LL | let x: &'static [T] = &[];
|
||||||
|
| - binding `x` declared here
|
||||||
LL | &x
|
LL | &x
|
||||||
| ^^
|
| ^^
|
||||||
| |
|
| |
|
||||||
|
@ -16,6 +18,8 @@ LL | };
|
||||||
error[E0597]: `x` does not live long enough
|
error[E0597]: `x` does not live long enough
|
||||||
--> $DIR/generic-slice.rs:27:5
|
--> $DIR/generic-slice.rs:27:5
|
||||||
|
|
|
|
||||||
|
LL | let x: &[_] = &[];
|
||||||
|
| - binding `x` declared here
|
||||||
LL | &x
|
LL | &x
|
||||||
| ^^
|
| ^^
|
||||||
| |
|
| |
|
||||||
|
|
|
@ -9,7 +9,11 @@ LL | let a = A(&mut true, &mut true, No);
|
||||||
LL | assert_foo(a);
|
LL | assert_foo(a);
|
||||||
| - borrow later used here
|
| - borrow later used here
|
||||||
|
|
|
|
||||||
= note: consider using a `let` binding to create a longer lived value
|
help: consider using a `let` binding to create a longer lived value
|
||||||
|
|
|
||||||
|
LL ~ let binding = true;
|
||||||
|
LL ~ let a = A(&mut binding, &mut true, No);
|
||||||
|
|
|
||||||
|
|
||||||
error[E0716]: temporary value dropped while borrowed
|
error[E0716]: temporary value dropped while borrowed
|
||||||
--> $DIR/auto-trait-regions.rs:48:35
|
--> $DIR/auto-trait-regions.rs:48:35
|
||||||
|
@ -22,7 +26,11 @@ LL | let a = A(&mut true, &mut true, No);
|
||||||
LL | assert_foo(a);
|
LL | assert_foo(a);
|
||||||
| - borrow later used here
|
| - borrow later used here
|
||||||
|
|
|
|
||||||
= note: consider using a `let` binding to create a longer lived value
|
help: consider using a `let` binding to create a longer lived value
|
||||||
|
|
|
||||||
|
LL ~ let binding = true;
|
||||||
|
LL ~ let a = A(&mut true, &mut binding, No);
|
||||||
|
|
|
||||||
|
|
||||||
error: implementation of `Foo` is not general enough
|
error: implementation of `Foo` is not general enough
|
||||||
--> $DIR/auto-trait-regions.rs:34:5
|
--> $DIR/auto-trait-regions.rs:34:5
|
||||||
|
|
|
@ -9,7 +9,11 @@ LL | let a = A(&mut true, &mut true, No);
|
||||||
LL | assert_foo(a);
|
LL | assert_foo(a);
|
||||||
| - borrow later used here
|
| - borrow later used here
|
||||||
|
|
|
|
||||||
= note: consider using a `let` binding to create a longer lived value
|
help: consider using a `let` binding to create a longer lived value
|
||||||
|
|
|
||||||
|
LL ~ let binding = true;
|
||||||
|
LL ~ let a = A(&mut binding, &mut true, No);
|
||||||
|
|
|
||||||
|
|
||||||
error[E0716]: temporary value dropped while borrowed
|
error[E0716]: temporary value dropped while borrowed
|
||||||
--> $DIR/auto-trait-regions.rs:48:35
|
--> $DIR/auto-trait-regions.rs:48:35
|
||||||
|
@ -22,7 +26,11 @@ LL | let a = A(&mut true, &mut true, No);
|
||||||
LL | assert_foo(a);
|
LL | assert_foo(a);
|
||||||
| - borrow later used here
|
| - borrow later used here
|
||||||
|
|
|
|
||||||
= note: consider using a `let` binding to create a longer lived value
|
help: consider using a `let` binding to create a longer lived value
|
||||||
|
|
|
||||||
|
LL ~ let binding = true;
|
||||||
|
LL ~ let a = A(&mut true, &mut binding, No);
|
||||||
|
|
|
||||||
|
|
||||||
error: implementation of `Foo` is not general enough
|
error: implementation of `Foo` is not general enough
|
||||||
--> $DIR/auto-trait-regions.rs:34:5
|
--> $DIR/auto-trait-regions.rs:34:5
|
||||||
|
|
|
@ -9,7 +9,11 @@ LL | let a = A(&mut true, &mut true, No);
|
||||||
LL | assert_foo(a);
|
LL | assert_foo(a);
|
||||||
| - borrow later used here
|
| - borrow later used here
|
||||||
|
|
|
|
||||||
= note: consider using a `let` binding to create a longer lived value
|
help: consider using a `let` binding to create a longer lived value
|
||||||
|
|
|
||||||
|
LL ~ let binding = true;
|
||||||
|
LL ~ let a = A(&mut binding, &mut true, No);
|
||||||
|
|
|
||||||
|
|
||||||
error[E0716]: temporary value dropped while borrowed
|
error[E0716]: temporary value dropped while borrowed
|
||||||
--> $DIR/auto-trait-regions.rs:48:35
|
--> $DIR/auto-trait-regions.rs:48:35
|
||||||
|
@ -22,7 +26,11 @@ LL | let a = A(&mut true, &mut true, No);
|
||||||
LL | assert_foo(a);
|
LL | assert_foo(a);
|
||||||
| - borrow later used here
|
| - borrow later used here
|
||||||
|
|
|
|
||||||
= note: consider using a `let` binding to create a longer lived value
|
help: consider using a `let` binding to create a longer lived value
|
||||||
|
|
|
||||||
|
LL ~ let binding = true;
|
||||||
|
LL ~ let a = A(&mut true, &mut binding, No);
|
||||||
|
|
|
||||||
|
|
||||||
error: implementation of `Foo` is not general enough
|
error: implementation of `Foo` is not general enough
|
||||||
--> $DIR/auto-trait-regions.rs:34:5
|
--> $DIR/auto-trait-regions.rs:34:5
|
||||||
|
|
|
@ -1,47 +0,0 @@
|
||||||
error[E0716]: temporary value dropped while borrowed
|
|
||||||
--> $DIR/auto-trait-regions.rs:48:24
|
|
||||||
|
|
|
||||||
LL | let a = A(&mut true, &mut true, No);
|
|
||||||
| ^^^^ - temporary value is freed at the end of this statement
|
|
||||||
| |
|
|
||||||
| creates a temporary value which is freed while still in use
|
|
||||||
...
|
|
||||||
LL | assert_foo(a);
|
|
||||||
| - borrow later used here
|
|
||||||
|
|
|
||||||
= note: consider using a `let` binding to create a longer lived value
|
|
||||||
|
|
||||||
error[E0716]: temporary value dropped while borrowed
|
|
||||||
--> $DIR/auto-trait-regions.rs:48:35
|
|
||||||
|
|
|
||||||
LL | let a = A(&mut true, &mut true, No);
|
|
||||||
| ^^^^ - temporary value is freed at the end of this statement
|
|
||||||
| |
|
|
||||||
| creates a temporary value which is freed while still in use
|
|
||||||
...
|
|
||||||
LL | assert_foo(a);
|
|
||||||
| - borrow later used here
|
|
||||||
|
|
|
||||||
= note: consider using a `let` binding to create a longer lived value
|
|
||||||
|
|
||||||
error: implementation of `Foo` is not general enough
|
|
||||||
--> $DIR/auto-trait-regions.rs:34:5
|
|
||||||
|
|
|
||||||
LL | assert_foo(gen);
|
|
||||||
| ^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough
|
|
||||||
|
|
|
||||||
= note: `&'0 OnlyFooIfStaticRef` must implement `Foo`, for any lifetime `'0`...
|
|
||||||
= note: ...but `Foo` is actually implemented for the type `&'static OnlyFooIfStaticRef`
|
|
||||||
|
|
||||||
error: implementation of `Foo` is not general enough
|
|
||||||
--> $DIR/auto-trait-regions.rs:54:5
|
|
||||||
|
|
|
||||||
LL | assert_foo(gen);
|
|
||||||
| ^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough
|
|
||||||
|
|
|
||||||
= note: `Foo` would have to be implemented for the type `A<'0, '1>`, for any two lifetimes `'0` and `'1`...
|
|
||||||
= note: ...but `Foo` is actually implemented for the type `A<'_, '2>`, for some specific lifetime `'2`
|
|
||||||
|
|
||||||
error: aborting due to 4 previous errors
|
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0716`.
|
|
|
@ -12,6 +12,8 @@ LL | async fn f2(m: Msg<'_>) {}
|
||||||
error[E0597]: `buf` does not live long enough
|
error[E0597]: `buf` does not live long enough
|
||||||
--> $DIR/issue-69314.rs:14:19
|
--> $DIR/issue-69314.rs:14:19
|
||||||
|
|
|
|
||||||
|
LL | let mut buf = [0; 512];
|
||||||
|
| ------- binding `buf` declared here
|
||||||
LL | let m2 = &buf[..];
|
LL | let m2 = &buf[..];
|
||||||
| ^^^ borrowed value does not live long enough
|
| ^^^ borrowed value does not live long enough
|
||||||
LL | let m = Self::g(m2).await;
|
LL | let m = Self::g(m2).await;
|
||||||
|
|
|
@ -31,7 +31,9 @@ error[E0597]: `c` does not live long enough
|
||||||
|
|
|
|
||||||
LL | fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
|
LL | fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
|
||||||
| -- lifetime `'a` defined here
|
| -- lifetime `'a` defined here
|
||||||
...
|
LL | let _closure = || {
|
||||||
|
LL | let c = 66;
|
||||||
|
| - binding `c` declared here
|
||||||
LL | SomeEnum::SomeVariant::<&'a u32> { t: &c };
|
LL | SomeEnum::SomeVariant::<&'a u32> { t: &c };
|
||||||
| ^^
|
| ^^
|
||||||
| |
|
| |
|
||||||
|
|
|
@ -31,7 +31,9 @@ error[E0597]: `c` does not live long enough
|
||||||
|
|
|
|
||||||
LL | fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
|
LL | fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
|
||||||
| -- lifetime `'a` defined here
|
| -- lifetime `'a` defined here
|
||||||
...
|
LL | let _closure = || {
|
||||||
|
LL | let c = 66;
|
||||||
|
| - binding `c` declared here
|
||||||
LL | SomeStruct::<&'a u32> { t: &c };
|
LL | SomeStruct::<&'a u32> { t: &c };
|
||||||
| ^^
|
| ^^
|
||||||
| |
|
| |
|
||||||
|
|
|
@ -34,7 +34,10 @@ error[E0597]: `c` does not live long enough
|
||||||
|
|
|
|
||||||
LL | fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
|
LL | fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
|
||||||
| -- lifetime `'a` defined here
|
| -- lifetime `'a` defined here
|
||||||
...
|
LL | let _closure = || {
|
||||||
|
LL | let c = 66;
|
||||||
|
| - binding `c` declared here
|
||||||
|
LL | combine(
|
||||||
LL | SomeEnum::SomeVariant(Cell::new(&c)),
|
LL | SomeEnum::SomeVariant(Cell::new(&c)),
|
||||||
| ----------^^-
|
| ----------^^-
|
||||||
| | |
|
| | |
|
||||||
|
|
|
@ -31,7 +31,9 @@ error[E0597]: `c` does not live long enough
|
||||||
|
|
|
|
||||||
LL | fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
|
LL | fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
|
||||||
| -- lifetime `'a` defined here
|
| -- lifetime `'a` defined here
|
||||||
...
|
LL | let _closure = || {
|
||||||
|
LL | let c = 66;
|
||||||
|
| - binding `c` declared here
|
||||||
LL | SomeEnum::SomeVariant::<&'a u32>(&c);
|
LL | SomeEnum::SomeVariant::<&'a u32>(&c);
|
||||||
| ^^
|
| ^^
|
||||||
| |
|
| |
|
||||||
|
|
|
@ -33,7 +33,10 @@ error[E0597]: `c` does not live long enough
|
||||||
|
|
|
|
||||||
LL | fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
|
LL | fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
|
||||||
| -- lifetime `'a` defined here
|
| -- lifetime `'a` defined here
|
||||||
...
|
LL | let _closure = || {
|
||||||
|
LL | let c = 66;
|
||||||
|
| - binding `c` declared here
|
||||||
|
LL | let f = SomeStruct::<&'a u32>;
|
||||||
LL | f(&c);
|
LL | f(&c);
|
||||||
| --^^-
|
| --^^-
|
||||||
| | |
|
| | |
|
||||||
|
@ -47,7 +50,9 @@ error[E0597]: `c` does not live long enough
|
||||||
|
|
|
|
||||||
LL | let f = SomeStruct::<&'a u32>;
|
LL | let f = SomeStruct::<&'a u32>;
|
||||||
| - lifetime `'1` appears in the type of `f`
|
| - lifetime `'1` appears in the type of `f`
|
||||||
...
|
LL | let _closure = || {
|
||||||
|
LL | let c = 66;
|
||||||
|
| - binding `c` declared here
|
||||||
LL | f(&c);
|
LL | f(&c);
|
||||||
| --^^-
|
| --^^-
|
||||||
| | |
|
| | |
|
||||||
|
|
|
@ -31,7 +31,9 @@ error[E0597]: `c` does not live long enough
|
||||||
|
|
|
|
||||||
LL | fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
|
LL | fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
|
||||||
| -- lifetime `'a` defined here
|
| -- lifetime `'a` defined here
|
||||||
...
|
LL | let _closure = || {
|
||||||
|
LL | let c = 66;
|
||||||
|
| - binding `c` declared here
|
||||||
LL | SomeStruct::<&'a u32>(&c);
|
LL | SomeStruct::<&'a u32>(&c);
|
||||||
| ^^
|
| ^^
|
||||||
| |
|
| |
|
||||||
|
|
|
@ -31,7 +31,9 @@ error[E0597]: `c` does not live long enough
|
||||||
|
|
|
|
||||||
LL | fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
|
LL | fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
|
||||||
| -- lifetime `'a` defined here
|
| -- lifetime `'a` defined here
|
||||||
...
|
LL | let _closure = || {
|
||||||
|
LL | let c = 66;
|
||||||
|
| - binding `c` declared here
|
||||||
LL | some_fn::<&'a u32>(&c);
|
LL | some_fn::<&'a u32>(&c);
|
||||||
| -------------------^^-
|
| -------------------^^-
|
||||||
| | |
|
| | |
|
||||||
|
|
|
@ -33,6 +33,8 @@ error[E0597]: `c` does not live long enough
|
||||||
LL | fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
|
LL | fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
|
||||||
| -- lifetime `'a` defined here
|
| -- lifetime `'a` defined here
|
||||||
...
|
...
|
||||||
|
LL | let c = 66;
|
||||||
|
| - binding `c` declared here
|
||||||
LL | a.method::<&'a u32>(b, &c);
|
LL | a.method::<&'a u32>(b, &c);
|
||||||
| ------------------------^^-
|
| ------------------------^^-
|
||||||
| | |
|
| | |
|
||||||
|
|
|
@ -33,6 +33,8 @@ error[E0597]: `c` does not live long enough
|
||||||
LL | fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
|
LL | fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
|
||||||
| -- lifetime `'a` defined here
|
| -- lifetime `'a` defined here
|
||||||
...
|
...
|
||||||
|
LL | let c = 66;
|
||||||
|
| - binding `c` declared here
|
||||||
LL | <_ as Bazoom<_>>::method::<&'a u32>(&a, b, &c);
|
LL | <_ as Bazoom<_>>::method::<&'a u32>(&a, b, &c);
|
||||||
| -------------------------------------------^^-
|
| -------------------------------------------^^-
|
||||||
| | |
|
| | |
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
error[E0597]: `p` does not live long enough
|
error[E0597]: `p` does not live long enough
|
||||||
--> $DIR/issue-18118.rs:4:9
|
--> $DIR/issue-18118.rs:4:9
|
||||||
|
|
|
|
||||||
|
LL | let p = 3;
|
||||||
|
| - binding `p` declared here
|
||||||
LL | &p
|
LL | &p
|
||||||
| ^^
|
| ^^
|
||||||
| |
|
| |
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue