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 unification of const variables #74040

Merged
merged 3 commits into from
Sep 21, 2020
Merged

Conversation

lcnr
Copy link
Contributor

@lcnr lcnr commented Jul 4, 2020

r? @nikomatsakis @varkor @eddyb let's just ping everyone here 😅

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Jul 4, 2020
TypeVariableValue::Unknown { universe: _ } => {
// FIXME: We may have to do something similar to what
// `Generalizer` is doing here.
false
Copy link
Contributor Author

@lcnr lcnr Jul 4, 2020

Choose a reason for hiding this comment

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

I am not too familiar with what has to be done with UniverseIndex here. When instantiating type inference variables, we sometimes adjust them, which we might also have to do for consts

if self.for_universe.can_name(universe) {
Ok(c)
} else {
let new_var_id = variable_table.new_key(ConstVarValue {
origin: var_value.origin,
val: ConstVariableValue::Unknown { universe: self.for_universe },
});
Ok(self.tcx().mk_const_var(new_var_id, c.ty))
}

and

match self.ambient_variance {
// Invariant: no need to make a fresh type variable.
ty::Invariant => {
if self.for_universe.can_name(universe) {
return Ok(t);
}
}
// Bivariant: make a fresh var, but we
// may need a WF predicate. See
// comment on `needs_wf` field for
// more info.
ty::Bivariant => self.needs_wf = true,
// Co/contravariant: this will be
// sufficiently constrained later on.
ty::Covariant | ty::Contravariant => (),
}
let origin =
*self.infcx.inner.borrow_mut().type_variables().var_origin(vid);
let new_var_id = self
.infcx
.inner
.borrow_mut()
.type_variables()
.new_var(self.for_universe, false, origin);
let u = self.tcx().mk_ty_var(new_var_id);
debug!("generalize: replacing original vid={:?} with new={:?}", vid, u);
Ok(u)

Copy link
Contributor

Choose a reason for hiding this comment

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

OK, so, the idea is that... if we are providing a value V for some variable ?A, then we have to ensure that the value V can be named from within the universe of ?A. e.g., if ?A is in the root universe, then V can only reference names in the root universe.

Therefore, if V contains some other variable ?B, then the universe Universe(?B) of ?B must be some ancestor of Universe(?A).

We have to decide how "eagerly" we want to report these errors.

In chalk at least, we treat type variables and lifetime variables differently. For example, if we have exists<T> { forall<U> { T = U } } in chalk, we consider that to be a unification failure. But if we have exists<'a> { forall<'b> { 'a = 'b } } in chalk, we produce a region constraint that will never be satisfied.

However, Rust doesn't presently have binders over type variables like this, so the question doesn't arise in stable rust. I guess I have to go read what the unification code does 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.

Hm, so I guess the goal is to use a TypeFolder instead of a visitor here and update the type and const variables if they are in a universe which can't be named.

I am still not completely sure where this is needed and how to test this, so it might be fine to merge this with a FIXME here

Copy link
Contributor

Choose a reason for hiding this comment

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

Given the limited range of "forall" currently possible in Rust, that may well be true...not sure. I guess there might be things like exists<'a> { forall<'b> { <T as Foo<'a>>::BAR = <T as Foo<'b>>::BAR } } or something that might indirectly relate lifetimes with universes and be led astray.

Copy link
Contributor

Choose a reason for hiding this comment

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

I guess I should review the type unification code.

@varkor varkor added the F-const_generics `#![feature(const_generics)]` label Jul 4, 2020
@lcnr
Copy link
Contributor Author

lcnr commented Jul 6, 2020

@nikomatsakis @varkor I added a comment which explains what we are trying to prevent here,
please tell me if there is anything else you want me to elaborate on.

@lcnr lcnr force-pushed the const-occurs-check branch 3 times, most recently from b35f0eb to 240601d Compare July 6, 2020 18:48
@nikomatsakis
Copy link
Contributor

Sorry for slow review. Will try to get this done ASAP!

@nikomatsakis
Copy link
Contributor

OK, I read the comments here, but @lcnr I'm feeling a bit uncertain as to what I think is best. Maybe we should find some time to chat a bit interactively?

TypeVariableValue::Unknown { universe: _ } => {
// FIXME: We may have to do something similar to what
// `Generalizer` is doing here.
false
Copy link
Contributor

Choose a reason for hiding this comment

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

OK, so, the idea is that... if we are providing a value V for some variable ?A, then we have to ensure that the value V can be named from within the universe of ?A. e.g., if ?A is in the root universe, then V can only reference names in the root universe.

Therefore, if V contains some other variable ?B, then the universe Universe(?B) of ?B must be some ancestor of Universe(?A).

We have to decide how "eagerly" we want to report these errors.

In chalk at least, we treat type variables and lifetime variables differently. For example, if we have exists<T> { forall<U> { T = U } } in chalk, we consider that to be a unification failure. But if we have exists<'a> { forall<'b> { 'a = 'b } } in chalk, we produce a region constraint that will never be satisfied.

