Evaluation overflow with specialization feature

b70b733
Opened by Joshua Liebow-Feeser at 2022-09-23 04:55:01

The current nightly compiler gives the error "overflow evaluating requirement" when a type is used as a trait with a default impl. For example:

#![feature(specialization)]

fn main() {
    println!("{}", <(usize) as TypeString>::type_string());
}

trait TypeString {
    fn type_string() -> &'static str;
}

default impl<T> TypeString for T {
    fn type_string() -> &'static str {
        "unknown type"
    }
}

impl TypeString for () {
    fn type_string() -> &'static str {
        "()"
    }
}

(playground link)

...gives the following error:

error[E0275]: overflow evaluating the requirement `usize: TypeString`
 --> src/main.rs:4:20
  |
4 |     println!("{}", <(usize) as TypeString>::type_string());
  |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |
note: required by `TypeString::type_string`
 --> src/main.rs:8:5
  |
8 |     fn type_string() -> &'static str;
  |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Note that if we change <(usize) as TypeString>::type_string() to <() as TypeString>::type_string() - () has a specialized impl - it compiles and runs correctly.

  1. Note if you move the default keyword to the fn itself, it works. Not sure if this is intentional or not.

    vitalyd at 2018-02-24 20:26:17

  2. Oh, odd. And it looks like it's allowed to have the default keyword on both the impl and the fn, although that doesn't fix this bug. That's pretty confusing. Does anyone know if they do different things, or are they just synonyms?

    Joshua Liebow-Feeser at 2018-02-24 21:08:58

  3. impl with defaulted items and default impl are different as described in rust-lang/rfcs#1210. However, unfortunately, they had been implemented uniformly before #45404.

    Masaki Hara at 2018-02-25 02:59:07

  4. Am I misreading the RFC? It looks like it doesn't define default impl at all:

    Why mark default on items rather than the entire impl? Again, this is largely about granularity; it's useful to be able to pin down part of an impl while leaving others open for specialization. Furthermore, while this RFC doesn't propose to do it, we could easily add a shorthand later on in which default impl Trait for Type is sugar for adding default to all items in the impl.

    Joshua Liebow-Feeser at 2018-02-25 23:19:26

  5. Strange. The other parts of the RFC mention default impl with the clear example:

    // the `default` qualifier here means (1) not all items are impled
    // and (2) those that are can be further specialized
    default impl<T: Clone, Rhs> Add<Rhs> for T {
        fn add_assign(&mut self, rhs: R) {
            let tmp = self.clone() + rhs;
            *self = tmp;
        }
    }
    

    To me the RFC seems to be self-contradicting a bit.

    Anyway, from the example above, we can see that default impls with partial implementation are allowed. The remaining point is whether default impls with full implementation are used to resolve trait obligation. I think it is good to treat them uniformly with partial default impls, as @nikomatsakis says.

    Masaki Hara at 2018-02-26 14:08:33

  6. #![feature(specialization)]
    trait Type {
    	const FOO: bool;
    }
    default impl<T> Type for T {
    	const FOO: bool = false;
    }
    fn main() {
        <u8 as Type>::FOO;
    }
    

    Another example.

    Aidan Hobson Sayers at 2018-03-12 18:36:01

  7. Any progress on this? I ran into it again. Anybody I should consult on this? I'd like to help debug since this is blocking me on some work.

    EDIT: Not blocked anymore; I figured out a workaround.

    Joshua Liebow-Feeser at 2019-03-02 06:33:59

  8. Would you mind sharing that workaround @joshlf?

    Joel Höner at 2019-03-06 12:14:39

  9. It's unfortunately not a general workaround; I just figured out a way to avoid using this feature entirely so it wasn't a problem.

    Joshua Liebow-Feeser at 2019-03-06 17:59:40

  10. Anyone know, where to start fixing this? The workaround worked for my use case, but it's a little strange and unexpected. Just adding a message to the error about this issue could help some.

    Avi Dessauer at 2020-06-03 00:49:27

  11. lol i keep forgetting about this and running into it.

    estk at 2022-09-23 04:55:01