about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2018-08-10 02:18:21 +0000
committerbors <bors@rust-lang.org>2018-08-10 02:18:21 +0000
commitf6d43ed84207c7e58f363f46e5a438ff40f2b311 (patch)
tree06b2c362ee071fa25d2450a42a246696b56eda11
parentdb1acaac7f8c84d8fb46211f5e96f678c28628a8 (diff)
parent31657c99533f7c5dc44229c709a2ce6ad24908db (diff)
downloadrust-f6d43ed84207c7e58f363f46e5a438ff40f2b311.tar.gz
rust-f6d43ed84207c7e58f363f46e5a438ff40f2b311.zip
Auto merge of #53124 - davidtwco:issue-52742, r=nikomatsakis
region error messages involving impls are confusing

Part of #52742.

r? @nikomatsakis
-rw-r--r--src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs2
-rw-r--r--src/librustc/ty/mod.rs8
-rw-r--r--src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs42
-rw-r--r--src/test/ui/lifetime-errors/ex2b-push-no-existing-names.nll.stderr6
-rw-r--r--src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-2.nll.stderr6
-rw-r--r--src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-3.nll.stderr8
-rw-r--r--src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-4.nll.stderr8
-rw-r--r--src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs.nll.stderr6
-rw-r--r--src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-2.nll.stderr6
-rw-r--r--src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-3.nll.stderr6
-rw-r--r--src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-4.nll.stderr6
-rw-r--r--src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct.nll.stderr6
-rw-r--r--src/test/ui/nll/issue-52742.rs31
-rw-r--r--src/test/ui/nll/issue-52742.stderr12
14 files changed, 95 insertions, 58 deletions
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 ca71b0aeed9..4e26a4178b9 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 0c962fff272..6c27d527ae8 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -52,7 +52,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;
@@ -825,6 +825,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 8c2a5f19038..6acf3aadf51 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 614034794bd..b7c252cac9b 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<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`
 
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 2829fbcd32a..618817fd57b 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 8171ee758b0..b4767afd413 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 99b64605bae..e2fcbaa4c3c 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 c9542d31069..79f1a8c0ccf 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<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`
 
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 459796760e1..0bacd894e6e 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 5fc1755ed39..f40c67b8d11 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 835f95880a7..f9168dcf583 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 7aed5fe626f..c43f8477232 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 00000000000..c36e4cc70fd
--- /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 <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)]
+#![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 00000000000..515ba55cf6f
--- /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
+