Skip to content

Commit 2679944

Browse files
committed
fix broken assertion in type_param
Nested generics (aka method generics) in trait methods don't have an *additional* Self parameter in their own type parameter list (they have a Self parameter in the parent generics), so don't try to check we're correctly adjusting for it. Fixes #46568.
1 parent e798cb0 commit 2679944

File tree

3 files changed

+71
-28
lines changed

3 files changed

+71
-28
lines changed

src/librustc/ty/mod.rs

+22-6
Original file line numberDiff line numberDiff line change
@@ -778,25 +778,41 @@ impl<'a, 'gcx, 'tcx> Generics {
778778
if let Some(idx) = param.idx.checked_sub(self.parent_count() as u32) {
779779
// non-Self type parameters are always offset by exactly
780780
// `self.regions.len()`. In the absence of a Self, this is obvious,
781-
// but even in the absence of a `Self` we just have to "compensate"
781+
// but even in the presence of a `Self` we just have to "compensate"
782782
// for the regions:
783783
//
784-
// For example, for `trait Foo<'a, 'b, T1, T2>`, the
784+
// Without a `Self` (or in a nested generics that doesn't have
785+
// a `Self` in itself, even through it parent does), for example
786+
// for `fn foo<'a, T1, T2>()`, the situation is:
787+
// Substs:
788+
// 0 1 2
789+
// 'a T1 T2
790+
// generics.types:
791+
// 0 1
792+
// T1 T2
793+
//
794+
// And with a `Self`, for example for `trait Foo<'a, 'b, T1, T2>`, the
785795
// situation is:
786796
// Substs:
787797
// 0 1 2 3 4
788798
// Self 'a 'b T1 T2
789799
// generics.types:
790800
// 0 1 2
791801
// Self T1 T2
792-
// And it can be seen that to move from a substs offset to a
793-
// generics offset you just have to offset by the number of regions.
802+
//
803+
// And it can be seen that in both cases, to move from a substs
804+
// offset to a generics offset you just have to offset by the
805+
// number of regions.
794806
let type_param_offset = self.regions.len();
807+
808+
let has_self = self.has_self && self.parent.is_none();
809+
let is_separated_self = type_param_offset != 0 && idx == 0 && has_self;
810+
795811
if let Some(idx) = (idx as usize).checked_sub(type_param_offset) {
796-
assert!(!(self.has_self && idx == 0));
812+
assert!(!is_separated_self, "found a Self after type_param_offset");
797813
&self.types[idx]
798814
} else {
799-
assert!(self.has_self && idx == 0);
815+
assert!(is_separated_self, "non-Self param before type_param_offset");
800816
&self.types[0]
801817
}
802818
} else {

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

+8
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,19 @@ struct Foo<T> {
3333
trait X<K>: Sized {
3434
fn foo<'a, L: X<&'a Nested<K>>>();
3535
//~^ ERROR may not live long enough
36+
3637
// check that we give a sane error for `Self`
3738
fn bar<'a, L: X<&'a Nested<Self>>>();
3839
//~^ ERROR may not live long enough
40+
41+
// check that we give a sane error for nested generics
42+
fn baz<'a, L, M: X<&'a Nested<L>>>() {
43+
//~^ ERROR may not live long enough
44+
}
3945
}
4046

47+
trait TraitB {}
48+
4149
struct Nested<K>(K);
4250
impl<K> Nested<K> {
4351
fn generic_in_parent<'a, L: X<&'a Nested<K>>>() {

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

+41-22
Original file line numberDiff line numberDiff line change
@@ -41,54 +41,73 @@ note: ...so that the reference type `&'a Nested<K>` does not outlive the data it
4141
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
4242

4343
error[E0309]: the parameter type `Self` may not live long enough
44-
--> $DIR/lifetime-doesnt-live-long-enough.rs:37:5
44+
--> $DIR/lifetime-doesnt-live-long-enough.rs:38:5
4545
|
46-
37 | fn bar<'a, L: X<&'a Nested<Self>>>();
46+
38 | fn bar<'a, L: X<&'a Nested<Self>>>();
4747
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
4848
|
4949
= help: consider adding an explicit lifetime bound `Self: 'a`...
5050
note: ...so that the reference type `&'a Nested<Self>` does not outlive the data it points at
51-
--> $DIR/lifetime-doesnt-live-long-enough.rs:37:5
51+
--> $DIR/lifetime-doesnt-live-long-enough.rs:38:5
5252
|
53-
37 | fn bar<'a, L: X<&'a Nested<Self>>>();
53+
38 | fn bar<'a, L: X<&'a Nested<Self>>>();
5454
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
5555

56+
error[E0309]: the parameter type `L` may not live long enough
57+
--> $DIR/lifetime-doesnt-live-long-enough.rs:42:5
58+
|
59+
42 | fn baz<'a, L, M: X<&'a Nested<L>>>() {
60+
| ^ - help: consider adding an explicit lifetime bound `L: 'a`...
61+
| _____|
62+
| |
63+
43 | | //~^ ERROR may not live long enough
64+
44 | | }
65+
| |_____^
66+
|
67+
note: ...so that the reference type `&'a Nested<L>` does not outlive the data it points at
68+
--> $DIR/lifetime-doesnt-live-long-enough.rs:42:5
69+
|
70+
42 | / fn baz<'a, L, M: X<&'a Nested<L>>>() {
71+
43 | | //~^ ERROR may not live long enough
72+
44 | | }
73+
| |_____^
74+
5675
error[E0309]: the parameter type `K` may not live long enough
57-
--> $DIR/lifetime-doesnt-live-long-enough.rs:43:5
76+
--> $DIR/lifetime-doesnt-live-long-enough.rs:51:5
5877
|
59-
42 | impl<K> Nested<K> {
78+
50 | impl<K> Nested<K> {
6079
| - help: consider adding an explicit lifetime bound `K: 'a`...
61-
43 | / fn generic_in_parent<'a, L: X<&'a Nested<K>>>() {
62-
44 | | //~^ ERROR may not live long enough
63-
45 | | }
80+
51 | / fn generic_in_parent<'a, L: X<&'a Nested<K>>>() {
81+
52 | | //~^ ERROR may not live long enough
82+
53 | | }
6483
| |_____^
6584
|
6685
note: ...so that the reference type `&'a Nested<K>` does not outlive the data it points at
67-
--> $DIR/lifetime-doesnt-live-long-enough.rs:43:5
86+
--> $DIR/lifetime-doesnt-live-long-enough.rs:51:5
6887
|
69-
43 | / fn generic_in_parent<'a, L: X<&'a Nested<K>>>() {
70-
44 | | //~^ ERROR may not live long enough
71-
45 | | }
88+
51 | / fn generic_in_parent<'a, L: X<&'a Nested<K>>>() {
89+
52 | | //~^ ERROR may not live long enough
90+
53 | | }
7291
| |_____^
7392

7493
error[E0309]: the parameter type `M` may not live long enough
75-
--> $DIR/lifetime-doesnt-live-long-enough.rs:46:5
94+
--> $DIR/lifetime-doesnt-live-long-enough.rs:54:5
7695
|
77-
46 | fn generic_in_child<'a, 'b, L: X<&'a Nested<M>>, M: 'b>() {
96+
54 | fn generic_in_child<'a, 'b, L: X<&'a Nested<M>>, M: 'b>() {
7897
| ^ -- help: consider adding an explicit lifetime bound `M: 'a`...
7998
| _____|
8099
| |
81-
47 | | //~^ ERROR may not live long enough
82-
48 | | }
100+
55 | | //~^ ERROR may not live long enough
101+
56 | | }
83102
| |_____^
84103
|
85104
note: ...so that the reference type `&'a Nested<M>` does not outlive the data it points at
86-
--> $DIR/lifetime-doesnt-live-long-enough.rs:46:5
105+
--> $DIR/lifetime-doesnt-live-long-enough.rs:54:5
87106
|
88-
46 | / fn generic_in_child<'a, 'b, L: X<&'a Nested<M>>, M: 'b>() {
89-
47 | | //~^ ERROR may not live long enough
90-
48 | | }
107+
54 | / fn generic_in_child<'a, 'b, L: X<&'a Nested<M>>, M: 'b>() {
108+
55 | | //~^ ERROR may not live long enough
109+
56 | | }
91110
| |_____^
92111

93-
error: aborting due to 6 previous errors
112+
error: aborting due to 7 previous errors
94113

0 commit comments

Comments
 (0)