Skip to content

refactor(mir-transform): Merge can_be_overridden, is_required and is_enabled into one - #160015

Open
clubby789 wants to merge 2 commits into
rust-lang:mainfrom
clubby789:merge-required-suppressed
Open

refactor(mir-transform): Merge can_be_overridden, is_required and is_enabled into one#160015
clubby789 wants to merge 2 commits into
rust-lang:mainfrom
clubby789:merge-required-suppressed

Conversation

@clubby789

@clubby789 clubby789 commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

View all comments

#128657 and #134082 both merged at similar times, and added two similar flags to the MirPass trait

  • can_be_overridden: Controls if -Zmir-enable-passes can enable/disable a pass; only set to false for ForceInline
  • is_required: Controls if #[optimize(none)] should suppress a pass; set to explicitly true/false across all passes based on which appeared to be unconditionally enabled at the time
This adds some redundancy, so this PR merges both into `can_be_overridden`: - removes cases of `is_required(&self) -> bool { true }` - replaces `is_required(&self) -> bool { false }` with `can_be_overridden(&self) -> bool { true }`

Also, previously, -Zmir-enable-passes took precedence, but now #[optimize(none)] does, as the latter is more local.

This merges both functions as well as is_enabled into a single PassPolicy enum

r? @RalfJung

@rustbot

rustbot commented Jul 27, 2026

Copy link
Copy Markdown
Collaborator

Some changes occurred to MIR optimizations

cc @rust-lang/wg-mir-opt

Some changes occurred in coverage instrumentation.

cc @Zalathar

@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 Jul 27, 2026
@rustbot

rustbot commented Jul 27, 2026

Copy link
Copy Markdown
Collaborator

RalfJung is not on the review rotation at the moment.
They may take a while to respond.

@RalfJung

RalfJung commented Jul 27, 2026

Copy link
Copy Markdown
Member

Thanks for helping with the cleanup!

This adds some redundancy, so this PR merges both into can_be_overridden:

The two have slightly different semantics though, don't they?
For instance, CheckAlignment is a pass that can be turned off by -Zmir-enable-passes=-CheckAlignment, but that probably should not be turned off by #[optimize(none)].

So I think we need a 3-variant enum here: passes that are actually required (as they implement parts of the MIR semantics), passes that are optional but not "optimizations", and passes that are truly just optimizations. An actually required pass should have an is_enabled of true (which is the default but that's a bad default so we should change it, though that can be a future PR). Every pass marked as truly required should have a comment why it is required so this becomes easier to audit.

That still spreads the logic across both is_enabled and this 3-vairant classification so maybe this should be unified further into a single function to avoid the redundancy.

@RalfJung

RalfJung commented Jul 27, 2026

Copy link
Copy Markdown
Member

Every pass marked as truly required should have a comment why it is required so this becomes easier to audit.

FWIW I had started doing this until I realized that is_required does not actually mean "is required", it means "optional pass controlled by is_enabled that should be enabled even under #[optimize(none)]". But some of the comments I added could be useful. See b537849.

@rust-log-analyzer

This comment has been minimized.

@RalfJung

RalfJung commented Jul 27, 2026

Copy link
Copy Markdown
Member

That still spreads the logic across both is_enabled and this 3-vairant classification so maybe this should be unified further into a single function to avoid the redundancy.

Thinking a bit more about this... one way we could represent this is with an enum like this:

enum PassEnabled {
  /// This pass implements a mandatory lowering step, either to implement parts of the MIR semantics
  /// or to bring MIR into a shape that is easier to deal with for later passes / codegen.
  /// Passes using this cannot be disable via any means. They must not remove any UB.
  Required,
  /// This pass is optional, it can be controlled via `-Zmir-enable-passes`.
  Optional {
    /// Whether the pass should be enabled in this compilation session by default,
    /// i.e., before applying `-Zmir-enable-passes` or `#[optimize(...)]`.
    default_enabled: bool,
    /// Whether this is an optimization pass. Only optimization passes are disabled by
    /// `#[optimize(none)]`. A pass can be optional without being an optimization pass,
    /// e.g. if it just adds extra debug checks that one can anyway also turn off.
    optimization: bool,
  }
}

One could then have a few convenient constructors for the typical cases to make this less verbose.

What I am missing in this proposal is a way to explicitly mark an optimization as "I promise not to remove UB". Maybe that should also be a field on PassEnabled::Optional?
Writing this up makes me wonder why we even distinguish between -Zmir-opt-level=0 and -Zmir-preserve-ub. Can't we just define opt-level 0 to be the "UB-preserving level"? There is anyway no way to get that level on stable, even debug builds default to mir-opt-level 1. -Zmir-preserve-ub currently does two things: it disables the RemovePlaceMention pass, and it changes the behavior of CfgSimplifier. It seems that makes CfgSimplifier a pass that may or may not remove UB depending on configuration, but we could deal with that by having the field be specified as follows:

/// If this is `true`, then the pass promises that *if `mir_opt_level() == 0`*, it will not remove any UB.
/// Passes that set this to `false` automatically get disabled at MIR optimization level 0.
preserves_ub: bool,

Cc @saethlin @davidtwco @fee1-dead

@clubby789
clubby789 force-pushed the merge-required-suppressed branch from 7099c7f to 5a391ab Compare July 27, 2026 17:45
@clubby789

clubby789 commented Jul 27, 2026

Copy link
Copy Markdown
Contributor Author

I wrote up an approach revolving around the below enum, with is_enabled being removed and folded into enabled_by_default.
Folding Optimization/Optional into one may make sense, especially if we're adding a preserves_ub flag.

EDIT: Folded together

/// Rules outlining when this pass may be overridden or suppressed.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub(crate) enum PassPolicy {
    /// Part of MIR semantics and must run, even in Miri.
    /// Such passes must therefore never remove UB, and should come with a comment justifying
    /// why they must always run.
    Required,
    /// Not an optimization, but may be configured by `-Zmir-enable-passes`.
    Optional {
        /// Whether this pass should be enabled by default in this session in the absence of
        /// an explicit `-Zmir-enable-passes`.
        enabled_by_default: bool,
    },
    /// An optimization pass, which may also be suppressed by `#[optimize(none)]`.
    Optimization {
        /// Whether this pass should be enabled by default in this session in the absence of
        /// an explicit `-Zmir-enable-passes` or `#[optimize]` attribute.
        enabled_by_default: bool,
    },
}

@clubby789
clubby789 force-pushed the merge-required-suppressed branch from 5a391ab to a94264c Compare July 27, 2026 18:03
@clubby789 clubby789 changed the title refactor(mir-transform): Merge can_be_overridden and is_required refactor(mir-transform): Merge can_be_overridden, is_required and is_enabled into one Jul 27, 2026
@rust-log-analyzer

This comment has been minimized.

@RalfJung

RalfJung commented Jul 27, 2026 via email

Copy link
Copy Markdown
Member

@clubby789
clubby789 force-pushed the merge-required-suppressed branch from a94264c to 61676eb Compare July 27, 2026 19:22

@RalfJung RalfJung left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This does not really help with ensuring that we don't run UB-removing passes in Miri... but that's fine, this PR does not have to solve all problems at once.

I haven't gone over every pass yet, here's a first round of comments.

View changes since this review

Comment thread compiler/rustc_mir_transform/src/coverage/mod.rs Outdated
Comment thread compiler/rustc_mir_transform/src/add_subtyping_projections.rs Outdated
Comment thread compiler/rustc_mir_transform/src/dataflow_const_prop.rs Outdated
Comment thread compiler/rustc_mir_transform/src/erase_deref_temps.rs Outdated
Comment thread compiler/rustc_mir_transform/src/pass_manager.rs Outdated
fn is_required(&self) -> bool {
self.1.is_required()
fn policy(&self, sess: &Session) -> PassPolicy {
self.1.policy(sess).and_enabled(sess.mir_opt_level() >= self.0 as usize)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This now invokes the underlying passes policy which previously was not the case. Does that change behavior anywhere we use WithMinOptLevel?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

AFAICT, the one place this does interact is that RemoveNoopLandingPads had an is_enabled of panic_strategy().unwinds() and is_required of true. Previously, this condition was ignored by the wrapper. Now it respects it

Comment thread compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs Outdated
Comment thread compiler/rustc_mir_transform/src/pass_manager.rs Outdated
@clubby789
clubby789 force-pushed the merge-required-suppressed branch from 2b080be to 225fe83 Compare July 28, 2026 17:18
JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request Jul 28, 2026
…alfJung

refactor(mir-transform): Calculate optimization status inside `run_passes_inner`

The `Optimizations` enum represents whether `#[optimize(none)]` has been applied to a function. Currently, `run_passes` takes an `Optimizations` which is confusing (rust-lang#160015 (comment)).
Calculate this in `run_passes_inner` instead (which also means `#[optimize(none)]` is applied more consistently.

r? @RalfJung
@rust-bors

This comment has been minimized.

rust-timer added a commit that referenced this pull request Jul 28, 2026
Rollup merge of #160057 - clubby789:local-optimizations, r=RalfJung

refactor(mir-transform): Calculate optimization status inside `run_passes_inner`

The `Optimizations` enum represents whether `#[optimize(none)]` has been applied to a function. Currently, `run_passes` takes an `Optimizations` which is confusing (#160015 (comment)).
Calculate this in `run_passes_inner` instead (which also means `#[optimize(none)]` is applied more consistently.

r? @RalfJung
pull Bot pushed a commit to LeeeeeeM/miri that referenced this pull request Jul 29, 2026
refactor(mir-transform): Calculate optimization status inside `run_passes_inner`

The `Optimizations` enum represents whether `#[optimize(none)]` has been applied to a function. Currently, `run_passes` takes an `Optimizations` which is confusing (rust-lang/rust#160015 (comment)).
Calculate this in `run_passes_inner` instead (which also means `#[optimize(none)]` is applied more consistently.

r? @RalfJung
Comment thread compiler/rustc_mir_transform/src/elaborate_box_derefs.rs
Comment thread compiler/rustc_mir_transform/src/check_enums.rs Outdated
@clubby789

This comment was marked as outdated.

@clubby789
clubby789 force-pushed the merge-required-suppressed branch from 225fe83 to 9472a44 Compare July 29, 2026 14:12
@RalfJung

Copy link
Copy Markdown
Member

CheckAlignment/CheckEnums/CheckNull (required=true, enabled=ub_checks() -> non_optimization(ub_checks()))

That's not a change?

@clubby789

Copy link
Copy Markdown
Contributor Author

Indeed, I think I confused myself with the naming... I will see if it's possible to split the policy changes into a second commit

@clubby789
clubby789 force-pushed the merge-required-suppressed branch 2 times, most recently from 8a2e5c8 to 750cb0d Compare July 29, 2026 17:24
@rustbot

rustbot commented Jul 29, 2026

Copy link
Copy Markdown
Collaborator

This PR was rebased onto a different main commit. Here's a range-diff highlighting what actually changed.

Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers.

@clubby789

Copy link
Copy Markdown
Contributor Author

Split into two commits, the first should be only refactoring and the second introduces changes to the policies and adding justifications from your commit

Comment thread compiler/rustc_mir_transform/src/pass_manager.rs Outdated

@RalfJung RalfJung left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Yes I like it. :) Just some comment nits.
@rustbot author

We probably want to further tweak optimize(none) behavior and maybe have a mir-opt level that disables all optional passes but that's further refactoring which does not have to happen in this PR.

View changes since this review

Comment thread compiler/rustc_mir_transform/src/prettify.rs Outdated
Comment thread compiler/rustc_mir_transform/src/add_subtyping_projections.rs Outdated
Comment thread compiler/rustc_mir_transform/src/deref_separator.rs Outdated
Comment thread compiler/rustc_mir_transform/src/erase_deref_temps.rs Outdated
Comment thread compiler/rustc_mir_transform/src/lint_and_remove_uninhabited.rs
@rustbot rustbot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jul 30, 2026
@rustbot

rustbot commented Jul 30, 2026

Copy link
Copy Markdown
Collaborator

Reminder, once the PR becomes ready for a review, use @rustbot ready.

@clubby789
clubby789 force-pushed the merge-required-suppressed branch from 750cb0d to 6ec44cd Compare July 30, 2026 13:59
@RalfJung

Copy link
Copy Markdown
Member

r=me when CI is green. :)
@bors delegate+

@rust-bors

rust-bors Bot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

✌️ @clubby789, you can now approve this pull request!

If @RalfJung told you to "r=me" after making some further change, then please make that change and post @bors r=RalfJung.

View changes since this delegation.

@clubby789

Copy link
Copy Markdown
Contributor Author

I will probably investigate #160057 (comment) as a followup, but I think this is a good start to clarify and correct the policies for now.

@clubby789

Copy link
Copy Markdown
Contributor Author

@bors r=RalfJung

@rust-bors

rust-bors Bot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

📌 Commit 6ec44cd has been approved by RalfJung

It is now in the queue for this repository.

@rust-bors rust-bors Bot 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-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Jul 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

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.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants