-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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
Implement in-band lifetime bindings #46051
Conversation
c011bd9
to
4a9bac5
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, the high-level strategy in this code makes sense to me, though I'd like to see it better documented. I think the most important thing though is to expand the set of tests. I went through and wrote-up all the tests I could think of based on a reading of the spec here in this gist. Do you think you would have time to add such tests and see whether your code behaves in the right way? (If not, I can take a stab at adding the tests at some point, but not tonight!)
src/librustc/hir/lowering.rs
Outdated
@@ -105,6 +105,13 @@ pub struct LoweringContext<'a> { | |||
is_in_loop_condition: bool, | |||
is_in_trait_impl: bool, | |||
|
|||
// Used to create lifetime definitions from in-band lifetime usages. | |||
// e.g. `fn foo(x: &'x u8) -> &'x u8` to `fn foo<'x>(x: &'x u8) -> &'x u8` | |||
lifetimes_to_define: Vec<(Span, Name)>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment is a bit sparse. Could you say a bit about how it's used?
src/librustc/hir/lowering.rs
Outdated
// Used to create lifetime definitions from in-band lifetime usages. | ||
// e.g. `fn foo(x: &'x u8) -> &'x u8` to `fn foo<'x>(x: &'x u8) -> &'x u8` | ||
lifetimes_to_define: Vec<(Span, Name)>, | ||
is_collecting_in_band_lifetimes: bool, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similarly here and below.
src/librustc/hir/lowering.rs
Outdated
(lifetime_defs, res) | ||
} | ||
|
||
fn with_out_of_band_lifetime_defs<T, F>( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comment plz.
src/librustc/hir/lowering.rs
Outdated
f: F | ||
) -> (Vec<hir::LifetimeDef>, T) where F: FnOnce(&mut LoweringContext) -> T | ||
{ | ||
self.lifetimes_to_define = Vec::new(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems a bit odd to put a new vector but here but a few lines down to use split_off
(presumably with intention of re-using the backing buffer). Maybe just assert!(self.lifetimes_to_define.is_empty())
?
name: hir::LifetimeName::Name(name), | ||
}, | ||
bounds: Vec::new().into(), | ||
pure_wrt_drop: false, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess it's a FIXME to include some sort of synthetic
field here, right? I definitely think we should do that.
4a9bac5
to
22dcad6
Compare
☔ The latest upstream changes (presumably #45905) made this pull request unmergeable. Please resolve the merge conflicts. |
bd74337
to
e45d3ad
Compare
@nikomatsakis I've addressed the review comments and added a bunch of tests to cover the cases described in your gist. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I found a few nits in the tests. Also, I didn't see a test for intermingled lists, did I?
e.g., fn foo<'a>(x: &'a u32, y: &'b u32)
?
#![allow(warnings)] | ||
#![feature(in_band_lifetimes)] | ||
|
||
fn foo(x: &'a u32, y: u32) -> &'a u32 { y } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: I think this was supposed to be y: &u32
, to show that it works the same for anon and named
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
error[E0621]: explicit lifetime required in the type of `y` | ||
--> $DIR/mismatched_trait.rs:16:9 | ||
| | ||
15 | fn baz(&self, x: &'a u32, y: &u32) -> &'a u32 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Love it. Happy the errors still work. Not that there is any reason they wouldn't.
--> $DIR/no_in_band_in_struct.rs:15:9 | ||
| | ||
15 | x: &'test u32, | ||
| ^^^^^ undeclared lifetime |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if we should give some better tip here. Seems orthogonal to your PR, but might be worth opening a follow-up pointing to the struct and suggesting that the lifetime parameter be added there.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
e45d3ad
to
893840d
Compare
That's the test for E0688. |
@cramertj ok great! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
r=me with one last test (sorry, I'm a pain)
|
||
fn foo(x: fn(&'a u32)) {} | ||
|
||
fn bar(x: &Fn(&'a u32)) {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, one last set of tests I would like to see -- I didn't notice this particular scenario. I'm 99.9% sure it works correctly, but it seems like we might as well be complete!
fn bar<F>(x: &F)
where F: Fn(&'a u32) { } //~ ERROR
fn bar(x: &impl Fn(&'a u32)) //~ ERROR
But:
fn bar<F>(x: &F) // OK
where F: SomeTrait<'a>
fn bar(x: &impl SomeTrait<'a>) // OK
If you are too busy, I can try adding them, since I'd love to r+ ASAP. =)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
893840d
to
8ea891d
Compare
@bors r+ |
📌 Commit 8ea891d has been approved by |
8ea891d
to
9775263
Compare
☔ The latest upstream changes (presumably #45701) made this pull request unmergeable. Please resolve the merge conflicts. |
a85a453
to
9775263
Compare
I also added some comments explaining what is going on. In short, the changes in question do not, in fact, affect the`TypeckTables` in any semantic way. However, altering the order of lowering can cause it appear to affect the `TypeckTables`: if we lower generics before the body, then the `HirId` for things in the body will be affected. In this case, we are now lowering the generics etc *after* the body, so the hash no longer changes. This seems good.
There's still merge conflict. |
1e0af43
to
79bf7db
Compare
@bors r+ |
📌 Commit 79bf7db has been approved by |
Implement in-band lifetime bindings TODO (perhaps in a future PR): Should we ban explicit instantiation of generics with in-band lifetimes, or is it uncontroversial to just append them to the end of the lifetimes list? Fixes #46042, cc #44524. r? @nikomatsakis
☀️ Test successful - status-appveyor, status-travis |
TODO (perhaps in a future PR): Should we ban explicit instantiation of generics with in-band lifetimes, or is it uncontroversial to just append them to the end of the lifetimes list?
Fixes #46042, cc #44524.
r? @nikomatsakis