rust-lang / rust-lang/rust

assoc types in binders can pass wf check but error when trying to normalize via impl

Open
#161,405 5 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

A-coherence A-GATs A-higher-ranked A-impossible-bounds C-bug I-unsound P-medium T-types
Dominant language
Rust
Stars
119k
Forks
16.1k
PR merge metrics
PR metrics pending

Description

I've been using LLMs to find soundness issues in various programs, including rust. This bug was discussed on zulip (t-types thread) where @lcnr diagnosed the root cause and believes it affects stable (and also identified the regressing PR). Filing the bug here.

I tried this code:

#![forbid(unsafe_code)]
use std::any::type_name;

trait Overlap {
    type Out;
}

impl<T: ?Sized + Gated> Overlap for T
where
    for<'a> <T as Gated>::Assoc<'a>: Copy,
{
    type Out = usize;
}

impl Overlap for str {
    type Out = &'static u64;
}

trait Gated {
    type Assoc<'a>: Copy
    where
        Self: Sized;
}
impl Gated for str {}

fn cast<T: ?Sized + Gated>() -> <T as Overlap>::Out {
    println!("cast: Out = {}", type_name::<<T as Overlap>::Out>()); // usize
    8
}

fn main() {
    let r = cast::<str>();
    println!("main: Out = {} = {r:p}", type_name::<<str as Overlap>::Out>()); // &u64 = 0x8
    println!("{}", *r); // SIGSEGV
}

compiled with -Znext-solver.

I expected to see this happen: the program is rejected

Instead, this happened: -Znext-solver accepts it and the program prints

cast: Out = usize
main: Out = &u64 = 0x8
Segmentation fault

From @lcnr's analysis, the underlying issue also affects stable, : https://rust.godbolt.org/z/7scG3Pqjh (and a second demonstration in impossible_predicates: https://rust.godbolt.org/z/fG6v7K6fP). Also found the regression to be https://github.com/rust-lang/rust/pull/144064#issuecomment-3127365540 (https://rust.godbolt.org/z/Mb4ExdjeG).

Meta
nightly: rustc 1.100.0-nightly (8fa1c96cf 2026-08-17)
stable (old solver rejects the program above; stable godbolt link above shows the underlying issue): rustc 1.97.1 (8bab26f4f 2026-07-14)
Root cause (analysis by lcnr)

<T as Gated>::Assoc<'a>: Copy does not make sense because the associated type is only well-formed if T is Sized — now clearly, this should not be allowed. This error is ignored in WF check. This error is not ignored when actually normalizing, because we've instantiated the binder at this point.

What exactly is going on:

  • we have a type which implements a trait, with a GAT where-clause that may not hold
  • trying to normalize that where-clause for this type always errors as normalization rechecks GAT item bounds
  • we don't check GAT where-clauses in well-formedness checking of the impl if they reference bound variables
  • using an item bound does not need to prove GAT where-bounds
  • this means using an impl with that where-clause must use an item bound instead of actually the impl itself, causing the impl to be applicable
  • when normalizing via a concrete impl [it] does check GAT where-clauses, so the impl no longer applies

A stupid fix would be to not check GAT where-clauses in coherence when using impls — [but that is] insufficient, [it] also causes problems in impossible_predicates (godbolt link above). The proper fix is the higher-ranked region rework.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the Rust reproducer in the issue using -Znext-solver, then compare the linked impossible_predicates example and the stable Godbolt demonstrations. Investigate well-formedness checking, coherence, and normalization of GAT where-clauses, including the higher-ranked region rework mentioned in the analysis. Done means the unsound program is rejected without regressing the related cases.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
compilers
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.