Skip to content

Commit 622a78c

Browse files
committed
handle nested generics in Generics::type_param/region_param
Fixes #44952.
1 parent 0defa20 commit 622a78c

File tree

5 files changed

+68
-11
lines changed

5 files changed

+68
-11
lines changed

src/librustc/infer/error_reporting/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -795,7 +795,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
795795
// Account for the case where `did` corresponds to `Self`, which doesn't have
796796
// the expected type argument.
797797
if generics.types.len() > 0 {
798-
let type_param = generics.type_param(param);
798+
let type_param = generics.type_param(param, self.tcx);
799799
let hir = &self.tcx.hir;
800800
hir.as_local_node_id(type_param.def_id).map(|id| {
801801
// Get the `hir::TyParam` to verify wether it already has any bounds.

src/librustc/ty/mod.rs

+21-7
Original file line numberDiff line numberDiff line change
@@ -729,7 +729,7 @@ pub struct Generics {
729729
pub has_late_bound_regions: Option<Span>,
730730
}
731731

732-
impl Generics {
732+
impl<'a, 'gcx, 'tcx> Generics {
733733
pub fn parent_count(&self) -> usize {
734734
self.parent_regions as usize + self.parent_types as usize
735735
}
@@ -742,14 +742,28 @@ impl Generics {
742742
self.parent_count() + self.own_count()
743743
}
744744

745-
pub fn region_param(&self, param: &EarlyBoundRegion) -> &RegionParameterDef {
746-
assert_eq!(self.parent_count(), 0);
747-
&self.regions[param.index as usize - self.has_self as usize]
745+
pub fn region_param(&'tcx self,
746+
param: &EarlyBoundRegion,
747+
tcx: TyCtxt<'a, 'gcx, 'tcx>)
748+
-> &'tcx RegionParameterDef
749+
{
750+
if let Some(index) = param.index.checked_sub(self.parent_count() as u32) {
751+
&self.regions[index as usize - self.has_self as usize]
752+
} else {
753+
tcx.generics_of(self.parent.expect("parent_count>0 but no parent?"))
754+
.region_param(param, tcx)
755+
}
748756
}
749757

750-
pub fn type_param(&self, param: &ParamTy) -> &TypeParameterDef {
751-
assert_eq!(self.parent_count(), 0);
752-
&self.types[param.idx as usize - self.has_self as usize - self.regions.len()]
758+
pub fn type_param(&'tcx self,
759+
param: &ParamTy,
760+
tcx: TyCtxt<'a, 'gcx, 'tcx>) -> &TypeParameterDef {
761+
if let Some(idx) = param.idx.checked_sub(self.parent_count() as u32) {
762+
&self.types[idx as usize - self.has_self as usize - self.regions.len()]
763+
} else {
764+
tcx.generics_of(self.parent.expect("parent_count>0 but no parent?"))
765+
.type_param(param, tcx)
766+
}
753767
}
754768
}
755769

src/librustc/ty/util.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -515,11 +515,11 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
515515
let result = item_substs.iter().zip(impl_substs.iter())
516516
.filter(|&(_, &k)| {
517517
if let Some(&ty::RegionKind::ReEarlyBound(ref ebr)) = k.as_region() {
518-
!impl_generics.region_param(ebr).pure_wrt_drop
518+
!impl_generics.region_param(ebr, self).pure_wrt_drop
519519
} else if let Some(&ty::TyS {
520520
sty: ty::TypeVariants::TyParam(ref pt), ..
521521
}) = k.as_type() {
522-
!impl_generics.type_param(pt).pure_wrt_drop
522+
!impl_generics.type_param(pt, self).pure_wrt_drop
523523
} else {
524524
// not a type or region param - this should be reported
525525
// as an error.

src/test/ui/lifetimes/lifetime-doesnt-live-long-enough.rs

+10
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,14 @@ struct Foo<T> {
2828
foo: &'static T
2929
}
3030

31+
trait X<T> {}
32+
33+
struct Nested<K>(K);
34+
impl<K> Nested<K> {
35+
fn generic_in_parent<'a, L: X<&'a Nested<K>>>() {
36+
}
37+
fn generic_in_child<'a, 'b, L: X<&'a Nested<M>>, M: 'b>() {
38+
}
39+
}
40+
3141
fn main() {}

src/test/ui/lifetimes/lifetime-doesnt-live-long-enough.stderr

+34-1
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,38 @@ note: ...so that the reference type `&'static T` does not outlive the data it po
2626
28 | foo: &'static T
2727
| ^^^^^^^^^^^^^^^
2828

29-
error: aborting due to 2 previous errors
29+
error[E0309]: the parameter type `K` may not live long enough
30+
--> $DIR/lifetime-doesnt-live-long-enough.rs:35:5
31+
|
32+
34 | impl<K> Nested<K> {
33+
| - help: consider adding an explicit lifetime bound `K: 'a`...
34+
35 | / fn generic_in_parent<'a, L: X<&'a Nested<K>>>() {
35+
36 | | }
36+
| |_____^
37+
|
38+
note: ...so that the reference type `&'a Nested<K>` does not outlive the data it points at
39+
--> $DIR/lifetime-doesnt-live-long-enough.rs:35:5
40+
|
41+
35 | / fn generic_in_parent<'a, L: X<&'a Nested<K>>>() {
42+
36 | | }
43+
| |_____^
44+
45+
error[E0309]: the parameter type `M` may not live long enough
46+
--> $DIR/lifetime-doesnt-live-long-enough.rs:37:5
47+
|
48+
37 | fn generic_in_child<'a, 'b, L: X<&'a Nested<M>>, M: 'b>() {
49+
| ^ -- help: consider adding an explicit lifetime bound `M: 'a`...
50+
| _____|
51+
| |
52+
38 | | }
53+
| |_____^
54+
|
55+
note: ...so that the reference type `&'a Nested<M>` does not outlive the data it points at
56+
--> $DIR/lifetime-doesnt-live-long-enough.rs:37:5
57+
|
58+
37 | / fn generic_in_child<'a, 'b, L: X<&'a Nested<M>>, M: 'b>() {
59+
38 | | }
60+
| |_____^
61+
62+
error: aborting due to 4 previous errors
3063

0 commit comments

Comments
 (0)