-
Notifications
You must be signed in to change notification settings - Fork 13.2k
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
Introduce a wrapper for "typed valtrees" and properly check the type before extracting the value #136180
Conversation
Some changes occurred in cc @BoxyUwU Some changes occurred to the CTFE machinery cc @rust-lang/wg-const-eval The Miri subtree was changed cc @rust-lang/miri Some changes occurred in cc @BoxyUwU Some changes occurred to the core trait solver cc @rust-lang/initiative-trait-system-refactor Some changes occurred in compiler/rustc_sanitizers cc @rust-lang/project-exploit-mitigations, @rcvalle Some changes occurred in compiler/rustc_codegen_cranelift cc @bjorn3 Some changes occurred in match checking cc @Nadrieril Some changes occurred in src/tools/clippy cc @rust-lang/clippy |
pub fn try_to_bool(self) -> Option<bool> { | ||
self.try_to_valtree()?.0.try_to_scalar_int()?.try_to_bool().ok() | ||
} | ||
|
||
#[inline] | ||
pub fn try_to_target_usize(self, tcx: TyCtxt<'tcx>) -> Option<u64> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Keeping this on ty::Const
because there's a large amount of code that inspects array lengths that would be made worse by having to do try_to_value().and_then(|val| val.try_to_target_usize(tcx))
?
Seems reasonable to me 🤔 can a comment be added to state that since it doesn't seem unlikely that someone might come across this and be confused why it's the way it is
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Keeping this on
ty::Const
because there's a large amount of code that inspects array lengths that would be made worse by having to dotry_to_value().and_then(|val| val.try_to_target_usize(tcx))
?
Yeah, this is used all over the place, including codegen, mir opts and clippy lints.
Seems reasonable to me 🤔 can a comment be added to state that since it doesn't seem unlikely that someone might come across this and be confused why it's the way it is
👍
bug!("we checked that this is a valtree") | ||
}; | ||
let mut cx = FmtPrinter::new(tcx, Namespace::ValueNS); | ||
cx.pretty_print_const_valtree(valtree, ty, /*print_ty*/ true)?; | ||
cx.pretty_print_const_valtree(cv.valtree, cv.ty, /*print_ty*/ true)?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
would it make sense to make pretty_print_const_valtree
just be pretty_print_const_value
and accept ty::Value
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are also valtree_to_const_value
(the fn that backs the query) and valtree_to_pat
that still accept ty and valtree separately. I left these out for now to keep the diff smaller, but I can also change them here if you prefer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now that you mention valtree_to_const_value
I'm realising that there's an unfortunate naming overlap between mir::ConstValue
and ty::Const::Value
lol. We should probably just leave the name as const_valtree
even if it's updated to take a ty::Value
as otherwise you'd wind up with weird functions like const_value_to_const_value
...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
for valtree_to_pat
I'd just leave that up to oli as he's more familiar with the way mir pattern logic interacts with ty::Const
and I don't want to make a decision there since I don't really work on that logic 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems reasonable to me to use this in valtree_to_pat
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Leave a FIXME for pretty_print_const_valtree
to be changed to using this type
Probably, this closure rust/compiler/rustc_middle/src/mir/pretty.rs Lines 1432 to 1436 in aa6f5ab
should become something like let fmt_valtree = |cv: &ty::Value<'tcx>| {
let mut cx = FmtPrinter::new(self.tcx, Namespace::ValueNS);
cx.pretty_print_const_valtree(cv.valtree, cv.ty, /*print_ty*/ true).unwrap();
cx.into_buffer()
}; IMO, it should accepts the new Note that it implies that This may or may not be a follow-up of this PR. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think everything needs to happen in this PR, but leave some FIXMEs and add the doc comment on the ty::Const
method
ty::ConstKind::Value(_, val) => convert.valtree_to_pat(val, ty), | ||
ty::ConstKind::Value(cv) => convert.valtree_to_pat(cv.valtree, cv.ty), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Leave a FIXME to change valtree_to_pat
to taking a Value
directly
bug!("we checked that this is a valtree") | ||
}; | ||
let mut cx = FmtPrinter::new(tcx, Namespace::ValueNS); | ||
cx.pretty_print_const_valtree(valtree, ty, /*print_ty*/ true)?; | ||
cx.pretty_print_const_valtree(cv.valtree, cv.ty, /*print_ty*/ true)?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Leave a FIXME for pretty_print_const_valtree
to be changed to using this type
cv.ty, | ||
cv.valtree, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Leave a FIXME to change this to take the cv
instead of its components
@bors r+ |
This comment has been minimized.
This comment has been minimized.
@bors r- |
Co-authored-by: FedericoBruzzone <federico.bruzzone.i@gmail.com>
and remove `ty::Const::try_to_scalar` because it becomes redundant
ab2eb92
to
ca3ff83
Compare
@bors r+ |
…iaskrgr Rollup of 9 pull requests Successful merges: - rust-lang#135026 (Cast global variables to default address space) - rust-lang#135475 (uefi: Implement path) - rust-lang#135852 (Add `AsyncFn*` to `core` prelude) - rust-lang#136004 (tests: Skip const OOM tests on aarch64-unknown-linux-gnu) - rust-lang#136157 (override build profile for bootstrap tests) - rust-lang#136180 (Introduce a wrapper for "typed valtrees" and properly check the type before extracting the value) - rust-lang#136256 (Add release notes for 1.84.1) - rust-lang#136271 (Remove minor future footgun in `impl Debug for MaybeUninit`) - rust-lang#136288 (Improve documentation for file locking) r? `@ghost` `@rustbot` modify labels: rollup
Rollup merge of rust-lang#136180 - lukas-code:typed-valtree, r=oli-obk Introduce a wrapper for "typed valtrees" and properly check the type before extracting the value This PR adds a new wrapper type `ty::Value` to replace the tuple `(Ty, ty::ValTree)` and become the new canonical representation of type-level constant values. The value extraction methods `try_to_bits`/`try_to_bool`/`try_to_target_usize` are moved to this new type. For `try_to_bits` in particular, this avoids some redundant matches on `ty::ConstKind::Value`. Furthermore, these methods and will now properly check the type before extracting the value, which fixes some ICEs. The name `ty::Value` was chosen to be consistent with `ty::Expr`. Commit 1 should be non-functional and commit 2 adds the type check. --- fixes rust-lang#131102 supercedes rust-lang#136130 r? `@oli-obk` cc `@FedericoBruzzone` `@BoxyUwU`
… r=oli-obk Use the type-level constant value `ty::Value` where needed **Follow-up to rust-lang#136180** ### Summary This PR refactors functions to accept a single type-level constant value `ty::Value` instead of separate `ty::ValTree` and `ty::Ty` parameters: - `valtree_to_const_value`: now takes `ty::Value` - `pretty_print_const_valtree`: now takes `ty::Value` - Uses `pretty_print_const_valtree` for formatting valtrees when `visit_const_operand` - Moves `try_to_raw_bytes` from `ty::Valtree` to `ty::Value` --- r? `@lukas-code` `@oli-obk`
… r=oli-obk Use the type-level constant value `ty::Value` where needed **Follow-up to rust-lang#136180** ### Summary This PR refactors functions to accept a single type-level constant value `ty::Value` instead of separate `ty::ValTree` and `ty::Ty` parameters: - `valtree_to_const_value`: now takes `ty::Value` - `pretty_print_const_valtree`: now takes `ty::Value` - Uses `pretty_print_const_valtree` for formatting valtrees when `visit_const_operand` - Moves `try_to_raw_bytes` from `ty::Valtree` to `ty::Value` --- r? ``@lukas-code`` ``@oli-obk``
Rollup merge of rust-lang#136430 - FedericoBruzzone:follow-up-136180, r=oli-obk Use the type-level constant value `ty::Value` where needed **Follow-up to rust-lang#136180** ### Summary This PR refactors functions to accept a single type-level constant value `ty::Value` instead of separate `ty::ValTree` and `ty::Ty` parameters: - `valtree_to_const_value`: now takes `ty::Value` - `pretty_print_const_valtree`: now takes `ty::Value` - Uses `pretty_print_const_valtree` for formatting valtrees when `visit_const_operand` - Moves `try_to_raw_bytes` from `ty::Valtree` to `ty::Value` --- r? ``@lukas-code`` ``@oli-obk``
valtree performance tuning Summary: This PR makes type checking of code with many type-level constants faster. After rust-lang#136180 was merged, we observed a small perf regression (rust-lang#136318 (comment)). This happened because that PR introduced additional copies in the fast reject code path for consts, which is very hot for certain crates: https://github.com/rust-lang/rust/blob/6c1d960d88dd3755548b3818630acb63fa98187e/compiler/rustc_type_ir/src/fast_reject.rs#L486-L487 This PR improves the performance again by properly interning the valtrees so that copying and comparing them becomes faster. This will become especially useful with `feature(adt_const_params)`, so the fast reject code doesn't have to do a deep compare of the valtrees. A less invasive alternative that I considered is simply avoiding copies introduced by rust-lang#136180 and comparing the valtrees it in-place (see commit: rust-lang@9e91e50 / perf results: rust-lang#136593 (comment)), however that was still measurably slower than interning.
valtree performance tuning Summary: This PR makes type checking of code with many type-level constants faster. After rust-lang#136180 was merged, we observed a small perf regression (rust-lang#136318 (comment)). This happened because that PR introduced additional copies in the fast reject code path for consts, which is very hot for certain crates: https://github.com/rust-lang/rust/blob/6c1d960d88dd3755548b3818630acb63fa98187e/compiler/rustc_type_ir/src/fast_reject.rs#L486-L487 This PR improves the performance again by properly interning the valtrees so that copying and comparing them becomes faster. This will become especially useful with `feature(adt_const_params)`, so the fast reject code doesn't have to do a deep compare of the valtrees. Note that we can't just compare the interned consts themselves in the fast reject, because sometimes `'static` lifetimes in the type are be replaced with inference variables (due to canonicalization) on one side but not the other. A less invasive alternative that I considered is simply avoiding copies introduced by rust-lang#136180 and comparing the valtrees it in-place (see commit: rust-lang@9e91e50 / perf results: rust-lang#136593 (comment)), however that was still measurably slower than interning. There are some minor regressions in secondary benchmarks: These happen due to changes in memory allocations and seem acceptable to me. The crates that make heavy use of valtrees show no significant changes in memory usage.
valtree performance tuning Summary: This PR makes type checking of code with many type-level constants faster. After rust-lang/rust#136180 was merged, we observed a small perf regression (rust-lang/rust#136318 (comment)). This happened because that PR introduced additional copies in the fast reject code path for consts, which is very hot for certain crates: https://github.com/rust-lang/rust/blob/6c1d960d88dd3755548b3818630acb63fa98187e/compiler/rustc_type_ir/src/fast_reject.rs#L486-L487 This PR improves the performance again by properly interning the valtrees so that copying and comparing them becomes faster. This will become especially useful with `feature(adt_const_params)`, so the fast reject code doesn't have to do a deep compare of the valtrees. Note that we can't just compare the interned consts themselves in the fast reject, because sometimes `'static` lifetimes in the type are be replaced with inference variables (due to canonicalization) on one side but not the other. A less invasive alternative that I considered is simply avoiding copies introduced by rust-lang/rust#136180 and comparing the valtrees it in-place (see commit: rust-lang/rust@9e91e50 / perf results: rust-lang/rust#136593 (comment)), however that was still measurably slower than interning. There are some minor regressions in secondary benchmarks: These happen due to changes in memory allocations and seem acceptable to me. The crates that make heavy use of valtrees show no significant changes in memory usage.
valtree performance tuning Summary: This PR makes type checking of code with many type-level constants faster. After rust-lang/rust#136180 was merged, we observed a small perf regression (rust-lang/rust#136318 (comment)). This happened because that PR introduced additional copies in the fast reject code path for consts, which is very hot for certain crates: https://github.com/rust-lang/rust/blob/6c1d960d88dd3755548b3818630acb63fa98187e/compiler/rustc_type_ir/src/fast_reject.rs#L486-L487 This PR improves the performance again by properly interning the valtrees so that copying and comparing them becomes faster. This will become especially useful with `feature(adt_const_params)`, so the fast reject code doesn't have to do a deep compare of the valtrees. Note that we can't just compare the interned consts themselves in the fast reject, because sometimes `'static` lifetimes in the type are be replaced with inference variables (due to canonicalization) on one side but not the other. A less invasive alternative that I considered is simply avoiding copies introduced by rust-lang/rust#136180 and comparing the valtrees it in-place (see commit: rust-lang/rust@9e91e50 / perf results: rust-lang/rust#136593 (comment)), however that was still measurably slower than interning. There are some minor regressions in secondary benchmarks: These happen due to changes in memory allocations and seem acceptable to me. The crates that make heavy use of valtrees show no significant changes in memory usage.
valtree performance tuning Summary: This PR makes type checking of code with many type-level constants faster. After rust-lang/rust#136180 was merged, we observed a small perf regression (rust-lang/rust#136318 (comment)). This happened because that PR introduced additional copies in the fast reject code path for consts, which is very hot for certain crates: https://github.com/rust-lang/rust/blob/6c1d960d88dd3755548b3818630acb63fa98187e/compiler/rustc_type_ir/src/fast_reject.rs#L486-L487 This PR improves the performance again by properly interning the valtrees so that copying and comparing them becomes faster. This will become especially useful with `feature(adt_const_params)`, so the fast reject code doesn't have to do a deep compare of the valtrees. Note that we can't just compare the interned consts themselves in the fast reject, because sometimes `'static` lifetimes in the type are be replaced with inference variables (due to canonicalization) on one side but not the other. A less invasive alternative that I considered is simply avoiding copies introduced by rust-lang/rust#136180 and comparing the valtrees it in-place (see commit: rust-lang/rust@9e91e50 / perf results: rust-lang/rust#136593 (comment)), however that was still measurably slower than interning. There are some minor regressions in secondary benchmarks: These happen due to changes in memory allocations and seem acceptable to me. The crates that make heavy use of valtrees show no significant changes in memory usage.
valtree performance tuning Summary: This PR makes type checking of code with many type-level constants faster. After rust-lang/rust#136180 was merged, we observed a small perf regression (rust-lang/rust#136318 (comment)). This happened because that PR introduced additional copies in the fast reject code path for consts, which is very hot for certain crates: https://github.com/rust-lang/rust/blob/6c1d960d88dd3755548b3818630acb63fa98187e/compiler/rustc_type_ir/src/fast_reject.rs#L486-L487 This PR improves the performance again by properly interning the valtrees so that copying and comparing them becomes faster. This will become especially useful with `feature(adt_const_params)`, so the fast reject code doesn't have to do a deep compare of the valtrees. Note that we can't just compare the interned consts themselves in the fast reject, because sometimes `'static` lifetimes in the type are be replaced with inference variables (due to canonicalization) on one side but not the other. A less invasive alternative that I considered is simply avoiding copies introduced by rust-lang/rust#136180 and comparing the valtrees it in-place (see commit: rust-lang/rust@9e91e50 / perf results: rust-lang/rust#136593 (comment)), however that was still measurably slower than interning. There are some minor regressions in secondary benchmarks: These happen due to changes in memory allocations and seem acceptable to me. The crates that make heavy use of valtrees show no significant changes in memory usage.
This PR adds a new wrapper type
ty::Value
to replace the tuple(Ty, ty::ValTree)
and become the new canonical representation of type-level constant values.The value extraction methods
try_to_bits
/try_to_bool
/try_to_target_usize
are moved to this new type. Fortry_to_bits
in particular, this avoids some redundant matches onty::ConstKind::Value
. Furthermore, these methods and will now properly check the type before extracting the value, which fixes some ICEs.The name
ty::Value
was chosen to be consistent withty::Expr
.Commit 1 should be non-functional and commit 2 adds the type check.
fixes #131102
supercedes #136130
r? @oli-obk
cc @FedericoBruzzone @BoxyUwU