Skip to content

generalization doesn't immediately normalize aliases #262

Closed

Description

@lcnr

https://rust-lang.zulipchat.com/#narrow/channel/364551-t-types.2Ftrait-system-refactor/topic/.60husky.60.20candidate.20preference.20thingy/with/569048045 affects husky

trait View {}
trait HasAssoc {
    type Assoc;
}

struct StableVec<T>(T);
impl<T> View for StableVec<T> {}

fn assert_view<F: View>(f: F) -> F { f }

fn store<T>() -> StableVec<T::Assoc>
where
    T: HasAssoc,
    StableVec<T>: View,
{
    let x = todo!();
    assert_view(x)
}

This errors with

error[E0271]: type mismatch resolving `T == <T as HasAssoc>::Assoc`
  --> src/main.rs:17:17
   |
17 |     assert_view(x)
   |                 ^ types differ

error[E0308]: mismatched types
  --> src/main.rs:17:5
   |
11 | fn store<T>() -> StableVec<T::Assoc>
   |                  ------------------- expected `StableVec<<T as HasAssoc>::Assoc>` because of return type
...
17 |     assert_view(x)
   |     ^^^^^^^^^^^^^^ types differ
   |
   = note: expected struct `StableVec<<T as HasAssoc>::Assoc>`
              found struct `StableVec<T>`

Further minimizing this is really hard. See the zulip thread for what I think is going on. I think the fix here is related to the fix for #191.

Generalization should try to actually normalize aliases instead of just replacing them with infer vars and emitting an AliasRelate goal. We should also do this for aliases with escaping bound vars, except there we also need to replace the bound vars with placeholders and need to make sure we lower the universes of anything we fail to map back to bound vars after trying to normalize (and we replace it with an alias again if normalization was ambig)

Activity

  1. moved this from todo to in progress in -Znext-solver=globallyon Feb 5, 2026
  2. lcnr commented on Feb 25, 2026

    @lcnr
    ContributorAuthor

    likely also the cause of the regression in bacon-sci https://rust-lang.zulipchat.com/#narrow/channel/364551-t-types.2Ftrait-system-refactor/topic/crater.20triage.20.3A3/near/575461950

    trait HasAssoc {
        type Assoc;
    }
    
    trait Blanket<N, R> {}
    
    struct ImplsBlanket;
    impl<N, R> Blanket<N, R> for ImplsBlanket {}
    
    struct U1;
    
    struct Wrapper<N, R>(N, R);
    
    impl<N, R> Wrapper<N, R> {
        fn requires_blanket()
        where
            ImplsBlanket: Blanket<N, R>,
        {
        }
    }
    
    fn test<N>()
    where
        N: HasAssoc,
        ImplsBlanket: Blanket<N, U1>,
    {
        // we have the obligation `ImplsBlanket: Blanket<?t, U1>`.
        // the first param is an infer var because the projection `N::Assoc` is normalized to an infer var.
        // we have two candidates for the trait goal.
        // the env one: unify `?t` with `N`.
        // the impl one: ambiguous due to unsatisfied `?t: Sized`.
        // so we end up with `?t = N` which causes error in the projection alias relate goal later.
        Wrapper::<N::Assoc, U1>::requires_blanket();
    }
  3. lcnr commented on Mar 4, 2026

    @lcnr
    ContributorAuthor

    likely also the cause of claw-ql https://rust-lang.zulipchat.com/#narrow/channel/364551-t-types.2Ftrait-system-refactor/topic/crater.20triage.20.3A3/near/577136564

    trait Database {
        type Connection;
    }
    
    trait Executor: Send {}
    
    trait DeleteOneFragment {
        type Inner: Send;
    }
    
    struct DeleteSt<S: Database>(S);
    
    
    fn is_send<T: Send>(value: T) {
    }
    
    fn howdy<S, L>(mut worker_data: L::Inner)
    where
        S: Database + Send,
        L: DeleteOneFragment,
        for<'c> &'c mut S::Connection: Executor,
    {
        // to prove `{closure}: Send -: &mut ?worker_data: Send`
        // next-solver prefers a candidate from the param_env,
        // `for<'c> &'c mut S::Connection: Executor<Database = S>`,
        // results in `&mut worker_data = &mut S::Connection`
        is_send(|| {
            let worker_data = &mut worker_data;
        });
    }
  4. added a commit that references this issue on Mar 20, 2026
  5. lcnr commented on Jul 27, 2026

    @lcnr
    ContributorAuthor

    This was fixed by adding rigid aliases rust-lang/rust#156742

  6. added
    E-needs-testCall for participation: An issue has been fixed and does not reproduce, but no test has been added.
    on Jul 27, 2026
  7. added a commit that references this issue on Aug 6, 2026
  8. added 5 commits that reference this issue on Aug 6, 2026
  9. added a commit that references this issue on Aug 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-incompleteincorrectly return `NoSolution`, unsound during coherenceA-normalizationE-needs-testCall for participation: An issue has been fixed and does not reproduce, but no test has been added.

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions