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

Fix for #62691: use the largest niche across all fields #70411

Merged
merged 4 commits into from
Mar 26, 2020

Conversation

ogoffart
Copy link
Contributor

fixes #62691

(The second commit is a small optimization but it makes the code less pretty and i don't know if it is worth it.)

@rust-highfive
Copy link
Collaborator

r? @cramertj

(rust_highfive has picked a reviewer for you, use r? to override)

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Mar 25, 2020
@Centril
Copy link
Contributor

Centril commented Mar 25, 2020

r? @eddyb cc @RalfJung

@rust-highfive rust-highfive assigned eddyb and unassigned cramertj Mar 25, 2020
Comment on lines 912 to 927
variants[i].iter().enumerate().fold(None, |acc, (j, &field)| {
let niche = match &field.largest_niche {
Some(niche) => niche,
_ => return acc,
};
let ns = niche.available(dl);
if ns <= niche_size {
return acc;
}
match niche.reserve(self, count) {
Some(pair) => {
niche_size = ns;
Some((j, niche, pair.0, pair.1))
}
None => acc,
}
Copy link
Member

Choose a reason for hiding this comment

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

You don't need this complication, just have .max_by_key(|(_, niche, _)| niche.available(dl)) before .and_then(|(_, niche)| Some((i, niche, niche.reserve(self, count)?))).

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 wanted to do that but that's not exactly the same thing. If it fails for the largest niche, but would have succeeded for a smaller niche, we would end up with None instead of using the smaller niche.
Now, maybe this cannot succeed for a smaller niche and fail for a bigger one so in that case that would be indeed best.

Copy link
Member

Choose a reason for hiding this comment

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

Now, maybe this cannot succeed for a smaller niche and fail for a bigger one so in that case that would be indeed best.

Yeah, that's why we want bigger niches in general: they succeed strictly more often.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is what i've done now.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

But looking at the code of Niche::reserve, it seems it can still fail if valid_range_contains despite being the largest niche while a smaller niche would work. or is that really unlikely?

Copy link
Member

Choose a reason for hiding this comment

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

The calculations are equivalent, I think I even double-checked them using bruteforce for small bitwidths.

niche.reserve(count) is checking niche.available() >= count but using values it has to compute anyway (i.e. the remaining validity range), instead of actually using available.

Comment on lines 910 to 918
if let Some((field_index, niche, (niche_start, niche_scalar))) = variants[i]
.iter()
.enumerate()
.filter_map(|(i, &field)| {
let niche = field.largest_niche.as_ref()?;
Some((i, niche, niche.reserve(self, count)?))
})
.max_by_key(|(_, niche, _)| niche.available(dl))
{
Copy link
Member

Choose a reason for hiding this comment

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

I really like how readable this is!

Comment on lines 910 to 927
let mut niche_size = 0;
if let Some((field_index, niche, niche_start, niche_scalar)) =
variants[i].iter().enumerate().fold(None, |acc, (j, &field)| {
let niche = match &field.largest_niche {
Some(niche) => niche,
_ => return acc,
};
let ns = niche.available(dl);
if ns <= niche_size {
return acc;
}
match niche.reserve(self, count) {
Some(pair) => {
niche_size = ns;
Some((j, niche, pair.0, pair.1))
}
None => acc,
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Consider sprinkling some comments here btw, and/or extracting functions :)

Copy link
Member

Choose a reason for hiding this comment

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

Hopefully we can keep something close to the first commit, as it's more functional and way easier to explain as "find the largest niche among the fields" + "make sure it can fit our variant count".

@eddyb
Copy link
Member

eddyb commented Mar 26, 2020

r=me after #70411 (comment) is addressed (which should be easier now, with the more functional approach - if you want, you can extract some of that into a variable that you then take apart using e.g. if let Some(...) = niche_candidate, instead of having everything in the RHS of the if let).

@ogoffart
Copy link
Contributor Author

Updated.

@eddyb
Copy link
Member

eddyb commented Mar 26, 2020

@bors r+ Thanks!

@bors
Copy link
Contributor

bors commented Mar 26, 2020

📌 Commit 0b00c20 has been approved by eddyb

@bors bors 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 Mar 26, 2020
bors added a commit to rust-lang-ci/rust that referenced this pull request Mar 26, 2020
Rollup of 5 pull requests

Successful merges:

 - rust-lang#68004 (permit negative impls for non-auto traits)
 - rust-lang#70385 (Miri nits: comment and var name improvement)
 - rust-lang#70411 (Fix for rust-lang#62691: use the largest niche across all fields)
 - rust-lang#70417 (parser: recover on `...` as a pattern, suggesting `..`)
 - rust-lang#70424 (simplify match stmt)

Failed merges:

r? @ghost
@bors bors merged commit f9d1378 into rust-lang:master Mar 26, 2020
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.

Suboptimal niche usage within the fields of a variant.
6 participants