Skip to content
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

Merged
merged 1 commit into from
Dec 21, 2017
Merged

Generics refactoring (groundwork for const generics) #45930

merged 1 commit into from
Dec 21, 2017

Conversation

jplatte
Copy link
Contributor

@jplatte jplatte commented Nov 11, 2017

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 Vecs 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.

@@ -598,7 +598,7 @@ impl<'a> TraitDef<'a> {

let predicate = ast::WhereBoundPredicate {
span: self.span,
bound_lifetimes: vec![],
bound_generics: Default::default(),
Copy link
Member

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.

where_predicates: simplify::where_clauses(cx, where_predicates),
}
}
}

impl Default for Generics {
Copy link
Member

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.

Copy link
Contributor Author

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.

@@ -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) {
Copy link
Member

@eddyb eddyb Nov 11, 2017

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.

/// Any lifetimes from a `for` binding
pub bound_lifetimes: Vec<LifetimeDef>,
/// Any generics from a `for` binding
pub bound_generics: Generics,
Copy link
Contributor

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.

Copy link
Contributor

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.

Copy link
Member

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)).

Copy link
Contributor

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.

Copy link
Member

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>,
Copy link
Contributor

@petrochenkov petrochenkov Nov 11, 2017

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?

Copy link
Contributor

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?

Copy link
Member

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.

@kennytm kennytm added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Nov 11, 2017
@bors
Copy link
Contributor

bors commented Nov 12, 2017

☔ The latest upstream changes (presumably #45848) made this pull request unmergeable. Please resolve the merge conflicts.

@alexcrichton
Copy link
Member

r? @eddyb

(just making sure there's an assigned reviewer)

@kennytm kennytm added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Nov 12, 2017
@@ -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() {
Copy link
Member

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.

@bors
Copy link
Contributor

bors commented Nov 21, 2017

☔ The latest upstream changes (presumably #45701) made this pull request unmergeable. Please resolve the merge conflicts.

@carols10cents
Copy link
Member

@jplatte friendly triage ping! how's this going? Looks like there are some merge conflicts for you!

@jplatte
Copy link
Contributor Author

jplatte commented Nov 27, 2017

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());
Copy link
Member

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);
Copy link
Member

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.

}

pub fn is_parameterized(&self) -> bool {
self.is_lt_parameterized() || self.is_type_parameterized()
!self.params.is_empty()
Copy link
Member

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<_>>(),
Copy link
Member

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].

Copy link
Contributor Author

@jplatte jplatte Nov 29, 2017

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>?

Copy link
Member

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 {
Copy link
Member

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?

Copy link
Contributor Author

@jplatte jplatte Nov 29, 2017

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.

Copy link
Member

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.

Copy link
Contributor Author

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).

Copy link
Member

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 {
Copy link
Member

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() {
Copy link
Member

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?

Copy link
Contributor Author

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 {
Copy link
Member

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 {
Copy link
Member

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()
Copy link
Member

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 {
Copy link
Member

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 {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as #45930 (comment).

@bors
Copy link
Contributor

bors commented Dec 21, 2017

⌛ Testing commit b43275f9081821b03058688c683a1f4383cfcec9 with merge 92c7dd4b58c9cdd56633015888cb25284ab1496a...

@bors
Copy link
Contributor

bors commented Dec 21, 2017

💔 Test failed - status-travis

@eddyb
Copy link
Member

eddyb commented Dec 21, 2017

I think you need to rebase, because some NLL testcases got added just now and they break.

@kennytm kennytm added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. labels Dec 21, 2017
@eddyb
Copy link
Member

eddyb commented Dec 21, 2017

@bors r+

@bors
Copy link
Contributor

bors commented Dec 21, 2017

📌 Commit b9e4b30 has been approved by eddyb

@kennytm kennytm added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Dec 21, 2017
@bors
Copy link
Contributor

bors commented Dec 21, 2017

🔒 Merge conflict

@bors
Copy link
Contributor

bors commented Dec 21, 2017

☔ The latest upstream changes (presumably #46754) made this pull request unmergeable. Please resolve the merge conflicts.

@kennytm kennytm added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. labels Dec 21, 2017
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.
@eddyb
Copy link
Member

eddyb commented Dec 21, 2017

@bors r+

@bors
Copy link
Contributor

bors commented Dec 21, 2017

📌 Commit 78493ed has been approved by eddyb

@kennytm kennytm added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Dec 21, 2017
@bors
Copy link
Contributor

bors commented Dec 21, 2017

⌛ Testing commit 78493ed with merge 250b492...

bors added a commit that referenced this pull request Dec 21, 2017
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`.
@bors
Copy link
Contributor

bors commented Dec 21, 2017

☀️ Test successful - status-appveyor, status-travis
Approved by: eddyb
Pushing 250b492 to master...

@bors bors merged commit 78493ed into rust-lang:master Dec 21, 2017
Manishearth added a commit to rust-lang/rust-clippy that referenced this pull request Dec 22, 2017
@jplatte jplatte deleted the generics_refactoring branch April 25, 2018 10:35
bors added a commit that referenced this pull request Jun 21, 2018
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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants