Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Higher-order bound on associated type does not support type inference #97554

Closed
danielhenrymantilla opened this issue May 30, 2022 · 3 comments
Closed
Labels
A-trait-system Area: Trait system C-bug Category: This is a bug.

Comments

@danielhenrymantilla
Copy link
Contributor

I tried this code:

trait SomeBound {} // e.g., `Sized`, `Copy`, `Debug`, or w/e

trait Trait<'__> {
    // Notice that in the general case we don't know
    // if `Assoc : SomeBound` holds.
    type Assoc : ?Sized;
}

impl Trait<'_> for () {
    type Assoc = u8;
}
impl SomeBound for u8 {}

fn check<T>(_: T)
where
    for<'any>
        T : Trait<'any>
    ,
    for<'any>
        <T as Trait<'any>>::Assoc : SomeBound
    ,
{}

fn main() {
    check::<()>(()); // OK
    check::<_> (()); // Errors
    check      (()); // Errors
}

I expected to see this happen: Code compiles fine, whether T is inferred to be () or explicitly turbofished

Instead, this happened: when T is inferred (explicitly or implicitly), an error about the trait for<'any> Bound not being satisfied for <_ as Trait<'any>>::Assoc:

error[[E0277]](https://doc.rust-lang.org/stable/error-index.html#E0277): the trait bound `for<'any> <_ as Trait<'any>>::Assoc: SomeBound` is not satisfied
  --> src/main.rs:26:5
   |
26 |     check::<_>(()); // Errors
   |     ^^^^^^^^^^ the trait `for<'any> SomeBound` is not implemented for `<_ as Trait<'any>>::Assoc`
   |
note: required by a bound in `check`
  --> src/main.rs:20:37
   |
14 | fn check<T>(_: T)
   |    ----- required by a bound in this
...
20 |         <T as Trait<'any>>::Assoc : SomeBound
   |                                     ^^^^^^^^^ required by this bound in `check`

This happens on all versions of Rust (up to 1.0.0!)

@rustbot modify labels: A-traits

@danielhenrymantilla danielhenrymantilla added the C-bug Category: This is a bug. label May 30, 2022
@rustbot rustbot added the A-trait-system Area: Trait system label May 30, 2022
@danielhenrymantilla
Copy link
Contributor Author

danielhenrymantilla commented May 30, 2022

FWIW, here is the current way to work around this:

  1. Define a helper trait with a bound on the associated type:

    trait TraitWithBoundOnAssoc<'lt> {
        type Assoc : ?Sized + SomeBound;
    }
  2. Have a blanket impl to forward the original implementations that meet the bound to this new trait (this impl is not higher-order, thereby dodging the issue):

    impl<'lt, T : ?Sized> TraitWithBoundOnAssoc<'lt> for T
    where
        T : Trait<'lt>,
        <T as Trait<'lt>>::Assoc : SomeBound,
    {
        type Assoc = <T as Trait<'lt>>::Assoc;
    }
  3. Wrap the original function within one which uses this "assoc-type-bounded trait alias" instead, while also adding an equality close in between the two associated types:

    // wrapping function
    fn check<T>(it: T)
    where
        T : for<'any> Trait<'any,
    +       Assoc = <T as TraitWithBoundOnAssoc<'any>>::Assoc,
        >,
        for<'any>
    -      <T as Trait<'any>>::Assoc : SomeBound
    +       T : TraitWithBoundOnAssoc<'any>
        ,
    {
        // original function which can be left untouched:
        fn check<T> …
    
        check::<T>(it) // <- turbofish to avoid the issue mentioned in this very issue!
    }

@compiler-errors
Copy link
Member

I think this is #88460

@jackh726
Copy link
Member

This is #89196. Closing as duplicate.

@jackh726 jackh726 closed this as not planned Won't fix, can't repro, duplicate, stale May 31, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-trait-system Area: Trait system C-bug Category: This is a bug.
Projects
None yet
Development

No branches or pull requests

4 participants