-
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
Generics refactoring (groundwork for const generics) #45930
Conversation
@@ -598,7 +598,7 @@ impl<'a> TraitDef<'a> { | |||
|
|||
let predicate = ast::WhereBoundPredicate { | |||
span: self.span, | |||
bound_lifetimes: vec![], | |||
bound_generics: Default::default(), |
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.
Here, and in a few other places, you have Default::default()
, I would prefer Generics::default()
for clarity.
src/librustdoc/clean/mod.rs
Outdated
where_predicates: simplify::where_clauses(cx, where_predicates), | ||
} | ||
} | ||
} | ||
|
||
impl Default for Generics { |
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.
You can just derive Default
instead of manually implementing it.
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.
Huh, dunno why I missed that this is the same thing that the derive would generate.
src/librustc/hir/intravisit.rs
Outdated
@@ -279,6 +279,12 @@ pub trait Visitor<'v> : Sized { | |||
fn visit_ty(&mut self, t: &'v Ty) { | |||
walk_ty(self, t) | |||
} | |||
fn visit_ty_param(&mut self, t: &'v TyParam) { |
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 isn't actually used - I'd prefer if people went through visit_generic_param
or visit_generics
instead - that way, when const generics are added, they're harder to miss.
Also, have you considered removing visit_lifetime_def
? I believe that was the reason I mentioned changing Vec<LifetimeDef>
to Generics
, because then all the cases can be handled together.
src/libsyntax/ast.rs
Outdated
/// Any lifetimes from a `for` binding | ||
pub bound_lifetimes: Vec<LifetimeDef>, | ||
/// Any generics from a `for` binding | ||
pub bound_generics: Generics, |
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.
There may be reasons to change Vec<LifetimeDef>
into Vec<GenericParam>
in the future, but why Generics
?
I'd rather just leave Vec<LifetimeDef>
in place, this change doesn't help const generics in any way and permits too many things in AST that can't happen in actual code.
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.
Same for BareFnTy
and PolyTraitRef
.
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.
IIRC there are a bunch of places where visit_lifetime_def
is implemented separately from type parameters (visit_generics
), only because visit_generics
wouldn't be called in those Vec<LifetimeDef>
cases (see also #45930 (comment)).
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'm not sure the current situation is significantly worse than a bunch of impossible "span_bug
" code.
If visit_lifetime_def
is removed and visit_generic_param
is uniformly used for visiting (#45930 (comment)) then Generics
here could be replaced with Vec<GenericParam>
improving situation somewhat.
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.
FWIW I expect @nikomatsakis would eventually want HRTB to include where
clauses too, on top of for<T: Trait>
, but I don't know the exact plans.
Vec<GenericParam>
is fine with me too.
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] | ||
pub struct Generics { | ||
pub lifetimes: Vec<LifetimeDef>, | ||
pub ty_params: Vec<TyParam>, | ||
pub params: Vec<GenericParam>, |
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.
Also the invariant "all lifetime parameters go before type parameters" is lost in the new AST/HIR (enforced only by parser).
I don't remember if it was relied on anywhere, in matching against generic arguments maybe?
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.
What happens if a syntax extension generates parameters in intermixed order and send them to further compilation?
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.
ast_validation
should probably enforce the limitation until we want to lift it.
☔ The latest upstream changes (presumably #45848) made this pull request unmergeable. Please resolve the merge conflicts. |
r? @eddyb (just making sure there's an assigned reviewer) |
@@ -309,7 +309,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { | |||
} | |||
|
|||
fn visit_generics(&mut self, generics: &'hir Generics) { | |||
for ty_param in generics.ty_params.iter() { | |||
for ty_param in generics.ty_params() { |
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 should be uniform and have a single Node
variant instead of NodeTyParam
and NodeLifetimeParam
.
☔ The latest upstream changes (presumably #45701) made this pull request unmergeable. Please resolve the merge conflicts. |
@jplatte friendly triage ping! how's this going? Looks like there are some merge conflicts for you! |
I think the test failures are the bigger issue.. I've rebased a bunch of times and I will do that again now. But I've put some time into figuring out why some tests fail and haven't been able to figure it out yet. I have one idea still, but I'm not that optimistic... |
if node_id == ty_param.id { | ||
add_bounds.entry(ty_param.id) | ||
.or_insert(Vec::new()) | ||
.push(bound.clone()); |
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.
FWIW cloning isn't necessary here if the reference can be used directly.
|
||
fn visit_generics(&mut self, generics: &'a Generics) { | ||
visit::walk_generics(self, generics); |
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 can be removed, since walking is the default action.
src/librustc/hir/mod.rs
Outdated
} | ||
|
||
pub fn is_parameterized(&self) -> bool { | ||
self.is_lt_parameterized() || self.is_type_parameterized() | ||
!self.params.is_empty() |
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.
Could maybe inline this, since it's about as long.
this.check_lifetime_defs(old_scope, &generics.lifetimes); | ||
this.check_lifetime_defs( | ||
old_scope, | ||
&generics.lifetimes().cloned().collect::<Vec<_>>(), |
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.
Should avoid doing this cloning, preferably just pass in the &[GenericParam]
.
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.
generics.lifetimes().collect::<Vec<_>>()[..]
(without .cloned()
) is a &[&GenericParam]
though, is there a way of converting that or would I have to make check_lifetime_defs
generic over Iterator<Item = &GenericParam>
?
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'd rename check_lifetime_defs
to check_lifetime_params
and have it take the entire &[GenericParam]
, and use .lifetimes()
inside itself.
}).collect(), | ||
lifetimes: c.generic_params | ||
.iter() | ||
.flat_map(|param| if let hir::GenericParam::Lifetime(ref def) = *param { |
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.
Hmm, you're not using .lifetimes()
here, but you are above, is that intentional?
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.
Can't because this is a Vec<GenericParam>
, not a Generics
instance. In my WIP rebase, this case actually came up a bunch more and I added a GenericParmsExt
to deal with this (where I had to write out the FlatMap type bc. impl trait in traits isn't available yet), but then came to realize that it's sometimes hir::GenericParam
and sometimes ast::GenericParam
.
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.
At least in this file it's always HIR.
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 just re-checked and it's actually almost always HIR, just in the form of P<[GenericParam]>
in some cases. Only very few things that were new when I started the rebase were in the AST (in the ast -> hir lowering specifically).
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.
You can impl the trait on [GenericParam]
directly.
&c.generic_params | ||
.iter() | ||
.flat_map(|param| { | ||
if let hir::GenericParam::Lifetime(ref def) = *param { |
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.
Same as #45930 (comment).
ref bound_generic_params, | ||
.. | ||
}) => { | ||
if bound_generic_params.iter().find(|p| p.is_lifetime_param()).is_some() { |
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 is just .any(|p| p.is_lifetime_param())
, right?
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.
Yeah
}).collect(), | ||
lifetimes: bound_generic_params.iter() | ||
.flat_map(|param| { | ||
if let hir::GenericParam::Lifetime(ref def) = *param { |
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.
Same as #45930 (comment).
old_scope, | ||
&bound_generic_params.iter() | ||
.flat_map(|param| { | ||
if let hir::GenericParam::Lifetime(ref ld) = *param { |
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.
Same as #45930 (comment).
@@ -519,22 +557,38 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { | |||
_modifier: hir::TraitBoundModifier) { | |||
debug!("visit_poly_trait_ref trait_ref={:?}", trait_ref); | |||
|
|||
if !self.trait_ref_hack || !trait_ref.bound_lifetimes.is_empty() { | |||
if !self.trait_ref_hack || | |||
trait_ref.bound_generic_params.iter().find(|p| p.is_lifetime_param()).is_some() |
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.
Same as #45930 (comment).
}).collect(), | ||
lifetimes: trait_ref.bound_generic_params.iter() | ||
.flat_map(|param| { | ||
if let hir::GenericParam::Lifetime(ref def) = *param { |
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.
Same as #45930 (comment).
old_scope, | ||
&trait_ref.bound_generic_params.iter() | ||
.flat_map(|param| { | ||
if let hir::GenericParam::Lifetime(ref ld) = *param { |
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.
Same as #45930 (comment).
⌛ Testing commit b43275f9081821b03058688c683a1f4383cfcec9 with merge 92c7dd4b58c9cdd56633015888cb25284ab1496a... |
💔 Test failed - status-travis |
I think you need to rebase, because some NLL testcases got added just now and they break. |
@bors r+ |
📌 Commit b9e4b30 has been approved by |
🔒 Merge conflict |
☔ The latest upstream changes (presumably #46754) made this pull request unmergeable. Please resolve the merge conflicts. |
The Generics now contain one Vec of an enum for the generic parameters, rather than two separate Vec's for lifetime and type parameters. Additionally, places that previously used Vec<LifetimeDef> now use Vec<GenericParam> instead.
@bors r+ |
📌 Commit 78493ed has been approved by |
Generics refactoring (groundwork for const generics) These changes were suggested by @eddyb. After this change, the `Generics` contain one `Vec` of an enum for the generic parameters, rather than two separate `Vec`s for lifetime and type parameters. Type params and const params will need to be in a shared `Vec` to preserve their ordering, and moving lifetimes into the same `Vec` should simplify the code that processes `Generics`.
☀️ Test successful - status-appveyor, status-travis |
introduced in rust-lang/rust#45930
The Great Generics Generalisation: HIR Edition This is essentially a followup to #45930, consolidating the use of separate lifetime and type vectors into single kinds vectors wherever possible. This is intended to provide more of the groundwork for const generics (#44580). r? @eddyb cc @yodaldevoid
These changes were suggested by @eddyb.
After this change, the
Generics
contain oneVec
of an enum for the generic parameters, rather than two separateVec
s for lifetime and type parameters. Type params and const params will need to be in a sharedVec
to preserve their ordering, and moving lifetimes into the sameVec
should simplify the code that processesGenerics
.