diff --git a/src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs b/src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs index ca71b0aeed9a5..4e26a4178b95d 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs @@ -129,7 +129,7 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> { ty::BrNamed(..) => true, _ => false, }, - ty::ReEarlyBound(_) => true, + ty::ReEarlyBound(ebr) => ebr.has_name(), _ => false, } } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 4fda3bdca3dfc..d7e30b0ca7143 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -51,7 +51,7 @@ use std::{mem, ptr}; use syntax::ast::{self, DUMMY_NODE_ID, Name, Ident, NodeId}; use syntax::attr; use syntax::ext::hygiene::Mark; -use syntax::symbol::{Symbol, LocalInternedString, InternedString}; +use syntax::symbol::{keywords, Symbol, LocalInternedString, InternedString}; use syntax_pos::{DUMMY_SP, Span}; use rustc_data_structures::accumulate_vec::IntoIter as AccIntoIter; @@ -824,6 +824,12 @@ impl ty::EarlyBoundRegion { pub fn to_bound_region(&self) -> ty::BoundRegion { ty::BoundRegion::BrNamed(self.def_id, self.name) } + + /// Does this early bound region have a name? Early bound regions normally + /// always have names except when using anonymous lifetimes (`'_`). + pub fn has_name(&self) -> bool { + self.name != keywords::UnderscoreLifetime.name().as_interned_str() + } } #[derive(Clone, Debug, RustcEncodable, RustcDecodable)] 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 8c2a5f19038bb..6acf3aadf5169 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 @@ -95,8 +95,12 @@ impl<'tcx> RegionInferenceContext<'tcx> { debug!("give_region_a_name: error_region = {:?}", error_region); match error_region { ty::ReEarlyBound(ebr) => { - self.highlight_named_span(tcx, error_region, &ebr.name, diag); - Some(ebr.name) + if ebr.has_name() { + self.highlight_named_span(tcx, error_region, &ebr.name, diag); + Some(ebr.name) + } else { + None + } }, ty::ReStatic => Some(keywords::StaticLifetime.name().as_interned_str()), @@ -238,17 +242,14 @@ impl<'tcx> RegionInferenceContext<'tcx> { return Some(region_name); } - let (_argument_name, argument_span) = self.get_argument_name_and_span_for_region( - mir, argument_index); - - let region_name = self.synthesize_region_name(counter); - - diag.span_label( - argument_span, - format!("lifetime `{}` appears in this argument", region_name,), - ); - - Some(region_name) + self.give_name_if_we_cannot_match_hir_ty( + infcx, + mir, + fr, + arg_ty, + counter, + diag, + ) } fn give_name_if_we_can_match_hir_ty_from_argument( @@ -366,14 +367,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { search_stack.push((argument_ty, argument_hir_ty)); - let mut closest_match: &hir::Ty = argument_hir_ty; - while let Some((ty, hir_ty)) = search_stack.pop() { - // While we search, also track the closet match. - if tcx.any_free_region_meets(&ty, |r| r.to_region_vid() == needle_fr) { - closest_match = hir_ty; - } - match (&ty.sty, &hir_ty.node) { // Check if the `argument_ty` is `&'X ..` where `'X` // is the region we are looking for -- if so, and we have a `&T` @@ -448,13 +442,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { } } - let region_name = self.synthesize_region_name(counter); - diag.span_label( - closest_match.span, - format!("lifetime `{}` appears in this type", region_name), - ); - - return Some(region_name); + return None; } /// We've found an enum/struct/union type with the substitutions diff --git a/src/test/ui/lifetime-errors/ex2b-push-no-existing-names.nll.stderr b/src/test/ui/lifetime-errors/ex2b-push-no-existing-names.nll.stderr index 614034794bd60..b7c252cac9bc7 100644 --- a/src/test/ui/lifetime-errors/ex2b-push-no-existing-names.nll.stderr +++ b/src/test/ui/lifetime-errors/ex2b-push-no-existing-names.nll.stderr @@ -8,9 +8,9 @@ error: unsatisfied lifetime constraints --> $DIR/ex2b-push-no-existing-names.rs:16:5 | LL | fn foo(x: &mut Vec>, y: Ref) { - | -------- -------- lifetime `'1` appears in this type - | | - | lifetime `'2` appears in this type + | - - has type `Ref<'1, i32>` + | | + | has type `&mut std::vec::Vec>` LL | x.push(y); //~ ERROR lifetime mismatch | ^^^^^^^^^ argument requires that `'1` must outlive `'2` diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-2.nll.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-2.nll.stderr index 2829fbcd32a1b..618817fd57b31 100644 --- a/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-2.nll.stderr +++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-2.nll.stderr @@ -8,9 +8,9 @@ error: unsatisfied lifetime constraints --> $DIR/ex3-both-anon-regions-both-are-structs-2.rs:16:5 | LL | fn foo(mut x: Ref, y: Ref) { - | --- --- lifetime `'1` appears in this type - | | - | lifetime `'2` appears in this type + | ----- - has type `Ref<'_, '1>` + | | + | has type `Ref<'_, '2>` LL | x.b = y.b; //~ ERROR lifetime mismatch | ^^^^^^^^^ requires that `'1` must outlive `'2` diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-3.nll.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-3.nll.stderr index 8171ee758b066..b4767afd4138a 100644 --- a/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-3.nll.stderr +++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-3.nll.stderr @@ -8,10 +8,10 @@ error: unsatisfied lifetime constraints --> $DIR/ex3-both-anon-regions-both-are-structs-3.rs:16:5 | LL | fn foo(mut x: Ref) { - | --- - | | - | lifetime `'1` appears in this type - | lifetime `'2` appears in this type + | ----- + | | + | has type `Ref<'_, '1>` + | has type `Ref<'2, '_>` LL | x.a = x.b; //~ ERROR lifetime mismatch | ^^^^^^^^^ requires that `'1` must outlive `'2` diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-4.nll.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-4.nll.stderr index 99b64605baec1..e2fcbaa4c3c55 100644 --- a/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-4.nll.stderr +++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-4.nll.stderr @@ -8,10 +8,10 @@ error: unsatisfied lifetime constraints --> $DIR/ex3-both-anon-regions-both-are-structs-4.rs:16:5 | LL | fn foo(mut x: Ref) { - | --- - | | - | lifetime `'1` appears in this type - | lifetime `'2` appears in this type + | ----- + | | + | has type `Ref<'_, '1>` + | has type `Ref<'2, '_>` LL | x.a = x.b; //~ ERROR lifetime mismatch | ^^^^^^^^^ requires that `'1` must outlive `'2` diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs.nll.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs.nll.stderr index c9542d3106979..79f1a8c0ccf7d 100644 --- a/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs.nll.stderr +++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs.nll.stderr @@ -8,9 +8,9 @@ error: unsatisfied lifetime constraints --> $DIR/ex3-both-anon-regions-both-are-structs.rs:15:5 | LL | fn foo(mut x: Vec, y: Ref) { - | --- --- lifetime `'1` appears in this type - | | - | lifetime `'2` appears in this type + | ----- - has type `Ref<'1>` + | | + | has type `std::vec::Vec>` LL | x.push(y); //~ ERROR lifetime mismatch | ^^^^^^^^^ argument requires that `'1` must outlive `'2` diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-2.nll.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-2.nll.stderr index 459796760e1b4..0bacd894e6e9a 100644 --- a/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-2.nll.stderr +++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-2.nll.stderr @@ -8,9 +8,9 @@ error: unsatisfied lifetime constraints --> $DIR/ex3-both-anon-regions-one-is-struct-2.rs:14:5 | LL | fn foo(mut x: Ref, y: &u32) { - | --- - let's call the lifetime of this reference `'2` - | | - | lifetime `'1` appears in this type + | ----- - let's call the lifetime of this reference `'2` + | | + | has type `Ref<'_, '1>` LL | y = x.b; //~ ERROR lifetime mismatch | ^^^^^^^ requires that `'1` must outlive `'2` diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-3.nll.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-3.nll.stderr index 5fc1755ed390a..f40c67b8d114c 100644 --- a/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-3.nll.stderr +++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-3.nll.stderr @@ -8,9 +8,9 @@ error: unsatisfied lifetime constraints --> $DIR/ex3-both-anon-regions-one-is-struct-3.rs:14:5 | LL | fn foo(mut y: Ref, x: &u32) { - | --- - let's call the lifetime of this reference `'1` - | | - | lifetime `'2` appears in this type + | ----- - let's call the lifetime of this reference `'1` + | | + | has type `Ref<'_, '2>` LL | y.b = x; //~ ERROR lifetime mismatch | ^^^^^^^ requires that `'1` must outlive `'2` diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-4.nll.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-4.nll.stderr index 835f95880a744..f9168dcf5837b 100644 --- a/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-4.nll.stderr +++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-4.nll.stderr @@ -8,9 +8,9 @@ error: unsatisfied lifetime constraints --> $DIR/ex3-both-anon-regions-one-is-struct-4.rs:14:5 | LL | fn foo(mut y: Ref, x: &u32) { - | --- - let's call the lifetime of this reference `'1` - | | - | lifetime `'2` appears in this type + | ----- - let's call the lifetime of this reference `'1` + | | + | has type `Ref<'_, '2>` LL | y.b = x; //~ ERROR lifetime mismatch | ^^^^^^^ requires that `'1` must outlive `'2` diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct.nll.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct.nll.stderr index 7aed5fe626f06..c43f847723240 100644 --- a/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct.nll.stderr +++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct.nll.stderr @@ -8,9 +8,9 @@ error: unsatisfied lifetime constraints --> $DIR/ex3-both-anon-regions-one-is-struct.rs:17:5 | LL | fn foo(mut x: Ref, y: &u32) { - | --- - let's call the lifetime of this reference `'1` - | | - | lifetime `'2` appears in this type + | ----- - let's call the lifetime of this reference `'1` + | | + | has type `Ref<'_, '2>` LL | x.b = y; //~ ERROR lifetime mismatch | ^^^^^^^ requires that `'1` must outlive `'2` diff --git a/src/test/ui/nll/issue-52742.rs b/src/test/ui/nll/issue-52742.rs new file mode 100644 index 0000000000000..c36e4cc70fd58 --- /dev/null +++ b/src/test/ui/nll/issue-52742.rs @@ -0,0 +1,31 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(nll)] +#![feature(in_band_lifetimes)] +#![feature(impl_header_lifetime_elision)] + +struct Foo<'a, 'b> { + x: &'a u32, + y: &'b u32, +} + +struct Bar<'b> { + z: &'b u32 +} + +impl Foo<'_, '_> { + fn take_bar(&mut self, b: Bar<'_>) { + self.y = b.z + //~^ ERROR unsatisfied lifetime constraints + } +} + +fn main() { } diff --git a/src/test/ui/nll/issue-52742.stderr b/src/test/ui/nll/issue-52742.stderr new file mode 100644 index 0000000000000..515ba55cf6f5b --- /dev/null +++ b/src/test/ui/nll/issue-52742.stderr @@ -0,0 +1,12 @@ +error: unsatisfied lifetime constraints + --> $DIR/issue-52742.rs:26:9 + | +LL | fn take_bar(&mut self, b: Bar<'_>) { + | --------- -- let's call this `'1` + | | + | has type `&mut Foo<'_, '2>` +LL | self.y = b.z + | ^^^^^^^^^^^^ requires that `'1` must outlive `'2` + +error: aborting due to previous error +