Skip to content

Normalize before checking trivial bounds - #159118

Open
sjwang05 wants to merge 1 commit into
rust-lang:mainfrom
sjwang05:issue-154145
Open

Normalize before checking trivial bounds#159118
sjwang05 wants to merge 1 commit into
rust-lang:mainfrom
sjwang05:issue-154145

Conversation

@sjwang05

@sjwang05 sjwang05 commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

View all comments

Based on #140313
zulip discussion: #t-types > working on issue #154145

Currently, if a trivial bound is placed on an assoc type, and the type contains generics, check_false_global_bounds improperly tries to prove the predicate globally, since normalization, which would reveal the generics, happens only after the is_global() check. This PR moves normalization occur before the globality check. Additionally, we skip only the outermost HRTB with pred.kind().bound_vars().is_empty() rather than checking !pred.has_type_flags(TypeFlags::HAS_BINDER_VARS).

As a consequence of normalizing, this PR emits errors for code like this, which currently compiles:

fn foo<T>()
where
    T: Trait<Assoc = String>,
    <T as Trait>::Assoc: Copy,
{}

fixes #154145
fixes #140309

r? lcnr

@rustbot rustbot added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Jul 11, 2026
@rustbot rustbot added the T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. label Jul 11, 2026
@sjwang05

sjwang05 commented Jul 11, 2026

Copy link
Copy Markdown
Contributor Author

Seems like CI is failing because of this proc macro in salsa: https://github.com/salsa-rs/salsa/blob/5e239195eee4e54440b84593396ec1c8ca37146c/components/salsa-macro-rules/src/setup_tracked_fn.rs#L495-L497
which expands to the trivial bound for<'trivial_bounds> salsa::plumbing::function::NoopEviction: salsa::plumbing::function::HasCapacity when lru isn't passed as one of the args to the macro, since NoopEviction doesn't impl HasCapacity, which happens here in rust-analyzer:

#[salsa::tracked(returns(as_deref))]

#[salsa::tracked(returns(deref))]

So I guess it's a hacky version of "trivial_bounds but for stable" to make set_lru_capacity uncallable when the lru's size isn't provided?

@rust-log-analyzer

This comment has been minimized.

@lcnr

lcnr commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Additionally, rather than skipping HRTBs with !pred.has_type_flags(TypeFlags::HAS_BINDER_VARS), we instead call enter_forall so we can properly instantiate and deal with them.

I think not checking trivial bounds if they are higher ranked where-clauses is intended. We want to give users a way to opt-out of this check and this is something that users rely on.

I want us to continue to ignore for<'a> SomeType: Bound where-bounds, but to start checking Wrapper<for<'a> fn(&' ())>: Bound where-bounds.

@sjwang05

Copy link
Copy Markdown
Contributor Author

Ah got it, I looked through #48214 and couldn't find much discussion as to whether this should be allowed or not, so thanks for clarifying. I updated the tests and changed it back to bound_vars().is_empty().

@rust-log-analyzer

This comment has been minimized.

@rustbot

rustbot commented Jul 15, 2026

Copy link
Copy Markdown
Collaborator

This PR modifies tests/ui/issues/. If this PR is adding new tests to tests/ui/issues/,
please refrain from doing so, and instead add it to more descriptive subdirectories.

@rustbot rustbot added the WG-trait-system-refactor The Rustc Trait System Refactor Initiative (-Znext-solver) label Jul 15, 2026
@rustbot

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rustbot

rustbot commented Jul 15, 2026

Copy link
Copy Markdown
Collaborator

This PR changes a file inside tests/crashes. If a crash was fixed, please move into the corresponding ui subdir and add 'Fixes #' to the PR description to autoclose the issue upon merge.

@rust-log-analyzer

This comment has been minimized.

@rust-bors

This comment has been minimized.

@rustbot

rustbot commented Jul 15, 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.

@lcnr

lcnr commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

@bors try @rust-timer queue

let's do a crater run 😁

@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 Jul 21, 2026
@rust-bors

This comment has been minimized.

rust-bors Bot pushed a commit that referenced this pull request Jul 21, 2026
Normalize before checking trivial bounds
@rust-bors

rust-bors Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

☀️ Try build successful (CI)
Build commit: ac56ae8 (ac56ae821c3737dd227af5395216be69b814e0ca)
Base parent: 5a8cd23 (5a8cd237d4fad99d862aed51fab8cb5345c97013)

@rust-timer

This comment has been minimized.

@rust-timer

Copy link
Copy Markdown
Collaborator

Finished benchmarking commit (ac56ae8): comparison URL.

Overall result: ❌ regressions - please read:

Benchmarking means the PR may be perf-sensitive. It's automatically marked not fit for rolling up. Overriding is possible but disadvised: it risks changing compiler perf.

Next, please: If you can, justify the regressions found in this try perf run in writing along with @rustbot label: +perf-regression-triaged. If not, fix the regressions and do another perf run. Neutral or positive results will clear the label automatically.

@bors rollup=never rustc-perf
@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.3% [0.2%, 0.4%] 7
Regressions ❌
(secondary)
0.9% [0.6%, 1.4%] 6
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) 0.3% [0.2%, 0.4%] 7

Max RSS (memory usage)

Results (secondary 4.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)
4.9% [3.7%, 6.1%] 2
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) - - 0

Cycles

Results (primary 2.3%)

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

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

Binary size

This perf run didn't have relevant results for this metric.

Bootstrap: 487.476s -> 490.061s (0.53%)
Artifact size: 387.96 MiB -> 387.92 MiB (-0.01%)

@rustbot rustbot added perf-regression Performance regression. and removed S-waiting-on-perf Status: Waiting on a perf run to be completed. labels Jul 21, 2026
@rust-bors

rust-bors Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

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

@lcnr

lcnr commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

@craterbot check

@craterbot

Copy link
Copy Markdown
Collaborator

👌 Experiment pr-159118 created and queued.
🤖 Automatically detected try build ac56ae8
🔍 You can check out the queue and this experiment's details.

ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more

@craterbot craterbot added S-waiting-on-crater Status: Waiting on a crater run to be completed. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jul 29, 2026
@craterbot

Copy link
Copy Markdown
Collaborator

🚧 Experiment pr-159118 is now running

ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more

@craterbot

Copy link
Copy Markdown
Collaborator

🎉 Experiment pr-159118 is completed!
📊 191 regressed and 0 fixed (1053871 total)
📊 5991 spurious results on the retry-regressed-list.txt, consider a retry1 if this is a significant amount.
📰 Open the summary report.

⚠️ If you notice any spurious failure please add them to the denylist!
ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more

Footnotes

  1. re-run the experiment with crates=https://crater-reports.s3.amazonaws.com/pr-159118/retry-regressed-list.txt

@craterbot craterbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-crater Status: Waiting on a crater run to be completed. labels Aug 13, 2026
@sjwang05

Copy link
Copy Markdown
Contributor Author

So of the dependency tree roots that caused other crates to transitively fail:

  • alloy-rpc-client didn't compile from 0.1.1 through 0.9.2, but 1.0.0 onward through current compiles. This was the cause of 181 of the failures. There are also a few forks of pre-1.0.0 code that fail to compile.
  • beet_core failed to compile in 0.0.6 and fixed in 0.0.7, current is also fine
  • bevy_flurx stopped compiling in 0.12.0, 0.13.0 up through current is fine.

wyre-0.2.16 seems to be spurious, since cargo failed to resolve its bytes dependency.

Of the ones whose latest still don't compile:

  • wgsl_linker and wgsl-analyzer both need just a #[derive(Default)] on one struct, since its trivial bound currently comes from a parser generator, and both those structs are empty
  • overflowing_int needs a for<'trivial>-esque binder on 4 bounds
  • mzPeak and advent-utils need a similar binder on one bound each

For the last three crates, the bounds were false and the functions were never callable in the first place, so adding the higher-ranked binder preserves existing behavior while letting them compile again, which I verified using the branch's stage1.

fn ice()
where
(for<'b> fn(&'b ())): Trait
//~^ ERROR the trait bound `for<'b> fn(&'b ()): Trait` is not satisfied

@lcnr lcnr Aug 25, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

please instead add feature(trivial_bounds) and keep this as check-pass. Otherwise this test doesn't test what it's intended to anymore

View changes since the review

@lcnr lcnr left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

similar to the one review, if there are any test which test the behavior on compilation success, please try to instead keep them as check-pass by enabling feature(trivial_bounds)

View changes since this review

Comment on lines +2316 to +2317
let pred = self.deeply_normalize(span, None, Unnormalized::new_wip(pred));
if pred.is_global() && pred.kind().bound_vars().is_empty() {

@lcnr lcnr Aug 25, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

one option would be to only check pred.is_is_global() && normalize_pred && normalized_pred.is_global() which would allow <T as Normalize>::WillBeUsize: Trait to keep compiling.

Doing this would minimize the breakage and perf impact.

One other option would be to change this function to not be on the wf-check but instead use a separate ObligationCtxt at which point we should then be able to emit the trait errors as future compat warnings instead.

Thinking about this, I generally feel kind of :/ about breaking anything here. I feel like trivial bounds should be a deny-by-default lint and we should just stabilize feature(trivial_bounds) 🤔

not sure what to ask/expect of you here. Would you be interested in looking into the existing trivial_bounds tracking issue and related work/discussions to try and summarize what is blocking there currently?

View changes since the review

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. WG-trait-system-refactor The Rustc Trait System Refactor Initiative (-Znext-solver)

Projects

None yet

6 participants