rust-lang / rust-lang/rust

Precise captures in ITIAT behave differently than refined RPITITs and TAITs

Open
#135,144 4 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

A-impl-trait A-lifetimes A-trait-system C-bug F-impl_trait_in_assoc_type S-has-mcve T-types
Dominant language
Rust
Stars
119k
Forks
16.1k
PR merge metrics
PR metrics pending

Description

I tried this code:

#![feature(impl_trait_in_assoc_type)]

pub trait Trait {}
impl<T> Trait for T {}
pub struct Context;

pub trait Component {
    type Creation<'a>: Trait;
    fn create(self, ctx: &Context) -> Self::Creation<'_>;
}

impl Component for String {
    // `+ use<>` is allowed without triggering this lint
    // #[allow(refining_impl_trait)]
    type Creation<'a> = impl Trait + use<>;
    fn create(self, _ctx: &Context) -> Self::Creation<'_> {
        self
    }
}

impl Component for &str {
    // `+ use<>` correctly rejects the defining use here
    type Creation<'a> = impl Trait /*+ use<>*/;
    fn create(self, ctx: &Context) -> Self::Creation<'_> {
        ctx
    }
}

// This should accept `T = String` and not `T = &str`, but it
// accepts neither
pub fn component<T, R>(prop: T)
where
    T: for<'a> Component<Creation<'a> = R>,
{
    move |ctx: &Context| prop.create(ctx);
}

fn main() {
    let but_does_it_work = component(String::new());
    // let but_does_it_work = component("");
}

I expected to see this happen: successful compilation

Instead, this happened:


error[E0308]: mismatched types
  --> src/main.rs:39:28
   |
15 |     type Creation<'a> = impl Trait + use<>;
   |                         ------------------
   |                         |
   |                         the expected opaque type
   |                         the found opaque type
...
39 |     let but_does_it_work = component(String::new());
   |                            ^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
   |
   = note: expected opaque type `<String as Component>::Creation<'a>`
              found opaque type `<String as Component>::Creation<'_>`
   = note: distinct uses of `impl Trait` result in different opaque types
note: the lifetime requirement is introduced here
  --> src/main.rs:33:26
   |
33 |     T: for<'a> Component<Creation<'a> = R>,
   |                          ^^^^^^^^^^^^^^^^
Why the expectation

The analogous refinement works with RPITIT and RTN.

Meta

Playground 1.86.0-nightly (2025-01-04 1891c28669863bf7ed3e)

@rustbot label +F-impl_trait_in_assoc_type +A-traits +T-types +requires-nightly

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 by compiling the provided Playground reproducer and compare its ITIAT behavior with the linked RPITIT and RTN example. The fix should allow the String implementation's refined associated type to satisfy the higher-ranked bound while continuing to reject the &str case.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.