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

Canonicalize inputs to const eval where needed #68505

Merged

Conversation

BenLewis-Seequent
Copy link

@BenLewis-Seequent BenLewis-Seequent commented Jan 24, 2020

Canonicalize inputs to const eval, so that they can contain inference variables. Which enables invoking const eval queries even if the current param env has inference variable within it, which can occur during trait selection.

This is a reattempt of #67717, in a far less invasive way.

Fixes #68477

r? @nikomatsakis
cc @eddyb

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Jan 24, 2020
@BenLewis-Seequent

This comment has been minimized.

@varkor varkor added the F-const_generics `#![feature(const_generics)]` label Jan 24, 2020
Copy link
Member

@eddyb eddyb left a comment

Choose a reason for hiding this comment

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

LGTM, but I'll leave the approval to @nikomatsakis.

let mut query_state = OriginalQueryValues::default();
let canonical = self.canonicalize_query(&(param_env, substs), &mut query_state);
let (param_env, substs) = canonical.value;
self.tcx.const_eval_resolve(param_env, def_id, substs, promoted, span)
Copy link
Member

Choose a reason for hiding this comment

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

Wait, I just remembered something: you need to replace the type with the original one, if you want to return the value (since it's not used, you could just opt to return Result<(), ...> for now).
This is because you don't want the canonical variables to stick around in the type.

There's also a related trick I've told @nikomatsakis about before:
The value produced by const-eval shouldn't depend on lifetimes, so we should probably always erase them in the input substs (and param_env even?).
But the type might have relevant lifetimes, which means we should (just like in the canonical case) use the original type along the new value.

I believe both canonicalizing and erasing lifetimes, would produce the correct value, but erasing them would result in perhaps better cache utilization.

Copy link
Contributor

Choose a reason for hiding this comment

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

Ideally, canonicalization would replace all lifetimes and hence be the same, from a cache perspective, but we may not currently handle things that way (we may treat 'static as special or something...)

Copy link
Author

Choose a reason for hiding this comment

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

I would think erasing lifetimes would also be benefical for const eval queries which don't use canonicalization, i.e. the ones that don't use InferCtxt::const_eval_reolve, although in most cases they already probably have there regions erased. It does look like canonicalize_query, which i'm using, does replace `static lifetimes.

Copy link
Author

@BenLewis-Seequent BenLewis-Seequent Jan 25, 2020

Choose a reason for hiding this comment

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

But the type might have relevant lifetimes, which means we should (just like in the canonical case) use the original type along the new value.

Most usage of const-eval is by codegen or inside miri which doesn't need/want lifetimes, and in other cases the caller knows what type it's expecting, so I think it should be up to the callers to the replace the type if they need to. One place I'm unsure about is:

match self.tcx.const_eval_resolve(

I'm not sure if lifetimes are important here or not, if they are I can replace the type with the node type retrieved above.

@nikomatsakis
Copy link
Contributor

Welp this is definitely shorter =)

It seems like we should do a perf run, though, right?

@nikomatsakis
Copy link
Contributor

@bors try

@bors
Copy link
Contributor

bors commented Jan 24, 2020

⌛ Trying commit 0f12888bfeab463a0e1278c13ea8869f49bdd559 with merge ed91a52f6d36d06eaf36de547fda2e61d41780af...

@nikomatsakis
Copy link
Contributor

@rust-timer queue

@rust-timer
Copy link
Collaborator

Awaiting bors try build completion

@bors
Copy link
Contributor

bors commented Jan 25, 2020

☀️ Try build successful - checks-azure
Build commit: ed91a52f6d36d06eaf36de547fda2e61d41780af (ed91a52f6d36d06eaf36de547fda2e61d41780af)

@rust-timer
Copy link
Collaborator

Queued ed91a52f6d36d06eaf36de547fda2e61d41780af with parent c2d141d, future comparison URL.

@rust-timer
Copy link
Collaborator

Finished benchmarking try commit ed91a52f6d36d06eaf36de547fda2e61d41780af, comparison URL.

@BenLewis-Seequent
Copy link
Author

Can I get another perf run to see if erasing lifetimes has any effect on performance?

@varkor
Copy link
Member

varkor commented Jan 25, 2020

@bors try
@rust-timer queue

@rust-timer
Copy link
Collaborator

Awaiting bors try build completion

@bors
Copy link
Contributor

bors commented Jan 25, 2020

⌛ Trying commit c8e35e3df4016e72bf7eb3a1508a592a80d1f3ae with merge d7a172c31012c265a79fc422a27e2b8e35978ff3...

@bors
Copy link
Contributor

bors commented Jan 25, 2020

☀️ Try build successful - checks-azure
Build commit: d7a172c31012c265a79fc422a27e2b8e35978ff3 (d7a172c31012c265a79fc422a27e2b8e35978ff3)

@rust-timer
Copy link
Collaborator

Queued d7a172c31012c265a79fc422a27e2b8e35978ff3 with parent 8bf1758, future comparison URL.

@BenLewis-Seequent
Copy link
Author

Perf numbers looks like just noise.

src/librustc/ty/sty.rs Outdated Show resolved Hide resolved
@BenLewis-Seequent
Copy link
Author

This actually now does fix #68477, as we are now erasing lifetimes of all inputs to const-eval, including region inference variables.

@Aaron1011
Copy link
Member

What's the status of this PR?

@varkor
Copy link
Member

varkor commented Jan 30, 2020

This is waiting for a review by @nikomatsakis, who has been at the Mozilla All Hands this week, so I imagine it'll be reviewed next week.

@bors
Copy link
Contributor

bors commented Feb 6, 2020

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

Copy link
Contributor

@nikomatsakis nikomatsakis left a comment

Choose a reason for hiding this comment

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

This seems good to me. My only hesitation is that I can't quite tell what was going on with the erase-regions question, I guess maybe I need to dig a bit deeper there to form an opinion?

src/librustc/infer/canonical/substitute.rs Outdated Show resolved Hide resolved
src/librustc/mir/interpret/queries.rs Show resolved Hide resolved
@shisoft
Copy link

shisoft commented Feb 11, 2020

Hi, what's the status of this PR?

@nikomatsakis
Copy link
Contributor

nikomatsakis commented Feb 14, 2020

I think the status is that we are waiting for @Skinny121 to do the following:

@bors
Copy link
Contributor

bors commented Feb 17, 2020

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

Dylan-DPC-zz pushed a commit to Dylan-DPC-zz/rust that referenced this pull request Feb 18, 2020
Change const eval to just return the value

As discussed in rust-lang#68505 (comment), the type of consts shouldn't be returned from const eval queries.

r? @eddyb
cc @nikomatsakis
@BenLewis-Seequent
Copy link
Author

Should be ready for code review again. #69181 changed the return type of const eval queries to just the value as requested, as a result the changes to substitute_value are no longer needed as no canonical variables can exist in the resultant ConstValue.

@nikomatsakis
Copy link
Contributor

@Skinny121 if I understood correctly, this means my comments about refactoring the substitution code is no longer relevant, but @eddyb's concern around erasing regions is still relevant, right? Any thoughts on fixing that as they suggested?

@BenLewis-Seequent
Copy link
Author

@nikomatsakis That concern isn't relevant any more as the erased regions don't escape that function, as ConstEvalResult<'tcx> is now Result<ConstValue<'tcx>, ErrorHandled>, which doesn't contain any types/regions.

@nikomatsakis
Copy link
Contributor

@bors r+

@bors
Copy link
Contributor

bors commented Feb 26, 2020

📌 Commit ebfa2f4 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 Feb 26, 2020
@bors
Copy link
Contributor

bors commented Feb 28, 2020

⌛ Testing commit ebfa2f4 with merge bfc32dd...

@bors
Copy link
Contributor

bors commented Feb 28, 2020

☀️ Test successful - checks-azure
Approved by: nikomatsakis
Pushing bfc32dd to master...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
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.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

ICE cause by tokio::spawn a async function return future opaque type