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

Validate before interning #122432

Closed
wants to merge 10 commits into from

Conversation

oli-obk
Copy link
Contributor

@oli-obk oli-obk commented Mar 13, 2024

based on #122397

fixes #122398

r? @RalfJung

There are more cleanups that can be done afterwards, but I think they may be unnecessary to make this PR useful on its own

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Mar 13, 2024
@rustbot
Copy link
Collaborator

rustbot commented Mar 13, 2024

Some changes occurred to the CTFE / Miri engine

cc @rust-lang/miri

The Miri subtree was changed

cc @rust-lang/miri

Comment on lines 1049 to 1059
{
for (_, prov) in alloc.provenance().ptrs().iter() {
if let AllocKind::Dead = self.get_alloc_info(prov.alloc_id()).2 {
throw_validation_failure!(
path,
DanglingPtrUseAfterFree { ptr_kind: PointerKind::Ref(Mutability::Not) }
)
}
}
}
Ok(())
Copy link
Contributor Author

Choose a reason for hiding this comment

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

There are more improvements to do here (like check unions) to get better paths, but that's harder

@rust-log-analyzer

This comment has been minimized.

@bors
Copy link
Contributor

bors commented Mar 14, 2024

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

};
// We always intern with `inner_mutability`, and furthermore we ensured above that if
// that is "immutable", then there are *no* mutable pointers anywhere in the newly
// interned memory -- justifying that we can indeed intern immutably. However this also
Copy link
Member

@RalfJung RalfJung Mar 18, 2024

Choose a reason for hiding this comment

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

Hm, we're not really ensuring this any more, are we?

Copy link
Member

Choose a reason for hiding this comment

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

That check is now done by intern_const_alloc_recursive. And that function has to re-compute inner_mutability just for that purpose.

Maybe patch_mutability_of_allocs should still do the check, but just return whether there was a problem or not, then we run validation, and then if validation didn't error and there was a problem during patch_mutability_of_allocs, then we show the other error? Thinking about it, if we do that we can probably still do interning before validation... 🙈

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yea, there were more follow-up cleanups to do, but I didn't want to change too much in one go

Copy link
Member

Choose a reason for hiding this comment

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

If we follow the strategy of "do interning first, record if there was an error, but delay reporting that until after validation" -- that requires way fewer changes than this PR, doesn't it?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'll try it out, I should have noted down what I thought I could improve/clean up if we did this

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oh I remember now: we can make interning completely infallible by moving the CONST_EVAL_MUTABLE_PTR_IN_FINAL_VALUE into validation

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok, I implemented this in #122684

I think we should still go with this PR, as it allows making individual things simpler, even if it means validation needs to handle allocations that haven't been interned yet. Most of the time that should be resolveable by using general interpreter methods instead of using dedicated global_alloc code paths

Copy link
Member

@RalfJung RalfJung Mar 18, 2024

Choose a reason for hiding this comment

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

Oh I remember now: we can make interning completely infallible by moving the CONST_EVAL_MUTABLE_PTR_IN_FINAL_VALUE into validation

I don't think that works. Validation is inherently a type-based traversal, so data stored in unions (or padding) is completely ignored. (And that's arguably by design.) However we need to check all pointers to ensure none of them are mutable, including those stored in unions (and padding).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I changed that in this PR. After a place has been validated, we also do some checks on all relocations of that place

Copy link
Member

Choose a reason for hiding this comment

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

Hm, to me that doesn't fit with the intention of validation as a type-driven traversal... I'll have to think about this.

tests/ui/consts/dangling-alloc-id-ice.stderr Show resolved Hide resolved
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
= note: the raw bytes of the constant (size: 8, align: 8) {
╾ALLOC0<imm>╼ │ ╾──────╼
Copy link
Member

Choose a reason for hiding this comment

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

You probably want to add the usual HEX_DUMP normalization rules to avoid having to make this stderr file per-bitwidth.

@oli-obk
Copy link
Contributor Author

oli-obk commented Mar 18, 2024

@bors try @rust-timer queue

@rust-timer

This comment has been minimized.

@rustbot rustbot added the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Mar 18, 2024
@bors
Copy link
Contributor

bors commented Mar 18, 2024

⌛ Trying commit c99636f with merge abaca54...

bors added a commit to rust-lang-ci/rust that referenced this pull request Mar 18, 2024
…=<try>

Validate before interning

based on rust-lang#122397

fixes rust-lang#122398

r? `@RalfJung`

There are more cleanups that can be done afterwards, but I think they may be unnecessary to make this PR useful on its own
@rust-log-analyzer

This comment has been minimized.

@bors
Copy link
Contributor

bors commented Mar 18, 2024

☀️ Try build successful - checks-actions
Build commit: abaca54 (abaca5464bf7ed3697dd7e8b56e7d4c4793c11b3)

@rust-timer

This comment has been minimized.

const BAR: Union = { //~ ERROR it is undefined behavior
let x = 42;
Union { ptr: &x }
};
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Before this PR we had no tests actually excercising this code path

@rust-timer
Copy link
Collaborator

Finished benchmarking commit (abaca54): comparison URL.

Overall result: ❌ regressions - 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.

Next Steps: If you can justify the regressions found in this try perf run, please indicate this with @rustbot label: +perf-regression-triaged along with sufficient written justification. If you cannot justify the regressions please fix the regressions and do another perf run. If the next run shows neutral or positive results, the label will be automatically removed.

@bors rollup=never
@rustbot label: -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.

mean range count
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
1.5% [1.2%, 1.8%] 6
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
-0.4% [-0.4%, -0.4%] 1
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.

mean range count
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
3.9% [3.9%, 3.9%] 1
Improvements ✅
(primary)
-2.2% [-2.3%, -2.0%] 3
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) -2.2% [-2.3%, -2.0%] 3

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.

mean range count
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
- - 0
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
-2.2% [-2.2%, -2.1%] 3
All ❌✅ (primary) - - 0

Binary size

This benchmark run did not return any relevant results for this metric.

Bootstrap: 668.532s -> 668.042s (-0.07%)
Artifact size: 312.74 MiB -> 312.80 MiB (0.02%)

@rustbot rustbot added perf-regression Performance regression. and removed S-waiting-on-perf Status: Waiting on a perf run to be completed. labels Mar 18, 2024
@RalfJung
Copy link
Member

So, to me the alternative at #122684 seems conceptually simpler. What are the benefits of the approach in this PR?

@oli-obk
Copy link
Contributor Author

oli-obk commented Mar 19, 2024

What are the benefits of the approach in this PR?

you get a path to where things are wrong, even if they are in padding or unions.

And it does some separation of concerns, giving us simpler code for the mutability changes and the actual interning, instead of doing both at the same time.

@RalfJung
Copy link
Member

RalfJung commented Mar 19, 2024

you get a path to where things are wrong, even if they are in padding or unions.

How is that tied to having the separate "patch allocation mutability" pass? It seems to me that the exact same code you wrote here would also achieve this for the other PR.

(Over in that PR I am arguing maybe we want the interner to handle those errors, but that's a separate discussion from whether validation happens before or after interning. My only concern for these errors in the interner is having extra complexity in the validator which doesn't ever do anything visible without miri-unleashed.)

And it does some separation of concerns, giving us simpler code for the mutability changes and the actual interning, instead of doing both at the same time.

I would say it splits what feels like a single job into two. There's even some code duplication between the alloc-mutbl-patch pass and the interner.

@oli-obk
Copy link
Contributor Author

oli-obk commented Mar 19, 2024

My next step was to get rid of found_bad_mutable_pointer and instead make that check part of validation, so we also get paths for it. At that point interning is just a loop over all allocations to intern them.

I guess we'll have two of those loops then. Yea the benefits are not very large.

I'll move the latest commits from here over to the other PR then

@oli-obk oli-obk closed this Mar 19, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
perf-regression Performance regression. S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. 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.

const-eval: perform validation before interning
6 participants