Skip to content

Overhaul ensure_ok#153383

Open
nnethercote wants to merge 3 commits intorust-lang:mainfrom
nnethercote:overhaul-ensure_ok
Open

Overhaul ensure_ok#153383
nnethercote wants to merge 3 commits intorust-lang:mainfrom
nnethercote:overhaul-ensure_ok

Conversation

@nnethercote
Copy link
Contributor

The interaction of ensure_ok and the return_result_from_ensure_ok query modifier is weird and hacky. This PR cleans it up. Details in the individual commits.

r? @Zalathar

`query_get_at`, `query_ensure`, and `query_ensure_error_guarantee` are
very similar functions, but they all use different control flow styles
which obscures the similarities. This commit rewrites them to all use
a `match`.
Two places where `ensure_ok` can be used but currently isn't. (These
queries are marked with `return_result_from_ensure_ok`, which means that
`ensure_ok` returns `Result<(), ErrorGuaranteed>`.) This is potentially
a perf win, because `ensure_ok` query calls can be faster.
@rustbot
Copy link
Collaborator

rustbot commented Mar 4, 2026

Some changes occurred to MIR optimizations

cc @rust-lang/wg-mir-opt

Some changes occurred to the CTFE machinery

cc @RalfJung, @oli-obk, @lcnr

Some changes occurred to constck

cc @fee1-dead

@rustbot rustbot added A-query-system Area: The rustc query system (https://rustc-dev-guide.rust-lang.org/query.html) 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. T-rustdoc Relevant to the rustdoc team, which will review and decide on the PR/issue. labels Mar 4, 2026
@rustbot
Copy link
Collaborator

rustbot commented Mar 4, 2026

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

Comment on lines +479 to +488
$(#[$attr])*
#[inline(always)]
pub fn $name(self, key: query_helper_param_ty!($($K)*)) {
crate::query::inner::query_ensure_ok_or_done(
self.tcx,
&self.tcx.query_system.query_vtables.$name,
$crate::query::IntoQueryParam::into_query_param(key),
$crate::query::EnsureMode::Ok,
)
}
Copy link
Member

Choose a reason for hiding this comment

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

Question: Would it make sense to forbid ensure_ok calls for queries that return Result<_, ErrorGuaranteed>?

(By gating this method with #[cfg(not($returns_error_guaranteed))].)

I haven't fully considered the consequences, but intuitively it feels like a footgun to allow such calls.

Copy link
Contributor Author

@nnethercote nnethercote Mar 4, 2026

Choose a reason for hiding this comment

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

I tried this before filing the PR and had problems here. Currently that forces tcx.foo() being supported for every query. It's possible this might be adjusted away, but it felt like a bridge too far for this PR.

Copy link
Member

Choose a reason for hiding this comment

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

To clarify, I meant forbidding tcx.ensure_ok().$query(..), not tcx.$query(..).

But it turns out that I was planning to get rid of call_query_method_fn anyway:

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sorry I misread. Back to the original question: I tried forbidding it like you suggested. There are two places it causes problems. A line in compiler/rustc_interface/src/passes.rs:

tcx.ensure_ok().mir_borrowck(def_id);

and a line in src/librustdoc/core.rs:

tcx.sess.time("wf_checking", || tcx.ensure_ok().check_type_wf(()));

Both of these queries return Result<_, ErrorGuaranteed> but neither was marked with return_result_from_ensure_ok. They could be changed to use ensure_result() (which requires a let _ = ...) but I don't think it's worthwhile. After all, every query that returns a value (i.e. most of them) can be called with ensure_ok, so it seems weird to ban ensure_ok just for the Result<_, ErrorGuaranteed> ones.

`ensure_ok` provides a special, more efficient way of calling a query
when its return value isn't needed. But there is a complication: if the
query is marked with the `return_result_from_ensure_ok` modifier, then
it will return `Result<(), ErrorGuaranteed`. This is clunky and feels
tacked on. It's annoying to have to add a modifier to a query to declare
information present in its return type, and it's confusing that queries
called via `ensure_ok` have different return types depending on the
modifier.

This commit:

- Eliminates the `return_result_from_ensure_ok` modifier. The proc macro
  now looks at the return type and detects if it matches `Result<_,
  ErrorGuarantee>`. If so, it adds the modifier
  `returns_result_with_error_guarantee`. (Aside: We need better
  terminology to distinguish modifiers written by the user in a `query`
  declaration (e.g. `cycle_delayed_bug`) from modifiers added by the
  proc macro (e.g. `cycle_error_handling`.))

- Introduces `ensure_result`, which replaces the use of `ensure_ok` for
  queries that return `Result<_, ErrorGuarantee>`. As a result,
  `ensure_ok` can now only be used for the "ignore the return value"
  case.
@nnethercote
Copy link
Contributor Author

@bors try @rust-timer queue

@rust-timer

This comment has been minimized.

@rust-bors

This comment has been minimized.

rust-bors bot pushed a commit that referenced this pull request Mar 4, 2026
@rustbot rustbot added the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Mar 4, 2026
@rust-bors
Copy link
Contributor

rust-bors bot commented Mar 4, 2026

☀️ Try build successful (CI)
Build commit: 61d1293 (61d12939576562cd1a24b416ffcb69ce1ef6562e, parent: d933cf483edf1605142ac6899ff32536c0ad8b22)

@rust-timer

This comment has been minimized.

if try_get_cached(tcx, &query.cache, &key).is_none() {
(query.execute_query_fn)(tcx, DUMMY_SP, key, QueryMode::Ensure { ensure_mode });
match try_get_cached(tcx, &query.cache, &key) {
Some(_value) => {}
Copy link
Contributor

Choose a reason for hiding this comment

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

I suspect this is going to be reverted next time anyone runs clippy on the compiler.

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 tried clippy on a test program with the same structure and it didn't complain.

@rust-timer
Copy link
Collaborator

Finished benchmarking commit (61d1293): comparison URL.

Overall result: ✅ improvements - no action needed

Benchmarking this pull request means it may be perf-sensitive – we'll automatically label it not fit for rolling up. You can override this, but we strongly advise not to, due to possible changes in compiler perf.

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

Instruction count

Our most reliable metric. Used to determine the overall result above. However, even this metric can be noisy.

mean range count
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
- - 0
Improvements ✅
(primary)
-0.1% [-0.1%, -0.1%] 1
Improvements ✅
(secondary)
-0.2% [-0.2%, -0.1%] 3
All ❌✅ (primary) -0.1% [-0.1%, -0.1%] 1

Max RSS (memory usage)

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

Cycles

Results (secondary -1.9%)

A less reliable metric. May be of interest, but not used to determine the overall result above.

mean range count
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
2.8% [1.3%, 4.7%] 3
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
-15.7% [-15.7%, -15.7%] 1
All ❌✅ (primary) - - 0

Binary size

Results (primary 0.1%, secondary 0.1%)

A less reliable metric. May be of interest, but not used to determine the overall result above.

mean range count
Regressions ❌
(primary)
0.1% [0.0%, 0.1%] 23
Regressions ❌
(secondary)
0.1% [0.0%, 0.1%] 46
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) 0.1% [0.0%, 0.1%] 23

Bootstrap: 481.183s -> 478.51s (-0.56%)
Artifact size: 394.90 MiB -> 395.01 MiB (0.03%)

@rustbot rustbot removed the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Mar 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-query-system Area: The rustc query system (https://rustc-dev-guide.rust-lang.org/query.html) 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. 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.

5 participants