Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

region error messages involving impls are confusing #53124

Merged
merged 3 commits into from Aug 10, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -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,
}
}
Expand Down
8 changes: 7 additions & 1 deletion src/librustc/ty/mod.rs
Expand Up @@ -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;
Expand Down Expand Up @@ -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)]
Expand Down
Expand Up @@ -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()),
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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`
Expand Down Expand Up @@ -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
Expand Down
Expand Up @@ -8,9 +8,9 @@ error: unsatisfied lifetime constraints
--> $DIR/ex2b-push-no-existing-names.rs:16:5
|
LL | fn foo(x: &mut Vec<Ref<i32>>, y: Ref<i32>) {
| -------- -------- lifetime `'1` appears in this type
| |
| lifetime `'2` appears in this type
| - - has type `Ref<'1, i32>`
| |
| has type `&mut std::vec::Vec<Ref<'2, i32>>`
LL | x.push(y); //~ ERROR lifetime mismatch
| ^^^^^^^^^ argument requires that `'1` must outlive `'2`

Expand Down
Expand Up @@ -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`

Expand Down
Expand Up @@ -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`

Expand Down
Expand Up @@ -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`

Expand Down
Expand Up @@ -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<Ref>, y: Ref) {
| --- --- lifetime `'1` appears in this type
| |
| lifetime `'2` appears in this type
| ----- - has type `Ref<'1>`
| |
| has type `std::vec::Vec<Ref<'2>>`
LL | x.push(y); //~ ERROR lifetime mismatch
| ^^^^^^^^^ argument requires that `'1` must outlive `'2`

Expand Down
Expand Up @@ -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`

Expand Down
Expand Up @@ -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`

Expand Down
Expand Up @@ -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`

Expand Down
Expand Up @@ -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`

Expand Down
31 changes: 31 additions & 0 deletions 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![feature(nll)]
#![feature(in_band_lifetimes)]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the problem here is that we now need another feature gate here

#![feature(impl_header_lifetime_elision)]

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

#![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() { }
12 changes: 12 additions & 0 deletions 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