Skip to content

stepping into where-clauses during normalization may be productive#155388

Open
lcnr wants to merge 1 commit into
rust-lang:mainfrom
lcnr:norm-where-bounds-may-be-productive
Open

stepping into where-clauses during normalization may be productive#155388
lcnr wants to merge 1 commit into
rust-lang:mainfrom
lcnr:norm-where-bounds-may-be-productive

Conversation

@lcnr

@lcnr lcnr commented Apr 16, 2026

Copy link
Copy Markdown
Contributor

fixes rust-lang/trait-system-refactor-initiative#273, see that issue for more info.

Whether stepping into a where-clause is productive depends not on whether we're proving a NormalizesTo or Trait goal, but instead on how both the impl and the cycle rely on it.

In the example in tests/ui/traits/next-solver/cycles/normalizes-to-is-not-productive-2.rs this is just a productive use given the way @Nadrieril and I are thinking about it right now.

We're changing such cycles to be ambiguous for now, so this does not commit us to anything.

This previously caused a lot of breakage when normalizing where-clauses, e.g. rust-lang/trait-system-refactor-initiative#176, however with #158643 that is no longer an issue. We will need to figure out what to do here if we want to properly fix ParamEnv normalization in the future

r? @BoxyUwU or @nikomatsakis

@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 Apr 16, 2026
@rust-log-analyzer

This comment has been minimized.

@lcnr
lcnr force-pushed the norm-where-bounds-may-be-productive branch from 7e15d0a to 7149592 Compare April 17, 2026 07:58
@rustbot

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@lcnr
lcnr force-pushed the norm-where-bounds-may-be-productive branch from 7149592 to 45934b8 Compare April 17, 2026 09:33
@BoxyUwU

BoxyUwU commented May 1, 2026

Copy link
Copy Markdown
Member

@rustbot author

pending figuring out how breaking this is

@rustbot rustbot removed the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label May 1, 2026
@rustbot

rustbot commented May 1, 2026

Copy link
Copy Markdown
Collaborator

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

@rustbot rustbot added the S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. label May 1, 2026
@rust-bors

This comment has been minimized.

@Randl

Randl commented May 20, 2026

Copy link
Copy Markdown
Contributor

Not sure if you're already aware but this PR ICEs on the following

//@ revisions: current next
//@ ignore-compare-mode-next-solver (explicit revisions)
//@[next] compile-flags: -Znext-solver
//@ edition: 2021
//@ compile-flags: --crate-type=lib
//@ build-pass

use std::future::Future;
use std::pin::Pin;
use std::sync::Arc;
use std::task::Context;
use std::task::Poll;

struct Buffer;
type Result<T> = std::result::Result<T, ()>;
type BoxedFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>;

trait Read: Unpin + Send {
    fn read(&mut self) -> impl Future<Output = Result<Buffer>>;
}

trait ReadDyn: Unpin + Send + Sync {}
type Reader = Box<dyn ReadDyn>;

trait Access: Send + Sync + Unpin {
    type Reader;
    fn read(&self) -> impl Future<Output = Result<(u32, Self::Reader)>> + Send;
}

trait AccessDyn: Send + Sync + Unpin {
    fn read_dyn(&self) -> BoxedFuture<'_, Result<(u32, Reader)>>;
}

impl Access for dyn AccessDyn {
    type Reader = Reader;
    async fn read(&self) -> Result<(u32, Self::Reader)> {
        self.read_dyn().await
    }
}

impl<T: Access + ?Sized> Access for Arc<T> {
    type Reader = T::Reader;
    fn read(&self) -> impl Future<Output = Result<(u32, Self::Reader)>> + Send {
        async { self.as_ref().read().await }
    }
}

struct ReadContext {
    acc: Arc<dyn AccessDyn>,
}

struct ReadGenerator {
    ctx: Arc<ReadContext>,
}

impl ReadGenerator {
    async fn next_reader(&self) -> Result<Option<Reader>> {
        let (_, r) = self.ctx.acc.read().await?;
        Ok(Some(r))
    }
}

trait Stream {
    type Item;
    fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>>;
}

enum TwoWays<A, B> {
    One(A),
    Two(B),
}

impl<A: Read, B: Read> Read for TwoWays<A, B> {
    async fn read(&mut self) -> Result<Buffer> {
        match self {
            TwoWays::One(v) => v.read().await,
            TwoWays::Two(v) => v.read().await,
        }
    }
}

struct StreamingReader {
    generator: ReadGenerator,
}

impl Read for StreamingReader {
    async fn read(&mut self) -> Result<Buffer> {
        let _ = self.generator.next_reader().await;
        loop {}
    }
}

struct ChunkedReader;

impl Read for ChunkedReader {
    async fn read(&mut self) -> Result<Buffer> {
        loop {}
    }
}

enum State {
    Idle(Option<TwoWays<StreamingReader, ChunkedReader>>),
    Reading(Pin<Box<dyn Future<Output = (TwoWays<StreamingReader, ChunkedReader>, Result<Buffer>)> + Send>>),
}

struct BufferStream {
    state: State,
}

impl Stream for BufferStream {
    type Item = Result<()>;

    fn poll_next(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
        let this = unsafe { self.get_unchecked_mut() };
        loop {
            match &mut this.state {
                State::Idle(reader) => {
                    let mut reader = reader.take().unwrap();
                    let fut = async {
                        let ret = reader.read().await;
                        (reader, ret)
                    };
                    this.state = State::Reading(Box::pin(fut));
                }
                State::Reading(_) => return Poll::Pending,
            }
        }
    }
}

with

error: internal compiler error: compiler/rustc_mir_transform/src/validate.rs:81:25: broken MIR in Item(DefId(0:86 ~ async_block_box_pin_unsize_broken_mir[e897]::{impl#6}::poll_next)) (after phase change to runtime-optimized) at bb8[0]:
                                Unsize coercion, but `std::pin::Pin<std::boxed::Box<{async block@/Users/evgeniizh/RustroverProjects/rust/tests/ui/traits/next-solver/async-block-box-pin-unsize-broken-mir.rs:131:31: 131:36}>>` isn't coercible to `std::pin::Pin<std::boxed::Box<dyn std::future::Future<Output = (TwoWays<StreamingReader, ChunkedReader>, std::result::Result<Buffer, ()>)> + std::marker::Send>>`
  --> /Users/evgeniizh/RustroverProjects/rust/tests/ui/traits/next-solver/async-block-box-pin-unsize-broken-mir.rs:135:49
   |
LL |                     this.state = State::Reading(Box::pin(fut));
   |                                                 ^^^^^^^^^^^^^


thread 'rustc' (4832989) panicked at compiler/rustc_mir_transform/src/validate.rs:81:25:

while current main doesn't.

@Randl

Randl commented May 20, 2026

Copy link
Copy Markdown
Contributor

Hm never mind looks like it passes after rebase on main

@lcnr
lcnr force-pushed the norm-where-bounds-may-be-productive branch from 45934b8 to 20b2ce1 Compare July 16, 2026 07:46
@rustbot

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@lcnr
lcnr force-pushed the norm-where-bounds-may-be-productive branch from 20b2ce1 to e4c693d Compare July 16, 2026 09:10
@lcnr lcnr changed the title stepping into NormalizesTo where-clauses may be productive stepping into where-clauses during normalization may be productive Jul 22, 2026
@BoxyUwU

BoxyUwU commented Jul 22, 2026

Copy link
Copy Markdown
Member

@bors delegate+

r=me after rebasing

@rustbot author

@rust-bors

rust-bors Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

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

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

View changes since this delegation.

@lcnr
lcnr force-pushed the norm-where-bounds-may-be-productive branch from e4c693d to 66d0fb8 Compare July 22, 2026 11:02
@rustbot

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. 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.

entering normalization where-bounds incorrectly considered non-productive

5 participants