From b210b3168a572c84710bc160915592307f7a3ac5 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sat, 15 Sep 2018 15:45:12 +0100 Subject: [PATCH 1/5] Make the span of the MIR return place point to the return type --- src/librustc_mir/build/mod.rs | 63 ++++++++++++++----- .../min_const_fn/min_const_fn.nll.stderr | 32 +++++----- .../consts/min_const_fn/min_const_fn.stderr | 32 +++++----- 3 files changed, 81 insertions(+), 46 deletions(-) diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index d2061d8eecf5f..f75ce7b08162d 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -40,16 +40,44 @@ pub fn mir_build<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Mir<'t let id = tcx.hir.as_local_node_id(def_id).unwrap(); // Figure out what primary body this item has. - let body_id = match tcx.hir.get(id) { + let (body_id, return_ty_span) = match tcx.hir.get(id) { Node::Variant(variant) => return create_constructor_shim(tcx, id, &variant.node.data), Node::StructCtor(ctor) => return create_constructor_shim(tcx, id, ctor), - _ => match tcx.hir.maybe_body_owned_by(id) { - Some(body) => body, - None => span_bug!(tcx.hir.span(id), "can't build MIR for {:?}", def_id), - }, + Node::Expr(hir::Expr { node: hir::ExprKind::Closure(_, decl, body_id, _, _), .. }) + | Node::Item(hir::Item { node: hir::ItemKind::Fn(decl, _, _, body_id), .. }) + | Node::ImplItem( + hir::ImplItem { + node: hir::ImplItemKind::Method(hir::MethodSig { decl, .. }, body_id), + .. + } + ) + | Node::TraitItem( + hir::TraitItem { + node: hir::TraitItemKind::Method( + hir::MethodSig { decl, .. }, + hir::TraitMethod::Provided(body_id), + ), + .. + } + ) => { + (*body_id, decl.output.span()) + } + Node::Item(hir::Item { node: hir::ItemKind::Static(ty, _, body_id), .. }) + | Node::Item(hir::Item { node: hir::ItemKind::Const(ty, body_id), .. }) + | Node::ImplItem(hir::ImplItem { node: hir::ImplItemKind::Const(ty, body_id), .. }) + | Node::TraitItem( + hir::TraitItem { node: hir::TraitItemKind::Const(ty, Some(body_id)), .. } + ) => { + (*body_id, ty.span) + } + Node::AnonConst(hir::AnonConst { body, id, .. }) => { + (*body, tcx.hir.span(*id)) + } + + _ => span_bug!(tcx.hir.span(id), "can't build MIR for {:?}", def_id), }; tcx.infer_ctxt().enter(|infcx| { @@ -124,9 +152,9 @@ pub fn mir_build<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Mir<'t }; build::construct_fn(cx, id, arguments, safety, abi, - return_ty, yield_ty, body) + return_ty, yield_ty, return_ty_span, body) } else { - build::construct_const(cx, body_id) + build::construct_const(cx, body_id, return_ty_span) }; // Convert the Mir to global types. @@ -494,6 +522,7 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>, abi: Abi, return_ty: Ty<'gcx>, yield_ty: Option>, + return_ty_span: Span, body: &'gcx hir::Body) -> Mir<'tcx> where A: Iterator> @@ -547,6 +576,7 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>, arguments.len(), safety, return_ty, + return_ty_span, upvar_decls); let fn_def_id = tcx.hir.local_def_id(fn_id); @@ -601,15 +631,17 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>, mir } -fn construct_const<'a, 'gcx, 'tcx>(hir: Cx<'a, 'gcx, 'tcx>, - body_id: hir::BodyId) - -> Mir<'tcx> { +fn construct_const<'a, 'gcx, 'tcx>( + hir: Cx<'a, 'gcx, 'tcx>, + body_id: hir::BodyId, + ty_span: Span, +) -> Mir<'tcx> { let tcx = hir.tcx(); let ast_expr = &tcx.hir.body(body_id).value; let ty = hir.tables().expr_ty_adjusted(ast_expr); let owner_id = tcx.hir.body_owner(body_id); let span = tcx.hir.span(owner_id); - let mut builder = Builder::new(hir.clone(), span, 0, Safety::Safe, ty, vec![]); + let mut builder = Builder::new(hir.clone(), span, 0, Safety::Safe, ty, ty_span,vec![]); let mut block = START_BLOCK; let expr = builder.hir.mirror(ast_expr); @@ -637,7 +669,7 @@ fn construct_error<'a, 'gcx, 'tcx>(hir: Cx<'a, 'gcx, 'tcx>, let owner_id = hir.tcx().hir.body_owner(body_id); let span = hir.tcx().hir.span(owner_id); let ty = hir.tcx().types.err; - let mut builder = Builder::new(hir, span, 0, Safety::Safe, ty, vec![]); + let mut builder = Builder::new(hir, span, 0, Safety::Safe, ty, span, vec![]); let source_info = builder.source_info(span); builder.cfg.terminate(START_BLOCK, source_info, TerminatorKind::Unreachable); builder.finish(None) @@ -649,6 +681,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { arg_count: usize, safety: Safety, return_ty: Ty<'tcx>, + return_span: Span, upvar_decls: Vec) -> Builder<'a, 'gcx, 'tcx> { let lint_level = LintLevel::Explicit(hir.root_lint_level); @@ -665,8 +698,10 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { push_unsafe_count: 0, unpushed_unsafe: safety, breakable_scopes: vec![], - local_decls: IndexVec::from_elem_n(LocalDecl::new_return_place(return_ty, - span), 1), + local_decls: IndexVec::from_elem_n( + LocalDecl::new_return_place(return_ty, return_span), + 1, + ), upvar_decls, var_indices: NodeMap(), unit_temp: None, diff --git a/src/test/ui/consts/min_const_fn/min_const_fn.nll.stderr b/src/test/ui/consts/min_const_fn/min_const_fn.nll.stderr index b156e5a9731da..5803b5e355a2c 100644 --- a/src/test/ui/consts/min_const_fn/min_const_fn.nll.stderr +++ b/src/test/ui/consts/min_const_fn/min_const_fn.nll.stderr @@ -5,10 +5,10 @@ LL | const fn into_inner(self) -> T { self.0 } //~ destructors cannot be eva | ^^^^ constant functions cannot evaluate destructors error: mutable references in const fn are unstable - --> $DIR/min_const_fn.rs:51:5 + --> $DIR/min_const_fn.rs:51:36 | LL | const fn get_mut(&mut self) -> &mut T { &mut self.0 } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^ error[E0493]: destructors cannot be evaluated at compile-time --> $DIR/min_const_fn.rs:56:28 @@ -17,10 +17,10 @@ LL | const fn into_inner_lt(self) -> T { self.0 } //~ destructors cannot be | ^^^^ constant functions cannot evaluate destructors error: mutable references in const fn are unstable - --> $DIR/min_const_fn.rs:58:5 + --> $DIR/min_const_fn.rs:58:42 | LL | const fn get_mut_lt(&'a mut self) -> &mut T { &mut self.0 } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^ error[E0493]: destructors cannot be evaluated at compile-time --> $DIR/min_const_fn.rs:63:27 @@ -29,16 +29,16 @@ LL | const fn into_inner_s(self) -> T { self.0 } //~ ERROR destructors | ^^^^ constant functions cannot evaluate destructors error: mutable references in const fn are unstable - --> $DIR/min_const_fn.rs:65:5 + --> $DIR/min_const_fn.rs:65:38 | LL | const fn get_mut_s(&mut self) -> &mut T { &mut self.0 } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^ error: mutable references in const fn are unstable - --> $DIR/min_const_fn.rs:70:5 + --> $DIR/min_const_fn.rs:70:39 | LL | const fn get_mut_sq(&mut self) -> &mut T { &mut self.0 } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^ error: trait bounds other than `Sized` on const fn parameters are unstable --> $DIR/min_const_fn.rs:88:16 @@ -155,10 +155,10 @@ LL | impl Foo { | ^ error: `impl Trait` in const fn is unstable - --> $DIR/min_const_fn.rs:137:1 + --> $DIR/min_const_fn.rs:137:24 | LL | const fn no_rpit2() -> AlanTuring { AlanTuring(0) } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: trait bounds other than `Sized` on const fn parameters are unstable --> $DIR/min_const_fn.rs:139:34 @@ -173,10 +173,10 @@ LL | const fn no_apit(_x: impl std::fmt::Debug) {} //~ ERROR trait bounds other | ^^^^^^^^^^^^^^^^^^^^ error: `impl Trait` in const fn is unstable - --> $DIR/min_const_fn.rs:142:1 + --> $DIR/min_const_fn.rs:142:23 | LL | const fn no_rpit() -> impl std::fmt::Debug {} //~ ERROR `impl Trait` in const fn is unstable - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^ error: trait bounds other than `Sized` on const fn parameters are unstable --> $DIR/min_const_fn.rs:143:23 @@ -185,10 +185,10 @@ LL | const fn no_dyn_trait(_x: &dyn std::fmt::Debug) {} //~ ERROR trait bounds o | ^^ error: trait bounds other than `Sized` on const fn parameters are unstable - --> $DIR/min_const_fn.rs:144:1 + --> $DIR/min_const_fn.rs:144:32 | LL | const fn no_dyn_trait_ret() -> &'static dyn std::fmt::Debug { &() } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0597]: borrowed value does not live long enough --> $DIR/min_const_fn.rs:144:64 @@ -213,10 +213,10 @@ LL | const fn no_fn_ptrs(_x: fn()) {} | ^^ error: function pointers in const fn are unstable - --> $DIR/min_const_fn.rs:154:1 + --> $DIR/min_const_fn.rs:154:27 | LL | const fn no_fn_ptrs2() -> fn() { fn foo() {} foo } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^ error: aborting due to 36 previous errors diff --git a/src/test/ui/consts/min_const_fn/min_const_fn.stderr b/src/test/ui/consts/min_const_fn/min_const_fn.stderr index 019948c31b15c..6779b8a761461 100644 --- a/src/test/ui/consts/min_const_fn/min_const_fn.stderr +++ b/src/test/ui/consts/min_const_fn/min_const_fn.stderr @@ -5,10 +5,10 @@ LL | const fn into_inner(self) -> T { self.0 } //~ destructors cannot be eva | ^^^^ constant functions cannot evaluate destructors error: mutable references in const fn are unstable - --> $DIR/min_const_fn.rs:51:5 + --> $DIR/min_const_fn.rs:51:36 | LL | const fn get_mut(&mut self) -> &mut T { &mut self.0 } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^ error[E0493]: destructors cannot be evaluated at compile-time --> $DIR/min_const_fn.rs:56:28 @@ -17,10 +17,10 @@ LL | const fn into_inner_lt(self) -> T { self.0 } //~ destructors cannot be | ^^^^ constant functions cannot evaluate destructors error: mutable references in const fn are unstable - --> $DIR/min_const_fn.rs:58:5 + --> $DIR/min_const_fn.rs:58:42 | LL | const fn get_mut_lt(&'a mut self) -> &mut T { &mut self.0 } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^ error[E0493]: destructors cannot be evaluated at compile-time --> $DIR/min_const_fn.rs:63:27 @@ -29,16 +29,16 @@ LL | const fn into_inner_s(self) -> T { self.0 } //~ ERROR destructors | ^^^^ constant functions cannot evaluate destructors error: mutable references in const fn are unstable - --> $DIR/min_const_fn.rs:65:5 + --> $DIR/min_const_fn.rs:65:38 | LL | const fn get_mut_s(&mut self) -> &mut T { &mut self.0 } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^ error: mutable references in const fn are unstable - --> $DIR/min_const_fn.rs:70:5 + --> $DIR/min_const_fn.rs:70:39 | LL | const fn get_mut_sq(&mut self) -> &mut T { &mut self.0 } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^ error: trait bounds other than `Sized` on const fn parameters are unstable --> $DIR/min_const_fn.rs:88:16 @@ -155,10 +155,10 @@ LL | impl Foo { | ^ error: `impl Trait` in const fn is unstable - --> $DIR/min_const_fn.rs:137:1 + --> $DIR/min_const_fn.rs:137:24 | LL | const fn no_rpit2() -> AlanTuring { AlanTuring(0) } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: trait bounds other than `Sized` on const fn parameters are unstable --> $DIR/min_const_fn.rs:139:34 @@ -173,10 +173,10 @@ LL | const fn no_apit(_x: impl std::fmt::Debug) {} //~ ERROR trait bounds other | ^^^^^^^^^^^^^^^^^^^^ error: `impl Trait` in const fn is unstable - --> $DIR/min_const_fn.rs:142:1 + --> $DIR/min_const_fn.rs:142:23 | LL | const fn no_rpit() -> impl std::fmt::Debug {} //~ ERROR `impl Trait` in const fn is unstable - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^ error: trait bounds other than `Sized` on const fn parameters are unstable --> $DIR/min_const_fn.rs:143:23 @@ -185,10 +185,10 @@ LL | const fn no_dyn_trait(_x: &dyn std::fmt::Debug) {} //~ ERROR trait bounds o | ^^ error: trait bounds other than `Sized` on const fn parameters are unstable - --> $DIR/min_const_fn.rs:144:1 + --> $DIR/min_const_fn.rs:144:32 | LL | const fn no_dyn_trait_ret() -> &'static dyn std::fmt::Debug { &() } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: trait bounds other than `Sized` on const fn parameters are unstable --> $DIR/min_const_fn.rs:149:41 @@ -203,10 +203,10 @@ LL | const fn no_fn_ptrs(_x: fn()) {} | ^^ error: function pointers in const fn are unstable - --> $DIR/min_const_fn.rs:154:1 + --> $DIR/min_const_fn.rs:154:27 | LL | const fn no_fn_ptrs2() -> fn() { fn foo() {} foo } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^ error: aborting due to 35 previous errors From fcd0cd0adef72e2bc00016eccd97af2ebf70c12c Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sat, 15 Sep 2018 18:24:18 +0100 Subject: [PATCH 2/5] Don't try to use a path to a type alias as a path to the adt it aliases --- .../error_reporting/region_name.rs | 27 +++++++++------ src/test/ui/nll/type-alias-free-regions.rs | 33 +++++++++++++++++++ .../ui/nll/type-alias-free-regions.stderr | 22 +++++++++++++ 3 files changed, 72 insertions(+), 10 deletions(-) create mode 100644 src/test/ui/nll/type-alias-free-regions.rs create mode 100644 src/test/ui/nll/type-alias-free-regions.stderr diff --git a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs index 857f1dae7ab51..f704ee61c8847 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs @@ -452,16 +452,23 @@ impl<'tcx> RegionInferenceContext<'tcx> { ty::Adt(_adt_def, substs), hir::TyKind::Path(hir::QPath::Resolved(None, path)), ) => { - if let Some(last_segment) = path.segments.last() { - if let Some(name) = self.match_adt_and_segment( - substs, - needle_fr, - last_segment, - counter, - diag, - search_stack, - ) { - return Some(name); + match path.def { + // Type parameters of the type alias have no reason to + // be the same as those of the ADT. + // FIXME: We should be able to do something similar to + // match_adt_and_segment in this case. + hir::def::Def::TyAlias(_) => (), + _ => if let Some(last_segment) = path.segments.last() { + if let Some(name) = self.match_adt_and_segment( + substs, + needle_fr, + last_segment, + counter, + diag, + search_stack, + ) { + return Some(name); + } } } } diff --git a/src/test/ui/nll/type-alias-free-regions.rs b/src/test/ui/nll/type-alias-free-regions.rs new file mode 100644 index 0000000000000..6e480dcaac08f --- /dev/null +++ b/src/test/ui/nll/type-alias-free-regions.rs @@ -0,0 +1,33 @@ +// Test that we don't assume that type aliases have the same type parameters +// as the type they alias and then panic when we see this. + +#![feature(nll)] + +type a<'a> = &'a isize; +type b<'a> = Box>; + +struct c<'a> { + f: Box> +} + +trait FromBox<'a> { + fn from_box(b: Box) -> Self; +} + +impl<'a> FromBox<'a> for c<'a> { + fn from_box(b: Box) -> Self { + c { f: b } //~ ERROR + } +} + +trait FromTuple<'a> { + fn from_tuple( b: (b,)) -> Self; +} + +impl<'a> FromTuple<'a> for c<'a> { + fn from_tuple(b: (b,)) -> Self { + c { f: Box::new(b.0) } //~ ERROR + } +} + +fn main() {} diff --git a/src/test/ui/nll/type-alias-free-regions.stderr b/src/test/ui/nll/type-alias-free-regions.stderr new file mode 100644 index 0000000000000..05f2c9309446a --- /dev/null +++ b/src/test/ui/nll/type-alias-free-regions.stderr @@ -0,0 +1,22 @@ +error: unsatisfied lifetime constraints + --> $DIR/type-alias-free-regions.rs:19:9 + | +LL | impl<'a> FromBox<'a> for c<'a> { + | -- lifetime `'a` defined here +LL | fn from_box(b: Box) -> Self { + | - has type `std::boxed::Box>` +LL | c { f: b } //~ ERROR + | ^^^^^^^^^^ returning this value requires that `'1` must outlive `'a` + +error: unsatisfied lifetime constraints + --> $DIR/type-alias-free-regions.rs:29:9 + | +LL | impl<'a> FromTuple<'a> for c<'a> { + | -- lifetime `'a` defined here +LL | fn from_tuple(b: (b,)) -> Self { + | - has type `(std::boxed::Box<&'1 isize>,)` +LL | c { f: Box::new(b.0) } //~ ERROR + | ^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'1` must outlive `'a` + +error: aborting due to 2 previous errors + From 6e425219f1067096463b2e48c00ba7d7d2d8fdde Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sat, 15 Sep 2018 18:28:52 +0100 Subject: [PATCH 3/5] Don't claim that locals in a function are declared outside of the function body --- .../nll/region_infer/error_reporting/mod.rs | 6 +++++- .../regions/regions-infer-paramd-indirect.nll.stderr | 11 ++++++----- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs index dfed41cb1defd..b7000b254a7de 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs @@ -391,7 +391,11 @@ impl<'tcx> RegionInferenceContext<'tcx> { 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() { + // Revert to the normal error in these cases. + // Assignments aren't "escapes" in function items. + if (fr_name_and_span.is_none() && outlived_fr_name_and_span.is_none()) + || (category == ConstraintCategory::Assignment && escapes_from == "function") + { return self.report_general_error(mir, infcx, mir_def_id, fr, true, outlived_fr, false, category, span, errors_buffer); diff --git a/src/test/ui/regions/regions-infer-paramd-indirect.nll.stderr b/src/test/ui/regions/regions-infer-paramd-indirect.nll.stderr index 8e29e77713ba5..7558c5caa0e24 100644 --- a/src/test/ui/regions/regions-infer-paramd-indirect.nll.stderr +++ b/src/test/ui/regions/regions-infer-paramd-indirect.nll.stderr @@ -1,12 +1,13 @@ -error: borrowed data escapes outside of function +error: unsatisfied lifetime constraints --> $DIR/regions-infer-paramd-indirect.rs:33:9 | +LL | impl<'a> set_f<'a> for c<'a> { + | -- lifetime `'a` defined here +... LL | fn set_f_bad(&mut self, b: Box) { - | --------- - `b` is a reference that is only valid in the function body - | | - | `self` is declared here, outside of the function body + | - has type `std::boxed::Box>` LL | self.f = b; - | ^^^^^^ `b` escapes the function body here + | ^^^^^^ assignment requires that `'1` must outlive `'a` error: aborting due to previous error From 994dc4bd1ef01b45408750679d9ec46bc1c2ff33 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sat, 15 Sep 2018 18:30:14 +0100 Subject: [PATCH 4/5] Classify outlives constraints when type checking The MIR/NLL type checker is in a much better position to classify constraints and already has to classify into boring and interesting. Adds spans to Locations::All for error reporting Adds more constraint categories --- src/librustc/infer/opaque_types/mod.rs | 2 +- .../borrow_check/nll/constraints/graph.rs | 7 +- .../borrow_check/nll/constraints/mod.rs | 39 ++ .../borrow_check/nll/region_infer/dump_mir.rs | 4 +- .../nll/region_infer/error_reporting/mod.rs | 146 +------ .../borrow_check/nll/region_infer/mod.rs | 4 +- .../nll/type_check/constraint_conversion.rs | 6 +- .../nll/type_check/free_region_relations.rs | 5 +- .../nll/type_check/input_output.rs | 59 ++- .../nll/type_check/liveness/trace.rs | 9 +- .../borrow_check/nll/type_check/mod.rs | 387 +++++++++++------- .../borrow_check/nll/type_check/relate_tys.rs | 13 +- 12 files changed, 377 insertions(+), 304 deletions(-) diff --git a/src/librustc/infer/opaque_types/mod.rs b/src/librustc/infer/opaque_types/mod.rs index 9d65c3950626c..c6f910c4ad7a4 100644 --- a/src/librustc/infer/opaque_types/mod.rs +++ b/src/librustc/infer/opaque_types/mod.rs @@ -284,7 +284,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } } - fn constrain_opaque_type>( + pub fn constrain_opaque_type>( &self, def_id: DefId, opaque_defn: &OpaqueTypeDecl<'tcx>, diff --git a/src/librustc_mir/borrow_check/nll/constraints/graph.rs b/src/librustc_mir/borrow_check/nll/constraints/graph.rs index b1e8b974379d6..2e018f746f389 100644 --- a/src/librustc_mir/borrow_check/nll/constraints/graph.rs +++ b/src/librustc_mir/borrow_check/nll/constraints/graph.rs @@ -9,10 +9,12 @@ // except according to those terms. use borrow_check::nll::type_check::Locations; -use borrow_check::nll::constraints::{ConstraintIndex, ConstraintSet, OutlivesConstraint}; +use borrow_check::nll::constraints::{ConstraintCategory, ConstraintIndex}; +use borrow_check::nll::constraints::{ConstraintSet, OutlivesConstraint}; use rustc::ty::RegionVid; use rustc_data_structures::graph; use rustc_data_structures::indexed_vec::IndexVec; +use syntax_pos::DUMMY_SP; /// The construct graph organizes the constraints by their end-points. /// It can be used to view a `R1: R2` constraint as either an edge `R1 @@ -174,7 +176,8 @@ impl<'s, D: ConstraintGraphDirecton> Iterator for Edges<'s, D> { Some(OutlivesConstraint { sup: self.static_region, sub: next_static_idx.into(), - locations: Locations::All, + locations: Locations::All(DUMMY_SP), + category: ConstraintCategory::Internal, }) } else { None diff --git a/src/librustc_mir/borrow_check/nll/constraints/mod.rs b/src/librustc_mir/borrow_check/nll/constraints/mod.rs index 41c846509cddb..76ebc06bfd2f6 100644 --- a/src/librustc_mir/borrow_check/nll/constraints/mod.rs +++ b/src/librustc_mir/borrow_check/nll/constraints/mod.rs @@ -23,6 +23,42 @@ crate struct ConstraintSet { constraints: IndexVec, } +/// Constraints can be categorized to determine whether and why they are +/// interesting. Order of variants indicates sort order of the category, +/// thereby influencing diagnostic output. +#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] +pub enum ConstraintCategory { + Return, + TypeAnnotation, + Cast, + CallArgument, + + /// A constraint that came from checking the body of a closure. + /// + /// Ideally we would give an explanation that points to the relevant part + /// of the closure's body. + ClosureBounds, + CopyBound, + SizedBound, + Assignment, + OpaqueType, + + /// A "boring" constraint (caused by the given location) is one that + /// the user probably doesn't want to see described in diagnostics, + /// because it is kind of an artifact of the type system setup. + /// Example: `x = Foo { field: y }` technically creates + /// intermediate regions representing the "type of `Foo { field: y + /// }`", and data flows from `y` into those variables, but they + /// are not very interesting. The assignment into `x` on the other + /// hand might be. + Boring, + // Boring and applicable everywhere. + BoringNoLocation, + + /// A constraint that doesn't correspond to anything the user sees. + Internal, +} + impl ConstraintSet { crate fn push(&mut self, constraint: OutlivesConstraint) { debug!( @@ -87,6 +123,9 @@ pub struct OutlivesConstraint { /// Where did this constraint arise? pub locations: Locations, + + /// What caused this constraint? + pub category: ConstraintCategory, } impl fmt::Debug for OutlivesConstraint { diff --git a/src/librustc_mir/borrow_check/nll/region_infer/dump_mir.rs b/src/librustc_mir/borrow_check/nll/region_infer/dump_mir.rs index d3b4f0a0447a1..ee900afc44de8 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/dump_mir.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/dump_mir.rs @@ -88,11 +88,13 @@ impl<'tcx> RegionInferenceContext<'tcx> { sup, sub, locations, + category, } = constraint; with_msg(&format!( - "{:?}: {:?} due to {:?}", + "{:?}: {:?} due to {:?} at {:?}", sup, sub, + category, locations, ))?; } diff --git a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs index b7000b254a7de..1abc105ac2890 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs @@ -8,14 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use borrow_check::nll::constraints::OutlivesConstraint; +use borrow_check::nll::constraints::{OutlivesConstraint, ConstraintCategory}; use borrow_check::nll::region_infer::RegionInferenceContext; -use borrow_check::nll::type_check::Locations; use rustc::hir::def_id::DefId; use rustc::infer::error_reporting::nice_region_error::NiceRegionError; use rustc::infer::InferCtxt; -use rustc::mir::{self, Location, Mir, Place, Rvalue, StatementKind, TerminatorKind}; -use rustc::ty::{self, TyCtxt, RegionVid}; +use rustc::mir::{Location, Mir}; +use rustc::ty::{self, RegionVid}; use rustc_data_structures::indexed_vec::IndexVec; use rustc_errors::{Diagnostic, DiagnosticBuilder}; use std::collections::VecDeque; @@ -28,19 +27,6 @@ mod var_name; use self::region_name::RegionName; -/// Constraints that are considered interesting can be categorized to -/// determine why they are interesting. Order of variants indicates -/// sort order of the category, thereby influencing diagnostic output. -#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] -enum ConstraintCategory { - Cast, - Assignment, - Return, - CallArgument, - Other, - Boring, -} - 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. @@ -49,7 +35,14 @@ impl fmt::Display for ConstraintCategory { ConstraintCategory::Return => write!(f, "returning this value "), ConstraintCategory::Cast => write!(f, "cast "), ConstraintCategory::CallArgument => write!(f, "argument "), - _ => write!(f, ""), + ConstraintCategory::TypeAnnotation => write!(f, "type annotation "), + ConstraintCategory::ClosureBounds => write!(f, "closure body "), + ConstraintCategory::SizedBound => write!(f, "proving this value is `Sized` "), + ConstraintCategory::CopyBound => write!(f, "copying this value "), + ConstraintCategory::OpaqueType => write!(f, "opaque type "), + ConstraintCategory::Boring + | ConstraintCategory::BoringNoLocation + | ConstraintCategory::Internal => write!(f, ""), } } } @@ -71,7 +64,6 @@ impl<'tcx> RegionInferenceContext<'tcx> { fn best_blame_constraint( &self, mir: &Mir<'tcx>, - tcx: TyCtxt<'_, '_, 'tcx>, from_region: RegionVid, target_test: impl Fn(RegionVid) -> bool, ) -> (ConstraintCategory, Span, RegionVid) { @@ -96,7 +88,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { // Classify each of the constraints along the path. let mut categorized_path: Vec<(ConstraintCategory, Span)> = path .iter() - .map(|&index| self.classify_constraint(index, mir, tcx)) + .map(|constraint| (constraint.category, constraint.locations.span(mir))) .collect(); debug!( "best_blame_constraint: categorized_path={:#?}", @@ -129,12 +121,10 @@ impl<'tcx> RegionInferenceContext<'tcx> { let constraint_sup_scc = self.constraint_sccs.scc(constraint.sup); match categorized_path[i].0 { - ConstraintCategory::Boring => false, - ConstraintCategory::Other => { - // other isn't interesting when the two lifetimes - // are unified. - constraint_sup_scc != self.constraint_sccs.scc(constraint.sub) - } + ConstraintCategory::OpaqueType + | ConstraintCategory::Boring + | ConstraintCategory::BoringNoLocation + | ConstraintCategory::Internal => false, _ => constraint_sup_scc != target_scc, } }); @@ -220,106 +210,6 @@ impl<'tcx> RegionInferenceContext<'tcx> { None } - /// This function will return true if a constraint is interesting and false if a constraint - /// is not. It is useful in filtering constraint paths to only interesting points. - fn constraint_is_interesting(&self, constraint: OutlivesConstraint) -> bool { - debug!( - "constraint_is_interesting: locations={:?} constraint={:?}", - constraint.locations, constraint - ); - - match constraint.locations { - Locations::Interesting(_) | Locations::All => true, - _ => false, - } - } - - /// This function classifies a constraint from a location. - fn classify_constraint( - &self, - constraint: OutlivesConstraint, - mir: &Mir<'tcx>, - tcx: TyCtxt<'_, '_, 'tcx>, - ) -> (ConstraintCategory, Span) { - debug!("classify_constraint: constraint={:?}", constraint); - let span = constraint.locations.span(mir); - let location = constraint - .locations - .from_location() - .unwrap_or(Location::START); - - if !self.constraint_is_interesting(constraint) { - return (ConstraintCategory::Boring, span); - } - - let data = &mir[location.block]; - debug!( - "classify_constraint: location={:?} data={:?}", - location, data - ); - let category = if location.statement_index == data.statements.len() { - if let Some(ref terminator) = data.terminator { - debug!("classify_constraint: terminator.kind={:?}", terminator.kind); - match terminator.kind { - TerminatorKind::DropAndReplace { .. } => ConstraintCategory::Assignment, - // Classify calls differently depending on whether or not - // the sub region appears in the destination type (so the - // sup region is in the return type). If the return type - // contains the sub-region, then this is either an - // assignment or a return, depending on whether we are - // writing to the RETURN_PLACE or not. - // - // The idea here is that the region is being propagated - // from an input into the output place, so it's a kind of - // assignment. Otherwise, if the sub-region only appears in - // the argument types, then use the CallArgument - // classification. - TerminatorKind::Call { destination: Some((ref place, _)), .. } => { - if tcx.any_free_region_meets( - &place.ty(mir, tcx).to_ty(tcx), - |region| self.to_region_vid(region) == constraint.sub, - ) { - match place { - Place::Local(mir::RETURN_PLACE) => ConstraintCategory::Return, - _ => ConstraintCategory::Assignment, - } - } else { - ConstraintCategory::CallArgument - } - } - TerminatorKind::Call { destination: None, .. } => { - ConstraintCategory::CallArgument - } - _ => ConstraintCategory::Other, - } - } else { - ConstraintCategory::Other - } - } else { - let statement = &data.statements[location.statement_index]; - debug!("classify_constraint: statement.kind={:?}", statement.kind); - match statement.kind { - StatementKind::Assign(ref place, ref rvalue) => { - debug!("classify_constraint: place={:?} rvalue={:?}", place, rvalue); - if *place == Place::Local(mir::RETURN_PLACE) { - ConstraintCategory::Return - } else { - match rvalue { - Rvalue::Cast(..) => ConstraintCategory::Cast, - Rvalue::Use(..) | Rvalue::Aggregate(..) => { - ConstraintCategory::Assignment - } - _ => ConstraintCategory::Other, - } - } - } - _ => ConstraintCategory::Other, - } - }; - - (category, span) - } - /// Report an error because the universal region `fr` was required to outlive /// `outlived_fr` but it is not known to do so. For example: /// @@ -341,7 +231,6 @@ impl<'tcx> RegionInferenceContext<'tcx> { let (category, span, _) = self.best_blame_constraint( mir, - infcx.tcx, fr, |r| r == outlived_fr ); @@ -574,11 +463,10 @@ impl<'tcx> RegionInferenceContext<'tcx> { crate fn find_outlives_blame_span( &self, mir: &Mir<'tcx>, - tcx: TyCtxt<'_, '_, 'tcx>, fr1: RegionVid, fr2: RegionVid, ) -> Span { - let (_, span, _) = self.best_blame_constraint(mir, tcx, fr1, |r| r == fr2); + let (_, span, _) = self.best_blame_constraint(mir, fr1, |r| r == fr2); span } } diff --git a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs index d1713a520a79c..75f14a6bbdac8 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs @@ -1062,7 +1062,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { longer_fr, shorter_fr, ); - let blame_span = self.find_outlives_blame_span(mir, infcx.tcx, longer_fr, shorter_fr); + let blame_span = self.find_outlives_blame_span(mir, longer_fr, shorter_fr); if let Some(propagated_outlives_requirements) = propagated_outlives_requirements { // Shrink `fr` until we find a non-local region (if we do). @@ -1147,7 +1147,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { }; // Find the code to blame for the fact that `longer_fr` outlives `error_fr`. - let span = self.find_outlives_blame_span(mir, infcx.tcx, longer_fr, error_region); + let span = self.find_outlives_blame_span(mir, longer_fr, error_region); // Obviously, this error message is far from satisfactory. // At present, though, it only appears in unit tests -- diff --git a/src/librustc_mir/borrow_check/nll/type_check/constraint_conversion.rs b/src/librustc_mir/borrow_check/nll/type_check/constraint_conversion.rs index 64a61972a2206..430c8d673921b 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/constraint_conversion.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/constraint_conversion.rs @@ -9,7 +9,7 @@ // except according to those terms. use borrow_check::location::LocationTable; -use borrow_check::nll::constraints::{ConstraintSet, OutlivesConstraint}; +use borrow_check::nll::constraints::{ConstraintCategory, ConstraintSet, OutlivesConstraint}; use borrow_check::nll::facts::AllFacts; use borrow_check::nll::region_infer::{RegionTest, TypeTest}; use borrow_check::nll::type_check::Locations; @@ -30,6 +30,7 @@ crate struct ConstraintConversion<'a, 'gcx: 'tcx, 'tcx: 'a> { implicit_region_bound: Option>, param_env: ty::ParamEnv<'tcx>, locations: Locations, + category: ConstraintCategory, outlives_constraints: &'a mut ConstraintSet, type_tests: &'a mut Vec>, all_facts: &'a mut Option, @@ -44,6 +45,7 @@ impl<'a, 'gcx, 'tcx> ConstraintConversion<'a, 'gcx, 'tcx> { implicit_region_bound: Option>, param_env: ty::ParamEnv<'tcx>, locations: Locations, + category: ConstraintCategory, outlives_constraints: &'a mut ConstraintSet, type_tests: &'a mut Vec>, all_facts: &'a mut Option, @@ -56,6 +58,7 @@ impl<'a, 'gcx, 'tcx> ConstraintConversion<'a, 'gcx, 'tcx> { implicit_region_bound, param_env, locations, + category, outlives_constraints, type_tests, all_facts, @@ -183,6 +186,7 @@ impl<'a, 'gcx, 'tcx> ConstraintConversion<'a, 'gcx, 'tcx> { fn add_outlives(&mut self, sup: ty::RegionVid, sub: ty::RegionVid) { self.outlives_constraints.push(OutlivesConstraint { locations: self.locations, + category: self.category, sub, sup, }); diff --git a/src/librustc_mir/borrow_check/nll/type_check/free_region_relations.rs b/src/librustc_mir/borrow_check/nll/type_check/free_region_relations.rs index e21c490622c08..61c612b3c0118 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/free_region_relations.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/free_region_relations.rs @@ -14,6 +14,7 @@ use borrow_check::nll::type_check::constraint_conversion; use borrow_check::nll::type_check::{Locations, MirTypeckRegionConstraints}; use borrow_check::nll::universal_regions::UniversalRegions; use borrow_check::nll::ToRegionVid; +use borrow_check::nll::constraints::ConstraintCategory; use rustc::infer::canonical::QueryRegionConstraint; use rustc::infer::outlives::free_region_map::FreeRegionRelations; use rustc::infer::region_constraints::GenericKind; @@ -23,6 +24,7 @@ use rustc::traits::query::type_op::{self, TypeOp}; use rustc::ty::{self, RegionVid, Ty}; use rustc_data_structures::transitive_relation::TransitiveRelation; use std::rc::Rc; +use syntax_pos::DUMMY_SP; #[derive(Debug)] crate struct UniversalRegionRelations<'tcx> { @@ -283,7 +285,8 @@ impl UniversalRegionRelationsBuilder<'cx, 'gcx, 'tcx> { &self.region_bound_pairs, self.implicit_region_bound, self.param_env, - Locations::All, + Locations::All(DUMMY_SP), + ConstraintCategory::Internal, &mut self.constraints.outlives_constraints, &mut self.constraints.type_tests, &mut self.all_facts, diff --git a/src/librustc_mir/borrow_check/nll/type_check/input_output.rs b/src/librustc_mir/borrow_check/nll/type_check/input_output.rs index 265cd305eb97e..6c7e2e9b72e30 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/input_output.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/input_output.rs @@ -29,8 +29,9 @@ use rustc::ty::subst::Subst; use rustc::ty::Ty; use rustc_data_structures::indexed_vec::Idx; +use syntax_pos::Span; -use super::{Locations, TypeChecker}; +use super::{ConstraintCategory, Locations, TypeChecker}; impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { pub(super) fn equate_inputs_and_outputs( @@ -56,7 +57,12 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { ); let mir_input_ty = mir.local_decls[local].ty; - self.equate_normalized_input_or_output(normalized_input_ty, mir_input_ty); + let mir_input_span = mir.local_decls[local].source_info.span; + self.equate_normalized_input_or_output( + normalized_input_ty, + mir_input_ty, + mir_input_span, + ); } assert!( @@ -65,16 +71,19 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { ); if let Some(mir_yield_ty) = mir.yield_ty { let ur_yield_ty = universal_regions.yield_ty.unwrap(); - self.equate_normalized_input_or_output(ur_yield_ty, mir_yield_ty); + let yield_span = mir.local_decls[RETURN_PLACE].source_info.span; + self.equate_normalized_input_or_output(ur_yield_ty, mir_yield_ty, yield_span); } // Return types are a bit more complex. They may contain existential `impl Trait` // types. let param_env = self.param_env; let mir_output_ty = mir.local_decls[RETURN_PLACE].ty; + let output_span = mir.local_decls[RETURN_PLACE].source_info.span; let opaque_type_map = self.fully_perform_op( - Locations::All, + Locations::All(output_span), + ConstraintCategory::BoringNoLocation, CustomTypeOp::new( |infcx| { let mut obligations = ObligationAccumulator::default(); @@ -152,26 +161,38 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { // prove that `T: Iterator` where `T` is the type we // instantiated it with). if let Some(opaque_type_map) = opaque_type_map { - self.fully_perform_op( - Locations::All, - CustomTypeOp::new( - |_cx| { - infcx.constrain_opaque_types(&opaque_type_map, universal_region_relations); - Ok(InferOk { - value: (), - obligations: vec![], - }) - }, - || "opaque_type_map".to_string(), - ), - ).unwrap(); + for (opaque_def_id, opaque_decl) in opaque_type_map { + self.fully_perform_op( + Locations::All(infcx.tcx.def_span(opaque_def_id)), + ConstraintCategory::OpaqueType, + CustomTypeOp::new( + |_cx| { + infcx.constrain_opaque_type( + opaque_def_id, + &opaque_decl, + universal_region_relations + ); + Ok(InferOk { + value: (), + obligations: vec![], + }) + }, + || "opaque_type_map".to_string(), + ), + ).unwrap(); + } } } - fn equate_normalized_input_or_output(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) { + fn equate_normalized_input_or_output(&mut self, a: Ty<'tcx>, b: Ty<'tcx>, span: Span) { debug!("equate_normalized_input_or_output(a={:?}, b={:?})", a, b); - if let Err(terr) = self.eq_types(a, b, Locations::All) { + if let Err(terr) = self.eq_types( + a, + b, + Locations::All(span), + ConstraintCategory::BoringNoLocation, + ) { span_mirbug!( self, Location::START, diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs index 47e6ce05cec1f..e706c1adaddfb 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs @@ -8,10 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use borrow_check::nll::constraints::ConstraintCategory; use borrow_check::nll::region_infer::values::{self, PointIndex, RegionValueElements}; use borrow_check::nll::type_check::liveness::liveness_map::{LiveVar, NllLivenessMap}; use borrow_check::nll::type_check::liveness::local_use_map::LocalUseMap; -use borrow_check::nll::type_check::AtLocation; +use borrow_check::nll::type_check::NormalizeLocation; use borrow_check::nll::type_check::TypeChecker; use dataflow::move_paths::indexes::MovePathIndex; use dataflow::move_paths::MoveData; @@ -487,7 +488,11 @@ impl LivenessContext<'_, '_, '_, '_, 'tcx> { if let Some(data) = &drop_data.region_constraint_data { for &drop_location in drop_locations { self.typeck - .push_region_constraints(drop_location.boring(), data); + .push_region_constraints( + drop_location.to_locations(), + ConstraintCategory::Boring, + data, + ); } } diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index de96539ec30f1..c58518011aaf1 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -13,7 +13,7 @@ use borrow_check::borrow_set::BorrowSet; use borrow_check::location::LocationTable; -use borrow_check::nll::constraints::{ConstraintSet, OutlivesConstraint}; +use borrow_check::nll::constraints::{ConstraintCategory, ConstraintSet, OutlivesConstraint}; use borrow_check::nll::facts::AllFacts; use borrow_check::nll::region_infer::values::{LivenessValues, RegionValueElements}; use borrow_check::nll::region_infer::{ClosureRegionRequirementsExt, TypeTest}; @@ -252,7 +252,8 @@ impl<'a, 'b, 'gcx, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'gcx, 'tcx> { constant.ty, ty::Variance::Invariant, user_ty, - location.boring(), + location.to_locations(), + ConstraintCategory::Boring, ) { span_mirbug!( self, @@ -281,7 +282,8 @@ impl<'a, 'b, 'gcx, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'gcx, 'tcx> { local_decl.ty, ty::Variance::Invariant, user_ty, - Locations::All, + Locations::All(local_decl.source_info.span), + ConstraintCategory::TypeAnnotation, ) { span_mirbug!( self, @@ -364,14 +366,19 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> { let instantiated_predicates = tcx.predicates_of(def_id).instantiate(tcx, substs); type_checker.normalize_and_prove_instantiated_predicates( instantiated_predicates, - location.boring(), + location.to_locations(), ); } debug!("sanitize_constant: expected_ty={:?}", constant.literal.ty); if let Err(terr) = self.cx - .eq_types(constant.literal.ty, constant.ty, location.boring()) + .eq_types( + constant.literal.ty, + constant.ty, + location.to_locations(), + ConstraintCategory::Boring, + ) { span_mirbug!( self, @@ -417,7 +424,12 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> { let sty = self.sanitize_type(place, sty); let ty = self.tcx().type_of(def_id); let ty = self.cx.normalize(ty, location); - if let Err(terr) = self.cx.eq_types(ty, sty, location.boring()) { + if let Err(terr) = self.cx.eq_types( + ty, + sty, + location.to_locations(), + ConstraintCategory::Boring, + ) { span_mirbug!( self, place, @@ -461,7 +473,11 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> { // (e.g., #29149). Note that we decide to use Copy before knowing whether the bounds // fully apply: in effect, the rule is that if a value of some type could implement // Copy, then it must. - self.cx.prove_trait_ref(trait_ref, location.interesting()); + self.cx.prove_trait_ref( + trait_ref, + location.to_locations(), + ConstraintCategory::CopyBound, + ); } place_ty } @@ -560,7 +576,12 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> { ProjectionElem::Field(field, fty) => { let fty = self.sanitize_type(place, fty); match self.field_ty(place, base, field, location) { - Ok(ty) => if let Err(terr) = self.cx.eq_types(ty, fty, location.boring()) { + Ok(ty) => if let Err(terr) = self.cx.eq_types( + ty, + fty, + location.to_locations(), + ConstraintCategory::Boring, + ) { span_mirbug!( self, place, @@ -740,43 +761,32 @@ pub enum Locations { /// user-given type annotations; e.g., if the user wrote `let mut /// x: &'static u32 = ...`, we would ensure that all values /// assigned to `x` are of `'static` lifetime. - All, - - /// A "boring" constraint (caused by the given location) is one that - /// the user probably doesn't want to see described in diagnostics, - /// because it is kind of an artifact of the type system setup. /// - /// Example: `x = Foo { field: y }` technically creates - /// intermediate regions representing the "type of `Foo { field: y - /// }`", and data flows from `y` into those variables, but they - /// are not very interesting. The assignment into `x` on the other - /// hand might be. - Boring(Location), - - /// An *important* outlives constraint (caused by the given - /// location) is one that would be useful to highlight in - /// diagnostics, because it represents a point where references - /// flow from one spot to another (e.g., `x = y`) - Interesting(Location), + /// The span points to the place the constraint arose. For example, + /// it points to the type in a user-given type annotation. If + /// there's no sensible span then it's DUMMY_SP. + All(Span), + + /// An outlives constraint that only has to hold at a single location, + /// usually it represents a point where references flow from one spot to + /// another (e.g., `x = y`) + Single(Location), } impl Locations { pub fn from_location(&self) -> Option { match self { - Locations::All => None, - Locations::Boring(from_location) | Locations::Interesting(from_location) => { - Some(*from_location) - } + Locations::All(_) => None, + Locations::Single(from_location) => Some(*from_location), } } /// Gets a span representing the location. pub fn span(&self, mir: &Mir<'_>) -> Span { - let span_location = match self { - Locations::All => Location::START, - Locations::Boring(l) | Locations::Interesting(l) => *l, - }; - mir.source_info(span_location).span + match self { + Locations::All(span) => *span, + Locations::Single(l) => mir.source_info(*l).span, + } } } @@ -816,12 +826,13 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { fn fully_perform_op( &mut self, locations: Locations, + category: ConstraintCategory, op: impl type_op::TypeOp<'gcx, 'tcx, Output = R>, ) -> Fallible { let (r, opt_data) = op.fully_perform(self.infcx)?; if let Some(data) = &opt_data { - self.push_region_constraints(locations, data); + self.push_region_constraints(locations, category, data); } Ok(r) @@ -830,6 +841,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { fn push_region_constraints( &mut self, locations: Locations, + category: ConstraintCategory, data: &[QueryRegionConstraint<'tcx>], ) { debug!( @@ -846,6 +858,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { self.implicit_region_bound, self.param_env, locations, + category, &mut borrowck_context.constraints.outlives_constraints, &mut borrowck_context.constraints.type_tests, &mut borrowck_context.all_facts, @@ -853,22 +866,36 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { } } - fn sub_types(&mut self, sub: Ty<'tcx>, sup: Ty<'tcx>, locations: Locations) -> Fallible<()> { + fn sub_types( + &mut self, + sub: Ty<'tcx>, + sup: Ty<'tcx>, + locations: Locations, + category: ConstraintCategory, + ) -> Fallible<()> { relate_tys::sub_types( self.infcx, sub, sup, locations, + category, self.borrowck_context.as_mut().map(|x| &mut **x), ) } - fn eq_types(&mut self, a: Ty<'tcx>, b: Ty<'tcx>, locations: Locations) -> Fallible<()> { + fn eq_types( + &mut self, + a: Ty<'tcx>, + b: Ty<'tcx>, + locations: Locations, + category: ConstraintCategory, + ) -> Fallible<()> { relate_tys::eq_types( self.infcx, a, b, locations, + category, self.borrowck_context.as_mut().map(|x| &mut **x), ) } @@ -879,6 +906,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { v: ty::Variance, b: CanonicalTy<'tcx>, locations: Locations, + category: ConstraintCategory, ) -> Fallible<()> { relate_tys::relate_type_and_user_type( self.infcx, @@ -886,6 +914,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { v, b, locations, + category, self.borrowck_context.as_mut().map(|x| &mut **x), ) } @@ -903,21 +932,22 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { // they are not caused by the user, but rather artifacts // of lowering. Assignments to other sorts of places *are* interesting // though. - let is_temp = if let Place::Local(l) = *place { - l != RETURN_PLACE && !mir.local_decls[l].is_user_variable.is_some() - } else { - false - }; - - let locations = if is_temp { - location.boring() - } else { - location.interesting() + let category = match *place { + Place::Local(RETURN_PLACE) => ConstraintCategory::Return, + Place::Local(l) if !mir.local_decls[l].is_user_variable.is_some() => { + ConstraintCategory::Boring + } + _ => ConstraintCategory::Assignment, }; let place_ty = place.ty(mir, tcx).to_ty(tcx); let rv_ty = rv.ty(mir, tcx); - if let Err(terr) = self.sub_types(rv_ty, place_ty, locations) { + if let Err(terr) = self.sub_types( + rv_ty, + place_ty, + location.to_locations(), + category, + ) { span_mirbug!( self, stmt, @@ -933,7 +963,8 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { rv_ty, ty::Variance::Invariant, user_ty, - location.boring(), + location.to_locations(), + ConstraintCategory::Boring, ) { span_mirbug!( self, @@ -952,7 +983,11 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { def_id: tcx.lang_items().sized_trait().unwrap(), substs: tcx.mk_substs_trait(place_ty, &[]), }; - self.prove_trait_ref(trait_ref, location.interesting()); + self.prove_trait_ref( + trait_ref, + location.to_locations(), + ConstraintCategory::SizedBound, + ); } } StatementKind::SetDiscriminant { @@ -983,7 +1018,13 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { StatementKind::AscribeUserType(ref place, variance, c_ty) => { let place_ty = place.ty(mir, tcx).to_ty(tcx); if let Err(terr) = - self.relate_type_and_user_type(place_ty, variance, c_ty, Locations::All) + self.relate_type_and_user_type( + place_ty, + variance, + c_ty, + Locations::All(stmt.source_info.span), + ConstraintCategory::TypeAnnotation, + ) { span_mirbug!( self, @@ -1035,8 +1076,13 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { let place_ty = location.ty(mir, tcx).to_ty(tcx); let rv_ty = value.ty(mir, tcx); - let locations = term_location.interesting(); - if let Err(terr) = self.sub_types(rv_ty, place_ty, locations) { + let locations = term_location.to_locations(); + if let Err(terr) = self.sub_types( + rv_ty, + place_ty, + locations, + ConstraintCategory::Assignment, + ) { span_mirbug!( self, term, @@ -1053,7 +1099,12 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { .. } => { let discr_ty = discr.ty(mir, tcx); - if let Err(terr) = self.sub_types(discr_ty, switch_ty, term_location.boring()) { + if let Err(terr) = self.sub_types( + discr_ty, + switch_ty, + term_location.to_locations(), + ConstraintCategory::Assignment, + ) { span_mirbug!( self, term, @@ -1093,7 +1144,8 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { self.prove_predicates( sig.inputs().iter().map(|ty| ty::Predicate::WellFormed(ty)), - term_location.boring(), + term_location.to_locations(), + ConstraintCategory::Boring, ); // The ordinary liveness rules will ensure that all @@ -1139,7 +1191,12 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { match mir.yield_ty { None => span_mirbug!(self, term, "yield in non-generator"), Some(ty) => { - if let Err(terr) = self.sub_types(value_ty, ty, term_location.interesting()) + if let Err(terr) = self.sub_types( + value_ty, + ty, + term_location.to_locations(), + ConstraintCategory::Return, + ) { span_mirbug!( self, @@ -1168,19 +1225,22 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { match *destination { Some((ref dest, _target_block)) => { let dest_ty = dest.ty(mir, tcx).to_ty(tcx); - let is_temp = if let Place::Local(l) = *dest { - l != RETURN_PLACE && !mir.local_decls[l].is_user_variable.is_some() - } else { - false + let category = match *dest { + Place::Local(RETURN_PLACE) => ConstraintCategory::Return, + Place::Local(l) if !mir.local_decls[l].is_user_variable.is_some() => { + ConstraintCategory::Boring + } + _ => ConstraintCategory::Assignment, }; - let locations = if is_temp { - term_location.boring() - } else { - term_location.interesting() - }; + let locations = term_location.to_locations(); - if let Err(terr) = self.sub_types(sig.output(), dest_ty, locations) { + if let Err(terr) = self.sub_types( + sig.output(), + dest_ty, + locations, + category, + ) { span_mirbug!( self, term, @@ -1221,7 +1281,12 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { } for (n, (fn_arg, op_arg)) in sig.inputs().iter().zip(args).enumerate() { let op_arg_ty = op_arg.ty(mir, self.tcx()); - if let Err(terr) = self.sub_types(op_arg_ty, fn_arg, term_location.interesting()) { + if let Err(terr) = self.sub_types( + op_arg_ty, + fn_arg, + term_location.to_locations(), + ConstraintCategory::CallArgument, + ) { span_mirbug!( self, term, @@ -1470,7 +1535,11 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { substs: tcx.mk_substs_trait(operand_ty, &[]), }; - self.prove_trait_ref(trait_ref, location.interesting()); + self.prove_trait_ref( + trait_ref, + location.to_locations(), + ConstraintCategory::CopyBound, + ); }, Rvalue::NullaryOp(_, ty) => { @@ -1485,24 +1554,34 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { substs: tcx.mk_substs_trait(ty, &[]), }; - self.prove_trait_ref(trait_ref, location.interesting()); + self.prove_trait_ref( + trait_ref, + location.to_locations(), + ConstraintCategory::SizedBound, + ); } - Rvalue::Cast(cast_kind, op, ty) => match cast_kind { - CastKind::ReifyFnPointer => { - let fn_sig = op.ty(mir, tcx).fn_sig(tcx); + Rvalue::Cast(cast_kind, op, ty) => { + match cast_kind { + CastKind::ReifyFnPointer => { + let fn_sig = op.ty(mir, tcx).fn_sig(tcx); - // The type that we see in the fcx is like - // `foo::<'a, 'b>`, where `foo` is the path to a - // function definition. When we extract the - // signature, it comes from the `fn_sig` query, - // and hence may contain unnormalized results. - let fn_sig = self.normalize(fn_sig, location); + // The type that we see in the fcx is like + // `foo::<'a, 'b>`, where `foo` is the path to a + // function definition. When we extract the + // signature, it comes from the `fn_sig` query, + // and hence may contain unnormalized results. + let fn_sig = self.normalize(fn_sig, location); - let ty_fn_ptr_from = tcx.mk_fn_ptr(fn_sig); + let ty_fn_ptr_from = tcx.mk_fn_ptr(fn_sig); - if let Err(terr) = self.eq_types(ty_fn_ptr_from, ty, location.interesting()) { - span_mirbug!( + if let Err(terr) = self.eq_types( + ty_fn_ptr_from, + ty, + location.to_locations(), + ConstraintCategory::Cast, + ) { + span_mirbug!( self, rvalue, "equating {:?} with {:?} yields {:?}", @@ -1510,20 +1589,25 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { ty, terr ); + } } - } - CastKind::ClosureFnPointer => { - let sig = match op.ty(mir, tcx).sty { - ty::Closure(def_id, substs) => { - substs.closure_sig_ty(def_id, tcx).fn_sig(tcx) - } - _ => bug!(), - }; - let ty_fn_ptr_from = tcx.coerce_closure_fn_ty(sig); + CastKind::ClosureFnPointer => { + let sig = match op.ty(mir, tcx).sty { + ty::Closure(def_id, substs) => { + substs.closure_sig_ty(def_id, tcx).fn_sig(tcx) + } + _ => bug!(), + }; + let ty_fn_ptr_from = tcx.coerce_closure_fn_ty(sig); - if let Err(terr) = self.eq_types(ty_fn_ptr_from, ty, location.interesting()) { - span_mirbug!( + if let Err(terr) = self.eq_types( + ty_fn_ptr_from, + ty, + location.to_locations(), + ConstraintCategory::Cast, + ) { + span_mirbug!( self, rvalue, "equating {:?} with {:?} yields {:?}", @@ -1531,23 +1615,28 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { ty, terr ); + } } - } - CastKind::UnsafeFnPointer => { - let fn_sig = op.ty(mir, tcx).fn_sig(tcx); + CastKind::UnsafeFnPointer => { + let fn_sig = op.ty(mir, tcx).fn_sig(tcx); - // The type that we see in the fcx is like - // `foo::<'a, 'b>`, where `foo` is the path to a - // function definition. When we extract the - // signature, it comes from the `fn_sig` query, - // and hence may contain unnormalized results. - let fn_sig = self.normalize(fn_sig, location); + // The type that we see in the fcx is like + // `foo::<'a, 'b>`, where `foo` is the path to a + // function definition. When we extract the + // signature, it comes from the `fn_sig` query, + // and hence may contain unnormalized results. + let fn_sig = self.normalize(fn_sig, location); - let ty_fn_ptr_from = tcx.safe_to_unsafe_fn_ty(fn_sig); + let ty_fn_ptr_from = tcx.safe_to_unsafe_fn_ty(fn_sig); - if let Err(terr) = self.eq_types(ty_fn_ptr_from, ty, location.interesting()) { - span_mirbug!( + if let Err(terr) = self.eq_types( + ty_fn_ptr_from, + ty, + location.to_locations(), + ConstraintCategory::Cast, + ) { + span_mirbug!( self, rvalue, "equating {:?} with {:?} yields {:?}", @@ -1555,21 +1644,26 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { ty, terr ); + } } - } - CastKind::Unsize => { - let &ty = ty; - let trait_ref = ty::TraitRef { - def_id: tcx.lang_items().coerce_unsized_trait().unwrap(), - substs: tcx.mk_substs_trait(op.ty(mir, tcx), &[ty.into()]), - }; + CastKind::Unsize => { + let &ty = ty; + let trait_ref = ty::TraitRef { + def_id: tcx.lang_items().coerce_unsized_trait().unwrap(), + substs: tcx.mk_substs_trait(op.ty(mir, tcx), &[ty.into()]), + }; - self.prove_trait_ref(trait_ref, location.interesting()); - } + self.prove_trait_ref( + trait_ref, + location.to_locations(), + ConstraintCategory::Cast, + ); + } - CastKind::Misc => {} - }, + CastKind::Misc => {} + } + } Rvalue::Ref(region, _borrow_kind, borrowed_place) => { self.add_reborrow_constraint(location, region, borrowed_place); @@ -1644,7 +1738,12 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { }; let operand_ty = operand.ty(mir, tcx); - if let Err(terr) = self.sub_types(operand_ty, field_ty, location.boring()) { + if let Err(terr) = self.sub_types( + operand_ty, + field_ty, + location.to_locations(), + ConstraintCategory::Boring, + ) { span_mirbug!( self, rvalue, @@ -1723,7 +1822,8 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { constraints.outlives_constraints.push(OutlivesConstraint { sup: ref_region.to_region_vid(), sub: borrow_region.to_region_vid(), - locations: location.boring(), + locations: location.to_locations(), + category: ConstraintCategory::Boring, }); if let Some(all_facts) = all_facts { @@ -1839,8 +1939,11 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { *substs, ); - // Hmm, are these constraints *really* boring? - self.push_region_constraints(location.boring(), &closure_constraints); + self.push_region_constraints( + location.to_locations(), + ConstraintCategory::ClosureBounds, + &closure_constraints, + ); } tcx.predicates_of(*def_id).instantiate(tcx, substs.substs) @@ -1855,16 +1958,22 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { self.normalize_and_prove_instantiated_predicates( instantiated_predicates, - location.boring(), + location.to_locations(), ); } - fn prove_trait_ref(&mut self, trait_ref: ty::TraitRef<'tcx>, locations: Locations) { + fn prove_trait_ref( + &mut self, + trait_ref: ty::TraitRef<'tcx>, + locations: Locations, + category: ConstraintCategory, + ) { self.prove_predicates( Some(ty::Predicate::Trait( trait_ref.to_poly_trait_ref().to_poly_trait_predicate(), )), locations, + category, ); } @@ -1875,7 +1984,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { ) { for predicate in instantiated_predicates.predicates { let predicate = self.normalize(predicate, locations); - self.prove_predicate(predicate, locations); + self.prove_predicate(predicate, locations, ConstraintCategory::Boring); } } @@ -1883,6 +1992,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { &mut self, predicates: impl IntoIterator>, locations: Locations, + category: ConstraintCategory, ) { for predicate in predicates { debug!( @@ -1890,11 +2000,16 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { predicate, locations, ); - self.prove_predicate(predicate, locations); + self.prove_predicate(predicate, locations, category); } } - fn prove_predicate(&mut self, predicate: ty::Predicate<'tcx>, locations: Locations) { + fn prove_predicate( + &mut self, + predicate: ty::Predicate<'tcx>, + locations: Locations, + category: ConstraintCategory, + ) { debug!( "prove_predicate(predicate={:?}, location={:?})", predicate, locations, @@ -1903,6 +2018,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { let param_env = self.param_env; self.fully_perform_op( locations, + category, param_env.and(type_op::prove_predicate::ProvePredicate::new(predicate)), ).unwrap_or_else(|NoSolution| { span_mirbug!(self, NoSolution, "could not prove {:?}", predicate); @@ -1943,6 +2059,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { let param_env = self.param_env; self.fully_perform_op( location.to_locations(), + ConstraintCategory::Boring, param_env.and(type_op::normalize::Normalize::new(value)), ).unwrap_or_else(|NoSolution| { span_mirbug!(self, NoSolution, "failed to normalize `{:?}`", value); @@ -1996,26 +2113,6 @@ impl MirPass for TypeckMir { } } -pub trait AtLocation { - /// Indicates a "boring" constraint that the user probably - /// woudln't want to see highlights. - fn boring(self) -> Locations; - - /// Indicates an "interesting" edge, which is of significance only - /// for diagnostics. - fn interesting(self) -> Locations; -} - -impl AtLocation for Location { - fn boring(self) -> Locations { - Locations::Boring(self) - } - - fn interesting(self) -> Locations { - Locations::Interesting(self) - } -} - trait NormalizeLocation: fmt::Debug + Copy { fn to_locations(self) -> Locations; } @@ -2028,6 +2125,6 @@ impl NormalizeLocation for Locations { impl NormalizeLocation for Location { fn to_locations(self) -> Locations { - self.boring() + Locations::Single(self) } } diff --git a/src/librustc_mir/borrow_check/nll/type_check/relate_tys.rs b/src/librustc_mir/borrow_check/nll/type_check/relate_tys.rs index 06cb44ac9714d..130b4b31d08e8 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/relate_tys.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/relate_tys.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use borrow_check::nll::constraints::OutlivesConstraint; +use borrow_check::nll::constraints::{ConstraintCategory, OutlivesConstraint}; use borrow_check::nll::type_check::{BorrowCheckContext, Locations}; use borrow_check::nll::universal_regions::UniversalRegions; use borrow_check::nll::ToRegionVid; @@ -28,6 +28,7 @@ pub(super) fn sub_types<'tcx>( a: Ty<'tcx>, b: Ty<'tcx>, locations: Locations, + category: ConstraintCategory, borrowck_context: Option<&mut BorrowCheckContext<'_, 'tcx>>, ) -> Fallible<()> { debug!("sub_types(a={:?}, b={:?}, locations={:?})", a, b, locations); @@ -35,6 +36,7 @@ pub(super) fn sub_types<'tcx>( infcx, ty::Variance::Covariant, locations, + category, borrowck_context, ty::List::empty(), ).relate(&a, &b)?; @@ -47,6 +49,7 @@ pub(super) fn eq_types<'tcx>( a: Ty<'tcx>, b: Ty<'tcx>, locations: Locations, + category: ConstraintCategory, borrowck_context: Option<&mut BorrowCheckContext<'_, 'tcx>>, ) -> Fallible<()> { debug!("eq_types(a={:?}, b={:?}, locations={:?})", a, b, locations); @@ -54,6 +57,7 @@ pub(super) fn eq_types<'tcx>( infcx, ty::Variance::Invariant, locations, + category, borrowck_context, ty::List::empty(), ).relate(&a, &b)?; @@ -69,6 +73,7 @@ pub(super) fn relate_type_and_user_type<'tcx>( v: ty::Variance, b: CanonicalTy<'tcx>, locations: Locations, + category: ConstraintCategory, borrowck_context: Option<&mut BorrowCheckContext<'_, 'tcx>>, ) -> Fallible<()> { debug!( @@ -89,6 +94,7 @@ pub(super) fn relate_type_and_user_type<'tcx>( infcx, v1, locations, + category, borrowck_context, b_variables, ).relate(&b_value, &a)?; @@ -124,6 +130,8 @@ struct TypeRelating<'cx, 'bccx: 'cx, 'gcx: 'tcx, 'tcx: 'bccx> { /// Where (and why) is this relation taking place? locations: Locations, + category: ConstraintCategory, + /// This will be `Some` when we are running the type check as part /// of NLL, and `None` if we are running a "sanity check". borrowck_context: Option<&'cx mut BorrowCheckContext<'bccx, 'tcx>>, @@ -161,6 +169,7 @@ impl<'cx, 'bccx, 'gcx, 'tcx> TypeRelating<'cx, 'bccx, 'gcx, 'tcx> { infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>, ambient_variance: ty::Variance, locations: Locations, + category: ConstraintCategory, borrowck_context: Option<&'cx mut BorrowCheckContext<'bccx, 'tcx>>, canonical_var_infos: CanonicalVarInfos<'tcx>, ) -> Self { @@ -171,6 +180,7 @@ impl<'cx, 'bccx, 'gcx, 'tcx> TypeRelating<'cx, 'bccx, 'gcx, 'tcx> { borrowck_context, locations, canonical_var_values, + category, a_scopes: vec![], b_scopes: vec![], } @@ -264,6 +274,7 @@ impl<'cx, 'bccx, 'gcx, 'tcx> TypeRelating<'cx, 'bccx, 'gcx, 'tcx> { sup, sub, locations: self.locations, + category: self.category, }); // FIXME all facts! From bd0895d7d011cc4c6bef4f95e6df64d2fee6ff73 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sat, 15 Sep 2018 18:30:29 +0100 Subject: [PATCH 5/5] Update ui tests --- ...fn-ret-contravariant.krisskross.nll.stderr | 15 ++--- ...-fn-ret-contravariant.transmute.nll.stderr | 2 +- ...ect-fn-ret-invariant.krisskross.nll.stderr | 15 ++--- ...ject-fn-ret-invariant.transmute.nll.stderr | 4 +- ...t_outlive_least_region_or_bound.nll.stderr | 6 +- .../static-return-lifetime-infered.nll.stderr | 4 +- .../type_parameters_captured.nll.stderr | 6 +- src/test/ui/issues/issue-10291.nll.stderr | 13 ++-- .../ex3-both-anon-regions-2.nll.stderr | 2 +- ...anon-regions-both-are-structs-2.nll.stderr | 2 +- ...anon-regions-both-are-structs-3.nll.stderr | 2 +- ...anon-regions-both-are-structs-4.nll.stderr | 2 +- ...th-anon-regions-one-is-struct-2.nll.stderr | 2 +- ...th-anon-regions-one-is-struct-3.nll.stderr | 2 +- ...th-anon-regions-one-is-struct-4.nll.stderr | 2 +- ...both-anon-regions-one-is-struct.nll.stderr | 2 +- .../escape-argument-callee.stderr | 2 +- .../propagate-approximated-ref.stderr | 7 ++- ...oximated-shorter-to-static-no-bound.stderr | 21 ++++--- ...mated-shorter-to-static-wrong-bound.stderr | 20 ++++--- .../propagate-approximated-val.stderr | 7 ++- src/test/ui/nll/issue-50716.stderr | 6 +- src/test/ui/nll/issue-52113.rs | 4 +- src/test/ui/nll/issue-52113.stderr | 7 ++- src/test/ui/nll/issue-52742.stderr | 2 +- src/test/ui/nll/mir_check_cast_reify.rs | 2 +- src/test/ui/nll/mir_check_cast_reify.stderr | 6 +- src/test/ui/nll/mir_check_cast_unsafe_fn.rs | 2 +- .../ui/nll/mir_check_cast_unsafe_fn.stderr | 6 +- src/test/ui/nll/mir_check_cast_unsize.stderr | 2 +- .../ui/nll/relate_tys/hr-fn-aaa-as-aba.stderr | 4 +- .../ui/nll/ty-outlives/impl-trait-outlives.rs | 4 +- .../ty-outlives/impl-trait-outlives.stderr | 12 ++-- .../projection-one-region-closure.stderr | 60 +++++++++---------- ...tion-one-region-trait-bound-closure.stderr | 12 ++-- ...tion-two-region-trait-bound-closure.stderr | 4 +- .../ui/nll/user-annotations/patterns.stderr | 4 +- ...ime-default-from-rptr-box-error.nll.stderr | 6 +- ...-default-from-rptr-struct-error.nll.stderr | 6 +- ...ion-object-lifetime-in-coercion.nll.stderr | 4 +- .../regions/regions-addr-of-self.nll.stderr | 2 +- .../regions-addr-of-upvar-self.nll.stderr | 18 +++--- ...ions-close-object-into-object-2.nll.stderr | 4 +- ...ions-close-object-into-object-4.nll.stderr | 16 ++--- ...ons-free-region-ordering-callee.nll.stderr | 2 +- .../ui/regions/regions-nested-fns.nll.stderr | 30 ++++++---- .../regions-trait-object-subtyping.nll.stderr | 2 +- .../dyn-trait-underscore.nll.stderr | 2 +- ...riance-contravariant-arg-object.nll.stderr | 4 +- .../variance-covariant-arg-object.nll.stderr | 4 +- .../variance-invariant-arg-object.nll.stderr | 4 +- 51 files changed, 205 insertions(+), 174 deletions(-) diff --git a/src/test/ui/associated-types/cache/project-fn-ret-contravariant.krisskross.nll.stderr b/src/test/ui/associated-types/cache/project-fn-ret-contravariant.krisskross.nll.stderr index b61ea27ebe19b..044a3f70b4a63 100644 --- a/src/test/ui/associated-types/cache/project-fn-ret-contravariant.krisskross.nll.stderr +++ b/src/test/ui/associated-types/cache/project-fn-ret-contravariant.krisskross.nll.stderr @@ -1,23 +1,24 @@ error: unsatisfied lifetime constraints - --> $DIR/project-fn-ret-contravariant.rs:53:12 + --> $DIR/project-fn-ret-contravariant.rs:55:4 | LL | fn transmute<'a,'b>(x: &'a u32, y: &'b u32) -> (&'a u32, &'b u32) { | -- -- lifetime `'b` defined here | | | lifetime `'a` defined here -LL | let a = bar(foo, y); - | ^^^^^^^^^^^ assignment requires that `'b` must outlive `'a` +... +LL | (a, b) //[krisskross]~ ERROR 55:5: 55:6: lifetime mismatch [E0623] + | ^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` error: unsatisfied lifetime constraints - --> $DIR/project-fn-ret-contravariant.rs:54:12 + --> $DIR/project-fn-ret-contravariant.rs:55:4 | LL | fn transmute<'a,'b>(x: &'a u32, y: &'b u32) -> (&'a u32, &'b u32) { | -- -- lifetime `'b` defined here | | | lifetime `'a` defined here -LL | let a = bar(foo, y); -LL | let b = bar(foo, x); - | ^^^^^^^^^^^ assignment requires that `'a` must outlive `'b` +... +LL | (a, b) //[krisskross]~ ERROR 55:5: 55:6: lifetime mismatch [E0623] + | ^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` error: aborting due to 2 previous errors diff --git a/src/test/ui/associated-types/cache/project-fn-ret-contravariant.transmute.nll.stderr b/src/test/ui/associated-types/cache/project-fn-ret-contravariant.transmute.nll.stderr index 2f632fec17e9e..10f70b525e055 100644 --- a/src/test/ui/associated-types/cache/project-fn-ret-contravariant.transmute.nll.stderr +++ b/src/test/ui/associated-types/cache/project-fn-ret-contravariant.transmute.nll.stderr @@ -14,7 +14,7 @@ LL | fn baz<'a,'b>(x: &'a u32) -> &'static u32 { | | | lifetime `'a` defined here LL | bar(foo, x) //[transmute]~ ERROR E0495 - | ^^^^^^^^^^^ requires that `'a` must outlive `'b` + | ^^^^^^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` error: aborting due to 2 previous errors diff --git a/src/test/ui/associated-types/cache/project-fn-ret-invariant.krisskross.nll.stderr b/src/test/ui/associated-types/cache/project-fn-ret-invariant.krisskross.nll.stderr index 971448997e3f6..1cb687856942d 100644 --- a/src/test/ui/associated-types/cache/project-fn-ret-invariant.krisskross.nll.stderr +++ b/src/test/ui/associated-types/cache/project-fn-ret-invariant.krisskross.nll.stderr @@ -1,23 +1,24 @@ error: unsatisfied lifetime constraints - --> $DIR/project-fn-ret-invariant.rs:63:12 + --> $DIR/project-fn-ret-invariant.rs:65:4 | LL | fn transmute<'a,'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { | -- -- lifetime `'b` defined here | | | lifetime `'a` defined here -LL | let a = bar(foo, y); //[krisskross]~ ERROR E0623 - | ^^^^^^^^^^^ assignment requires that `'b` must outlive `'a` +... +LL | (a, b) //[krisskross]~ ERROR E0623 + | ^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` error: unsatisfied lifetime constraints - --> $DIR/project-fn-ret-invariant.rs:64:12 + --> $DIR/project-fn-ret-invariant.rs:65:4 | LL | fn transmute<'a,'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { | -- -- lifetime `'b` defined here | | | lifetime `'a` defined here -LL | let a = bar(foo, y); //[krisskross]~ ERROR E0623 -LL | let b = bar(foo, x); - | ^^^^^^^^^^^ assignment requires that `'a` must outlive `'b` +... +LL | (a, b) //[krisskross]~ ERROR E0623 + | ^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` error: aborting due to 2 previous errors diff --git a/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.nll.stderr b/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.nll.stderr index 63e1f665005cc..2329adb5deab1 100644 --- a/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.nll.stderr +++ b/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.nll.stderr @@ -8,7 +8,7 @@ LL | bar(foo, x) //[transmute]~ ERROR E0495 | ^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static` error: unsatisfied lifetime constraints - --> $DIR/project-fn-ret-invariant.rs:58:13 + --> $DIR/project-fn-ret-invariant.rs:58:4 | LL | fn baz<'a,'b>(x: Type<'a>) -> Type<'static> { | -- -- lifetime `'b` defined here @@ -16,7 +16,7 @@ LL | fn baz<'a,'b>(x: Type<'a>) -> Type<'static> { | lifetime `'a` defined here ... LL | bar(foo, x) //[transmute]~ ERROR E0495 - | ^ requires that `'a` must outlive `'b` + | ^^^^^^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` error: aborting due to 2 previous errors diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr index 3019e3aa1f732..485d35662445d 100644 --- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr +++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr @@ -36,10 +36,10 @@ LL | move |_| println!("{}", y) | ^^^^^^^^^^^^^^^^^^^^^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` error[E0310]: the parameter type `T` may not live long enough - --> $DIR/must_outlive_least_region_or_bound.rs:34:5 + --> $DIR/must_outlive_least_region_or_bound.rs:32:51 | -LL | x - | ^ +LL | fn ty_param_wont_outlive_static(x: T) -> impl Debug + 'static { + | ^^^^^^^^^^^^^^^^^^^^ | = help: consider adding an explicit lifetime bound `T: 'static`... diff --git a/src/test/ui/impl-trait/static-return-lifetime-infered.nll.stderr b/src/test/ui/impl-trait/static-return-lifetime-infered.nll.stderr index 4bc8876c232e3..7e9aa90c6c50c 100644 --- a/src/test/ui/impl-trait/static-return-lifetime-infered.nll.stderr +++ b/src/test/ui/impl-trait/static-return-lifetime-infered.nll.stderr @@ -4,7 +4,7 @@ error: unsatisfied lifetime constraints LL | fn iter_values_anon(&self) -> impl Iterator { | - let's call the lifetime of this reference `'1` LL | self.x.iter().map(|a| a.0) - | ^^^^^^ cast requires that `'1` must outlive `'static` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'1` must outlive `'static` help: to allow this impl Trait to capture borrowed data with lifetime `'1`, add `'_` as a constraint | LL | fn iter_values_anon(&self) -> impl Iterator + '_ { @@ -16,7 +16,7 @@ error: unsatisfied lifetime constraints LL | fn iter_values<'a>(&'a self) -> impl Iterator { | -- lifetime `'a` defined here LL | self.x.iter().map(|a| a.0) - | ^^^^^^ cast requires that `'a` must outlive `'static` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static` help: to allow this impl Trait to capture borrowed data with lifetime `'a`, add `'a` as a constraint | LL | fn iter_values<'a>(&'a self) -> impl Iterator + 'a { diff --git a/src/test/ui/impl-trait/type_parameters_captured.nll.stderr b/src/test/ui/impl-trait/type_parameters_captured.nll.stderr index 3c2c86fffded0..18258ef1f9dc9 100644 --- a/src/test/ui/impl-trait/type_parameters_captured.nll.stderr +++ b/src/test/ui/impl-trait/type_parameters_captured.nll.stderr @@ -1,8 +1,8 @@ error[E0310]: the parameter type `T` may not live long enough - --> $DIR/type_parameters_captured.rs:19:5 + --> $DIR/type_parameters_captured.rs:17:20 | -LL | x - | ^ +LL | fn foo(x: T) -> impl Any + 'static { + | ^^^^^^^^^^^^^^^^^^ | = help: consider adding an explicit lifetime bound `T: 'static`... diff --git a/src/test/ui/issues/issue-10291.nll.stderr b/src/test/ui/issues/issue-10291.nll.stderr index d19c4d880c7c8..201a3b3d54a3f 100644 --- a/src/test/ui/issues/issue-10291.nll.stderr +++ b/src/test/ui/issues/issue-10291.nll.stderr @@ -1,10 +1,13 @@ error: unsatisfied lifetime constraints - --> $DIR/issue-10291.rs:12:5 + --> $DIR/issue-10291.rs:12:65 | -LL | fn test<'x>(x: &'x isize) { - | -- lifetime `'x` defined here -LL | drop:: FnMut(&'z isize) -> &'z isize>>(Box::new(|z| { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'x` must outlive `'static` +LL | fn test<'x>(x: &'x isize) { + | -- lifetime `'x` defined here +LL | drop:: FnMut(&'z isize) -> &'z isize>>(Box::new(|z| { + | _________________________________________________________________^ +LL | | x //~ ERROR E0312 +LL | | })); + | |_____^ closure body requires that `'x` must outlive `'static` error: aborting due to previous error diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-2.nll.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-2.nll.stderr index 017c3e977475c..e4aafd7b66e40 100644 --- a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-2.nll.stderr +++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-2.nll.stderr @@ -6,7 +6,7 @@ LL | fn foo(&mut (ref mut v, w): &mut (&u8, &u8), x: &u8) { | | | let's call the lifetime of this reference `'2` LL | *v = x; //~ ERROR lifetime mismatch - | ^^^^^^ requires that `'1` must outlive `'2` + | ^^^^^^ assignment requires that `'1` must outlive `'2` error: aborting due to previous error diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-2.nll.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-2.nll.stderr index b8e1b483081ba..934cdcd2ef28c 100644 --- a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-2.nll.stderr +++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-2.nll.stderr @@ -6,7 +6,7 @@ LL | fn foo(mut x: Ref, y: Ref) { | | | has type `Ref<'_, '2>` LL | x.b = y.b; //~ ERROR lifetime mismatch - | ^^^^^^^^^ requires that `'1` must outlive `'2` + | ^^^^^^^^^ assignment requires that `'1` must outlive `'2` error: aborting due to previous error diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-3.nll.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-3.nll.stderr index 4b7352fe22491..cbfd9d478091e 100644 --- a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-3.nll.stderr +++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-3.nll.stderr @@ -7,7 +7,7 @@ LL | fn foo(mut x: Ref) { | has type `Ref<'_, '1>` | has type `Ref<'2, '_>` LL | x.a = x.b; //~ ERROR lifetime mismatch - | ^^^^^^^^^ requires that `'1` must outlive `'2` + | ^^^^^^^^^ assignment requires that `'1` must outlive `'2` error: aborting due to previous error diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-4.nll.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-4.nll.stderr index 53a2fef480671..4f0efe24cf70a 100644 --- a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-4.nll.stderr +++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-4.nll.stderr @@ -7,7 +7,7 @@ LL | fn foo(mut x: Ref) { | has type `Ref<'_, '1>` | has type `Ref<'2, '_>` LL | x.a = x.b; //~ ERROR lifetime mismatch - | ^^^^^^^^^ requires that `'1` must outlive `'2` + | ^^^^^^^^^ assignment requires that `'1` must outlive `'2` error: aborting due to previous error diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-2.nll.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-2.nll.stderr index 1a5f788e14368..fc1fab7aab5bb 100644 --- a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-2.nll.stderr +++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-2.nll.stderr @@ -6,7 +6,7 @@ LL | fn foo(mut x: Ref, y: &u32) { | | | has type `Ref<'_, '1>` LL | y = x.b; //~ ERROR lifetime mismatch - | ^^^^^^^ requires that `'1` must outlive `'2` + | ^^^^^^^ assignment requires that `'1` must outlive `'2` error[E0384]: cannot assign to immutable argument `y` --> $DIR/ex3-both-anon-regions-one-is-struct-2.rs:14:5 diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-3.nll.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-3.nll.stderr index d098354d98393..8100fa89c2d0a 100644 --- a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-3.nll.stderr +++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-3.nll.stderr @@ -6,7 +6,7 @@ LL | fn foo(mut y: Ref, x: &u32) { | | | has type `Ref<'_, '2>` LL | y.b = x; //~ ERROR lifetime mismatch - | ^^^^^^^ requires that `'1` must outlive `'2` + | ^^^^^^^ assignment requires that `'1` must outlive `'2` error: aborting due to previous error diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-4.nll.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-4.nll.stderr index 17a70aa85beeb..1c4a8b6658932 100644 --- a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-4.nll.stderr +++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-4.nll.stderr @@ -6,7 +6,7 @@ LL | fn foo(mut y: Ref, x: &u32) { | | | has type `Ref<'_, '2>` LL | y.b = x; //~ ERROR lifetime mismatch - | ^^^^^^^ requires that `'1` must outlive `'2` + | ^^^^^^^ assignment requires that `'1` must outlive `'2` error: aborting due to previous error diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct.nll.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct.nll.stderr index 2ebdedddc5075..2a4c5a685f16a 100644 --- a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct.nll.stderr +++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct.nll.stderr @@ -6,7 +6,7 @@ LL | fn foo(mut x: Ref, y: &u32) { | | | has type `Ref<'_, '2>` LL | x.b = y; //~ ERROR lifetime mismatch - | ^^^^^^^ requires that `'1` must outlive `'2` + | ^^^^^^^ assignment requires that `'1` must outlive `'2` error: aborting due to previous error diff --git a/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr b/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr index 72b60188c4c6c..1f9cb6d050fb0 100644 --- a/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr +++ b/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr @@ -13,7 +13,7 @@ error: unsatisfied lifetime constraints --> $DIR/escape-argument-callee.rs:36:45 | LL | let mut closure = expect_sig(|p, y| *p = y); - | - - ^^^^^^ requires that `'1` must outlive `'2` + | - - ^^^^^^ assignment requires that `'1` must outlive `'2` | | | | | has type `&'1 i32` | has type `&mut &'2 i32` diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr index 1af96b97e73bd..2e1249a5e8126 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr @@ -34,19 +34,20 @@ LL | | } = note: defining type: DefId(0/0:6 ~ propagate_approximated_ref[317d]::supply[0]) with substs [] error: unsatisfied lifetime constraints - --> $DIR/propagate-approximated-ref.rs:53:5 + --> $DIR/propagate-approximated-ref.rs:53:47 | LL | fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) { | -- -- lifetime `'b` defined here | | | lifetime `'a` defined here -LL | / establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| { +LL | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| { + | _______________________________________________^ LL | | //~^ ERROR unsatisfied lifetime constraints LL | | LL | | // Only works if 'x: 'y: LL | | demand_y(x, y, x.get()) LL | | }); - | |______^ argument requires that `'a` must outlive `'b` + | |_____^ closure body requires that `'a` must outlive `'b` error: aborting due to previous error diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr index 9de9e21ba43d2..9f1d9d21d11c0 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr @@ -49,14 +49,21 @@ LL | | }); | |______^ `cell_a` escapes the function body here error: unsatisfied lifetime constraints - --> $DIR/propagate-approximated-shorter-to-static-no-bound.rs:45:29 + --> $DIR/propagate-approximated-shorter-to-static-no-bound.rs:45:47 | -LL | fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) { - | -- -- lifetime `'b` defined here - | | - | lifetime `'a` defined here -LL | establish_relationships(&cell_a, &cell_b, |_outlives, x, y| { - | ^^^^^^^ requires that `'a` must outlive `'b` +LL | fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | establish_relationships(&cell_a, &cell_b, |_outlives, x, y| { + | _______________________________________________^ +LL | | //~^ ERROR borrowed data escapes outside of function +LL | | //~| ERROR unsatisfied lifetime constraints +LL | | +LL | | // Only works if 'x: 'y: +LL | | demand_y(x, y, x.get()) +LL | | }); + | |_____^ closure body requires that `'a` must outlive `'b` error: aborting due to 2 previous errors diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr index 6acb675005540..4e72fe4bb28aa 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr @@ -47,14 +47,20 @@ LL | | }); | |______^ `cell_a` escapes the function body here error: unsatisfied lifetime constraints - --> $DIR/propagate-approximated-shorter-to-static-wrong-bound.rs:48:29 + --> $DIR/propagate-approximated-shorter-to-static-wrong-bound.rs:48:47 | -LL | fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) { - | -- -- lifetime `'b` defined here - | | - | lifetime `'a` defined here -LL | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| { - | ^^^^^^^ requires that `'a` must outlive `'b` +LL | fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| { + | _______________________________________________^ +LL | | //~^ ERROR borrowed data escapes outside of function +LL | | //~| ERROR unsatisfied lifetime constraints +LL | | // Only works if 'x: 'y: +LL | | demand_y(x, y, x.get()) +LL | | }); + | |_____^ closure body requires that `'a` must outlive `'b` error: aborting due to 2 previous errors diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr index e0902ca1ddbe8..de60b23ef6b97 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr @@ -34,19 +34,20 @@ LL | | } = note: defining type: DefId(0/0:6 ~ propagate_approximated_val[317d]::test[0]) with substs [] error: unsatisfied lifetime constraints - --> $DIR/propagate-approximated-val.rs:46:5 + --> $DIR/propagate-approximated-val.rs:46:45 | LL | fn test<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) { | -- -- lifetime `'b` defined here | | | lifetime `'a` defined here -LL | / establish_relationships(cell_a, cell_b, |outlives1, outlives2, x, y| { +LL | establish_relationships(cell_a, cell_b, |outlives1, outlives2, x, y| { + | _____________________________________________^ LL | | //~^ ERROR unsatisfied lifetime constraints LL | | LL | | // Only works if 'x: 'y: LL | | demand_y(outlives1, outlives2, x.get()) LL | | }); - | |______^ argument requires that `'a` must outlive `'b` + | |_____^ closure body requires that `'a` must outlive `'b` error: aborting due to previous error diff --git a/src/test/ui/nll/issue-50716.stderr b/src/test/ui/nll/issue-50716.stderr index f12ab9b4f9602..eddad056995a7 100644 --- a/src/test/ui/nll/issue-50716.stderr +++ b/src/test/ui/nll/issue-50716.stderr @@ -1,11 +1,11 @@ -error: borrowed data escapes outside of function +error: unsatisfied lifetime constraints --> $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 function body + | -- lifetime `'a` defined here ... LL | let _x = *s; //~ ERROR - | ^^ `s` escapes the function body here + | ^^ proving this value is `Sized` requires that `'a` must outlive `'static` error: aborting due to previous error diff --git a/src/test/ui/nll/issue-52113.rs b/src/test/ui/nll/issue-52113.rs index e484c249d84a5..af577e8499b09 100644 --- a/src/test/ui/nll/issue-52113.rs +++ b/src/test/ui/nll/issue-52113.rs @@ -40,11 +40,11 @@ fn produce3<'a, 'b: 'a>(data: &'a mut Vec<&'a u32>, value: &'b u32) -> impl Bazi } fn produce_err<'a, 'b: 'a>(data: &'b mut Vec<&'b u32>, value: &'a u32) -> impl Bazinga + 'b { - let x = move || { //~ ERROR unsatisfied lifetime constraints + let x = move || { let value: &'a u32 = value; data.push(value); }; - x + x //~ ERROR unsatisfied lifetime constraints } fn main() { } diff --git a/src/test/ui/nll/issue-52113.stderr b/src/test/ui/nll/issue-52113.stderr index b21539361e66f..45a192de454ef 100644 --- a/src/test/ui/nll/issue-52113.stderr +++ b/src/test/ui/nll/issue-52113.stderr @@ -1,12 +1,13 @@ error: unsatisfied lifetime constraints - --> $DIR/issue-52113.rs:43:9 + --> $DIR/issue-52113.rs:47:5 | LL | fn produce_err<'a, 'b: 'a>(data: &'b mut Vec<&'b u32>, value: &'a u32) -> impl Bazinga + 'b { | -- -- lifetime `'b` defined here | | | lifetime `'a` defined here -LL | let x = move || { //~ ERROR unsatisfied lifetime constraints - | ^ requires that `'a` must outlive `'b` +... +LL | x //~ ERROR unsatisfied lifetime constraints + | ^ returning this value requires that `'a` must outlive `'b` error: aborting due to previous error diff --git a/src/test/ui/nll/issue-52742.stderr b/src/test/ui/nll/issue-52742.stderr index 515ba55cf6f5b..83a594941c0a5 100644 --- a/src/test/ui/nll/issue-52742.stderr +++ b/src/test/ui/nll/issue-52742.stderr @@ -6,7 +6,7 @@ LL | fn take_bar(&mut self, b: Bar<'_>) { | | | has type `&mut Foo<'_, '2>` LL | self.y = b.z - | ^^^^^^^^^^^^ requires that `'1` must outlive `'2` + | ^^^^^^^^^^^^ assignment requires that `'1` must outlive `'2` error: aborting due to previous error diff --git a/src/test/ui/nll/mir_check_cast_reify.rs b/src/test/ui/nll/mir_check_cast_reify.rs index 332ec7a7da28c..c878be9e2a2dc 100644 --- a/src/test/ui/nll/mir_check_cast_reify.rs +++ b/src/test/ui/nll/mir_check_cast_reify.rs @@ -44,8 +44,8 @@ fn bar<'a>(x: &'a u32) -> &'static u32 { // The MIR type checker must therefore relate `'?0` to `'?1` and `'?2` // as part of checking the `ReifyFnPointer`. let f: fn(_) -> _ = foo; - //~^ ERROR unsatisfied lifetime constraints f(x) + //~^ ERROR unsatisfied lifetime constraints } fn main() {} diff --git a/src/test/ui/nll/mir_check_cast_reify.stderr b/src/test/ui/nll/mir_check_cast_reify.stderr index fa5c4100c91e4..fdb71b17287d9 100644 --- a/src/test/ui/nll/mir_check_cast_reify.stderr +++ b/src/test/ui/nll/mir_check_cast_reify.stderr @@ -1,11 +1,11 @@ error: unsatisfied lifetime constraints - --> $DIR/mir_check_cast_reify.rs:46:25 + --> $DIR/mir_check_cast_reify.rs:47:5 | LL | fn bar<'a>(x: &'a u32) -> &'static u32 { | -- lifetime `'a` defined here ... -LL | let f: fn(_) -> _ = foo; - | ^^^ cast requires that `'a` must outlive `'static` +LL | f(x) + | ^^^^ returning this value requires that `'a` must outlive `'static` error: aborting due to previous error diff --git a/src/test/ui/nll/mir_check_cast_unsafe_fn.rs b/src/test/ui/nll/mir_check_cast_unsafe_fn.rs index 937ab31c31586..be91a946857e3 100644 --- a/src/test/ui/nll/mir_check_cast_unsafe_fn.rs +++ b/src/test/ui/nll/mir_check_cast_unsafe_fn.rs @@ -16,8 +16,8 @@ fn bar<'a>(input: &'a u32, f: fn(&'a u32) -> &'a u32) -> &'static u32 { // Here the NLL checker must relate the types in `f` to the types // in `g`. These are related via the `UnsafeFnPointer` cast. let g: unsafe fn(_) -> _ = f; - //~^ ERROR unsatisfied lifetime constraints unsafe { g(input) } + //~^ ERROR unsatisfied lifetime constraints } fn main() {} diff --git a/src/test/ui/nll/mir_check_cast_unsafe_fn.stderr b/src/test/ui/nll/mir_check_cast_unsafe_fn.stderr index 82ff71c055157..c14fb93a525e5 100644 --- a/src/test/ui/nll/mir_check_cast_unsafe_fn.stderr +++ b/src/test/ui/nll/mir_check_cast_unsafe_fn.stderr @@ -1,11 +1,11 @@ error: unsatisfied lifetime constraints - --> $DIR/mir_check_cast_unsafe_fn.rs:18:32 + --> $DIR/mir_check_cast_unsafe_fn.rs:19:14 | LL | fn bar<'a>(input: &'a u32, f: fn(&'a u32) -> &'a u32) -> &'static u32 { | -- lifetime `'a` defined here ... -LL | let g: unsafe fn(_) -> _ = f; - | ^ cast requires that `'a` must outlive `'static` +LL | unsafe { g(input) } + | ^^^^^^^^ returning this value requires that `'a` must outlive `'static` error: aborting due to previous error diff --git a/src/test/ui/nll/mir_check_cast_unsize.stderr b/src/test/ui/nll/mir_check_cast_unsize.stderr index 77a2e8311f052..526dfb6013386 100644 --- a/src/test/ui/nll/mir_check_cast_unsize.stderr +++ b/src/test/ui/nll/mir_check_cast_unsize.stderr @@ -4,7 +4,7 @@ error: unsatisfied lifetime constraints LL | fn bar<'a>(x: &'a u32) -> &'static dyn Debug { | -- lifetime `'a` defined here LL | x - | ^ cast requires that `'a` must outlive `'static` + | ^ returning this value requires that `'a` must outlive `'static` error: aborting due to previous error diff --git a/src/test/ui/nll/relate_tys/hr-fn-aaa-as-aba.stderr b/src/test/ui/nll/relate_tys/hr-fn-aaa-as-aba.stderr index c9195395b878c..9a83872b965c9 100644 --- a/src/test/ui/nll/relate_tys/hr-fn-aaa-as-aba.stderr +++ b/src/test/ui/nll/relate_tys/hr-fn-aaa-as-aba.stderr @@ -5,10 +5,10 @@ LL | let a: for<'a, 'b> fn(&'a u32, &'b u32) -> &'a u32 = make_it(); | ^^^^^^^^^ error: higher-ranked subtype error - --> $DIR/hr-fn-aaa-as-aba.rs:32:58 + --> $DIR/hr-fn-aaa-as-aba.rs:32:9 | LL | let _: for<'a, 'b> fn(&'a u32, &'b u32) -> &'a u32 = make_it(); - | ^^^^^^^^^ + | ^ error: aborting due to 2 previous errors diff --git a/src/test/ui/nll/ty-outlives/impl-trait-outlives.rs b/src/test/ui/nll/ty-outlives/impl-trait-outlives.rs index 4366636589223..64eb735363867 100644 --- a/src/test/ui/nll/ty-outlives/impl-trait-outlives.rs +++ b/src/test/ui/nll/ty-outlives/impl-trait-outlives.rs @@ -15,11 +15,11 @@ use std::fmt::Debug; fn no_region<'a, T>(x: Box) -> impl Debug + 'a + //~^ ERROR the parameter type `T` may not live long enough [E0309] where T: Debug, { x - //~^ ERROR the parameter type `T` may not live long enough [E0309] } fn correct_region<'a, T>(x: Box) -> impl Debug + 'a @@ -30,11 +30,11 @@ where } fn wrong_region<'a, 'b, T>(x: Box) -> impl Debug + 'a + //~^ ERROR the parameter type `T` may not live long enough [E0309] where T: 'b + Debug, { x - //~^ ERROR the parameter type `T` may not live long enough [E0309] } fn outlives_region<'a, 'b, T>(x: Box) -> impl Debug + 'a diff --git a/src/test/ui/nll/ty-outlives/impl-trait-outlives.stderr b/src/test/ui/nll/ty-outlives/impl-trait-outlives.stderr index 05b674f8a9db5..61d2d2d6d82d8 100644 --- a/src/test/ui/nll/ty-outlives/impl-trait-outlives.stderr +++ b/src/test/ui/nll/ty-outlives/impl-trait-outlives.stderr @@ -1,16 +1,16 @@ error[E0309]: the parameter type `T` may not live long enough - --> $DIR/impl-trait-outlives.rs:21:5 + --> $DIR/impl-trait-outlives.rs:17:35 | -LL | x - | ^ +LL | fn no_region<'a, T>(x: Box) -> impl Debug + 'a + | ^^^^^^^^^^^^^^^ | = help: consider adding an explicit lifetime bound `T: ReEarlyBound(0, 'a)`... error[E0309]: the parameter type `T` may not live long enough - --> $DIR/impl-trait-outlives.rs:36:5 + --> $DIR/impl-trait-outlives.rs:32:42 | -LL | x - | ^ +LL | fn wrong_region<'a, 'b, T>(x: Box) -> impl Debug + 'a + | ^^^^^^^^^^^^^^^ | = help: consider adding an explicit lifetime bound `T: ReEarlyBound(0, 'a)`... diff --git a/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr b/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr index a91761f3ece2f..4bd96ab4e713d 100644 --- a/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr +++ b/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr @@ -32,8 +32,16 @@ LL | | } T ] +error[E0309]: the parameter type `T` may not live long enough + --> $DIR/projection-one-region-closure.rs:55:29 + | +LL | with_signature(cell, t, |cell, t| require(cell, t)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider adding an explicit lifetime bound `T: ReFree(DefId(0/0:8 ~ projection_one_region_closure[317d]::no_relationships_late[0]), BrNamed(crate0:DefIndex(1:16), 'a))`... + error: unsatisfied lifetime constraints - --> $DIR/projection-one-region-closure.rs:55:5 + --> $DIR/projection-one-region-closure.rs:55:29 | LL | fn no_relationships_late<'a, 'b, T>(cell: Cell<&'a ()>, t: T) | -- -- lifetime `'b` defined here @@ -41,15 +49,7 @@ LL | fn no_relationships_late<'a, 'b, T>(cell: Cell<&'a ()>, t: T) | lifetime `'a` defined here ... LL | with_signature(cell, t, |cell, t| require(cell, t)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a` - -error[E0309]: the parameter type `T` may not live long enough - --> $DIR/projection-one-region-closure.rs:55:29 - | -LL | with_signature(cell, t, |cell, t| require(cell, t)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: consider adding an explicit lifetime bound `T: ReFree(DefId(0/0:8 ~ projection_one_region_closure[317d]::no_relationships_late[0]), BrNamed(crate0:DefIndex(1:16), 'a))`... + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ closure body requires that `'b` must outlive `'a` note: External requirements --> $DIR/projection-one-region-closure.rs:66:29 @@ -86,8 +86,16 @@ LL | | } T ] +error[E0309]: the parameter type `T` may not live long enough + --> $DIR/projection-one-region-closure.rs:66:29 + | +LL | with_signature(cell, t, |cell, t| require(cell, t)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider adding an explicit lifetime bound `T: ReEarlyBound(0, 'a)`... + error: unsatisfied lifetime constraints - --> $DIR/projection-one-region-closure.rs:66:5 + --> $DIR/projection-one-region-closure.rs:66:29 | LL | fn no_relationships_early<'a, 'b, T>(cell: Cell<&'a ()>, t: T) | -- -- lifetime `'b` defined here @@ -95,15 +103,7 @@ LL | fn no_relationships_early<'a, 'b, T>(cell: Cell<&'a ()>, t: T) | lifetime `'a` defined here ... LL | with_signature(cell, t, |cell, t| require(cell, t)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a` - -error[E0309]: the parameter type `T` may not live long enough - --> $DIR/projection-one-region-closure.rs:66:29 - | -LL | with_signature(cell, t, |cell, t| require(cell, t)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: consider adding an explicit lifetime bound `T: ReEarlyBound(0, 'a)`... + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ closure body requires that `'b` must outlive `'a` note: External requirements --> $DIR/projection-one-region-closure.rs:87:29 @@ -140,8 +140,16 @@ LL | | } T ] +error[E0309]: the parameter type `T` may not live long enough + --> $DIR/projection-one-region-closure.rs:87:29 + | +LL | with_signature(cell, t, |cell, t| require(cell, t)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider adding an explicit lifetime bound `T: ReEarlyBound(0, 'a)`... + error: unsatisfied lifetime constraints - --> $DIR/projection-one-region-closure.rs:87:5 + --> $DIR/projection-one-region-closure.rs:87:29 | LL | fn projection_outlives<'a, 'b, T>(cell: Cell<&'a ()>, t: T) | -- -- lifetime `'b` defined here @@ -149,15 +157,7 @@ LL | fn projection_outlives<'a, 'b, T>(cell: Cell<&'a ()>, t: T) | lifetime `'a` defined here ... LL | with_signature(cell, t, |cell, t| require(cell, t)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a` - -error[E0309]: the parameter type `T` may not live long enough - --> $DIR/projection-one-region-closure.rs:87:29 - | -LL | with_signature(cell, t, |cell, t| require(cell, t)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: consider adding an explicit lifetime bound `T: ReEarlyBound(0, 'a)`... + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ closure body requires that `'b` must outlive `'a` note: External requirements --> $DIR/projection-one-region-closure.rs:99:29 diff --git a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr index 0064393f271ca..ccf70a77bffc1 100644 --- a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr +++ b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr @@ -32,7 +32,7 @@ LL | | } ] error: unsatisfied lifetime constraints - --> $DIR/projection-one-region-trait-bound-closure.rs:47:5 + --> $DIR/projection-one-region-trait-bound-closure.rs:47:29 | LL | fn no_relationships_late<'a, 'b, T>(cell: Cell<&'a ()>, t: T) | -- -- lifetime `'b` defined here @@ -40,7 +40,7 @@ LL | fn no_relationships_late<'a, 'b, T>(cell: Cell<&'a ()>, t: T) | lifetime `'a` defined here ... LL | with_signature(cell, t, |cell, t| require(cell, t)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ closure body requires that `'b` must outlive `'a` note: External requirements --> $DIR/projection-one-region-trait-bound-closure.rs:57:29 @@ -77,7 +77,7 @@ LL | | } ] error: unsatisfied lifetime constraints - --> $DIR/projection-one-region-trait-bound-closure.rs:57:5 + --> $DIR/projection-one-region-trait-bound-closure.rs:57:29 | LL | fn no_relationships_early<'a, 'b, T>(cell: Cell<&'a ()>, t: T) | -- -- lifetime `'b` defined here @@ -85,7 +85,7 @@ LL | fn no_relationships_early<'a, 'b, T>(cell: Cell<&'a ()>, t: T) | lifetime `'a` defined here ... LL | with_signature(cell, t, |cell, t| require(cell, t)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ closure body requires that `'b` must outlive `'a` note: External requirements --> $DIR/projection-one-region-trait-bound-closure.rs:77:29 @@ -122,7 +122,7 @@ LL | | } ] error: unsatisfied lifetime constraints - --> $DIR/projection-one-region-trait-bound-closure.rs:77:5 + --> $DIR/projection-one-region-trait-bound-closure.rs:77:29 | LL | fn projection_outlives<'a, 'b, T>(cell: Cell<&'a ()>, t: T) | -- -- lifetime `'b` defined here @@ -130,7 +130,7 @@ LL | fn projection_outlives<'a, 'b, T>(cell: Cell<&'a ()>, t: T) | lifetime `'a` defined here ... LL | with_signature(cell, t, |cell, t| require(cell, t)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ closure body requires that `'b` must outlive `'a` note: External requirements --> $DIR/projection-one-region-trait-bound-closure.rs:87:29 diff --git a/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr b/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr index 19dcb5f93dac3..372b803082f11 100644 --- a/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr +++ b/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr @@ -235,7 +235,7 @@ LL | | } ] error: unsatisfied lifetime constraints - --> $DIR/projection-two-region-trait-bound-closure.rs:105:5 + --> $DIR/projection-two-region-trait-bound-closure.rs:105:29 | LL | fn two_regions<'a, 'b, T>(cell: Cell<&'a ()>, t: T) | -- -- lifetime `'b` defined here @@ -243,7 +243,7 @@ LL | fn two_regions<'a, 'b, T>(cell: Cell<&'a ()>, t: T) | lifetime `'a` defined here ... LL | with_signature(cell, t, |cell, t| require(cell, t)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ closure body requires that `'b` must outlive `'a` note: External requirements --> $DIR/projection-two-region-trait-bound-closure.rs:115:29 diff --git a/src/test/ui/nll/user-annotations/patterns.stderr b/src/test/ui/nll/user-annotations/patterns.stderr index 563de1a9e02e0..f359608462d1d 100644 --- a/src/test/ui/nll/user-annotations/patterns.stderr +++ b/src/test/ui/nll/user-annotations/patterns.stderr @@ -131,12 +131,12 @@ LL | y //~ ERROR | ^ returning this value requires that `'a` must outlive `'static` error: unsatisfied lifetime constraints - --> $DIR/patterns.rs:117:40 + --> $DIR/patterns.rs:117:9 | LL | fn a_to_static_then_static<'a>(x: &'a u32) -> &'static u32 { | -- lifetime `'a` defined here LL | let (y, _z): (&'static u32, u32) = (x, 44); //~ ERROR - | ^^^^^^^ requires that `'a` must outlive `'static` + | ^^^^^^^ type annotation requires that `'a` must outlive `'static` error: aborting due to 14 previous errors diff --git a/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-box-error.nll.stderr b/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-box-error.nll.stderr index e62b9b070213d..a6bfcf1d3699a 100644 --- a/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-box-error.nll.stderr +++ b/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-box-error.nll.stderr @@ -1,10 +1,10 @@ -error: borrowed data escapes outside of function +error: unsatisfied lifetime constraints --> $DIR/object-lifetime-default-from-rptr-box-error.rs:25:5 | LL | fn c<'a>(t: &'a Box, mut ss: SomeStruct<'a>) { - | - `t` is a reference that is only valid in the function body + | -- lifetime `'a` defined here LL | ss.t = t; //~ ERROR mismatched types - | ^^^^^^^^ `t` escapes the function body here + | ^^^^^^^^ assignment requires that `'a` must outlive `'static` error: aborting due to previous error diff --git a/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-struct-error.nll.stderr b/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-struct-error.nll.stderr index 803f9d3fd7e5c..396ff1302b151 100644 --- a/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-struct-error.nll.stderr +++ b/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-struct-error.nll.stderr @@ -1,10 +1,10 @@ -error: borrowed data escapes outside of function +error: unsatisfied lifetime constraints --> $DIR/object-lifetime-default-from-rptr-struct-error.rs:31:5 | LL | fn c<'a>(t: &'a MyBox, mut ss: SomeStruct<'a>) { - | - `t` is a reference that is only valid in the function body + | -- lifetime `'a` defined here LL | ss.t = t; //~ ERROR mismatched types - | ^^^^^^^^ `t` escapes the function body here + | ^^^^^^^^ assignment requires that `'a` must outlive `'static` error: aborting due to previous error diff --git a/src/test/ui/regions/region-object-lifetime-in-coercion.nll.stderr b/src/test/ui/regions/region-object-lifetime-in-coercion.nll.stderr index e8c1d7e74a038..53d3b2d5323c2 100644 --- a/src/test/ui/regions/region-object-lifetime-in-coercion.nll.stderr +++ b/src/test/ui/regions/region-object-lifetime-in-coercion.nll.stderr @@ -1,10 +1,10 @@ error[E0621]: explicit lifetime required in the type of `v` - --> $DIR/region-object-lifetime-in-coercion.rs:18:33 + --> $DIR/region-object-lifetime-in-coercion.rs:18:9 | LL | fn a(v: &[u8]) -> Box { | ----- help: add explicit lifetime `'static` to the type of `v`: `&'static [u8]` LL | let x: Box = Box::new(v); - | ^^^^^^^^^^^ lifetime `'static` required + | ^ lifetime `'static` required error[E0621]: explicit lifetime required in the type of `v` --> $DIR/region-object-lifetime-in-coercion.rs:24:5 diff --git a/src/test/ui/regions/regions-addr-of-self.nll.stderr b/src/test/ui/regions/regions-addr-of-self.nll.stderr index a85822e48fa6a..0e38abef668ca 100644 --- a/src/test/ui/regions/regions-addr-of-self.nll.stderr +++ b/src/test/ui/regions/regions-addr-of-self.nll.stderr @@ -4,7 +4,7 @@ error: unsatisfied lifetime constraints LL | pub fn chase_cat(&mut self) { | - let's call the lifetime of this reference `'1` LL | let p: &'static mut usize = &mut self.cats_chased; //~ ERROR cannot infer - | ^ requires that `'1` must outlive `'static` + | ^ type annotation requires that `'1` must outlive `'static` error: aborting due to previous error diff --git a/src/test/ui/regions/regions-addr-of-upvar-self.nll.stderr b/src/test/ui/regions/regions-addr-of-upvar-self.nll.stderr index 9d6301af0fbea..6e4bf26047e46 100644 --- a/src/test/ui/regions/regions-addr-of-upvar-self.nll.stderr +++ b/src/test/ui/regions/regions-addr-of-upvar-self.nll.stderr @@ -4,7 +4,7 @@ error: unsatisfied lifetime constraints LL | let _f = || { | -- lifetime `'1` represents this closure's body LL | let p: &'static mut usize = &mut self.food; //~ ERROR cannot infer - | ^ requires that `'1` must outlive `'static` + | ^ type annotation requires that `'1` must outlive `'static` | = note: closure implements `FnMut`, so references to captured variables can't escape the closure @@ -16,17 +16,21 @@ LL | pub fn chase_cat(&mut self) { LL | let _f = || { | -- lifetime `'1` represents this closure's body LL | let p: &'static mut usize = &mut self.food; //~ ERROR cannot infer - | ^ requires that `'1` must outlive `'2` + | ^ type annotation requires that `'1` must outlive `'2` | = note: closure implements `FnMut`, so references to captured variables can't escape the closure error: unsatisfied lifetime constraints - --> $DIR/regions-addr-of-upvar-self.rs:19:13 + --> $DIR/regions-addr-of-upvar-self.rs:19:18 | -LL | pub fn chase_cat(&mut self) { - | - let's call the lifetime of this reference `'1` -LL | let _f = || { - | ^^ requires that `'1` must outlive `'static` +LL | pub fn chase_cat(&mut self) { + | - let's call the lifetime of this reference `'1` +LL | let _f = || { + | __________________^ +LL | | let p: &'static mut usize = &mut self.food; //~ ERROR cannot infer +LL | | *p = 3; +LL | | }; + | |_________^ closure body requires that `'1` must outlive `'static` error[E0597]: `self` does not live long enough --> $DIR/regions-addr-of-upvar-self.rs:20:46 diff --git a/src/test/ui/regions/regions-close-object-into-object-2.nll.stderr b/src/test/ui/regions/regions-close-object-into-object-2.nll.stderr index e619431ddbbc3..c073e3728e705 100644 --- a/src/test/ui/regions/regions-close-object-into-object-2.nll.stderr +++ b/src/test/ui/regions/regions-close-object-into-object-2.nll.stderr @@ -1,10 +1,10 @@ error: unsatisfied lifetime constraints - --> $DIR/regions-close-object-into-object-2.rs:20:11 + --> $DIR/regions-close-object-into-object-2.rs:20:5 | LL | fn g<'a, T: 'static>(v: Box+'a>) -> Box { | -- lifetime `'a` defined here LL | box B(&*v) as Box //~ ERROR cannot infer - | ^^^ cast requires that `'a` must outlive `'static` + | ^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static` error[E0597]: `*v` does not live long enough --> $DIR/regions-close-object-into-object-2.rs:20:11 diff --git a/src/test/ui/regions/regions-close-object-into-object-4.nll.stderr b/src/test/ui/regions/regions-close-object-into-object-4.nll.stderr index 1de1cdc9807f9..4b47b951d7717 100644 --- a/src/test/ui/regions/regions-close-object-into-object-4.nll.stderr +++ b/src/test/ui/regions/regions-close-object-into-object-4.nll.stderr @@ -6,6 +6,14 @@ LL | box B(&*v) as Box //~ ERROR cannot infer | = help: consider adding an explicit lifetime bound `U: 'static`... +error: unsatisfied lifetime constraints + --> $DIR/regions-close-object-into-object-4.rs:20:5 + | +LL | fn i<'a, T, U>(v: Box+'a>) -> Box { + | -- lifetime `'a` defined here +LL | box B(&*v) as Box //~ ERROR cannot infer + | ^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static` + error[E0310]: the parameter type `U` may not live long enough --> $DIR/regions-close-object-into-object-4.rs:20:9 | @@ -14,14 +22,6 @@ LL | box B(&*v) as Box //~ ERROR cannot infer | = help: consider adding an explicit lifetime bound `U: 'static`... -error: unsatisfied lifetime constraints - --> $DIR/regions-close-object-into-object-4.rs:20:11 - | -LL | fn i<'a, T, U>(v: Box+'a>) -> Box { - | -- lifetime `'a` defined here -LL | box B(&*v) as Box //~ ERROR cannot infer - | ^^^ cast requires that `'a` must outlive `'static` - error[E0597]: `*v` does not live long enough --> $DIR/regions-close-object-into-object-4.rs:20:11 | diff --git a/src/test/ui/regions/regions-free-region-ordering-callee.nll.stderr b/src/test/ui/regions/regions-free-region-ordering-callee.nll.stderr index 98a4dc29ae7e7..d060629571319 100644 --- a/src/test/ui/regions/regions-free-region-ordering-callee.nll.stderr +++ b/src/test/ui/regions/regions-free-region-ordering-callee.nll.stderr @@ -18,7 +18,7 @@ LL | fn ordering3<'a, 'b>(x: &'a usize, y: &'b usize) -> &'a &'b usize { | lifetime `'a` defined here LL | // Do not infer an ordering from the return value. LL | let z: &'b usize = &*x; - | ^^^ requires that `'a` must outlive `'b` + | ^^^ assignment requires that `'a` must outlive `'b` error: aborting due to 2 previous errors diff --git a/src/test/ui/regions/regions-nested-fns.nll.stderr b/src/test/ui/regions/regions-nested-fns.nll.stderr index 9e6c57f67332a..4bb602d572fa3 100644 --- a/src/test/ui/regions/regions-nested-fns.nll.stderr +++ b/src/test/ui/regions/regions-nested-fns.nll.stderr @@ -1,22 +1,14 @@ -error: unsatisfied lifetime constraints +error: borrowed data escapes outside of closure --> $DIR/regions-nested-fns.rs:20:9 | LL | let mut ay = &y; //~ ERROR E0495 - | ------ lifetime `'2` appears in the type of `ay` + | ------ `ay` is declared here, outside of the closure body LL | LL | ignore:: FnMut(&'z isize)>>(Box::new(|z| { - | - has type `&'1 isize` + | - `z` is a reference that is only valid in the closure body ... LL | ay = z; - | ^^^^^^ requires that `'1` must outlive `'2` - -error: unsatisfied lifetime constraints - --> $DIR/regions-nested-fns.rs:14:9 - | -LL | fn nested<'x>(x: &'x isize) { - | -- lifetime `'x` defined here -LL | let y = 3; - | ^ requires that `'x` must outlive `'static` + | ^^^^^^ `z` escapes the closure body here error[E0597]: `y` does not live long enough --> $DIR/regions-nested-fns.rs:15:18 @@ -43,6 +35,20 @@ LL | } | = note: borrowed value must be valid for the static lifetime... +error: unsatisfied lifetime constraints + --> $DIR/regions-nested-fns.rs:23:68 + | +LL | fn nested<'x>(x: &'x isize) { + | -- lifetime `'x` defined here +... +LL | ignore::< Box FnMut(&'z isize) -> &'z isize>>(Box::new(|z| { + | ____________________________________________________________________^ +LL | | if false { return x; } //~ ERROR E0312 +LL | | if false { return ay; } +LL | | return z; +LL | | })); + | |_____^ closure body requires that `'x` must outlive `'static` + error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/regions/regions-trait-object-subtyping.nll.stderr b/src/test/ui/regions/regions-trait-object-subtyping.nll.stderr index d4140242c01de..0a9bcee1ce29d 100644 --- a/src/test/ui/regions/regions-trait-object-subtyping.nll.stderr +++ b/src/test/ui/regions/regions-trait-object-subtyping.nll.stderr @@ -7,7 +7,7 @@ LL | fn foo3<'a,'b>(x: &'a mut Dummy) -> &'b mut Dummy { | lifetime `'a` defined here LL | // Without knowing 'a:'b, we can't coerce LL | x //~ ERROR lifetime bound not satisfied - | ^ returning this value requires that `'a` must outlive `'b` + | ^ cast requires that `'a` must outlive `'b` error: unsatisfied lifetime constraints --> $DIR/regions-trait-object-subtyping.rs:32:5 diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore.nll.stderr b/src/test/ui/underscore-lifetime/dyn-trait-underscore.nll.stderr index 745c65c54df4a..7adb195b7d022 100644 --- a/src/test/ui/underscore-lifetime/dyn-trait-underscore.nll.stderr +++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore.nll.stderr @@ -5,7 +5,7 @@ LL | fn a(items: &[T]) -> Box> { | - let's call the lifetime of this reference `'1` LL | // ^^^^^^^^^^^^^^^^^^^^^ bound *here* defaults to `'static` LL | Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime - | ^^^^^^^^^^^^^^^^^^^^^^ cast requires that `'1` must outlive `'static` + | ^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'1` must outlive `'static` error: aborting due to previous error diff --git a/src/test/ui/variance/variance-contravariant-arg-object.nll.stderr b/src/test/ui/variance/variance-contravariant-arg-object.nll.stderr index 4ef45edc24246..a30720dc6ba8a 100644 --- a/src/test/ui/variance/variance-contravariant-arg-object.nll.stderr +++ b/src/test/ui/variance/variance-contravariant-arg-object.nll.stderr @@ -7,7 +7,7 @@ LL | fn get_min_from_max<'min, 'max>(v: Box>) | lifetime `'min` defined here ... LL | v //~ ERROR mismatched types - | ^ cast requires that `'min` must outlive `'max` + | ^ returning this value requires that `'min` must outlive `'max` error: unsatisfied lifetime constraints --> $DIR/variance-contravariant-arg-object.rs:32:5 @@ -18,7 +18,7 @@ LL | fn get_max_from_min<'min, 'max, G>(v: Box>) | lifetime `'min` defined here ... LL | v //~ ERROR mismatched types - | ^ cast requires that `'min` must outlive `'max` + | ^ returning this value requires that `'min` must outlive `'max` error: aborting due to 2 previous errors diff --git a/src/test/ui/variance/variance-covariant-arg-object.nll.stderr b/src/test/ui/variance/variance-covariant-arg-object.nll.stderr index 3105ebaf03117..26699a537e810 100644 --- a/src/test/ui/variance/variance-covariant-arg-object.nll.stderr +++ b/src/test/ui/variance/variance-covariant-arg-object.nll.stderr @@ -7,7 +7,7 @@ LL | fn get_min_from_max<'min, 'max>(v: Box>) | lifetime `'min` defined here ... LL | v //~ ERROR mismatched types - | ^ cast requires that `'min` must outlive `'max` + | ^ returning this value requires that `'min` must outlive `'max` error: unsatisfied lifetime constraints --> $DIR/variance-covariant-arg-object.rs:32:5 @@ -18,7 +18,7 @@ LL | fn get_max_from_min<'min, 'max, G>(v: Box>) | lifetime `'min` defined here ... LL | v //~ ERROR mismatched types - | ^ cast requires that `'min` must outlive `'max` + | ^ returning this value requires that `'min` must outlive `'max` error: aborting due to 2 previous errors diff --git a/src/test/ui/variance/variance-invariant-arg-object.nll.stderr b/src/test/ui/variance/variance-invariant-arg-object.nll.stderr index 54ad4f4c5fbe6..20ab648598618 100644 --- a/src/test/ui/variance/variance-invariant-arg-object.nll.stderr +++ b/src/test/ui/variance/variance-invariant-arg-object.nll.stderr @@ -7,7 +7,7 @@ LL | fn get_min_from_max<'min, 'max>(v: Box>) | lifetime `'min` defined here ... LL | v //~ ERROR mismatched types - | ^ cast requires that `'min` must outlive `'max` + | ^ returning this value requires that `'min` must outlive `'max` error: unsatisfied lifetime constraints --> $DIR/variance-invariant-arg-object.rs:28:5 @@ -18,7 +18,7 @@ LL | fn get_max_from_min<'min, 'max, G>(v: Box>) | lifetime `'min` defined here ... LL | v //~ ERROR mismatched types - | ^ cast requires that `'min` must outlive `'max` + | ^ returning this value requires that `'min` must outlive `'max` error: aborting due to 2 previous errors