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

Change substitutions from a flat vector into 3 vectors #14604

Merged
merged 1 commit into from
Jun 13, 2014

Conversation

nikomatsakis
Copy link
Contributor

The current setup is to have a single vector of type parameters in
scope at any one time. We then have to concatenate the parameters from
the impl/trait with those of the method. This makes a lot of things
awkward, most notably associated fns ("static fns"). This branch
restructures the substitutions into three distinct namespaces (type,
self, fn). This makes most of the "type parameter management"
trivial. This also sets us up to support UFCS (though I haven't made
any particular changes in that direction in this patch).

Along the way, this patch fixes a few miscellaneous bits of code cleanup:

  1. Patch resolve to detect references to out-of-scope type parameters,
    rather than checking for "out of bound" indices during substitution
    (fixes Resolve is not detecting out-of-scope type parameters #14603).
  2. Move def out of libsyntax into librustc where it belongs. I should have
    moved DefId too, but didn't.
  3. Permit homogeneous tuples like (T, T, T) to be used as fixed-length
    vectors like [T, ..3]. This is awfully handy, though public facing.
    I suppose it requires an RFC.
  4. Add some missing tests.

cc #5527

r? @pcwalton or @pnkfelix

fn mut_iter<'a>(&'a mut self) -> MutItems<'a, $T>;
fn get<'a>(&'a self, index: uint) -> &'a $T;
fn get_mut<'a>(&'a mut self, index: uint) -> &'a mut $T;
}
Copy link
Member

Choose a reason for hiding this comment

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

Should the get and get_mut methods return Option<&T> to push failure towards the client?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

They should do whatever slices do. I think this has changed in the interim, so I can update.

Copy link
Member

Choose a reason for hiding this comment

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

I think the situation is a little confusing at the moment with a lack of Index traits. The slice method get returns an Option<&T>, and apparently get_mut doesn't exist on slices?!

For Vec, get and get_mut return &T and &mut T, but I believe this is a stopgap until the indexing traits are available, and then I think they should return the same thing as slices.

So basically we have two conventions, but I'd be more in favor of get and get_mut returning Option and then implementing the Index traits when they exist for tuples as well (failing if out of bounds).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

On Mon, Jun 02, 2014 at 09:53:17AM -0700, Alex Crichton wrote:

So basically we have two conventions, but I'd be more in favor of
get and get_mut returning Option and then implementing the
Index traits when they exist for tuples as well (failing if out of
bounds).

Agreed, this maps to Python (and maybe other languages too?) and I
always found it reasonable there.

Copy link
Member

Choose a reason for hiding this comment

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

(i will wait until such an update before r-plusing this PR)

@nikomatsakis
Copy link
Contributor Author

RFC for homogeneous tuple methods: rust-lang/rfcs#104

