Skip to content

fix broken assertion in type_param #46722

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Dec 16, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 22 additions & 6 deletions src/librustc/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -778,25 +778,41 @@ impl<'a, 'gcx, 'tcx> Generics {
if let Some(idx) = param.idx.checked_sub(self.parent_count() as u32) {
// non-Self type parameters are always offset by exactly
// `self.regions.len()`. In the absence of a Self, this is obvious,
// but even in the absence of a `Self` we just have to "compensate"
// but even in the presence of a `Self` we just have to "compensate"
// for the regions:
//
// For example, for `trait Foo<'a, 'b, T1, T2>`, the
// Without a `Self` (or in a nested generics that doesn't have
// a `Self` in itself, even through it parent does), for example
// for `fn foo<'a, T1, T2>()`, the situation is:
// Substs:
// 0 1 2
// 'a T1 T2
// generics.types:
// 0 1
// T1 T2
//
// And with a `Self`, for example for `trait Foo<'a, 'b, T1, T2>`, the
// situation is:
// Substs:
// 0 1 2 3 4
// Self 'a 'b T1 T2
// generics.types:
// 0 1 2
// Self T1 T2
// And it can be seen that to move from a substs offset to a
// generics offset you just have to offset by the number of regions.
//
// And it can be seen that in both cases, to move from a substs
// offset to a generics offset you just have to offset by the
// number of regions.
let type_param_offset = self.regions.len();

let has_self = self.has_self && self.parent.is_none();
let is_separated_self = type_param_offset != 0 && idx == 0 && has_self;

if let Some(idx) = (idx as usize).checked_sub(type_param_offset) {
assert!(!(self.has_self && idx == 0));
assert!(!is_separated_self, "found a Self after type_param_offset");
&self.types[idx]
} else {
assert!(self.has_self && idx == 0);
assert!(is_separated_self, "non-Self param before type_param_offset");
&self.types[0]
}
} else {
Expand Down
8 changes: 8 additions & 0 deletions src/test/ui/lifetimes/lifetime-doesnt-live-long-enough.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,19 @@ struct Foo<T> {
trait X<K>: Sized {
fn foo<'a, L: X<&'a Nested<K>>>();
//~^ ERROR may not live long enough

// check that we give a sane error for `Self`
fn bar<'a, L: X<&'a Nested<Self>>>();
//~^ ERROR may not live long enough

// check that we give a sane error for nested generics
fn baz<'a, L, M: X<&'a Nested<L>>>() {
//~^ ERROR may not live long enough
}
}

trait TraitB {}

struct Nested<K>(K);
impl<K> Nested<K> {
fn generic_in_parent<'a, L: X<&'a Nested<K>>>() {
Expand Down
63 changes: 41 additions & 22 deletions src/test/ui/lifetimes/lifetime-doesnt-live-long-enough.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -41,54 +41,73 @@ note: ...so that the reference type `&'a Nested<K>` does not outlive the data it
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

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

error[E0309]: the parameter type `L` may not live long enough
--> $DIR/lifetime-doesnt-live-long-enough.rs:42:5
|
42 | fn baz<'a, L, M: X<&'a Nested<L>>>() {
| ^ - help: consider adding an explicit lifetime bound `L: 'a`...
| _____|
| |
43 | | //~^ ERROR may not live long enough
44 | | }
| |_____^
|
note: ...so that the reference type `&'a Nested<L>` does not outlive the data it points at
--> $DIR/lifetime-doesnt-live-long-enough.rs:42:5
|
42 | / fn baz<'a, L, M: X<&'a Nested<L>>>() {
43 | | //~^ ERROR may not live long enough
44 | | }
| |_____^

error[E0309]: the parameter type `K` may not live long enough
--> $DIR/lifetime-doesnt-live-long-enough.rs:43:5
--> $DIR/lifetime-doesnt-live-long-enough.rs:51:5
|
42 | impl<K> Nested<K> {
50 | impl<K> Nested<K> {
| - help: consider adding an explicit lifetime bound `K: 'a`...
43 | / fn generic_in_parent<'a, L: X<&'a Nested<K>>>() {
44 | | //~^ ERROR may not live long enough
45 | | }
51 | / fn generic_in_parent<'a, L: X<&'a Nested<K>>>() {
52 | | //~^ ERROR may not live long enough
53 | | }
| |_____^
|
note: ...so that the reference type `&'a Nested<K>` does not outlive the data it points at
--> $DIR/lifetime-doesnt-live-long-enough.rs:43:5
--> $DIR/lifetime-doesnt-live-long-enough.rs:51:5
|
43 | / fn generic_in_parent<'a, L: X<&'a Nested<K>>>() {
44 | | //~^ ERROR may not live long enough
45 | | }
51 | / fn generic_in_parent<'a, L: X<&'a Nested<K>>>() {
52 | | //~^ ERROR may not live long enough
53 | | }
| |_____^

error[E0309]: the parameter type `M` may not live long enough
--> $DIR/lifetime-doesnt-live-long-enough.rs:46:5
--> $DIR/lifetime-doesnt-live-long-enough.rs:54:5
|
46 | fn generic_in_child<'a, 'b, L: X<&'a Nested<M>>, M: 'b>() {
54 | fn generic_in_child<'a, 'b, L: X<&'a Nested<M>>, M: 'b>() {
| ^ -- help: consider adding an explicit lifetime bound `M: 'a`...
| _____|
| |
47 | | //~^ ERROR may not live long enough
48 | | }
55 | | //~^ ERROR may not live long enough
56 | | }
| |_____^
|
note: ...so that the reference type `&'a Nested<M>` does not outlive the data it points at
--> $DIR/lifetime-doesnt-live-long-enough.rs:46:5
--> $DIR/lifetime-doesnt-live-long-enough.rs:54:5
|
46 | / fn generic_in_child<'a, 'b, L: X<&'a Nested<M>>, M: 'b>() {
47 | | //~^ ERROR may not live long enough
48 | | }
54 | / fn generic_in_child<'a, 'b, L: X<&'a Nested<M>>, M: 'b>() {
55 | | //~^ ERROR may not live long enough
56 | | }
| |_____^

error: aborting due to 6 previous errors
error: aborting due to 7 previous errors