Skip to content

opaque type leakage and RPITIT normalization #139788

Open
@lcnr

Description

@lcnr

related to rust-lang/trait-system-refactor-initiative#173, see added tests in #139789

trait Trait {
    // desugars to
    // type Assoc: Sized + Send;
    // fn foo(b: bool) -> Self::Assoc;
    fn foo(b: bool) -> impl Sized + Send;
}

impl Trait for u32 {
    // desugars to
    // type Assoc = impl_rpit::<Self>;
    // fn foo(b: bool) -> Self::Assoc { .. }
    fn foo(b: bool) -> impl Sized {
        if b {
            u32::foo(false)
        } else {
            1u32
        }
    }
}

This currently results in a query cycle:

  • type_of(impl::Assoc)
  • collect_return_position_impl_trait_in_trait_tys
  • impl_rpit: Send
  • type_of(impl_rpit) // auto trait leakage
  • typeck(impl::foo)
  • normalize(<u32 as Trait>::Assoc)
  • type_of(impl::Assoc)

I believe that this query cycle should not be there and can be avoided.

collect_return_position_impl_trait_in_trait_tys currently adds the item bounds of the RPITIT when replacing it with fresh infer vars. I believe this is not necessary to guide inference as the method signature is fully concrete.

We could therefore split this in two:

  • collect_return_position_impl_trait_in_trait_tys instantiates RPITIT with infer vars but does not check the item bounds of the RPITIT trait assoc type
  • compare_type_predicate_entailment (or a separate query, idk and idc :3) then uses collect_return_position_impl_trait_in_trait_tys and actually checks the item bounds

This means normalizing impl::Assoc no longer has to prove the item bounds of the RPITIT, allowing the above example to compile and fixing rust-lang/trait-system-refactor-initiative#173

cc @compiler-errors

Activity

added
needs-triageThis issue may need triage. Remove it if it has been sufficiently triaged.
on Apr 14, 2025
added
A-impl-traitArea: `impl Trait`. Universally / existentially quantified anonymous types with static dispatch.
WG-trait-system-refactorThe Rustc Trait System Refactor Initiative (-Znext-solver)
and removed
needs-triageThis issue may need triage. Remove it if it has been sufficiently triaged.
on Apr 14, 2025
compiler-errors

compiler-errors commented on Apr 14, 2025

@compiler-errors
Member

I'm confused here: we use the item bounds not just to enforce that the hidden types implement their bounds, but also in order to collect the hidden type of inner RPITITs, for example, so we at least need to keep around projection bounds, unless I'm missing something from the write-up above.

I believe the example I use throughout the documentation to motivate this is something like an RPITIT impl Deref<Assoc = impl Sized> being equated against an impl signature of &String so that we infer impl Sized := String.

I'm not certain I see how this scheme manages to compute the type of the inner impl Sized -- can you elaborate?

lcnr

lcnr commented on Apr 14, 2025

@lcnr
ContributorAuthor

I'm not certain I see how this scheme manages to compute the type of the inner impl Sized -- can you elaborate?

It does not '^^ I did not consider that we need this for nested RPITIT. We could filter the required item bounds to only prove bounds which may constrain nested RPITITs. But with this requirement changing the approach feels less obviously desirable to me 🤔 these projection bounds could still require leaking auto traits:

trait Project {
    type Assoc;
}
impl<T: Send> Project for Vec<T> {
    type Assoc = u32;
}

trait Trait {
    fn foo(b: bool) -> impl Project<Assoc = impl Sized>;
}
impl Trait for u32 {
    fn foo(b: bool) -> Vec<impl Sized> {
        if b {
            u32::foo(false)
        } else {
            vec![1u32]
        }
    }
}

otoh, we could add yet another TypingMode::ComputeSyntheticAssocItems which treats all impl Trait: AutoTrait bounds as trivially true (so it's unsound by itself) which we use to in collect_return_position_impl_trait_in_trait_tys and then recheck in TypingMode::Analysis proper while leaking auto traits as normal

compiler-errors

compiler-errors commented on Apr 14, 2025

@compiler-errors
Member

otoh, we could add yet another TypingMode::ComputeSyntheticAssocItems which treats all impl Trait: AutoTrait bounds as trivially true (so it's unsound by itself) which we use to in collect_return_position_impl_trait_in_trait_tys and then recheck in TypingMode::Analysis proper while leaking auto traits as normal

Yes, though stylistically it feels a bit different than other candidate assembly special casing because it would need to happen before we try to normalize the self type of the trait bound.

I'm personally not very keen to fix this cycle, since to me it feels qualitiatively different than the one I'm trying to fix in rust-lang/trait-system-refactor-initiative#173, which can be justified much more simply by "rigid projections should never be projected in the first place".

added a commit that references this issue on Apr 15, 2025

Rollup merge of rust-lang#139789 - lcnr:opaques-auto-trait-leakage, r…

b2897d0
added a commit that references this issue on Apr 15, 2025

Rollup merge of rust-lang#139789 - lcnr:opaques-auto-trait-leakage, r…

7823d49
added a commit that references this issue on Apr 15, 2025

Rollup merge of rust-lang#139789 - lcnr:opaques-auto-trait-leakage, r…

8118fca
added a commit that references this issue on Apr 15, 2025
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-impl-traitArea: `impl Trait`. Universally / existentially quantified anonymous types with static dispatch.F-return_position_impl_trait_in_trait`#![feature(return_position_impl_trait_in_trait)]`WG-trait-system-refactorThe Rustc Trait System Refactor Initiative (-Znext-solver)

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @compiler-errors@lcnr@rustbot

        Issue actions

          opaque type leakage and RPITIT normalization · Issue #139788 · rust-lang/rust