However, Rust doesn't presently have binders over type variables like this, so the question doesn't arise in stable rust. I guess I have to go read what the unification code does now.

@lcnr lcnr mentioned this pull request Jul 28, 2020
8 tasks
@lcnr lcnr force-pushed the const-occurs-check branch 2 times, most recently from f93c0cf to 23b032c Compare July 29, 2020 08:33
@Muirrum Muirrum added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Aug 13, 2020
@bors
Copy link
Contributor

bors commented Aug 30, 2020

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

@lcnr lcnr force-pushed the const-occurs-check branch 4 times, most recently from 82411a3 to 4720b47 Compare September 9, 2020 07:50
@lcnr lcnr changed the title implement the occurs check for const vars fix unification of const variables Sep 9, 2020
@bors
Copy link
Contributor

bors commented Sep 20, 2020

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

Note that reviewers usually do not review pull requests until merge conflicts are resolved! Once you resolve the conflicts, you should change the labels applied by bors to indicate that your PR is ready for review. Post this as a comment to change the labels:

@rustbot modify labels: +S-waiting-on-review -S-waiting-on-author

@nikomatsakis
Copy link
Contributor

Sorry for being super slow. I read over this quickly and everything looks right. Given how little time I have for reviewing I'm going to r+ despite not having done a deep read, I certainly trust @lcnr and we can patch it up later if there's something wrong =)

r=me but needs rebase.

@lcnr
Copy link
Contributor Author

lcnr commented Sep 21, 2020

let's not use a rollup here in case this breaks something

@bors r=nikomatsakis rollup=never

@bors
Copy link
Contributor

bors commented Sep 21, 2020

📌 Commit 0f17d355693c5c0fbc3ac5399273066725ddb476 has been approved by nikomatsakis

@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 Sep 21, 2020
@lcnr
Copy link
Contributor Author

lcnr commented Sep 21, 2020

@bors r- formatting

@bors bors 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 Sep 21, 2020
@lcnr
Copy link
Contributor Author

lcnr commented Sep 21, 2020

@bors r=nikomatsakis rollup=never

@bors
Copy link
Contributor

bors commented Sep 21, 2020

📌 Commit 2855b92 has been approved by nikomatsakis

@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-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Sep 21, 2020
@bors
Copy link
Contributor

bors commented Sep 21, 2020

⌛ Testing commit 2855b92 with merge e0bf356...

@bors
Copy link
Contributor

bors commented Sep 21, 2020

☀️ Test successful - checks-actions, checks-azure
Approved by: nikomatsakis
Pushing e0bf356 to master...

@bors bors added the merged-by-bors This PR was explicitly merged by bors. label Sep 21, 2020
@bors bors merged commit e0bf356 into rust-lang:master Sep 21, 2020
@rustbot rustbot added this to the 1.48.0 milestone Sep 21, 2020
@lcnr lcnr deleted the const-occurs-check branch September 21, 2020 17:06
@ecstatic-morse
Copy link
Contributor

Hi! This PR showed up in the weekly perf triage report. It seems to have caused a
moderate regression in instruction counts
(up to 3.3% on incr-full builds of coercions-debug).

However, no other benchmarks regressed, which is pretty unusual. I doubt that there's much to be done here, but just in case cc @lcnr

@lcnr
Copy link
Contributor Author

lcnr commented Sep 22, 2020

So we now do slightly more work when dealing with unevaluated constants, which rarely happens without const_generics so I did not expect a huge impact here.

The regression for coercions-debug looks like llvm has more work here, which really should not happen beause of that PR as I do not think we change anything outside of typeck, is it worth it to try and revert this to see if the regression is deterministic?

@ecstatic-morse
Copy link
Contributor

Looking at recent perf results, something seems to have introduced some bimodal noise for coercions-debug. I'll try to revert a few PRs in that range to see what the cause is.

@jyn514 jyn514 added the T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. label Nov 17, 2020
@lcnr lcnr added the A-const-generics Area: const generics (parameters and arguments) label Jan 20, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-const-generics Area: const generics (parameters and arguments) F-const_generics `#![feature(const_generics)]` merged-by-bors This PR was explicitly merged by bors. S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants