Skip to content

Rigidly project missing item due to guaranteed impossible sized predicate #139000

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

Merged
merged 4 commits into from
Apr 10, 2025

Conversation

compiler-errors
Copy link
Member

This is a somewhat involved change, but it amounts to treating missing impl items due to guaranteed impossible where clauses (dyn/str/slice sized, cc #135480) as rigid projections rather than projecting to an error term, since that was preventing either reporting a proper error (in an empty param env) or successfully type checking the code (in the presence of trivially false where clauses).

Fixes #138970

r? @lcnr @oli-obk

@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. WG-trait-system-refactor The Rustc Trait System Refactor Initiative (-Znext-solver) labels Mar 26, 2025
@lcnr
Copy link
Contributor

lcnr commented Mar 27, 2025

A somewhat annoying issue 🤔 the fix feels quite cumbersome and slightly brittle to me.

I think the delayed bug doesn't provide too much value. We now do allow missing associated items in some cases.

Instead of just using query defaultness which is computed by looking at the HIR, could we instead rely on the assoc item check in wf-checking, maybe splitting just that into a sub-query to check whether the assoc item is allowed to be missing? (we could then also change the error case to normalize to ty::Error 🤔)

I think returning a rigid alias during coherence is unsound here, with the following setup:

  • coherence fails to relate types due to a rigid alias, causing it to not detect overlapping impls
  • due to generic parameters, the impl checking that the self-type is definitely unsized, uses the first of the overlapping impls for normalization, not seeing the second one as it fails.
  • in a separate context, we can only use the second of the overlapping impls, normalizing the self-type to a sized type this time

So we should return ambiguity if we're in coherence

@lcnr
Copy link
Contributor

lcnr commented Mar 27, 2025

Maybe add a function fn constrain_term_to_rigid_except_ambiguous_in_coherence. The name is kinda meh, but I think we want this sort of behavior in multiple places 🤔

@BoxyUwU
Copy link
Member

BoxyUwU commented Mar 28, 2025

This can only occur when there's an impossible predicate right? I wouldn't expect coherence to matter as it would need to involve some kind of where str: Sized bound on an impl which makes it never apply. I guess that's not true if you're in an environment with a trivial bound 🤔 though such code can never actually be executed..

edit: yeah i spent more time thinking about this and I am not sure what example you're thinking of 🤷‍♀️

@compiler-errors
Copy link
Member Author

Yeah, I'm not sure how this could be turned into a coherence bug. I did pull this out into a query since it's nicer than having to recompute the struct tail, especially in the new trait solver.

@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 30, 2025
bors added a commit to rust-lang-ci/rust that referenced this pull request Mar 30, 2025
Rigidly project missing item due to guaranteed impossible sized predicate

This is a somewhat involved change, but it amounts to treating missing impl items due to guaranteed impossible where clauses (dyn/str/slice sized, cc rust-lang#135480) as *rigid projections* rather than projecting to an error term, since that was preventing either reporting a proper error (in an empty param env) *or* successfully type checking the code (in the presence of trivially false where clauses).

Fixes rust-lang#138970

r? `@lcnr` `@oli-obk`
@bors
Copy link
Collaborator

bors commented Mar 30, 2025

⌛ Testing commit 77e2d4a with merge 02c4769...

@compiler-errors
Copy link
Member Author

ugh race condition @bors r- retry

@bors bors added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. 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-review Status: Awaiting review from the assignee but also interested parties. S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Mar 30, 2025
@compiler-errors
Copy link
Member Author

@bors try @rust-timer queue

@rust-timer

This comment has been minimized.

@bors
Copy link
Collaborator

bors commented Mar 30, 2025

⌛ Trying commit 77e2d4a with merge a640b79...

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

Rigidly project missing item due to guaranteed impossible sized predicate

This is a somewhat involved change, but it amounts to treating missing impl items due to guaranteed impossible where clauses (dyn/str/slice sized, cc rust-lang#135480) as *rigid projections* rather than projecting to an error term, since that was preventing either reporting a proper error (in an empty param env) *or* successfully type checking the code (in the presence of trivially false where clauses).

Fixes rust-lang#138970

r? `@lcnr` `@oli-obk`
@bors
Copy link
Collaborator

bors commented Mar 30, 2025

☀️ Try build successful - checks-actions
Build commit: a640b79 (a640b791dff0d16733631f2e06fbf35825720209)

@rust-timer

This comment has been minimized.

@rust-timer
Copy link
Collaborator

Finished benchmarking commit (a640b79): comparison URL.

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

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

Instruction count

This is the most reliable metric that we have; it was used to determine the overall result at the top of this comment. However, even this metric can sometimes exhibit noise.

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

Max RSS (memory usage)

Results (secondary 3.8%)

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.8% [3.8%, 3.8%] 1
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
- - 0
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: 777.614s -> 777.094s (-0.07%)
Artifact size: 365.95 MiB -> 365.97 MiB (0.01%)

@rustbot rustbot removed the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Mar 30, 2025
@lcnr
Copy link
Contributor

lcnr commented Mar 31, 2025

r=me on the impl, checking it out locally to play with my concern wrt to correctness in coherence

@lcnr
Copy link
Contributor

lcnr commented Mar 31, 2025

wrt to the correctness issue in coherence. I was thinking of

// overlap error on nightly, compiles with this PR
struct MaybeUnsized<T: Overlap<U>, U>(<T as Overlap<U>>::MaybeUnsized);

trait ReqSized {
    type Missing1
    where
        Self: Sized;
    type Missing2
    where
        Self: Sized;
}
impl<T> ReqSized for MaybeUnsized<T, u32> {}

struct W<T: ?Sized>(T);
trait Eq<T> {}
impl<T> Eq<T> for W<T> {}

trait RelateReqSized {}
impl<T: ReqSized> RelateReqSized for T
where 
    W<T::Missing1>: Eq<T::Missing2> {}

// These two impls overlap if `MaybeUnsized<u32, u32>: Sized` holds
// and `T::Missing1` and `T::Missing2` are the same type.
//
// The check that that `MaybeUnsized<u32, u32>` is not `Sized`
// is done in a generic context where we just use the first impl. So
// even though the second impl would also be applicable, we treat the
// missing associated items as rigid.
trait Overlap<U> {
    type MaybeUnsized: ?Sized;
}
impl<T> Overlap<u32> for T {
    type MaybeUnsized = str;
}
impl<U> Overlap<U> for u32
where
    MaybeUnsized<U, u32>: RelateReqSized,
{
    type MaybeUnsized = u32;
}

I think it would be very difficult to exploit this issue, but I do think this behavior is buggy and it should continue to emit an overlap error.

@lcnr
Copy link
Contributor

lcnr commented Mar 31, 2025

from @BoxyUwU when chatting with her in priv:

the "can u elide items" check lets you elide it because the second impl cant apply due to T=/=u32
this is correct if you assume the impls don't overlap due to coherence having guaranteed it
but the fact that this check results in changing how normalizeation of aliases in coherence works means its effectively an input to coherence
divorcing coherence's handling of normalization of these aliases from whether its actually sized or not fixes that
changing the checks handlign to not involve trait solving whatsoever would also fix it (?)

@compiler-errors
Copy link
Member Author

@bors r=lcnr

@bors
Copy link
Collaborator

bors commented Apr 9, 2025

📌 Commit 6cd724b has been approved by lcnr

It is now in the queue for this repository.

@Zalathar
Copy link
Contributor

Scheduling: If/when the jumbo rollup #139612 fails, move on to a never PR instead of an iffy one.

@bors p=1

@bors
Copy link
Collaborator

bors commented Apr 10, 2025

⌛ Testing commit 6cd724b with merge 9d28fe3...

@bors
Copy link
Collaborator

bors commented Apr 10, 2025

☀️ Test successful - checks-actions
Approved by: lcnr
Pushing 9d28fe3 to master...

@bors bors added the merged-by-bors This PR was explicitly merged by bors. label Apr 10, 2025
@bors bors merged commit 9d28fe3 into rust-lang:master Apr 10, 2025
7 checks passed
@rustbot rustbot added this to the 1.88.0 milestone Apr 10, 2025
Copy link

What is this? This is an experimental post-merge analysis report that shows differences in test outcomes between the merged PR and its parent PR.

Comparing 6813f95 (parent) -> 9d28fe3 (this PR)

Test differences

Show 56 test diffs

Stage 1

  • [ui] tests/ui/traits/trivial-unsized-projection-2.rs#bad: [missing] -> pass (J1)
  • [ui] tests/ui/traits/trivial-unsized-projection-2.rs#bad_new: [missing] -> pass (J1)
  • [ui] tests/ui/traits/trivial-unsized-projection-2.rs#good: [missing] -> pass (J1)
  • [ui] tests/ui/traits/trivial-unsized-projection-2.rs#good_new: [missing] -> pass (J1)
  • [ui] tests/ui/traits/trivial-unsized-projection-in-coherence.rs: [missing] -> pass (J1)
  • [ui] tests/ui/traits/trivial-unsized-projection.rs#bad: [missing] -> pass (J1)
  • [ui] tests/ui/traits/trivial-unsized-projection.rs#bad_new: [missing] -> pass (J1)
  • [ui] tests/ui/traits/trivial-unsized-projection.rs#good: [missing] -> pass (J1)
  • [ui] tests/ui/traits/trivial-unsized-projection.rs#good_new: [missing] -> pass (J1)

Stage 2

  • [ui] tests/ui/traits/trivial-unsized-projection-2.rs#bad: [missing] -> pass (J0)
  • [ui] tests/ui/traits/trivial-unsized-projection-2.rs#bad_new: [missing] -> pass (J0)
  • [ui] tests/ui/traits/trivial-unsized-projection-2.rs#good: [missing] -> pass (J0)
  • [ui] tests/ui/traits/trivial-unsized-projection-2.rs#good_new: [missing] -> pass (J0)
  • [ui] tests/ui/traits/trivial-unsized-projection-in-coherence.rs: [missing] -> pass (J0)
  • [ui] tests/ui/traits/trivial-unsized-projection.rs#bad: [missing] -> pass (J0)
  • [ui] tests/ui/traits/trivial-unsized-projection.rs#bad_new: [missing] -> pass (J0)
  • [ui] tests/ui/traits/trivial-unsized-projection.rs#good: [missing] -> pass (J0)
  • [ui] tests/ui/traits/trivial-unsized-projection.rs#good_new: [missing] -> pass (J0)

Additionally, 38 doctest diffs were found. These are ignored, as they are noisy.

Job group index

Job duration changes

  1. dist-x86_64-apple: 9127.4s -> 12204.8s (33.7%)
  2. dist-apple-various: 8919.7s -> 6377.4s (-28.5%)
  3. x86_64-gnu-nopt: 5483.0s -> 6506.5s (18.7%)
  4. x86_64-apple-2: 5640.7s -> 4864.8s (-13.8%)
  5. aarch64-apple: 3774.1s -> 3464.1s (-8.2%)
  6. dist-aarch64-apple: 4683.0s -> 4331.3s (-7.5%)
  7. dist-loongarch64-linux: 6352.3s -> 5924.9s (-6.7%)
  8. dist-arm-linux: 5796.9s -> 5484.0s (-5.4%)
  9. dist-x86_64-illumos: 5590.9s -> 5865.2s (4.9%)
  10. dist-loongarch64-musl: 5544.2s -> 5292.1s (-4.5%)
How to interpret the job duration changes?

Job durations can vary a lot, based on the actual runner instance
that executed the job, system noise, invalidated caches, etc. The table above is provided
mostly for t-infra members, for simpler debugging of potential CI slow-downs.

@rust-timer
Copy link
Collaborator

Finished benchmarking commit (9d28fe3): comparison URL.

Overall result: ❌✅ regressions and improvements - no action needed

@rustbot label: -perf-regression

Instruction count

This is the most reliable metric that we have; it was used to determine the overall result at the top of this comment. However, even this metric can sometimes exhibit noise.

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

Max RSS (memory usage)

Results (primary -0.7%, secondary 3.7%)

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.8% [0.8%, 0.8%] 1
Regressions ❌
(secondary)
3.7% [1.7%, 8.1%] 5
Improvements ✅
(primary)
-2.2% [-2.2%, -2.2%] 1
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) -0.7% [-2.2%, 0.8%] 2

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: 780.636s -> 780.245s (-0.05%)
Artifact size: 366.13 MiB -> 366.19 MiB (0.02%)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
merged-by-bors This PR was explicitly merged by bors. 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. WG-trait-system-refactor The Rustc Trait System Refactor Initiative (-Znext-solver)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

ICE when referencing ill-formed associated type in ItemCtxts (self type impls trait but own bounds don't hold)
7 participants