From 6c026997bf1696ee64313135b82dfba3b0857805 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 26 Jan 2018 17:41:59 -0800 Subject: [PATCH] For named lifetimes point only at method signature When refering to named lifetime conflict, point only at the method's signature span instead of the entire method. When the expected and found sup and sub traces are the same, avoid redundant text. --- src/librustc/infer/error_reporting/mod.rs | 65 +++++++++++++------ .../regions-bound-missing-bound-in-impl.rs | 0 ...regions-bound-missing-bound-in-impl.stderr | 52 +++++++++++++++ .../expect-region-supply-region.stderr | 20 ++---- .../mismatched_trait_impl-2.rs | 22 +++++++ .../mismatched_trait_impl-2.stderr | 24 +++++++ .../mismatched_trait_impl.stderr | 11 +--- 7 files changed, 150 insertions(+), 44 deletions(-) rename src/test/{compile-fail => ui/borrowck}/regions-bound-missing-bound-in-impl.rs (100%) create mode 100644 src/test/ui/borrowck/regions-bound-missing-bound-in-impl.stderr create mode 100644 src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.rs create mode 100644 src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.stderr diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 541c1356dd4a..a10bd40af365 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -175,25 +175,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { ty::ReEarlyBound(_) | ty::ReFree(_) => { let scope = region.free_region_binding_scope(self); - let prefix = match *region { - ty::ReEarlyBound(ref br) => { - format!("the lifetime {} as defined on", br.name) - } - ty::ReFree(ref fr) => { - match fr.bound_region { - ty::BrAnon(idx) => { - format!("the anonymous lifetime #{} defined on", idx + 1) - } - ty::BrFresh(_) => "an anonymous lifetime defined on".to_owned(), - _ => { - format!("the lifetime {} as defined on", - fr.bound_region) - } - } - } - _ => bug!() - }; - let node = self.hir.as_local_node_id(scope) .unwrap_or(DUMMY_NODE_ID); let unknown; @@ -218,7 +199,26 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { &unknown } }; - let (msg, opt_span) = explain_span(self, tag, self.hir.span(node)); + let (prefix, span) = match *region { + ty::ReEarlyBound(ref br) => { + (format!("the lifetime {} as defined on", br.name), + self.sess.codemap().def_span(self.hir.span(node))) + } + ty::ReFree(ref fr) => { + match fr.bound_region { + ty::BrAnon(idx) => { + (format!("the anonymous lifetime #{} defined on", idx + 1), + self.hir.span(node)) + } + ty::BrFresh(_) => ("an anonymous lifetime defined on".to_owned(), + self.hir.span(node)), + _ => (format!("the lifetime {} as defined on", fr.bound_region), + self.sess.codemap().def_span(self.hir.span(node))), + } + } + _ => bug!() + }; + let (msg, opt_span) = explain_span(self, tag, span); (format!("{} {}", prefix, msg), opt_span) } @@ -1075,6 +1075,31 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { sup_region, "..."); + match (&sup_origin, &sub_origin) { + (&infer::Subtype(ref sup_trace), &infer::Subtype(ref sub_trace)) => { + if let (Some((sup_expected, sup_found)), + Some((sub_expected, sub_found))) = (self.values_str(&sup_trace.values), + self.values_str(&sub_trace.values)) { + if sub_expected == sup_expected && sub_found == sup_found { + self.tcx.note_and_explain_region( + region_scope_tree, + &mut err, + "...but the lifetime must also be valid for ", + sub_region, + "...", + ); + err.note(&format!("...so that the {}:\nexpected {}\n found {}", + sup_trace.cause.as_requirement_str(), + sup_expected.content(), + sup_found.content())); + err.emit(); + return; + } + } + } + _ => {} + } + self.note_region_origin(&mut err, &sup_origin); self.tcx.note_and_explain_region(region_scope_tree, &mut err, diff --git a/src/test/compile-fail/regions-bound-missing-bound-in-impl.rs b/src/test/ui/borrowck/regions-bound-missing-bound-in-impl.rs similarity index 100% rename from src/test/compile-fail/regions-bound-missing-bound-in-impl.rs rename to src/test/ui/borrowck/regions-bound-missing-bound-in-impl.rs diff --git a/src/test/ui/borrowck/regions-bound-missing-bound-in-impl.stderr b/src/test/ui/borrowck/regions-bound-missing-bound-in-impl.stderr new file mode 100644 index 000000000000..81aec9fd0b0f --- /dev/null +++ b/src/test/ui/borrowck/regions-bound-missing-bound-in-impl.stderr @@ -0,0 +1,52 @@ +error[E0195]: lifetime parameters or bounds on method `no_bound` do not match the trait declaration + --> $DIR/regions-bound-missing-bound-in-impl.rs:28:5 + | +28 | / fn no_bound<'b:'a>(self, b: Inv<'b>) { +29 | | //~^ ERROR lifetime parameters or bounds on method `no_bound` do not match +30 | | } + | |_____^ lifetimes do not match trait + +error[E0195]: lifetime parameters or bounds on method `has_bound` do not match the trait declaration + --> $DIR/regions-bound-missing-bound-in-impl.rs:32:5 + | +32 | / fn has_bound<'b>(self, b: Inv<'b>) { +33 | | //~^ ERROR lifetime parameters or bounds on method `has_bound` do not match +34 | | } + | |_____^ lifetimes do not match trait + +error[E0308]: method not compatible with trait + --> $DIR/regions-bound-missing-bound-in-impl.rs:36:5 + | +36 | / fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) { +37 | | //~^ ERROR method not compatible with trait +38 | | // +39 | | // Note: This is a terrible error message. It is caused +... | +47 | | // cases. +48 | | } + | |_____^ lifetime mismatch + | + = note: expected type `fn(&'a isize, Inv<'c>, Inv<'c>, Inv<'d>)` + found type `fn(&'a isize, Inv<'_>, Inv<'c>, Inv<'d>)` +note: the lifetime 'c as defined on the method body at 36:5... + --> $DIR/regions-bound-missing-bound-in-impl.rs:36:5 + | +36 | fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...does not necessarily outlive the lifetime 'c as defined on the method body at 36:5 + --> $DIR/regions-bound-missing-bound-in-impl.rs:36:5 + | +36 | fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0276]: impl has stricter requirements than trait + --> $DIR/regions-bound-missing-bound-in-impl.rs:53:5 + | +24 | fn another_bound<'x: 'a>(self, x: Inv<'x>, y: Inv<'t>); + | ------------------------------------------------------- definition of `another_bound` from trait +... +53 | fn another_bound<'x: 't>(self, x: Inv<'x>, y: Inv<'t>) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `'x: 't` + +error: aborting due to 4 previous errors + diff --git a/src/test/ui/closure-expected-type/expect-region-supply-region.stderr b/src/test/ui/closure-expected-type/expect-region-supply-region.stderr index ebb1e561e57a..5c612522d9a3 100644 --- a/src/test/ui/closure-expected-type/expect-region-supply-region.stderr +++ b/src/test/ui/closure-expected-type/expect-region-supply-region.stderr @@ -41,14 +41,8 @@ note: the anonymous lifetime #2 defined on the body at 47:29... note: ...does not necessarily outlive the lifetime 'x as defined on the function body at 42:1 --> $DIR/expect-region-supply-region.rs:42:1 | -42 | / fn expect_bound_supply_named<'x>() { -43 | | let mut f: Option<&u32> = None; -44 | | -45 | | // Here we give a type annotation that `x` should be free. We get -... | -54 | | }); -55 | | } - | |_^ +42 | fn expect_bound_supply_named<'x>() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0308]: mismatched types --> $DIR/expect-region-supply-region.rs:47:33 @@ -61,14 +55,8 @@ error[E0308]: mismatched types note: the lifetime 'x as defined on the function body at 42:1... --> $DIR/expect-region-supply-region.rs:42:1 | -42 | / fn expect_bound_supply_named<'x>() { -43 | | let mut f: Option<&u32> = None; -44 | | -45 | | // Here we give a type annotation that `x` should be free. We get -... | -54 | | }); -55 | | } - | |_^ +42 | fn expect_bound_supply_named<'x>() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: ...does not necessarily outlive the anonymous lifetime #2 defined on the body at 47:29 --> $DIR/expect-region-supply-region.rs:47:29 | diff --git a/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.rs b/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.rs new file mode 100644 index 000000000000..f845762cefd8 --- /dev/null +++ b/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.rs @@ -0,0 +1,22 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::ops::Deref; +trait Trait {} + +struct Struct; + +impl Deref for Struct { + type Target = Trait; + fn deref(&self) -> &Trait { + unimplemented!(); + } +} +//~^^^^ ERROR cannot infer an appropriate lifetime for lifetime parameter diff --git a/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.stderr b/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.stderr new file mode 100644 index 000000000000..770520f2e8cd --- /dev/null +++ b/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.stderr @@ -0,0 +1,24 @@ +error[E0601]: main function not found + +error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in generic type due to conflicting requirements + --> $DIR/mismatched_trait_impl-2.rs:18:5 + | +18 | / fn deref(&self) -> &Trait { +19 | | unimplemented!(); +20 | | } + | |_____^ + | +note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 18:5... + --> $DIR/mismatched_trait_impl-2.rs:18:5 + | +18 | / fn deref(&self) -> &Trait { +19 | | unimplemented!(); +20 | | } + | |_____^ + = note: ...but the lifetime must also be valid for the static lifetime... + = note: ...so that the method type is compatible with trait: + expected fn(&Struct) -> &Trait + 'static + found fn(&Struct) -> &Trait + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/in-band-lifetimes/mismatched_trait_impl.stderr b/src/test/ui/in-band-lifetimes/mismatched_trait_impl.stderr index e559405dbd8b..18aa980d6f3b 100644 --- a/src/test/ui/in-band-lifetimes/mismatched_trait_impl.stderr +++ b/src/test/ui/in-band-lifetimes/mismatched_trait_impl.stderr @@ -13,16 +13,11 @@ note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on th 20 | | x 21 | | } | |_____^ - = note: ...so that the method type is compatible with trait: - expected fn(&i32, &'a u32, &u32) -> &'a u32 - found fn(&i32, &u32, &u32) -> &u32 -note: but, the lifetime must be valid for the lifetime 'a as defined on the method body at 19:5... +note: ...but the lifetime must also be valid for the lifetime 'a as defined on the method body at 19:5... --> $DIR/mismatched_trait_impl.rs:19:5 | -19 | / fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 { //~ ERROR cannot infer -20 | | x -21 | | } - | |_____^ +19 | fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 { //~ ERROR cannot infer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: ...so that the method type is compatible with trait: expected fn(&i32, &'a u32, &u32) -> &'a u32 found fn(&i32, &u32, &u32) -> &u32