Implementing rust traits without a type conflict

As a learning exercise, I am trying to implement a pattern for parsing a string. However, the compiler says no! What should I be doing? Many thanks, Steve

use num_traits::{ConstOne, ConstZero, Num};

trait ParseItemSteve<'a, T> {
    fn parse_item(slice: &'a str, term: &str) -> Option<(&'a str, T)> {
        None
    }
}

impl<'a, T> ParseItemSteve<'a, T> for T
where
    T: Num + ConstZero + ConstOne,
{
    fn parse_item(slice: &'a str, term: &str) -> Option<(&'a str, T)> {
        None
    }
}

impl<'a> ParseItemSteve<'a, bool> for bool {
    fn parse_item(slice: &'a str, term: &str) -> Option<(&'a str, bool)> {
        if slice.starts_with(term) {
            Some((&slice[term.len()..], true))
        } else {
            None
        }
    }
}

Please read the pinned code formatting guide.

You can replace your blanket implementation with a macro that implements the trait for specific types.

Thank you very much!
And I will make sure to use the right pinned code conventions in the future :slight_smile:

1 Like

I was hoping for a different answer. I want to implement a trait for various types, and the issue is that the types might overlap.
Is there something idiomatic to Rust that will help me understand this problem in general?

See this section of the re-rebalanced orphan rules RFC for an explanation of what coherence is,[1] and why the orphan rules -- which limit which traits you can implement for which types[2] -- exist. There's some more motivation on why the orphan rules are balanced how they are in this pre-1.0 RFC.

Now, for your particular situation: You have a blanket implementation -- an implementation for all T, modulo some where clauses -- and you have an implementation for a foreign type (bool) that does not, today, meet those where clauses.

For coherence to work,[3] it has to be able to rely on the where clauses not holding. This is often called "negative reasoning". But this is an issue in the context of balancing what changes are supposed to be non-breaking: like the error notes,

   = note: upstream crates may add a new impl of trait `num_traits::Num` for type `bool` in future versions
   = note: upstream crates may add a new impl of trait `num_traits::ConstZero` for type `bool` in future versions
   = note: upstream crates may add a new impl of trait `num_traits::ConstOne` for type `bool` in future versions

The error preventing your bool implementation ensures it's not a breaking change for num_traits to add these implementations for its local trait in the future.

(If you could have your bool implementation and num_traits added those implementations, coherence would have to break your crate due to overlapping implementations.)

The limits on negative reasoning follows the orphan rules[4] (as updated by RFC 2451). You're not allowed to impl Num for bool for example, so you can't rely on the lack of such an implementation today.


If you use the macro and not a blanket implementation, num_traits adding those implementations can't break your crate.

Specialization may some day allow overlapping implementations, so long as the intersection of all overlaps is exactly covered by a specializing implementation. At least, I believe that's how it works under the current unstable feature. However, that is a long way off (if ever[5]), and the feature as it is today isn't a solution to your OP.[6]


  1. a lack of coherence is also generally unsound, in addition to being confusing ↩︎

  2. especially when implementing generically ↩︎

  3. without specialization at least (which we do not have yet) ↩︎

  4. n.b. the Type: !Trait pseudo-syntax used in that section has a more nuanced meaning than "the Type doesn't currently implement the Trait" in modern Rust language development ↩︎

  5. or if ever in its current form ↩︎

  6. I'm not sure why and whether or not it's by design. ↩︎