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

Use only ty::Unevaluated<'tcx, ()> in type system #98588

Merged
merged 11 commits into from
Sep 17, 2022

Conversation

b-naber
Copy link
Contributor

@b-naber b-naber commented Jun 27, 2022

r? @lcnr

@rust-highfive
Copy link
Collaborator

Some changes occured to the CTFE / Miri engine

cc @rust-lang/miri

Some changes occured in const_evaluatable.rs

cc @lcnr

Some changes occured to rustc_codegen_cranelift

cc @bjorn3

Some changes occured to the CTFE / Miri engine

cc @rust-lang/miri

@rustbot rustbot added T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-rustdoc Relevant to the rustdoc team, which will review and decide on the PR/issue. labels Jun 27, 2022
@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Jun 27, 2022
let val =
self.subst_from_current_frame_and_normalize_erasing_regions(constant.literal)?;
debug!(?val);
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 prefer if we wouldn't sprinkle debug all over the codebase. That makes it super hard to debug the things I want to look into because all information drowns in noise.

At least this should be made trace -- we only want to see this when we are at maximal verbosity level.

@@ -632,7 +635,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
}
ty::ConstKind::Unevaluated(uv) => {
let instance = self.resolve(uv.def, uv.substs)?;
Ok(self.eval_to_allocation(GlobalId { instance, promoted: uv.promoted })?.into())
Ok(self.eval_to_allocation(GlobalId { instance, promoted: None })?.into())
Copy link
Member

Choose a reason for hiding this comment

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

Why does this make sense? It might be a promoted after all...

Copy link
Member

Choose a reason for hiding this comment

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

Also can't this call uneval_to_op now?

Copy link
Contributor

Choose a reason for hiding this comment

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

this function should be replaced with a function fn ty_const_to_value instead of going to an Operand in one go. I think we should require the caller to normalize unevaluated type system constants and we just always return TooGeneric for ty::Unevaluated here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Can you explain why we would want to do that? It's doesn't make sense to me why we should first create a ConstValue when we only only want an Operand (we would call eval_to_allocation for creating the ConstValue anyway).

@@ -645,6 +648,16 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
}
}

/// Tries to evaluate an unevaluated constant from the MIR (and not the type-system).
Copy link
Member

Choose a reason for hiding this comment

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

I don't understand this comment. The type of the argument is ty::Unevaluated, that sounds like a type system thing to me?

Copy link
Contributor

Choose a reason for hiding this comment

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

we use ty::Unevaluated for both type system constants, in which case promoted is () and unevaluated mir constants, in which case promoted is Option<Promoted>.

It is true that this means that ty isn't really the right module for this but idk where else to put it 😆

@rust-log-analyzer

This comment has been minimized.

Copy link
Contributor

@lcnr lcnr left a comment

Choose a reason for hiding this comment

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

maybe we want to instead represent ConstantKind::Unevaluated completely without ty::Unevaluated but instead inline the fields 🤔

any shared eval code should then again take def_id, substs, promoted separately. This also avoids the use of ty::X for stuff only used in the mir. not 100% sure what's the best design here.

Comment on lines 1846 to 1822
ConstantKind::Ty(ct) => match ct.kind() {
ty::ConstKind::Unevaluated(uv) => Some(uv),
ty::ConstKind::Unevaluated(uv) => Some(uv.expand()),
_ => None,
},
Copy link
Contributor

Choose a reason for hiding this comment

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

this can never be an inline const, can just return None there.

please change this match to be exhaustive

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Doing this causes the test in src/test/ui/inline-const/const-expr-lifetime-err.rs to compile successfully

Copy link
Contributor

Choose a reason for hiding this comment

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

hmm we should lower inline consts to mir constants, not ty constants 🤔 that's a bug during inline const lowering then

Copy link
Contributor

Choose a reason for hiding this comment

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

still relevant

compiler/rustc_codegen_cranelift/src/constant.rs Outdated Show resolved Hide resolved
mir::ConstantKind::Ty(ct) => ct,
let uv = match ct {
mir::ConstantKind::Ty(ct) => match ct.kind() {
ty::ConstKind::Unevaluated(uv) => uv.expand(),
Copy link
Contributor

Choose a reason for hiding this comment

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

again only ConstKind::Value should be possible

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No, we can still have ConstKind::Unevaluated here.

Copy link
Contributor

Choose a reason for hiding this comment

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

that seems wrong? the constant should be evaluated in monomorphize 🤔

maybe we should return an Err here if this fails to evaluate

let constant = constant.try_super_fold_with(self)?;
Ok(constant.eval(self.infcx.tcx, self.param_env))

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's also not clear to me why we would want to error here if we can't evaluate yet, this is called all the time during typecheck, isn't it?

Copy link
Contributor

Choose a reason for hiding this comment

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

no, the normalize query isn't used during typeck, it's only used afterwards.

i guess it's fine to keep this for now 🤷 will be easier to fix this once your pr has landed

@@ -632,7 +635,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
}
ty::ConstKind::Unevaluated(uv) => {
let instance = self.resolve(uv.def, uv.substs)?;
Ok(self.eval_to_allocation(GlobalId { instance, promoted: uv.promoted })?.into())
Ok(self.eval_to_allocation(GlobalId { instance, promoted: None })?.into())
Copy link
Contributor

Choose a reason for hiding this comment

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

this function should be replaced with a function fn ty_const_to_value instead of going to an Operand in one go. I think we should require the caller to normalize unevaluated type system constants and we just always return TooGeneric for ty::Unevaluated here.

ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted })
if matches!(
self.tcx.def_kind(def.did),
DefKind::AnonConst | DefKind::InlineConst
Copy link
Contributor

Choose a reason for hiding this comment

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

it can be InlineConst? that shouldn't be the case

Copy link
Contributor

Choose a reason for hiding this comment

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

still relevant

compiler/rustc_monomorphize/src/polymorphize.rs Outdated Show resolved Hide resolved
mir::ConstantKind::Val(_, _) => constant.try_super_fold_with(self)?,
mir::ConstantKind::Val(_, _) | mir::ConstantKind::Unevaluated(..) => {
constant.try_super_fold_with(self)?
}
Copy link
Contributor

Choose a reason for hiding this comment

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

this try_fold_mir_const can now stop with the weird ConstantKind::Ty . The default impl of that method should now be good enough

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Don't understand what you mean here, we def do need try_fold_mir_const here afaict, since this is where we convert valtrees to constvals.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think we should do that conversion lazily. keep the mir constant as ConstantKind::Ty(ConstKind::Value(..)) until we actually need it

Copy link
Contributor

Choose a reason for hiding this comment

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

still relevant

compiler/rustc_typeck/src/check/wfcheck.rs Outdated Show resolved Hide resolved
@bors
Copy link
Contributor

bors commented Jun 29, 2022

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

@rustbot
Copy link
Collaborator

rustbot commented Jun 30, 2022

Some changes occurred to the CTFE / Miri engine

cc @rust-lang/miri

Some changes occurred in compiler/rustc_codegen_cranelift

cc @bjorn3

Some changes occurred to the CTFE / Miri engine

cc @rust-lang/miri

Some changes occurred to MIR optimizations

cc @rust-lang/wg-mir-opt

Some changes occurred in const_evaluatable.rs

cc @lcnr

@b-naber
Copy link
Contributor Author

b-naber commented Jun 30, 2022

Still getting errors in the tests when implementing some of your suggestions, @lcnr.

Trying to find which changes are responsible for the failure, but since running the test set is slow on my machine, I'll use CI.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@b-naber
Copy link
Contributor Author

b-naber commented Jun 30, 2022

What is wrong in the commit that removes visit_const? I'd guess that we can't remove the default impl for super_constant? But how would we in general visit ConstantKind::Ty if we remove visit_const?

@b-naber b-naber force-pushed the valtrees-cleanup branch 2 times, most recently from bb2451e to 68369fd Compare July 1, 2022 13:39
@rust-log-analyzer

This comment has been minimized.

@b-naber b-naber force-pushed the valtrees-cleanup branch 2 times, most recently from 6e40c69 to 1e04998 Compare July 1, 2022 14:02
@rust-log-analyzer

This comment has been minimized.

@lcnr
Copy link
Contributor

lcnr commented Jul 1, 2022

But how would we in general visit ConstantKind::Ty if we remove visit_const?

not at all imo 😁 what visitor would want to only look at ConstantKind::Ty but not at ConstantKind::Unevaluated or the constants contained in the types of locals?

@b-naber
Copy link
Contributor Author

b-naber commented Jul 1, 2022

But how would we in general visit ConstantKind::Ty if we remove visit_const?

not at all imo 😁 what visitor would want to only look at ConstantKind::Ty but not at ConstantKind::Unevaluated or the constants contained in the types of locals?

I mean that's true, but what should the default impl for super_constant look like?

I don't like it at all that these super methods in the mir visitor aren't required in the impl, you can super easily shoot yourself in the foot as I'm doing right now. So if we don't have visitconst we cannot traverse ConstantKind::Ty in super_constant. What are we supposed to do there instead? Just do nothing? Since we're visiting ty in ConstantKind::Val and ConstantKind::Unevaluated it seeems to me we should call something like TyConstantKind::Ty(ct) => ct.visit_with(self), but mir::Visitors aren't TypeVisitors. To me this just seems inconsistent.

@rust-timer
Copy link
Collaborator

Queued 1a5b8c954e6c7b563df9c4b135bab9d8ffda9003 with parent 22f6aec, future comparison URL.

@rust-timer
Copy link
Collaborator

Finished benchmarking commit (1a5b8c954e6c7b563df9c4b135bab9d8ffda9003): comparison URL.

Overall result: ❌✅ regressions and improvements - no action needed

Benchmarking this pull request likely means that it is perf-sensitive, so we're automatically marking it as not fit for rolling up. While you can manually mark this PR as fit for rollup, we strongly recommend not doing so since this PR may lead to changes in compiler perf.

@bors rollup=never
@rustbot label: +S-waiting-on-review -S-waiting-on-perf -perf-regression

Instruction count

This is a highly reliable metric that was used to determine the overall result at the top of this comment.

mean1 range count2
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
1.6% [0.7%, 2.5%] 2
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
-0.7% [-1.3%, -0.4%] 6
All ❌✅ (primary) - - 0

Max RSS (memory usage)

Results

This is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.

mean1 range count2
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
- - 0
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
-3.3% [-5.3%, -1.3%] 2
All ❌✅ (primary) - - 0

Cycles

Results

This is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.

mean1 range count2
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
2.4% [2.4%, 2.4%] 1
Improvements ✅
(primary)
-1.3% [-1.3%, -1.3%] 1
Improvements ✅
(secondary)
-2.6% [-2.6%, -2.6%] 1
All ❌✅ (primary) -1.3% [-1.3%, -1.3%] 1

Footnotes

  1. the arithmetic mean of the percent change 2 3

  2. number of relevant changes 2 3

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-perf Status: Waiting on a perf run to be completed. labels Sep 16, 2022
@lcnr lcnr added A-const-generics Area: const generics (parameters and arguments) F-adt_const_params `#![feature(adt_const_params)]` labels Sep 16, 2022
@lcnr
Copy link
Contributor

lcnr commented Sep 16, 2022

looking good 👍

@bors r+ rollup=never p=10 somewhat bitrotty

@bors
Copy link
Contributor

bors commented Sep 16, 2022

📌 Commit d77248e has been approved by lcnr

It is now in the queue for this repository.

@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. S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Sep 16, 2022
@lcnr

This comment was marked as outdated.

@lcnr

This comment was marked as outdated.

@bors
Copy link
Contributor

bors commented Sep 17, 2022

⌛ Testing commit d77248e with merge c524c7d...

@bors
Copy link
Contributor

bors commented Sep 17, 2022

☀️ Test successful - checks-actions
Approved by: lcnr
Pushing c524c7d to master...

@bors bors added the merged-by-bors This PR was explicitly merged by bors. label Sep 17, 2022
@bors bors merged commit c524c7d into rust-lang:master Sep 17, 2022
@rustbot rustbot added this to the 1.65.0 milestone Sep 17, 2022
@rust-timer
Copy link
Collaborator

Finished benchmarking commit (c524c7d): comparison URL.

Overall result: ❌✅ regressions and improvements - no action needed

@rustbot label: -perf-regression

Instruction count

This is a highly reliable metric that was used to determine the overall result at the top of this comment.

mean1 range count2
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
2.2% [2.2%, 2.2%] 1
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
-0.6% [-0.6%, -0.6%] 3
All ❌✅ (primary) - - 0

Max RSS (memory usage)

Results

This is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.

mean1 range count2
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
4.9% [4.9%, 4.9%] 1
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
-4.3% [-4.3%, -4.3%] 1
All ❌✅ (primary) - - 0

Cycles

Results

This is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.

mean1 range count2
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
2.4% [2.4%, 2.4%] 1
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
-4.2% [-4.2%, -4.2%] 1
All ❌✅ (primary) - - 0

Footnotes

  1. the arithmetic mean of the percent change 2 3

  2. number of relevant changes 2 3

@b-naber b-naber deleted the valtrees-cleanup branch September 17, 2022 06:58
bjorn3 pushed a commit to bjorn3/rust that referenced this pull request Oct 23, 2022
Use only ty::Unevaluated<'tcx, ()> in type system

r? `@lcnr`
Comment on lines +567 to +575
// NOTE: We evaluate to a `ValTree` here as a check to ensure
// we're working with valid constants, even though we never need it.
let instance = self.resolve(uv.def, uv.substs)?;
Ok(self.eval_to_allocation(GlobalId { instance, promoted: uv.promoted })?.into())
let cid = GlobalId { instance, promoted: None };
let _valtree = self
.tcx
.eval_to_valtree(self.param_env.and(cid))?
.unwrap_or_else(|| bug!("unable to create ValTree for {:?}", uv));

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 a strange check. Why would CTFE care whether the constant is a valid valtree? What if uv has a type that does not even allow valtree construction, like a raw pointer?

Copy link
Member

@RalfJung RalfJung Nov 15, 2022

Choose a reason for hiding this comment

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

Oh, this is specifically for mir::ConstantKind::Ty, which I guess must always be valtree-constructible.

But then IMO it would make most sense to have a function that evaluates a ty::Const to a Valtree, and always go through that. Doesn't that exist as a query or so?

Copy link
Member

Choose a reason for hiding this comment

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

But then IMO it would make most sense to have a function that evaluates a ty::Const to a Valtree, and always go through that.

I will do that in #104317

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-adt_const_params `#![feature(adt_const_params)]` 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. T-rustdoc Relevant to the rustdoc team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants