Skip to content

Adding Op<&T> bound breaks code depending on Op<T> bound #77159

Closed
@WaffleLapkin

Description

@WaffleLapkin

I tried this code:

trait Op<Arg> { 
    fn op (_: Arg); 
}

trait Trait<'lt>: 'lt + Sized + Op<Self> + Op<&'lt Self> {}

trait WithAssoc<'lt> { type Assoc: Trait<'lt>; }

fn test<'lt, T: WithAssoc<'lt>> (it: T::Assoc) {
    <T::Assoc as Op<_>>::op(it)
}

I expected to see this happen: code compiles

Instead, this happened: code doesn't compile with the following error:

error[E0308]: mismatched types
  --> src/lib.rs:10:29
   |
10 |     <T::Assoc as Op<_>>::op(it)
   |                             ^^ expected reference, found associated type
   |
   = note:    expected reference `&'lt <T as WithAssoc<'lt>>::Assoc`
           found associated type `<T as WithAssoc<'lt>>::Assoc`
help: consider constraining the associated type `<T as WithAssoc<'lt>>::Assoc` to `&'lt <T as WithAssoc<'lt>>::Assoc`
   |
9  | fn test<'lt, T: WithAssoc<'lt, Assoc = &'lt <T as WithAssoc<'lt>>::Assoc>> (it: T::Assoc) {
   |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: consider borrowing here
   |
10 |     <T::Assoc as Op<_>>::op(&it)
   |                             ^^^
  1. T::Assoc should implement Op<T::Assoc> so the error shouldn't happen
  2. Compiler suggests using T: WithAssoc<'lt, Assoc = &'lt <T as WithAssoc<'lt>>::Assoc> which is reccursion
  3. The code works if
    1. you'll remove + Op<&'lt Self>
    2. you'll use op with explicit type <T::Assoc as Op<T::Assoc>>::op(it)
  4. There is a weird spacing between = note: and expected reference ... though this is unrelated to the problem

Playground: [link]

Meta

tested on 1.46.0 and 1.48.0-nightly (2020-09-23 8b40853)

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-bugCategory: This is a bug.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions