Skip to content

More robustly deal with relaxed bounds and improve their diagnostics #142693

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

Open
wants to merge 8 commits into
base: master
Choose a base branch
from

Conversation

fmease
Copy link
Member

@fmease fmease commented Jun 18, 2025

Scaffolding for #135229 (CC #135331)

Fixes #136944.
Fixes #142718.

@rustbot rustbot added the T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. label Jun 18, 2025
@fmease fmease force-pushed the unbound-bettering branch from 8d31700 to 4634541 Compare June 18, 2025 20:27
@fmease fmease changed the title [WIP] unbound bettering (refactoring) [WIP] unbound bettering Jun 18, 2025
@fmease fmease force-pushed the unbound-bettering branch 2 times, most recently from 69e237d to 03d01fa Compare June 19, 2025 02:46
@fmease fmease added the rla-silenced Silences rust-log-analyzer postings to the PR it's added on. label Jun 19, 2025
@rust-lang rust-lang deleted a comment from rust-log-analyzer Jun 19, 2025
@rust-lang rust-lang deleted a comment from rust-log-analyzer Jun 19, 2025
@rust-lang rust-lang deleted a comment from rust-log-analyzer Jun 19, 2025
@fmease fmease force-pushed the unbound-bettering branch 3 times, most recently from 8a6f65d to 04dad4e Compare June 20, 2025 21:17
@fmease fmease changed the title [WIP] unbound bettering More robustly deal with relaxed bounds and improve their diagnostics Jun 20, 2025
@rust-lang rust-lang deleted a comment from rust-bors bot Jun 20, 2025
@fmease
Copy link
Member Author

fmease commented Jun 20, 2025

@bors2 try @rust-timer queue

@rust-timer

This comment has been minimized.

@rust-bors
Copy link

rust-bors bot commented Jun 20, 2025

⌛ Trying commit 04dad4e with merge bfa10de

To cancel the try build, run the command @bors2 try cancel.

rust-bors bot added a commit that referenced this pull request Jun 20, 2025
More robustly deal with relaxed bounds and improve their diagnostics

Scaffolding for #135229 (CC #135331)

Fixes #136944.
Fixes #142718.
@rustbot rustbot added the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Jun 20, 2025
@rust-bors
Copy link

rust-bors bot commented Jun 20, 2025

☀️ Try build successful (CI)
Build commit: bfa10de (bfa10de6407128926b18c60d51c9f19df73e336c, parent: 9c4ff566babe632af5e30281a822d1ae9972873b)

@rust-timer

This comment has been minimized.

@rust-timer
Copy link
Collaborator

Finished benchmarking commit (bfa10de): comparison URL.

Overall result: ❌ regressions - please read the text below

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.

Next Steps: If you can justify the regressions found in this try perf run, please do so in sufficient writing along with @rustbot label: +perf-regression-triaged. If not, please fix the regressions and do another perf run. If its results are neutral or positive, the label will be automatically removed.

@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)
3.0% [3.0%, 3.0%] 1
Regressions ❌
(secondary)
- - 0
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) 3.0% [3.0%, 3.0%] 1

Max RSS (memory usage)

Results (secondary -2.7%)

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.4% [2.4%, 2.4%] 1
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
-3.5% [-5.8%, -1.8%] 6
All ❌✅ (primary) - - 0

Cycles

Results (primary 2.9%, secondary 4.4%)

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

mean range count
Regressions ❌
(primary)
2.9% [2.9%, 2.9%] 1
Regressions ❌
(secondary)
4.4% [2.8%, 7.6%] 10
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) 2.9% [2.9%, 2.9%] 1

Binary size

Results (primary 1.1%)

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

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

Bootstrap: 692.606s -> 692.191s (-0.06%)
Artifact size: 372.01 MiB -> 371.99 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 Jun 21, 2025
@bors
Copy link
Collaborator

bors commented Jun 27, 2025

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

@bors bors added the S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. label Jun 27, 2025
@fmease
Copy link
Member Author

fmease commented Jun 27, 2025

#142693 (comment)

Looks spurious?

@rust-bors
Copy link

rust-bors bot commented Jun 28, 2025

⌛ Trying commit c74e11c with merge 6893bb5

To cancel the try build, run the command @bors2 try cancel.

rust-bors bot added a commit that referenced this pull request Jun 28, 2025
More robustly deal with relaxed bounds and improve their diagnostics

Scaffolding for #135229 (CC #135331)

Fixes #136944.
Fixes #142718.
@rustbot rustbot added the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Jun 28, 2025
@rust-bors
Copy link

rust-bors bot commented Jun 28, 2025

☀️ Try build successful (CI)
Build commit: 6893bb5 (6893bb554373e6438fbf77486be0a58c34e372d4, parent: 7ba34c704529e7fcab80130c3fe40efe415d61b5)

@rust-timer

This comment has been minimized.

@rust-timer
Copy link
Collaborator

Finished benchmarking commit (6893bb5): 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
Improvements ✅
(secondary)
-0.0% [-0.0%, -0.0%] 1
All ❌✅ (primary) - - 0

Max RSS (memory usage)

Results (secondary -3.5%)

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)
3.3% [3.3%, 3.3%] 1
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
-6.9% [-8.3%, -5.4%] 2
All ❌✅ (primary) - - 0

Cycles

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

Binary size

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

Bootstrap: 689.948s -> 690.572s (0.09%)
Artifact size: 371.76 MiB -> 371.78 MiB (0.01%)

@rustbot rustbot removed S-waiting-on-perf Status: Waiting on a perf run to be completed. perf-regression Performance regression. labels Jun 28, 2025
Copy link
Member Author

@fmease fmease Jun 28, 2025

Choose a reason for hiding this comment

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

Previously, we would pass "fake" trait bound modifiers (constness=never, polarity=positive) for object bounds to HIR ty lowering, now we pass the actual modifiers.

This ofc means the compiler output becomes more verbose for inputs like this but these new errors are perfectly reasonable.

Motivation: If we ever start supporting const bounds in dyn-Trait (not unlikely) then we will have proper validation already in place thanks to this change. Continuing to pass fake modifiers runs the risk that we forget to add the validation before stabilization in this hypothetical scenario (sadly we have a bad track record for this, cc relaxed bounds).

// later desugars into a trait predicate.
let bounds = self.lower_param_bounds(bounds, itctx);

// FIXME(#135229): These should be forbidden!
Copy link
Member Author

@fmease fmease Jun 28, 2025

Choose a reason for hiding this comment

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

My plan is to make this change in PR #135331 once this PR merges and ask for a types FCP over there.

span: Span,
rbp: RelaxedBoundPolicy<'_>,
) {
let err = |message| feature_err(&self.tcx.sess, sym::more_maybe_bounds, span, message);
Copy link
Member Author

@fmease fmease Jun 29, 2025

Choose a reason for hiding this comment

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

I'm not super fond of the fact that we currently advertise the internal feature more_maybe_bounds (it's a bit distracting, too). I'd rather get rid of the feature suggestion similar to the internal feature negative_bounds. LMKWYT

Comment on lines +2071 to +2076
if let Some(res) = self.resolver.get_partial_res(id).and_then(|r| r.full_res())
&& let Res::Def(DefKind::TyParam, def_id) = res
&& params.iter().any(|p| def_id == self.local_def_id(p.id).to_def_id())
{
return;
}
Copy link
Member Author

@fmease fmease Jun 29, 2025

Choose a reason for hiding this comment

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

The old approach in lower_generics cached the datum of whether the bounded ty was a "good ty param" which we no longer do.

However if you think about it, the caching on master doesn't make any sense in practice for real user-written code: It did avoid recomputation in where T: ?Sized + ?Sized + ?Sized (nobody writes multiple relaxed bounds since they're later rejected during HIR ty lowering) but it didn't avoid the recalculation in where T: ?Sized, U: ?Sized, V: ?Sized which is what users actually write (to be clear, the new code also recomputes this, it just throws out the unnecessary caching logic).

diag.emit();
return;
}
RelaxedBoundForbiddenReason::LateBoundVarsInScope => {}
Copy link
Member Author

Choose a reason for hiding this comment

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

We could emit a custom diagnostic for this but it's simply not worth it.

err("`?Trait` bounds are only permitted at the point where a type parameter is declared")
err("this relaxed bound is not permitted here")
.with_note(
"in this context, relaxed bounds are only allowed on \
Copy link
Member Author

Choose a reason for hiding this comment

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

"in this context" because in other contexts like in assoc tys, relaxed bounds are also allowed in other places (in that case: assoc ty item bounds).

}
rustc_ast::BoundPolarity::Positive => (ty::PredicatePolarity::Positive, bounds),
rustc_ast::BoundPolarity::Negative(_) => (ty::PredicatePolarity::Negative, bounds),
// FIXME(fmease): This is super hacky! `Option<Polarity>` is also sad.

This comment was marked as outdated.

@fmease
Copy link
Member Author

fmease commented Jun 29, 2025

r? compiler-errors or reassign if you're busy or not interested

@fmease fmease marked this pull request as ready for review June 29, 2025 00:23
@rustbot rustbot added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Jun 29, 2025
@fmease

This comment was marked as resolved.

@fmease fmease removed the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Jun 29, 2025
fmease added 8 commits June 29, 2025 04:31
Only relevant to the internal feature `more_maybe_bounds`.
We no longer move trait predicates where the self ty is a ty param to
"the bounds of a ty param".
* The phrasing "only does something for" made sense back when this
  diagnostic was a (hard) warning. Now however, it's simply a hard
  error and thus completely rules out "doing something".
* The primary message was way too long
* The new wording more closely mirrors the wording we use for applying
  other bound modifiers (like `const` and `async`) to incompatible
  traits.
* "all other traits are not bound by default" is no longer accurate
  under Sized Hierarchy. E.g., traits and assoc tys are (currently)
  bounded by `MetaSized` by default but can't be relaxed using
  `?MetaSized` (instead, you relax it by adding `PointeeSized`).
* I've decided against adding any diagnositic notes or suggestions
  for now like "trait `Trait` can't be relaxed as it's not bound by
  default" which would be incorrect for `MetaSized` and assoc tys
  as mentioned above) or "consider changing `?MetaSized` to
  `PointeeSized`" as the Sized Hierarchy impl is still WIP)
Having multiple relaxed bounds like `?Sized + ?Iterator` is actually *fine*.
We actually want to reject *duplicate* relaxed bounds like `?Sized + ?Sized`
because these most certainly represent a user error.

Note that this doesn't mean that we accept more code because a bound like
`?Iterator` is still invalid as it's not relaxing a *default* trait and
the only way to define / use more default bounds is under the experimental
and internal feature `more_maybe_bounds` plus `lang_items` plus unstable
flag `-Zexperimental-default-bounds`.

Ultimately, this simply *reframes* the diagnostic. The scope of
`more_maybe_bounds` / `-Zexperimental-default-bounds` remains unchanged
as well.
@fmease fmease force-pushed the unbound-bettering branch from c74e11c to 45a63cb Compare June 29, 2025 02:35
@fmease fmease removed the rla-silenced Silences rust-log-analyzer postings to the PR it's added on. label Jun 29, 2025
@@ -70,13 +69,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
let guar = self.report_trait_object_addition_traits(&regular_traits);
return Ty::new_error(tcx, guar);
}
// We don't support `PointeeSized` principals
Copy link
Member Author

@fmease fmease Jun 29, 2025

Choose a reason for hiding this comment

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

My PR predates #143104.

This commit basically reverts this logic because it's unreachable due to us filtering out PointeeSized inside lower_poly_trait_ref. The diagnostic is definitely worse, we now say at least one trait is required for an object type instead of `PointeeSized` cannot be used with trait objects.

Welp, I guess I should address the diagnostic regression (😩) since it only makes sense if you know the lowering… This kinda ties in with finding a better solution for #142693 (comment)

// reject relaxed bounds outright during AST lowering.
// However, this can easily get out of sync! Ideally, we would perform this step
// where we are guaranteed to catch *all* bounds like in
// `Self::lower_poly_trait_ref`. List of concrete issues:
Copy link
Member Author

Choose a reason for hiding this comment

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

(We likely can't actually do it in lower_poly_trait_ref because we need access to all the neighboring HIR bounds)

Comment on lines +2071 to +2073
if let Some(res) = self.resolver.get_partial_res(id).and_then(|r| r.full_res())
&& let Res::Def(DefKind::TyParam, def_id) = res
&& params.iter().any(|p| def_id == self.local_def_id(p.id).to_def_id())
Copy link
Member Author

@fmease fmease Jun 29, 2025

Choose a reason for hiding this comment

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

(If you're curious, we can't simply replace this with something that's based on rustc_middle::ty and located in HIR ty lowering while preserving stable behavior: We need it to be based on the HIR to reject cases like (T): ?Sized at which point AST lowering remains a good enough place)

@fmease fmease added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Jun 29, 2025
Comment on lines +786 to +788
rustc_ast::BoundPolarity::Maybe(_) => {
(ty::PredicatePolarity::Positive, &mut Vec::new())
}
Copy link
Member Author

@fmease fmease Jun 29, 2025

Choose a reason for hiding this comment

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

(repost of #142693 (comment) which is on an outdated diff)

I'm not happy about the way this is structured and the fact that we map Maybe to Positive, it's a hack. The non-sentinel approach of using Option<ty::PredicatePolarity> just yields very verbose and still ugly code.

Bigger picture: As you can see a few lines further down we used to duplicate the lower_assoc_item_constraint loop to catch bad bounds like ?Sized<Undefined = ()>. This is obv annoying and not scalable (e.g., for PointeeSized we also need to validate the bound constness which is a lot more code I don't want to dupe / extract into a method (hmmm...)). So the new approach is to do as much normal lowering for these "fake bounds" as possible but send everything into the drain (&mut Vec::new()).

Idk :|

@rust-log-analyzer
Copy link
Collaborator

The job aarch64-gnu-llvm-19-2 failed! Check out the build log: (web) (plain)

Click to see the possible cause of the failure (guessed by this bot)
---- /checkout/obj/build/aarch64-unknown-linux-gnu/test/error-index.md - Rust_Compiler_Error_Index::E0203 (line 3446) stdout ----
error: bound modifier `?` can only be applied to `Sized`
##[error] --> /checkout/obj/build/aarch64-unknown-linux-gnu/test/error-index.md:3447:24
  |
3 | struct Bad<T: ?Sized + ?Send>{
  |                        ^^^^^

error: aborting due to 1 previous error

Some expected error codes were not found: ["E0203"]

failures:
    /checkout/obj/build/aarch64-unknown-linux-gnu/test/error-index.md - Rust_Compiler_Error_Index::E0203 (line 3446)

test result: FAILED. 1047 passed; 1 failed; 64 ignored; 0 measured; 0 filtered out; finished in 22.68s

Command has failed. Rerun with -v to see more details.
Build completed unsuccessfully in 0:37:46
  local time: Sun Jun 29 03:24:09 UTC 2025
  network time: Sun, 29 Jun 2025 03:24:10 GMT
##[error]Process completed with exit code 1.
Post job cleanup.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
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.

Sized hierarchy: PointeeSized bounds aren't fully validated during HIR ty lowering Reword ?Trait bound diagnostic
6 participants