Auto merge of #48592 - spastorino:borrowed_value_error, r=nikomatsakis

[NLL] Avoid borrowed value must be valid for lifetime '_#2r..." in errors

Closes #48428

- [x] If NLL is enabled, [do not invoke `note_and_explain_region`](https://github.com/rust-lang/rust/issues/48428#issuecomment-367691123)
- [x] Modify `-Zdump-nll-cause` to not print [the overwhelming debug output here](https://github.com/rust-lang/rust/blob/master/src/librustc_mir/borrow_check/nll/region_infer/mod.rs#L1288-L1299). This way we should I believe at least get nice-ish output for [our original example](https://github.com/rust-lang/rust/issues/48428#issue-299364536).
- [x] Extend `explain_why_borrow_contains_point` to also work for "universal lifetimes" like the `'a` in [the example at the end of this comment](https://github.com/rust-lang/rust/issues/48428#issuecomment-367691123).
- [ ] Figure out how to enable causal information all the time (but that is https://github.com/rust-lang/rust/issues/46590).
This commit is contained in:
bors 2018-03-04 18:16:43 +00:00
commit 259e4a6784
18 changed files with 788 additions and 564 deletions

File diff suppressed because it is too large Load Diff

View File

@ -16,7 +16,7 @@ use rustc::ty::{self, RegionKind};
use rustc_data_structures::indexed_vec::Idx;
use rustc_data_structures::sync::Lrc;
use super::{MirBorrowckCtxt, Context};
use super::{Context, MirBorrowckCtxt};
use super::{InitializationRequiringAction, PrefixSet};
use dataflow::{ActiveBorrows, BorrowData, FlowAtLocation, MovingOutStatements};
use dataflow::move_paths::MovePathIndex;
@ -96,7 +96,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
} else {
true
}
},
}
_ => true,
};
@ -106,9 +106,11 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
None => "value".to_owned(),
};
err.note(&format!("move occurs because {} has type `{}`, \
which does not implement the `Copy` trait",
note_msg, ty));
err.note(&format!(
"move occurs because {} has type `{}`, \
which does not implement the `Copy` trait",
note_msg, ty
));
}
}
@ -154,7 +156,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
span,
&self.describe_place(place).unwrap_or("_".to_owned()),
self.retrieve_borrow_span(borrow),
&self.describe_place(&borrow.borrowed_place).unwrap_or("_".to_owned()),
&self.describe_place(&borrow.borrowed_place)
.unwrap_or("_".to_owned()),
Origin::Mir,
);
@ -175,8 +178,14 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
use rustc::hir::ExprClosure;
use rustc::mir::AggregateKind;
let local = match self.mir[location.block].statements.get(location.statement_index) {
Some(&Statement { kind: StatementKind::Assign(Place::Local(local), _), .. }) => local,
let local = match self.mir[location.block]
.statements
.get(location.statement_index)
{
Some(&Statement {
kind: StatementKind::Assign(Place::Local(local), _),
..
}) => local,
_ => return None,
};
@ -202,8 +211,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
.with_freevars(node_id, |freevars| {
for (v, place) in freevars.iter().zip(places) {
match *place {
Operand::Copy(Place::Local(l)) |
Operand::Move(Place::Local(l)) if local == l =>
Operand::Copy(Place::Local(l))
| Operand::Move(Place::Local(l)) if local == l =>
{
debug!(
"find_closure_span: found captured local {:?}",
@ -232,7 +241,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
context: Context,
(place, span): (&Place<'tcx>, Span),
gen_borrow_kind: BorrowKind,
issued_borrow: &BorrowData,
issued_borrow: &BorrowData<'tcx>,
end_issued_loan_span: Option<Span>,
) {
let issued_span = self.retrieve_borrow_span(issued_borrow);
@ -255,8 +264,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
"immutable",
"mutable",
) {
(BorrowKind::Shared, lft, _, BorrowKind::Mut { .. }, _, rgt) |
(BorrowKind::Mut { .. }, _, lft, BorrowKind::Shared, rgt, _) => self.tcx
(BorrowKind::Shared, lft, _, BorrowKind::Mut { .. }, _, rgt)
| (BorrowKind::Mut { .. }, _, lft, BorrowKind::Shared, rgt, _) => self.tcx
.cannot_reborrow_already_borrowed(
span,
&desc_place,
@ -355,11 +364,13 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
context: Context,
borrow: &BorrowData<'tcx>,
drop_span: Span,
borrows: &ActiveBorrows<'cx, 'gcx, 'tcx>
borrows: &ActiveBorrows<'cx, 'gcx, 'tcx>,
) {
let end_span = borrows.opt_region_end_span(&borrow.region);
let scope_tree = borrows.0.scope_tree();
let root_place = self.prefixes(&borrow.borrowed_place, PrefixSet::All).last().unwrap();
let root_place = self.prefixes(&borrow.borrowed_place, PrefixSet::All)
.last()
.unwrap();
let borrow_span = self.mir.source_info(borrow.location).span;
let proper_span = match *root_place {
@ -367,13 +378,18 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
_ => drop_span,
};
if self.access_place_error_reported.contains(&(root_place.clone(), borrow_span)) {
debug!("suppressing access_place error when borrow doesn't live long enough for {:?}",
borrow_span);
if self.access_place_error_reported
.contains(&(root_place.clone(), borrow_span))
{
debug!(
"suppressing access_place error when borrow doesn't live long enough for {:?}",
borrow_span
);
return;
}
self.access_place_error_reported.insert((root_place.clone(), borrow_span));
self.access_place_error_reported
.insert((root_place.clone(), borrow_span));
match (borrow.region, &self.describe_place(&borrow.borrowed_place)) {
(RegionKind::ReScope(_), Some(name)) => {
@ -385,9 +401,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
drop_span,
borrow_span,
proper_span,
end_span
end_span,
);
},
}
(RegionKind::ReScope(_), None) => {
self.report_scoped_temporary_value_does_not_live_long_enough(
context,
@ -396,14 +412,14 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
drop_span,
borrow_span,
proper_span,
end_span
end_span,
);
},
(RegionKind::ReEarlyBound(_), Some(name)) |
(RegionKind::ReFree(_), Some(name)) |
(RegionKind::ReStatic, Some(name)) |
(RegionKind::ReEmpty, Some(name)) |
(RegionKind::ReVar(_), Some(name)) => {
}
(RegionKind::ReEarlyBound(_), Some(name))
| (RegionKind::ReFree(_), Some(name))
| (RegionKind::ReStatic, Some(name))
| (RegionKind::ReEmpty, Some(name))
| (RegionKind::ReVar(_), Some(name)) => {
self.report_unscoped_local_value_does_not_live_long_enough(
context,
name,
@ -414,12 +430,12 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
proper_span,
end_span,
);
},
(RegionKind::ReEarlyBound(_), None) |
(RegionKind::ReFree(_), None) |
(RegionKind::ReStatic, None) |
(RegionKind::ReEmpty, None) |
(RegionKind::ReVar(_), None) => {
}
(RegionKind::ReEarlyBound(_), None)
| (RegionKind::ReFree(_), None)
| (RegionKind::ReStatic, None)
| (RegionKind::ReEmpty, None)
| (RegionKind::ReVar(_), None) => {
self.report_unscoped_temporary_value_does_not_live_long_enough(
context,
&scope_tree,
@ -429,13 +445,13 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
proper_span,
end_span,
);
},
(RegionKind::ReLateBound(_, _), _) |
(RegionKind::ReSkolemized(_, _), _) |
(RegionKind::ReClosureBound(_), _) |
(RegionKind::ReErased, _) => {
}
(RegionKind::ReLateBound(_, _), _)
| (RegionKind::ReSkolemized(_, _), _)
| (RegionKind::ReClosureBound(_), _)
| (RegionKind::ReErased, _) => {
span_bug!(drop_span, "region does not make sense in this context");
},
}
}
}
@ -450,11 +466,16 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
_proper_span: Span,
end_span: Option<Span>,
) {
let mut err = self.tcx.path_does_not_live_long_enough(borrow_span,
&format!("`{}`", name),
Origin::Mir);
let mut err = self.tcx.path_does_not_live_long_enough(
borrow_span,
&format!("`{}`", name),
Origin::Mir,
);
err.span_label(borrow_span, "borrowed value does not live long enough");
err.span_label(drop_span, format!("`{}` dropped here while still borrowed", name));
err.span_label(
drop_span,
format!("`{}` dropped here while still borrowed", name),
);
if let Some(end) = end_span {
err.span_label(end, "borrowed value needs to live until here");
}
@ -472,11 +493,14 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
proper_span: Span,
end_span: Option<Span>,
) {
let mut err = self.tcx.path_does_not_live_long_enough(proper_span,
"borrowed value",
Origin::Mir);
let mut err =
self.tcx
.path_does_not_live_long_enough(proper_span, "borrowed value", Origin::Mir);
err.span_label(proper_span, "temporary value does not live long enough");
err.span_label(drop_span, "temporary value dropped here while still borrowed");
err.span_label(
drop_span,
"temporary value dropped here while still borrowed",
);
err.note("consider using a `let` binding to increase its lifetime");
if let Some(end) = end_span {
err.span_label(end, "temporary value needs to live until here");
@ -496,14 +520,31 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
_proper_span: Span,
_end_span: Option<Span>,
) {
let mut err = self.tcx.path_does_not_live_long_enough(borrow_span,
&format!("`{}`", name),
Origin::Mir);
debug!(
"report_unscoped_local_value_does_not_live_long_enough(\
{:?}, {:?}, {:?}, {:?}, {:?}, {:?}\
)",
context, name, scope_tree, borrow, drop_span, borrow_span
);
let mut err = self.tcx.path_does_not_live_long_enough(
borrow_span,
&format!("`{}`", name),
Origin::Mir,
);
err.span_label(borrow_span, "borrowed value does not live long enough");
err.span_label(drop_span, "borrowed value only lives until here");
self.tcx.note_and_explain_region(scope_tree, &mut err,
"borrowed value must be valid for ",
borrow.region, "...");
if !self.tcx.sess.nll() {
self.tcx.note_and_explain_region(
scope_tree,
&mut err,
"borrowed value must be valid for ",
borrow.region,
"...",
);
}
self.explain_why_borrow_contains_point(context, borrow, &mut err);
err.emit();
}
@ -516,16 +557,31 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
drop_span: Span,
_borrow_span: Span,
proper_span: Span,
_end_span: Option<Span>
_end_span: Option<Span>,
) {
let mut err = self.tcx.path_does_not_live_long_enough(proper_span,
"borrowed value",
Origin::Mir);
debug!(
"report_unscoped_temporary_value_does_not_live_long_enough(\
{:?}, {:?}, {:?}, {:?}, {:?}\
)",
context, scope_tree, borrow, drop_span, proper_span
);
let mut err =
self.tcx
.path_does_not_live_long_enough(proper_span, "borrowed value", Origin::Mir);
err.span_label(proper_span, "temporary value does not live long enough");
err.span_label(drop_span, "temporary value only lives until here");
self.tcx.note_and_explain_region(scope_tree, &mut err,
"borrowed value must be valid for ",
borrow.region, "...");
if !self.tcx.sess.nll() {
self.tcx.note_and_explain_region(
scope_tree,
&mut err,
"borrowed value must be valid for ",
borrow.region,
"...",
);
}
self.explain_why_borrow_contains_point(context, borrow, &mut err);
err.emit();
}
@ -534,7 +590,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
&mut self,
context: Context,
(place, span): (&Place<'tcx>, Span),
loan: &BorrowData,
loan: &BorrowData<'tcx>,
) {
let mut err = self.tcx.cannot_assign_to_borrowed(
span,
@ -706,9 +762,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
ProjectionElem::Field(_, field_type) => {
self.describe_field_from_ty(&field_type, field)
}
ProjectionElem::Index(..) |
ProjectionElem::ConstantIndex { .. } |
ProjectionElem::Subslice { .. } => {
ProjectionElem::Index(..)
| ProjectionElem::ConstantIndex { .. }
| ProjectionElem::Subslice { .. } => {
format!("{}", self.describe_field(&proj.base, field))
}
},
@ -765,13 +821,11 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
Place::Local(local) => {
let local = &self.mir.local_decls[*local];
Some(local.ty)
},
}
Place::Static(ref st) => Some(st.ty),
Place::Projection(ref proj) => {
match proj.elem {
ProjectionElem::Field(_, ty) => Some(ty),
_ => None,
}
Place::Projection(ref proj) => match proj.elem {
ProjectionElem::Field(_, ty) => Some(ty),
_ => None,
},
}
}

View File

@ -21,7 +21,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
pub(in borrow_check) fn explain_why_borrow_contains_point(
&self,
context: Context,
borrow: &BorrowData<'_>,
borrow: &BorrowData<'tcx>,
err: &mut DiagnosticBuilder<'_>,
) {
if let Some(regioncx) = &self.nonlexical_regioncx {
@ -70,9 +70,18 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
}
}
_ => {
cause.label_diagnostic(mir, err);
Cause::UniversalRegion(region_vid) => {
if let Some(region) = regioncx.to_error_region(region_vid) {
self.tcx.note_and_explain_free_region(
err,
"borrowed value must be valid for ",
region,
"...",
);
}
}
_ => {}
}
}
}

View File

@ -26,7 +26,6 @@ use rustc::ty::{self, RegionVid, Ty, TypeFoldable};
use rustc::util::common::ErrorReported;
use rustc_data_structures::bitvec::BitVector;
use rustc_data_structures::indexed_vec::IndexVec;
use rustc_errors::DiagnosticBuilder;
use std::fmt;
use std::rc::Rc;
use syntax::ast;
@ -435,7 +434,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
self.check_type_tests(infcx, mir, mir_def_id, outlives_requirements.as_mut());
self.check_universal_regions(infcx, mir, mir_def_id, outlives_requirements.as_mut());
self.check_universal_regions(infcx, mir_def_id, outlives_requirements.as_mut());
let outlives_requirements = outlives_requirements.unwrap_or(vec![]);
@ -574,10 +573,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
// an error that multiple bounds are required.
tcx.sess.span_err(
type_test.span,
&format!(
"`{}` does not live long enough",
type_test.generic_kind,
),
&format!("`{}` does not live long enough", type_test.generic_kind,),
);
}
}
@ -589,13 +585,13 @@ impl<'tcx> RegionInferenceContext<'tcx> {
/// existentially bound, then we check its inferred value and try
/// to find a good name from that. Returns `None` if we can't find
/// one (e.g., this is just some random part of the CFG).
fn to_error_region(&self, r: RegionVid) -> Option<ty::Region<'tcx>> {
pub fn to_error_region(&self, r: RegionVid) -> Option<ty::Region<'tcx>> {
if self.universal_regions.is_universal_region(r) {
return self.definitions[r].external_name;
} else {
let inferred_values = self.inferred_values
.as_ref()
.expect("region values not yet inferred");
.as_ref()
.expect("region values not yet inferred");
let upper_bound = self.universal_upper_bound(r);
if inferred_values.contains(r, upper_bound) {
self.to_error_region(upper_bound)
@ -807,9 +803,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
) -> bool {
debug!(
"eval_region_test(point={:?}, lower_bound={:?}, test={:?})",
point,
lower_bound,
test
point, lower_bound, test
);
match test {
@ -841,9 +835,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
) -> bool {
debug!(
"eval_outlives({:?}: {:?} @ {:?})",
sup_region,
sub_region,
point
sup_region, sub_region, point
);
// Roughly speaking, do a DFS of all region elements reachable
@ -897,7 +889,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
fn check_universal_regions<'gcx>(
&self,
infcx: &InferCtxt<'_, 'gcx, 'tcx>,
mir: &Mir<'tcx>,
mir_def_id: DefId,
mut propagated_outlives_requirements: Option<&mut Vec<ClosureOutlivesRequirement<'gcx>>>,
) {
@ -913,7 +904,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
for (fr, _) in universal_definitions {
self.check_universal_region(
infcx,
mir,
mir_def_id,
fr,
&mut propagated_outlives_requirements,
@ -932,7 +922,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
fn check_universal_region<'gcx>(
&self,
infcx: &InferCtxt<'_, 'gcx, 'tcx>,
mir: &Mir<'tcx>,
mir_def_id: DefId,
longer_fr: RegionVid,
propagated_outlives_requirements: &mut Option<&mut Vec<ClosureOutlivesRequirement<'gcx>>>,
@ -951,8 +940,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
debug!(
"check_universal_region: fr={:?} does not outlive shorter_fr={:?}",
longer_fr,
shorter_fr,
longer_fr, shorter_fr,
);
let blame_span = self.blame_span(longer_fr, shorter_fr);
@ -990,7 +978,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
// Note: in this case, we use the unapproximated regions
// to report the error. This gives better error messages
// in some cases.
self.report_error(infcx, mir, mir_def_id, longer_fr, shorter_fr, blame_span);
self.report_error(infcx, mir_def_id, longer_fr, shorter_fr, blame_span);
}
}
@ -1005,7 +993,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
fn report_error(
&self,
infcx: &InferCtxt<'_, '_, 'tcx>,
mir: &Mir<'tcx>,
mir_def_id: DefId,
fr: RegionVid,
outlived_fr: RegionVid,
@ -1039,12 +1026,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
&format!("{} does not outlive {}", fr_string, outlived_fr_string,),
);
// Find out why `fr` had to outlive `outlived_fr`...
let inferred_values = self.inferred_values.as_ref().unwrap();
if let Some(cause) = inferred_values.cause(fr, outlived_fr) {
cause.label_diagnostic(mir, &mut diag);
}
diag.emit();
}
@ -1134,10 +1115,7 @@ impl fmt::Debug for Constraint {
write!(
formatter,
"({:?}: {:?} @ {:?}) due to {:?}",
self.sup,
self.sub,
self.point,
self.span
self.sup, self.sub, self.point, self.span
)
}
}
@ -1187,9 +1165,7 @@ impl<'gcx, 'tcx> ClosureRegionRequirementsExt<'gcx, 'tcx> for ClosureRegionRequi
debug!(
"apply_requirements(location={:?}, closure_def_id={:?}, closure_substs={:?})",
location,
closure_def_id,
closure_substs
location, closure_def_id, closure_substs
);
// Get Tu.
@ -1217,9 +1193,7 @@ impl<'gcx, 'tcx> ClosureRegionRequirementsExt<'gcx, 'tcx> for ClosureRegionRequi
"apply_requirements: region={:?} \
outlived_region={:?} \
outlives_requirement={:?}",
region,
outlived_region,
outlives_requirement,
region, outlived_region, outlives_requirement,
);
infcx.sub_regions(origin, outlived_region, region);
}
@ -1230,9 +1204,7 @@ impl<'gcx, 'tcx> ClosureRegionRequirementsExt<'gcx, 'tcx> for ClosureRegionRequi
"apply_requirements: ty={:?} \
outlived_region={:?} \
outlives_requirement={:?}",
ty,
outlived_region,
outlives_requirement,
ty, outlived_region, outlives_requirement,
);
infcx.register_region_obligation(
body_id,
@ -1285,77 +1257,14 @@ impl CauseExt for Rc<Cause> {
}
impl Cause {
pub(crate) fn label_diagnostic(&self, mir: &Mir<'_>, diag: &mut DiagnosticBuilder<'_>) {
// The cause information is pretty messy. Only dump it as an
// internal debugging aid if -Znll-dump-cause is given.
let nll_dump_cause = ty::tls::with(|tcx| tcx.sess.nll_dump_cause());
if !nll_dump_cause {
return;
}
let mut string = String::new();
self.push_diagnostic_string(mir, &mut string);
diag.note(&string);
}
fn push_diagnostic_string(&self, mir: &Mir<'_>, string: &mut String) {
match self {
Cause::LiveVar(local, location) => {
string.push_str(&format!("because `{:?}` is live at {:?}", local, location));
}
Cause::DropVar(local, location) => {
string.push_str(&format!(
"because `{:?}` is dropped at {:?}",
local,
location
));
}
Cause::LiveOther(location) => {
string.push_str(&format!(
"because of a general liveness constraint at {:?}",
location
));
}
Cause::UniversalRegion(region_vid) => {
string.push_str(&format!(
"because `{:?}` is universally quantified",
region_vid
));
}
Cause::Outlives {
original_cause,
constraint_location,
constraint_span: _,
} => {
string.push_str(&format!(
"because of an outlives relation created at `{:?}`\n",
constraint_location
));
original_cause.push_diagnostic_string(mir, string);
}
}
}
pub(crate) fn root_cause(&self) -> &Cause {
match self {
Cause::LiveVar(..) |
Cause::DropVar(..) |
Cause::LiveOther(..) |
Cause::UniversalRegion(..) => {
self
}
Cause::LiveVar(..)
| Cause::DropVar(..)
| Cause::LiveOther(..)
| Cause::UniversalRegion(..) => self,
Cause::Outlives {
original_cause,
..
} => {
original_cause.root_cause()
}
Cause::Outlives { original_cause, .. } => original_cause.root_cause(),
}
}
}

View File

@ -0,0 +1,26 @@
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// compile-flags: -Znll-dump-cause
#![feature(nll)]
fn gimme(x: &(u32,)) -> &u32 {
&x.0
}
fn main() {
let x = gimme({
let v = (22,);
&v
//~^ ERROR `v` does not live long enough [E0597]
});
println!("{:?}", x);
}

View File

@ -0,0 +1,17 @@
error[E0597]: `v` does not live long enough
--> $DIR/borrowed-local-error.rs:22:9
|
LL | let x = gimme({
| _____________-
LL | | let v = (22,);
LL | | &v
| | ^^ borrowed value does not live long enough
LL | | //~^ ERROR `v` does not live long enough [E0597]
LL | | });
| |_____-- borrow later used here
| |
| borrowed value only lives until here
error: aborting due to previous error
If you want more information on this error, try using "rustc --explain E0597"

View File

@ -0,0 +1,26 @@
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// compile-flags: -Znll-dump-cause
#![feature(nll)]
fn gimme(x: &(u32,)) -> &u32 {
&x.0
}
fn main() {
let x = gimme({
let v = 22;
&(v,)
//~^ ERROR borrowed value does not live long enough [E0597]
});
println!("{:?}", x);
}

View File

@ -0,0 +1,14 @@
error[E0597]: borrowed value does not live long enough
--> $DIR/borrowed-temporary-error.rs:22:10
|
LL | &(v,)
| ^^^^ temporary value does not live long enough
LL | //~^ ERROR borrowed value does not live long enough [E0597]
LL | });
| - temporary value only lives until here
LL | println!("{:?}", x);
| - borrow later used here
error: aborting due to previous error
If you want more information on this error, try using "rustc --explain E0597"

View File

@ -0,0 +1,22 @@
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// compile-flags: -Znll-dump-cause
#![feature(nll)]
#![allow(warnings)]
fn foo<'a>(x: &'a (u32,)) -> &'a u32 {
let v = 22;
&v
//~^ ERROR `v` does not live long enough [E0597]
}
fn main() {}

View File

@ -0,0 +1,18 @@
error[E0597]: `v` does not live long enough
--> $DIR/borrowed-universal-error-2.rs:18:5
|
LL | &v
| ^^ borrowed value does not live long enough
LL | //~^ ERROR `v` does not live long enough [E0597]
LL | }
| - borrowed value only lives until here
|
note: borrowed value must be valid for the lifetime 'a as defined on the function body at 16:1...
--> $DIR/borrowed-universal-error-2.rs:16:1
|
LL | fn foo<'a>(x: &'a (u32,)) -> &'a u32 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error
If you want more information on this error, try using "rustc --explain E0597"

View File

@ -0,0 +1,26 @@
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// compile-flags: -Znll-dump-cause
#![feature(nll)]
#![allow(warnings)]
fn gimme(x: &(u32,)) -> &u32 {
&x.0
}
fn foo<'a>(x: &'a (u32,)) -> &'a u32 {
let v = 22;
gimme(&(v,))
//~^ ERROR borrowed value does not live long enough [E0597]
}
fn main() {}

View File

@ -0,0 +1,18 @@
error[E0597]: borrowed value does not live long enough
--> $DIR/borrowed-universal-error.rs:22:12
|
LL | gimme(&(v,))
| ^^^^ temporary value does not live long enough
LL | //~^ ERROR borrowed value does not live long enough [E0597]
LL | }
| - temporary value only lives until here
|
note: borrowed value must be valid for the lifetime 'a as defined on the function body at 20:1...
--> $DIR/borrowed-universal-error.rs:20:1
|
LL | fn foo<'a>(x: &'a (u32,)) -> &'a u32 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error
If you want more information on this error, try using "rustc --explain E0597"

View File

@ -9,8 +9,6 @@ LL | }
LL |
LL | deref(p);
| - borrow later used here
|
= note: borrowed value must be valid for lifetime '_#5r...
error: aborting due to previous error

View File

@ -34,8 +34,6 @@ LL | }
LL |
LL | deref(p);
| - borrow later used here
|
= note: borrowed value must be valid for lifetime '_#6r...
error: aborting due to previous error

View File

@ -61,8 +61,6 @@ LL | }
LL |
LL | deref(p);
| - borrow later used here
|
= note: borrowed value must be valid for lifetime '_#4r...
error: aborting due to previous error

View File

@ -38,8 +38,6 @@ LL | }
LL |
LL | deref(p);
| - borrow later used here
|
= note: borrowed value must be valid for lifetime '_#4r...
error: aborting due to previous error

View File

@ -78,8 +78,6 @@ LL | let cell = Cell::new(&a);
...
LL | }
| - borrowed value only lives until here
|
= note: borrowed value must be valid for lifetime '_#2r...
error: aborting due to 2 previous errors

View File

@ -6,8 +6,6 @@ LL | let ref mut x = 1234543; //~ ERROR borrowed value does not live long en
LL | x
LL | }
| - temporary value only lives until here
|
= note: borrowed value must be valid for lifetime '_#2r...
error: aborting due to previous error