/**
* A substitution mapping type/region parameters to new values. We
* identify each in-scope parameter by an *index* and a *parameter
* space* (which indices where the parameter is defined; see
Copy link
Member

Choose a reason for hiding this comment

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

typo: should be "which indicates"

@pnkfelix
Copy link
Member

pnkfelix commented Jun 3, 2014

Looks good to me overall. If possible please try to fix the commit history where some things seem like they were accidentally squashed into the wrong commit.

Though @pcwalton may want to skim over the resolve changes, which I largely rubber-stamped.

@nikomatsakis
Copy link
Contributor Author

Rebased. I removed the public-facing API changes and instead made them local to the compiler (see final commit). I also cleaned up the commit history. I will create a second PR with the homogeneous tuple API changes.

@alexcrichton
Copy link
Member

Note that I have un-gated the builder that this PR failed on (#14791), so a rebase will likely allow this to land.

parameters

This involves numerous substeps:

1. Treat Self same as any other parameter.
2. No longer compute offsets for method parameters.
3. Store all generic types (both trait/impl and method) with a method,
   eliminating odd discrepancies.
4. Stop doing unspeakable things to static methods and instead just use
   the natural types, now that we can easily add the type parameters from
   trait into the method's polytype.
5. No doubt some more. It was hard to separate these into distinct commits.

Fixes rust-lang#13564
bors added a commit that referenced this pull request Jun 13, 2014
… r=pcwalton

The current setup is to have a single vector of type parameters in
scope at any one time. We then have to concatenate the parameters from
the impl/trait with those of the method. This makes a lot of things
awkward, most notably associated fns ("static fns"). This branch
restructures the substitutions into three distinct namespaces (type,
self, fn). This makes most of the "type parameter management"
trivial. This also sets us up to support UFCS (though I haven't made
any particular changes in that direction in this patch).

Along the way, this patch fixes a few miscellaneous bits of code cleanup:

1. Patch resolve to detect references to out-of-scope type parameters,
   rather than checking for "out of bound" indices during substitution
   (fixes #14603).

2. Move def out of libsyntax into librustc where it belongs. I should have
   moved DefId too, but didn't.
   
3. Permit homogeneous tuples like `(T, T, T)` to be used as fixed-length
   vectors like `[T, ..3]`. This is awfully handy, though public facing.
   I suppose it requires an RFC.

4. Add some missing tests.

cc #5527

r? @pcwalton or @pnkfelix
@bors bors closed this Jun 13, 2014
@bors bors merged commit 9153d8a into rust-lang:master Jun 13, 2014
@huonw
Copy link
Member

huonw commented Jul 3, 2014

It looks like this may've contributed to a 250MB jump in memory use.

@pnkfelix
Copy link
Member

pnkfelix commented Jul 3, 2014

Hmm, I wonder if this is due to having triple the amount of excess capacity? Not sure if there's actually any correlation between the lengths of the three Vec's though.

We might just need to make calls to shrink_to_fit at certain points. Or change the representation of VecPerParamSpace so that it has just one vector "under the hood".

I will look into this today.

@pnkfelix
Copy link
Member

pnkfelix commented Jul 3, 2014

As a quick hack tonight, I did try adding calls to shrink_to_fit (under the assumption that if I added such calls in the right places, that would serve as an approximate lower-bound on how much memory we could expect to save if we e.g. changed from 3 Vecs to a single Vec with some sort of start/end metadata for each range).

As far as I can tell, calling shrink_to_fit did not resolve the problem, in that when I compared commit 9153d8a against its predecessor (and observed 200M mem usage increase when compiling librustc), and then added the shrink_to_fit calls, the mem usage increase remained.

For reference, here is the patch I used, in case I missed something: pnkfelix@cf8e44e

@pnkfelix
Copy link
Member

pnkfelix commented Jul 3, 2014

(There were a lot of other changes mixed in on this patch, so its possible that the 3 Vec part of the patch is a red herring here. Not sure yet.)

@pcwalton
Copy link
Contributor

pcwalton commented Jul 3, 2014

Note that shrink_to_fit() doesn't get rid of malloc slop.

pnkfelix added a commit to pnkfelix/rust that referenced this pull request Jul 5, 2014
In my informal measurements, this brings the peak memory usage when
building librustc from 1662M down to 1502M.  Since 1662 - 1502 = 160,
this may not recover the entirety of the observed memory regression
(250M) from PR rust-lang#14604.  (However, according to my local measurements,
the regression when building librustc was more like 209M, so perhaps
this will still recover the lions share of the lost memory.)
bors added a commit that referenced this pull request Jul 5, 2014
…cwalton

In my informal measurements, this brings the peak memory usage when
building librustc from 1662M down to 1502M.  Since 1662 - 1502 = 160,
this may not recover the entirety of the observed memory regression
(250M) from PR #14604.  (However, according to my local measurements,
the regression when building librustc was more like 209M, so perhaps
this will still recover the lions share of the lost memory.)
@nikomatsakis
Copy link
Contributor Author

I did at one point attempt an alternate version of this patch in which I used Rc<Vec<T>> in numerous places to try and get more re-use. This did not improve memory usage at all and in fact seemed to make things worse. Also, @cmr did some measurements of this patch before I landed it where things looked good -- but I can't recall if I compared against master, or only between the variation that used ref counting.

@pnkfelix
Copy link
Member

pnkfelix commented Jul 7, 2014

@nikomatsakis Hmm interesting. The majority of the regression has at this point been fixed, as huon reports here #15418 (comment)

So, just to try to understand, in the alternative version that you mention, you were trying to identify instances of Vec that could be shared between distinct instances of VecPerParamSpace ?

@nikomatsakis
Copy link
Contributor Author

On Mon, Jul 07, 2014 at 09:25:19AM -0700, Felix S Klock II wrote:

So, just to try to understand, in the alternative version that you
mention, you were trying to identify instances of Vec that could
be shared between distinct instances of VecPerParamSpace ?

Yes. Basically VecPerParamSpace stored Rc<Vec<T>>, and in some
places I used a Rc<VecPerParamSpace<T>> as well to avoid deep
cloning. This made the code a bit messier overall and didn't seam to
really help much in practice.

@nikomatsakis nikomatsakis deleted the issue-5527-namespace-substs branch March 30, 2016 16:15
bors added a commit to rust-lang-ci/rust that referenced this pull request Jun 5, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Resolve is not detecting out-of-scope type parameters
6 participants