diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 541c1356dd4ab..a10bd40af3650 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 0000000000000..81aec9fd0b0f5 --- /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 ebb1e561e57ab..5c612522d9a31 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 0000000000000..f845762cefd8b --- /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 0000000000000..770520f2e8cdd --- /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 e559405dbd8b1..18aa980d6f3bb 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