-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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 normalizing in different ParamEnv
s with the same InferCtxt
#124203
Conversation
@@ -78,11 +78,12 @@ pub struct ProjectionCacheStorage<'tcx> { | |||
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] | |||
pub struct ProjectionCacheKey<'tcx> { | |||
ty: ty::AliasTy<'tcx>, | |||
param_env: ty::ParamEnv<'tcx>, |
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.
won't that lead to tons of cache misses?
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.
Almost all code that isn't the AutoTraitFinder
will always use the same ParamEnv
for a single InferCtxt
, so I don't expect there to be many cache misses if any at all. But maybe start a perf run just to confirm? (I don't have permission)
@bors try @rust-timer queue |
This comment has been minimized.
This comment has been minimized.
…=<try> fix normalizing in different `ParamEnv`s with the same `InferCtxt` This PR changes the key of the projection cache from just `AliasTy` to `(AliasTy, ParamEnv)` to allow normalizing in different `ParamEnv`s without resetting caches. Previously, normalizing the same alias in different param envs would always reuse the cached result from the first normalization, which is incorrect if the projection clauses in the param env have changed. Fixing this bug allows us to get rid of `InferCtxt::clear_caches`, which was only used by the `AutoTraitFinder`, because it requires normalizing in different param envs. r? `@fmease`
☀️ Try build successful - checks-actions |
This comment has been minimized.
This comment has been minimized.
I thought I tried this before and the perf regression was really bad 🤔 |
Finished benchmarking commit (ceb60ad): comparison URL. Overall result: ✅ improvements - no action neededBenchmarking 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 Instruction countThis is a highly reliable metric that was used to determine the overall result at the top of this comment.
Max RSS (memory usage)ResultsThis 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.
CyclesResultsThis 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.
Binary sizeThis benchmark run did not return any relevant results for this metric. Bootstrap: 672.886s -> 671.734s (-0.17%) |
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.
Awesome. Glad to see this leads to a doc perf win, too.
@bors r+ |
…=compiler-errors fix normalizing in different `ParamEnv`s with the same `InferCtxt` This PR changes the key of the projection cache from just `AliasTy` to `(AliasTy, ParamEnv)` to allow normalizing in different `ParamEnv`s without resetting caches. Previously, normalizing the same alias in different param envs would always reuse the cached result from the first normalization, which is incorrect if the projection clauses in the param env have changed. Fixing this bug allows us to get rid of `InferCtxt::clear_caches`, which was only used by the `AutoTraitFinder`, because it requires normalizing in different param envs. r? `@fmease`
This comment has been minimized.
This comment has been minimized.
💔 Test failed - checks-actions |
Here's a minimal-ish example: use std::future::Future;
struct Size<T>(T);
trait Foo {
fn foo<K, V>() -> impl Future<Output = Size<impl Sized>> {
async {
Size(())
}
}
}
fn main() {} We can no longer rely on the RPITIT -> opaque tys having been stashed in the projection cache, so we need to use the |
It's actually the opposite happening here:
When normalizing the obligation in the rust/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs Lines 2038 to 2046 in fecb7b4
This makes me think that maybe we shouldn't normalize the RPITITs in default method implementations at all, because AFAICT there is not additional type information to be gained. Because it's impossible for a default method to specify a return type that's more concrete than the RPITIT that it's defining. |
I'm not certain what you mean -- RPITITs can specify default method bodies that constrain the opaque: trait RPITIT {
fn test() -> impl Sized { 0 }
} |
Oh, do you mean just in |
Yeah but type checking will only see Opposed to this, wich actually knows the concrete type for trait RPITIT {
fn test() -> impl Sized;
}
impl RPITIT for i32 {
fn test() -> i32 { 0 }
}
Yes, exactly. |
Alright, I found the actual problem. It was a missing |
Oh that's incredibly embarrassing but also i'm unsurprised that normalization usually hides this from being an issue. Thanks for looking into this. @bors r+ |
☀️ Test successful - checks-actions |
Finished benchmarking commit (1b3fba0): comparison URL. Overall result: ❌✅ regressions and improvements - ACTION NEEDEDNext Steps: If you can justify the regressions found in this perf run, please indicate this with @rustbot label: +perf-regression Instruction countThis is a highly reliable metric that was used to determine the overall result at the top of this comment.
Max RSS (memory usage)ResultsThis 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.
CyclesResultsThis 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.
Binary sizeThis benchmark run did not return any relevant results for this metric. Bootstrap: 669.682s -> 674.072s (0.66%) |
The regression is likely noise, it went back down in the following merge: #124241 (comment) / #124241 (comment). @rustbot label perf-regression-triaged |
This PR changes the key of the projection cache from just
AliasTy
to(AliasTy, ParamEnv)
to allow normalizing in differentParamEnv
s without resetting caches. Previously, normalizing the same alias in different param envs would always reuse the cached result from the first normalization, which is incorrect if the projection clauses in the param env have changed.Fixing this bug allows us to get rid of
InferCtxt::clear_caches
, which was only used by theAutoTraitFinder
, because it requires normalizing in different param envs.r? @fmease