Auto merge of #52648 - davidtwco:issue-52533, r=nikomatsakis

[nll] improve the "fully elaborated type" case in region errors

Fixes #52533.

r? @nikomatsakis
This commit is contained in:
bors 2018-07-27 13:01:48 +00:00
commit b6cbc1e147
30 changed files with 327 additions and 148 deletions

View File

@ -74,7 +74,7 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for FindLocalByTypeVisitor<'a, 'gcx, 'tcx> {
impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
fn extract_type_name(&self, ty: &'a Ty<'tcx>) -> String {
pub fn extract_type_name(&self, ty: &'a Ty<'tcx>) -> String {
if let ty::TyInfer(ty::TyVar(ty_vid)) = (*ty).sty {
let ty_vars = self.type_variables.borrow();
if let TypeVariableOrigin::TypeParameterDefinition(_, name) =

View File

@ -19,7 +19,7 @@ use ty::{TyError, TyStr, TyArray, TySlice, TyFloat, TyFnDef, TyFnPtr};
use ty::{TyParam, TyRawPtr, TyRef, TyNever, TyTuple};
use ty::{TyClosure, TyGenerator, TyGeneratorWitness, TyForeign, TyProjection, TyAnon};
use ty::{TyDynamic, TyInt, TyUint, TyInfer};
use ty::{self, Ty, TyCtxt, TypeFoldable, GenericParamCount, GenericParamDefKind};
use ty::{self, RegionVid, Ty, TyCtxt, TypeFoldable, GenericParamCount, GenericParamDefKind};
use util::nodemap::FxHashSet;
use std::cell::Cell;
@ -32,6 +32,12 @@ use syntax::ast::CRATE_NODE_ID;
use syntax::symbol::{Symbol, InternedString};
use hir;
thread_local! {
/// Mechanism for highlighting of specific regions for display in NLL region inference errors.
/// Contains region to highlight and counter for number to use when highlighting.
static HIGHLIGHT_REGION: Cell<Option<(RegionVid, usize)>> = Cell::new(None)
}
macro_rules! gen_display_debug_body {
( $with:path ) => {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
@ -562,6 +568,19 @@ pub fn parameterized<F: fmt::Write>(f: &mut F,
PrintContext::new().parameterized(f, substs, did, projections)
}
fn get_highlight_region() -> Option<(RegionVid, usize)> {
HIGHLIGHT_REGION.with(|hr| hr.get())
}
pub fn with_highlight_region<R>(r: RegionVid, counter: usize, op: impl FnOnce() -> R) -> R {
HIGHLIGHT_REGION.with(|hr| {
assert_eq!(hr.get(), None);
hr.set(Some((r, counter)));
let r = op();
hr.set(None);
r
})
}
impl<'a, T: Print> Print for &'a T {
fn print<F: fmt::Write>(&self, f: &mut F, cx: &mut PrintContext) -> fmt::Result {
@ -733,7 +752,7 @@ define_print! {
define_print! {
() ty::RegionKind, (self, f, cx) {
display {
if cx.is_verbose {
if cx.is_verbose || get_highlight_region().is_some() {
return self.print_debug(f, cx);
}
@ -905,6 +924,15 @@ impl fmt::Debug for ty::FloatVid {
impl fmt::Debug for ty::RegionVid {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if let Some((region, counter)) = get_highlight_region() {
debug!("RegionVid.fmt: region={:?} self={:?} counter={:?}", region, self, counter);
return if *self == region {
write!(f, "'{:?}", counter)
} else {
write!(f, "'_")
}
}
write!(f, "'_#{}r", self.index())
}
}
@ -1022,9 +1050,11 @@ define_print! {
TyRef(r, ty, mutbl) => {
write!(f, "&")?;
let s = r.print_to_string(cx);
write!(f, "{}", s)?;
if !s.is_empty() {
write!(f, " ")?;
if s != "'_" {
write!(f, "{}", s)?;
if !s.is_empty() {
write!(f, " ")?;
}
}
ty::TypeAndMut { ty, mutbl }.print(f, cx)
}

View File

@ -31,9 +31,7 @@ mod var_name;
enum ConstraintCategory {
Cast,
Assignment,
AssignmentToUpvar,
Return,
CallArgumentToUpvar,
CallArgument,
Other,
Boring,
@ -41,16 +39,13 @@ enum ConstraintCategory {
impl fmt::Display for ConstraintCategory {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
// Must end with a space. Allows for empty names to be provided.
match self {
ConstraintCategory::Assignment | ConstraintCategory::AssignmentToUpvar => {
write!(f, "assignment")
}
ConstraintCategory::Return => write!(f, "return"),
ConstraintCategory::Cast => write!(f, "cast"),
ConstraintCategory::CallArgument | ConstraintCategory::CallArgumentToUpvar => {
write!(f, "argument")
}
_ => write!(f, "free region"),
ConstraintCategory::Assignment => write!(f, "assignment "),
ConstraintCategory::Return => write!(f, "return "),
ConstraintCategory::Cast => write!(f, "cast "),
ConstraintCategory::CallArgument => write!(f, "argument "),
_ => write!(f, ""),
}
}
}
@ -224,10 +219,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
"constraint_is_interesting: locations={:?} constraint={:?}",
constraint.locations, constraint
);
if let Locations::Interesting(_) = constraint.locations {
true
} else {
false
match constraint.locations {
Locations::Interesting(_) | Locations::All => true,
_ => false,
}
}
@ -320,45 +315,26 @@ impl<'tcx> RegionInferenceContext<'tcx> {
}
}
let category = match (
category,
let (fr_is_local, outlived_fr_is_local): (bool, bool) = (
self.universal_regions.is_local_free_region(fr),
self.universal_regions.is_local_free_region(outlived_fr),
) {
(ConstraintCategory::Assignment, true, false) => ConstraintCategory::AssignmentToUpvar,
(ConstraintCategory::CallArgument, true, false) => {
ConstraintCategory::CallArgumentToUpvar
}
(category, _, _) => category,
};
);
debug!("report_error: fr_is_local={:?} outlived_fr_is_local={:?} category={:?}",
fr_is_local, outlived_fr_is_local, category);
debug!("report_error: category={:?}", category);
match category {
ConstraintCategory::AssignmentToUpvar | ConstraintCategory::CallArgumentToUpvar => self
.report_closure_error(
mir,
infcx,
mir_def_id,
fr,
outlived_fr,
category,
span,
errors_buffer,
),
_ => self.report_general_error(
mir,
infcx,
mir_def_id,
fr,
outlived_fr,
category,
span,
errors_buffer,
),
}
match (category, fr_is_local, outlived_fr_is_local) {
(ConstraintCategory::Assignment, true, false) |
(ConstraintCategory::CallArgument, true, false) =>
self.report_escaping_data_error(mir, infcx, mir_def_id, fr, outlived_fr,
category, span, errors_buffer),
_ =>
self.report_general_error(mir, infcx, mir_def_id, fr, fr_is_local,
outlived_fr, outlived_fr_is_local,
category, span, errors_buffer),
};
}
fn report_closure_error(
fn report_escaping_data_error(
&self,
mir: &Mir<'tcx>,
infcx: &InferCtxt<'_, '_, 'tcx>,
@ -373,29 +349,23 @@ impl<'tcx> RegionInferenceContext<'tcx> {
let outlived_fr_name_and_span =
self.get_var_name_and_span_for_region(infcx.tcx, mir, outlived_fr);
let escapes_from = if infcx.tcx.is_closure(mir_def_id) { "closure" } else { "function" };
if fr_name_and_span.is_none() && outlived_fr_name_and_span.is_none() {
return self.report_general_error(
mir,
infcx,
mir_def_id,
fr,
outlived_fr,
category,
span,
errors_buffer,
);
return self.report_general_error(mir, infcx, mir_def_id,
fr, true, outlived_fr, false,
category, span, errors_buffer);
}
let mut diag = infcx
.tcx
.sess
.struct_span_err(span, &format!("borrowed data escapes outside of closure"));
let mut diag = infcx.tcx.sess.struct_span_err(
span, &format!("borrowed data escapes outside of {}", escapes_from),
);
if let Some((outlived_fr_name, outlived_fr_span)) = outlived_fr_name_and_span {
if let Some(name) = outlived_fr_name {
diag.span_label(
outlived_fr_span,
format!("`{}` is declared here, outside of the closure body", name),
format!("`{}` is declared here, outside of the {} body", name, escapes_from),
);
}
}
@ -404,13 +374,12 @@ impl<'tcx> RegionInferenceContext<'tcx> {
if let Some(name) = fr_name {
diag.span_label(
fr_span,
format!(
"`{}` is a reference that is only valid in the closure body",
name
),
format!("`{}` is a reference that is only valid in the {} body",
name, escapes_from),
);
diag.span_label(span, format!("`{}` escapes the closure body here", name));
diag.span_label(span, format!("`{}` escapes the {} body here",
name, escapes_from));
}
}
@ -423,7 +392,9 @@ impl<'tcx> RegionInferenceContext<'tcx> {
infcx: &InferCtxt<'_, '_, 'tcx>,
mir_def_id: DefId,
fr: RegionVid,
fr_is_local: bool,
outlived_fr: RegionVid,
outlived_fr_is_local: bool,
category: ConstraintCategory,
span: Span,
errors_buffer: &mut Vec<Diagnostic>,
@ -434,17 +405,28 @@ impl<'tcx> RegionInferenceContext<'tcx> {
);
let counter = &mut 1;
let fr_name = self.give_region_a_name(infcx.tcx, mir, mir_def_id, fr, counter, &mut diag);
let outlived_fr_name =
self.give_region_a_name(infcx.tcx, mir, mir_def_id, outlived_fr, counter, &mut diag);
let fr_name = self.give_region_a_name(
infcx, mir, mir_def_id, fr, counter, &mut diag);
let outlived_fr_name = self.give_region_a_name(
infcx, mir, mir_def_id, outlived_fr, counter, &mut diag);
diag.span_label(
span,
format!(
"{} requires that `{}` must outlive `{}`",
category, fr_name, outlived_fr_name,
),
);
let mir_def_name = if infcx.tcx.is_closure(mir_def_id) { "closure" } else { "function" };
match (category, outlived_fr_is_local, fr_is_local) {
(ConstraintCategory::Return, true, _) => {
diag.span_label(span, format!(
"{} was supposed to return data with lifetime `{}` but it is returning \
data with lifetime `{}`",
mir_def_name, fr_name, outlived_fr_name,
));
},
_ => {
diag.span_label(span, format!(
"{}requires that `{}` must outlive `{}`",
category, fr_name, outlived_fr_name,
));
},
}
diag.buffer(errors_buffer);
}

View File

@ -12,9 +12,11 @@ use borrow_check::nll::region_infer::RegionInferenceContext;
use borrow_check::nll::ToRegionVid;
use rustc::hir;
use rustc::hir::def_id::DefId;
use rustc::infer::InferCtxt;
use rustc::mir::Mir;
use rustc::ty::subst::{Substs, UnpackedKind};
use rustc::ty::{self, RegionVid, Ty, TyCtxt};
use rustc::util::ppaux::with_highlight_region;
use rustc_errors::DiagnosticBuilder;
use syntax::ast::Name;
use syntax::symbol::keywords;
@ -48,7 +50,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
/// and then return the name `'1` for us to use.
crate fn give_region_a_name(
&self,
tcx: TyCtxt<'_, '_, 'tcx>,
infcx: &InferCtxt<'_, '_, 'tcx>,
mir: &Mir<'tcx>,
mir_def_id: DefId,
fr: RegionVid,
@ -59,17 +61,18 @@ impl<'tcx> RegionInferenceContext<'tcx> {
assert!(self.universal_regions.is_universal_region(fr));
self.give_name_from_error_region(tcx, mir_def_id, fr, counter, diag)
self.give_name_from_error_region(infcx.tcx, mir_def_id, fr, counter, diag)
.or_else(|| {
self.give_name_if_anonymous_region_appears_in_arguments(
tcx, mir, mir_def_id, fr, counter, diag)
infcx, mir, mir_def_id, fr, counter, diag)
})
.or_else(|| {
self.give_name_if_anonymous_region_appears_in_upvars(
tcx, mir, fr, counter, diag)
infcx.tcx, mir, fr, counter, diag)
})
.or_else(|| {
self.give_name_if_anonymous_region_appears_in_output(tcx, mir, fr, counter, diag)
self.give_name_if_anonymous_region_appears_in_output(
infcx.tcx, mir, fr, counter, diag)
})
.unwrap_or_else(|| span_bug!(mir.span, "can't make a name for free region {:?}", fr))
}
@ -130,7 +133,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
/// ```
fn give_name_if_anonymous_region_appears_in_arguments(
&self,
tcx: TyCtxt<'_, '_, 'tcx>,
infcx: &InferCtxt<'_, '_, 'tcx>,
mir: &Mir<'tcx>,
mir_def_id: DefId,
fr: RegionVid,
@ -138,12 +141,13 @@ impl<'tcx> RegionInferenceContext<'tcx> {
diag: &mut DiagnosticBuilder<'_>,
) -> Option<InternedString> {
let implicit_inputs = self.universal_regions.defining_ty.implicit_inputs();
let argument_index = self.get_argument_index_for_region(tcx, fr)?;
let argument_index = self.get_argument_index_for_region(infcx.tcx, fr)?;
let arg_ty =
self.universal_regions.unnormalized_input_tys[implicit_inputs + argument_index];
if let Some(region_name) = self.give_name_if_we_can_match_hir_ty_from_argument(
tcx,
infcx,
mir,
mir_def_id,
fr,
arg_ty,
@ -169,7 +173,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
fn give_name_if_we_can_match_hir_ty_from_argument(
&self,
tcx: TyCtxt<'_, '_, 'tcx>,
infcx: &InferCtxt<'_, '_, 'tcx>,
mir: &Mir<'tcx>,
mir_def_id: DefId,
needle_fr: RegionVid,
argument_ty: Ty<'tcx>,
@ -177,17 +182,24 @@ impl<'tcx> RegionInferenceContext<'tcx> {
counter: &mut usize,
diag: &mut DiagnosticBuilder<'_>,
) -> Option<InternedString> {
let mir_node_id = tcx.hir.as_local_node_id(mir_def_id)?;
let fn_decl = tcx.hir.fn_decl(mir_node_id)?;
let mir_node_id = infcx.tcx.hir.as_local_node_id(mir_def_id)?;
let fn_decl = infcx.tcx.hir.fn_decl(mir_node_id)?;
let argument_hir_ty: &hir::Ty = &fn_decl.inputs[argument_index];
match argument_hir_ty.node {
// This indicates a variable with no type annotation, like
// `|x|`... in that case, we can't highlight the type but
// must highlight the variable.
hir::TyKind::Infer => None,
hir::TyKind::Infer => self.give_name_if_we_cannot_match_hir_ty(
infcx,
mir,
needle_fr,
argument_ty,
counter,
diag,
),
_ => self.give_name_if_we_can_match_hir_ty(
tcx,
infcx.tcx,
needle_fr,
argument_ty,
argument_hir_ty,
@ -197,6 +209,49 @@ impl<'tcx> RegionInferenceContext<'tcx> {
}
}
/// Attempts to highlight the specific part of a type in an argument
/// that has no type annotation.
/// For example, we might produce an annotation like this:
///
/// ```
/// | foo(|a, b| b)
/// | - -
/// | | |
/// | | has type `&'1 u32`
/// | has type `&'2 u32`
/// ```
fn give_name_if_we_cannot_match_hir_ty(
&self,
infcx: &InferCtxt<'_, '_, 'tcx>,
mir: &Mir<'tcx>,
needle_fr: RegionVid,
argument_ty: Ty<'tcx>,
counter: &mut usize,
diag: &mut DiagnosticBuilder<'_>,
) -> Option<InternedString> {
let type_name = with_highlight_region(needle_fr, *counter, || {
infcx.extract_type_name(&argument_ty)
});
debug!("give_name_if_we_cannot_match_hir_ty: type_name={:?} needle_fr={:?}",
type_name, needle_fr);
let assigned_region_name = if type_name.find(&format!("'{}", counter)).is_some() {
// Only add a label if we can confirm that a region was labelled.
let argument_index = self.get_argument_index_for_region(infcx.tcx, needle_fr)?;
let (_, span) = self.get_argument_name_and_span_for_region(mir, argument_index);
diag.span_label(span, format!("has type `{}`", type_name));
// This counter value will already have been used, so this function will increment it
// so the next value will be used next and return the region name that would have been
// used.
Some(self.synthesize_region_name(counter))
} else {
None
};
assigned_region_name
}
/// Attempts to highlight the specific part of a type annotation
/// that contains the anonymous reference we want to give a name
/// to. For example, we might produce an annotation like this:

View File

@ -10,8 +10,8 @@ error: unsatisfied lifetime constraints
LL | invoke(&x, |a, b| if a > b { a } else { b }); //~ ERROR E0495
| ----------^^^^^-----------------
| | | |
| | | free region requires that `'1` must outlive `'2`
| | lifetime `'1` appears in this argument
| | | requires that `'1` must outlive `'2`
| | has type `&'1 i32`
| lifetime `'2` appears in return type
error: aborting due to previous error

View File

@ -10,21 +10,19 @@ warning: not reporting region error due to nll
LL | self.x.iter().map(|a| a.0)
| ^^^^
error: borrowed data escapes outside of closure
error: unsatisfied lifetime constraints
--> $DIR/static-return-lifetime-infered.rs:17:9
|
LL | fn iter_values_anon(&self) -> impl Iterator<Item=u32> {
| ----- `self` is a reference that is only valid in the closure body
| - let's call the lifetime of this reference `'1`
LL | self.x.iter().map(|a| a.0)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ `self` escapes the closure body here
| ^^^^^^^^^^^^^ requires that `'1` must outlive `'static`
error: borrowed data escapes outside of closure
error: unsatisfied lifetime constraints
--> $DIR/static-return-lifetime-infered.rs:21:9
|
LL | fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> {
| -------- `self` is a reference that is only valid in the closure body
LL | self.x.iter().map(|a| a.0)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ `self` escapes the closure body here
| ^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
error: aborting due to 2 previous errors

View File

@ -4,13 +4,13 @@ warning: not reporting region error due to nll
LL | static_val(x); //~ ERROR cannot infer
| ^
error: borrowed data escapes outside of closure
error: borrowed data escapes outside of function
--> $DIR/dyn-trait.rs:32:5
|
LL | fn with_dyn_debug_static<'a>(x: Box<dyn Debug + 'a>) {
| - `x` is a reference that is only valid in the closure body
| - `x` is a reference that is only valid in the function body
LL | static_val(x); //~ ERROR cannot infer
| ^^^^^^^^^^^^^ `x` escapes the closure body here
| ^^^^^^^^^^^^^ `x` escapes the function body here
error: aborting due to previous error

View File

@ -8,7 +8,7 @@ error: unsatisfied lifetime constraints
--> $DIR/issue-10291.rs:12:5
|
LL | drop::<Box<for<'z> FnMut(&'z isize) -> &'z isize>>(Box::new(|z| {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ free region requires that `'x` must outlive `'static`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'x` must outlive `'static`
error: aborting due to previous error

View File

@ -10,13 +10,13 @@ warning: not reporting region error due to nll
LL | self.a(); //~ ERROR cannot infer
| ^
error: borrowed data escapes outside of closure
error: borrowed data escapes outside of function
--> $DIR/issue-16683.rs:14:9
|
LL | fn b(&self) {
| ----- `self` is a reference that is only valid in the closure body
| ----- `self` is a reference that is only valid in the function body
LL | self.a(); //~ ERROR cannot infer
| ^^^^^^^^ `self` escapes the closure body here
| ^^^^^^^^ `self` escapes the function body here
error: aborting due to previous error

View File

@ -10,13 +10,13 @@ warning: not reporting region error due to nll
LL | self.foo();
| ^^^
error: borrowed data escapes outside of closure
error: borrowed data escapes outside of function
--> $DIR/issue-17758.rs:17:9
|
LL | fn bar(&self) {
| ----- `self` is a reference that is only valid in the closure body
| ----- `self` is a reference that is only valid in the function body
LL | self.foo();
| ^^^^^^^^^^ `self` escapes the closure body here
| ^^^^^^^^^^ `self` escapes the function body here
error: aborting due to previous error

View File

@ -6,7 +6,7 @@ LL | || {
| |_____|
| ||
LL | || &mut x
| || ^^^^^^ free region requires that `'1` must outlive `'2`
| || ^^^^^^ return requires that `'1` must outlive `'2`
LL | || };
| || -
| ||_____|

View File

@ -9,7 +9,7 @@ LL | || || {
| ||_________^
LL | ||| x.push(())
LL | ||| }
| |||_________^ free region requires that `'1` must outlive `'2`
| |||_________^ requires that `'1` must outlive `'2`
LL | || };
| || -
| ||_____|

View File

@ -8,7 +8,7 @@ error: unsatisfied lifetime constraints
--> $DIR/issue-52213.rs:13:11
|
LL | ((u,),) => u,
| ^ free region requires that `'a` must outlive `'b`
| ^ requires that `'a` must outlive `'b`
error: aborting due to previous error

View File

@ -0,0 +1,17 @@
warning: not reporting region error due to nll
--> $DIR/issue-52533-1.rs:19:18
|
LL | gimme(|x, y| y)
| ^
error: unsatisfied lifetime constraints
--> $DIR/issue-52533-1.rs:19:18
|
LL | gimme(|x, y| y)
| - - ^ closure was supposed to return data with lifetime `'1` but it is returning data with lifetime `'2`
| | |
| | has type `&Foo<'_, '1, u32>`
| has type `&Foo<'_, '2, u32>`
error: aborting due to previous error

View File

@ -0,0 +1,21 @@
// 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.
#![allow(warnings)]
struct Foo<'a, 'b, T: 'a + 'b> { x: &'a T, y: &'b T }
fn gimme(_: impl for<'a, 'b, 'c> FnOnce(&'a Foo<'a, 'b, u32>,
&'a Foo<'a, 'c, u32>) -> &'a Foo<'a, 'b, u32>) { }
fn main() {
gimme(|x, y| y)
//~^ ERROR mismatched types [E0308]
}

View File

@ -0,0 +1,22 @@
error[E0308]: mismatched types
--> $DIR/issue-52533-1.rs:19:18
|
LL | gimme(|x, y| y)
| ^ lifetime mismatch
|
= note: expected type `&Foo<'_, '_, u32>`
found type `&Foo<'_, '_, u32>`
note: the anonymous lifetime #4 defined on the body at 19:11...
--> $DIR/issue-52533-1.rs:19:11
|
LL | gimme(|x, y| y)
| ^^^^^^^^
note: ...does not necessarily outlive the anonymous lifetime #3 defined on the body at 19:11
--> $DIR/issue-52533-1.rs:19:11
|
LL | gimme(|x, y| y)
| ^^^^^^^^
error: aborting due to previous error
For more information about this error, try `rustc --explain E0308`.

View File

@ -0,0 +1,17 @@
warning: not reporting region error due to nll
--> $DIR/issue-52533.rs:15:16
|
LL | foo(|a, b| b)
| ^
error: unsatisfied lifetime constraints
--> $DIR/issue-52533.rs:15:16
|
LL | foo(|a, b| b)
| - - ^ closure was supposed to return data with lifetime `'1` but it is returning data with lifetime `'2`
| | |
| | has type `&'1 u32`
| has type `&'2 u32`
error: aborting due to previous error

View File

@ -0,0 +1,17 @@
// 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.
fn foo(_: impl for<'a> FnOnce(&'a u32, &u32) -> &'a u32) {
}
fn main() {
foo(|a, b| b)
//~^ ERROR lifetime of reference outlives lifetime of borrowed content...
}

View File

@ -0,0 +1,20 @@
error[E0312]: lifetime of reference outlives lifetime of borrowed content...
--> $DIR/issue-52533.rs:15:16
|
LL | foo(|a, b| b)
| ^
|
note: ...the reference is valid for the anonymous lifetime #2 defined on the body at 15:9...
--> $DIR/issue-52533.rs:15:9
|
LL | foo(|a, b| b)
| ^^^^^^^^
note: ...but the borrowed content is only valid for the anonymous lifetime #3 defined on the body at 15:9
--> $DIR/issue-52533.rs:15:9
|
LL | foo(|a, b| b)
| ^^^^^^^^
error: aborting due to previous error
For more information about this error, try `rustc --explain E0312`.

View File

@ -8,10 +8,10 @@ error: unsatisfied lifetime constraints
--> $DIR/escape-argument-callee.rs:36:45
|
LL | let mut closure = expect_sig(|p, y| *p = y);
| - - ^^^^^^ free region requires that `'1` must outlive `'2`
| - - ^^^^^^ requires that `'1` must outlive `'2`
| | |
| | lifetime `'1` appears in this argument
| lifetime `'2` appears in this argument
| | has type `&'1 i32`
| has type `&mut &'2 i32`
note: No external requirements
--> $DIR/escape-argument-callee.rs:36:38

View File

@ -8,9 +8,9 @@ error: unsatisfied lifetime constraints
--> $DIR/propagate-approximated-fail-no-postdom.rs:57:13
|
LL | |_outlives1, _outlives2, _outlives3, x, y| {
| ---------- ---------- lifetime `'2` appears in this argument
| ---------- ---------- has type `std::cell::Cell<&'2 &u32>`
| |
| lifetime `'1` appears in this argument
| has type `std::cell::Cell<&&'1 u32>`
...
LL | demand_y(x, y, p) //~ ERROR
| ^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2`

View File

@ -23,18 +23,18 @@ LL | | });
= note: number of external vids: 2
= note: where '_#1r: '_#0r
error: borrowed data escapes outside of closure
error: borrowed data escapes outside of function
--> $DIR/propagate-approximated-shorter-to-static-no-bound.rs:45:5
|
LL | fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
| ------ `cell_a` is a reference that is only valid in the closure body
| ------ `cell_a` is a reference that is only valid in the function body
LL | / establish_relationships(&cell_a, &cell_b, |_outlives, x, y| {
LL | | //~^ ERROR
LL | |
LL | | // Only works if 'x: 'y:
LL | | demand_y(x, y, x.get()) //~ WARNING not reporting region error due to nll
LL | | });
| |______^ `cell_a` escapes the closure body here
| |______^ `cell_a` escapes the function body here
note: No external requirements
--> $DIR/propagate-approximated-shorter-to-static-no-bound.rs:44:1

View File

@ -23,18 +23,18 @@ LL | | });
= note: number of external vids: 3
= note: where '_#1r: '_#0r
error: borrowed data escapes outside of closure
error: borrowed data escapes outside of function
--> $DIR/propagate-approximated-shorter-to-static-wrong-bound.rs:48:5
|
LL | fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
| ------ `cell_a` is a reference that is only valid in the closure body
| ------ `cell_a` is a reference that is only valid in the function body
LL | / establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
LL | | //~^ ERROR
LL | | // Only works if 'x: 'y:
LL | | demand_y(x, y, x.get())
LL | | //~^ WARNING not reporting region error due to nll
LL | | });
| |______^ `cell_a` escapes the closure body here
| |______^ `cell_a` escapes the function body here
note: No external requirements
--> $DIR/propagate-approximated-shorter-to-static-wrong-bound.rs:47:1

View File

@ -8,9 +8,9 @@ error: unsatisfied lifetime constraints
--> $DIR/propagate-fail-to-approximate-longer-no-bounds.rs:47:9
|
LL | establish_relationships(&cell_a, &cell_b, |_outlives, x, y| {
| --------- - lifetime `'1` appears in this argument
| --------- - has type `&std::cell::Cell<&'1 u32>`
| |
| lifetime `'2` appears in this argument
| has type `&std::cell::Cell<&'2 &u32>`
LL | // Only works if 'x: 'y:
LL | demand_y(x, y, x.get())
| ^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2`

View File

@ -8,9 +8,9 @@ error: unsatisfied lifetime constraints
--> $DIR/propagate-fail-to-approximate-longer-wrong-bounds.rs:51:9
|
LL | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
| ---------- ---------- lifetime `'2` appears in this argument
| ---------- ---------- has type `&std::cell::Cell<&'2 &u32>`
| |
| lifetime `'1` appears in this argument
| has type `&std::cell::Cell<&'1 &u32>`
LL | // Only works if 'x: 'y:
LL | demand_y(x, y, x.get())
| ^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2`

View File

@ -8,7 +8,7 @@ error: unsatisfied lifetime constraints
--> $DIR/region-lbr-named-does-not-outlive-static.rs:19:5
|
LL | &*x
| ^^^ free region requires that `'a` must outlive `'static`
| ^^^ requires that `'a` must outlive `'static`
error: aborting due to previous error

View File

@ -8,10 +8,10 @@ error: unsatisfied lifetime constraints
--> $DIR/return-wrong-bound-region.rs:21:23
|
LL | expect_sig(|a, b| b); // ought to return `a`
| - - ^ free region requires that `'1` must outlive `'2`
| - - ^ closure was supposed to return data with lifetime `'1` but it is returning data with lifetime `'2`
| | |
| | lifetime `'1` appears in this argument
| lifetime `'2` appears in this argument
| | has type `&'1 i32`
| has type `&'2 i32`
note: No external requirements
--> $DIR/return-wrong-bound-region.rs:21:16

View File

@ -1,11 +1,11 @@
error: borrowed data escapes outside of closure
error: borrowed data escapes outside of function
--> $DIR/issue-50716.rs:25:14
|
LL | fn foo<'a, T: 'static>(s: Box<<&'a T as A>::X>)
| - `s` is a reference that is only valid in the closure body
| - `s` is a reference that is only valid in the function body
...
LL | let _x = *s; //~ ERROR
| ^^ `s` escapes the closure body here
| ^^ `s` escapes the function body here
error: aborting due to previous error

View File

@ -4,14 +4,14 @@ warning: not reporting region error due to nll
LL | let f: fn(_) -> _ = foo;
| ^^^
error: borrowed data escapes outside of closure
error: borrowed data escapes outside of function
--> $DIR/mir_check_cast_reify.rs:48:5
|
LL | fn bar<'a>(x: &'a u32) -> &'static u32 {
| - `x` is a reference that is only valid in the closure body
| - `x` is a reference that is only valid in the function body
...
LL | f(x)
| ^^^^ `x` escapes the closure body here
| ^^^^ `x` escapes the function body here
error: aborting due to previous error

View File

@ -4,14 +4,14 @@ warning: not reporting region error due to nll
LL | let g: unsafe fn(_) -> _ = f;
| ^
error: borrowed data escapes outside of closure
error: borrowed data escapes outside of function
--> $DIR/mir_check_cast_unsafe_fn.rs:20:14
|
LL | fn bar<'a>(input: &'a u32, f: fn(&'a u32) -> &'a u32) -> &'static u32 {
| ----- `input` is a reference that is only valid in the closure body
| ----- `input` is a reference that is only valid in the function body
...
LL | unsafe { g(input) }
| ^^^^^^^^ `input` escapes the closure body here
| ^^^^^^^^ `input` escapes the function body here
error: aborting due to previous error