diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 3f22950fc77..72f24b62e68 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -795,7 +795,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // Account for the case where `did` corresponds to `Self`, which doesn't have // the expected type argument. if generics.types.len() > 0 { - let type_param = generics.type_param(param); + let type_param = generics.type_param(param, self.tcx); let hir = &self.tcx.hir; hir.as_local_node_id(type_param.def_id).map(|id| { // Get the `hir::TyParam` to verify wether it already has any bounds. diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index da635ec80fc..c57ecb9b69c 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -729,7 +729,7 @@ pub struct Generics { pub has_late_bound_regions: Option, } -impl Generics { +impl<'a, 'gcx, 'tcx> Generics { pub fn parent_count(&self) -> usize { self.parent_regions as usize + self.parent_types as usize } @@ -742,14 +742,28 @@ impl Generics { self.parent_count() + self.own_count() } - pub fn region_param(&self, param: &EarlyBoundRegion) -> &RegionParameterDef { - assert_eq!(self.parent_count(), 0); - &self.regions[param.index as usize - self.has_self as usize] + pub fn region_param(&'tcx self, + param: &EarlyBoundRegion, + tcx: TyCtxt<'a, 'gcx, 'tcx>) + -> &'tcx RegionParameterDef + { + if let Some(index) = param.index.checked_sub(self.parent_count() as u32) { + &self.regions[index as usize - self.has_self as usize] + } else { + tcx.generics_of(self.parent.expect("parent_count>0 but no parent?")) + .region_param(param, tcx) + } } - pub fn type_param(&self, param: &ParamTy) -> &TypeParameterDef { - assert_eq!(self.parent_count(), 0); - &self.types[param.idx as usize - self.has_self as usize - self.regions.len()] + pub fn type_param(&'tcx self, + param: &ParamTy, + tcx: TyCtxt<'a, 'gcx, 'tcx>) -> &TypeParameterDef { + if let Some(idx) = param.idx.checked_sub(self.parent_count() as u32) { + &self.types[idx as usize - self.has_self as usize - self.regions.len()] + } else { + tcx.generics_of(self.parent.expect("parent_count>0 but no parent?")) + .type_param(param, tcx) + } } } diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index 27819f551b9..c8037ce081a 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -515,11 +515,11 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { let result = item_substs.iter().zip(impl_substs.iter()) .filter(|&(_, &k)| { if let Some(&ty::RegionKind::ReEarlyBound(ref ebr)) = k.as_region() { - !impl_generics.region_param(ebr).pure_wrt_drop + !impl_generics.region_param(ebr, self).pure_wrt_drop } else if let Some(&ty::TyS { sty: ty::TypeVariants::TyParam(ref pt), .. }) = k.as_type() { - !impl_generics.type_param(pt).pure_wrt_drop + !impl_generics.type_param(pt, self).pure_wrt_drop } else { // not a type or region param - this should be reported // as an error. diff --git a/src/test/ui/lifetimes/lifetime-doesnt-live-long-enough.rs b/src/test/ui/lifetimes/lifetime-doesnt-live-long-enough.rs index 465b4271035..a41d8b0e342 100644 --- a/src/test/ui/lifetimes/lifetime-doesnt-live-long-enough.rs +++ b/src/test/ui/lifetimes/lifetime-doesnt-live-long-enough.rs @@ -28,4 +28,14 @@ struct Foo { foo: &'static T } +trait X {} + +struct Nested(K); +impl Nested { + fn generic_in_parent<'a, L: X<&'a Nested>>() { + } + fn generic_in_child<'a, 'b, L: X<&'a Nested>, M: 'b>() { + } +} + fn main() {} diff --git a/src/test/ui/lifetimes/lifetime-doesnt-live-long-enough.stderr b/src/test/ui/lifetimes/lifetime-doesnt-live-long-enough.stderr index e17a660c591..c74302fe9b3 100644 --- a/src/test/ui/lifetimes/lifetime-doesnt-live-long-enough.stderr +++ b/src/test/ui/lifetimes/lifetime-doesnt-live-long-enough.stderr @@ -26,5 +26,38 @@ note: ...so that the reference type `&'static T` does not outlive the data it po 28 | foo: &'static T | ^^^^^^^^^^^^^^^ -error: aborting due to 2 previous errors +error[E0309]: the parameter type `K` may not live long enough + --> $DIR/lifetime-doesnt-live-long-enough.rs:35:5 + | +34 | impl Nested { + | - help: consider adding an explicit lifetime bound `K: 'a`... +35 | / fn generic_in_parent<'a, L: X<&'a Nested>>() { +36 | | } + | |_____^ + | +note: ...so that the reference type `&'a Nested` does not outlive the data it points at + --> $DIR/lifetime-doesnt-live-long-enough.rs:35:5 + | +35 | / fn generic_in_parent<'a, L: X<&'a Nested>>() { +36 | | } + | |_____^ + +error[E0309]: the parameter type `M` may not live long enough + --> $DIR/lifetime-doesnt-live-long-enough.rs:37:5 + | +37 | fn generic_in_child<'a, 'b, L: X<&'a Nested>, M: 'b>() { + | ^ -- help: consider adding an explicit lifetime bound `M: 'a`... + | _____| + | | +38 | | } + | |_____^ + | +note: ...so that the reference type `&'a Nested` does not outlive the data it points at + --> $DIR/lifetime-doesnt-live-long-enough.rs:37:5 + | +37 | / fn generic_in_child<'a, 'b, L: X<&'a Nested>, M: 'b>() { +38 | | } + | |_____^ + +error: aborting due to 4 previous errors