Conflicting implementations of trait, `Copy` or not

trait CopySliceIndex {

}

impl CopySliceIndex for std::ops::RangeTo<usize> {}

trait CloneSliceIndex {

}

impl CloneSliceIndex for std::ops::RangeFrom<usize> {}


pub(crate) trait StrIndexExt<I: std::slice::SliceIndex<str>> {
    fn get_or_err(&self, i: I) -> Result<&I::Output, AppError>;
}

impl<I: std::slice::SliceIndex<str> + std::fmt::Debug + Copy + CopySliceIndex> StrIndexExt<I> for str {
    fn get_or_err(&self, i: I) -> Result<&I::Output, AppError> {
        match self.get(i) {
            Some(v) => Ok(v),
            None => Err(AppError::StrSliceError {
                string: self.to_string(),
                slice: format!("{:?}", i),
            }),
        }
    }
}

impl<I: std::slice::SliceIndex<str> + std::fmt::Debug + CloneSliceIndex> StrIndexExt<I> for str {
    fn get_or_err(&self, i: I) -> Result<&I::Output, AppError> {
        match self.get(i) {
            Some(v) => Ok(v),
            None => Err(AppError::StrSliceError {
                string: self.to_string(),
                slice: "unknown".into(),
            }),
        }
    }
}
error[E0119]: conflicting implementations of trait `StrIndexExt<_>` for type `str`
  --> toytool/src/aux.rs:94:1
   |
82 | impl<I: std::slice::SliceIndex<str> + std::fmt::Debug + Copy + CopySliceIndex> StrIndexExt<I> for str {
   | ----------------------------------------------------------------------------------------------------- first implementation here
...
94 | impl<I: std::slice::SliceIndex<str> + std::fmt::Debug + CloneSliceIndex> StrIndexExt<I> for str {
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `str`


Can I solve this?

I want to impl two versions by I: Copy or not.

That’s not currently possible. The general term is “specialization,” which is a feature that lots of people want, but the effort to implement it keeps getting bogged down in tricky soundness issues.

2 Likes

For the specific example given, std::slice::SliceIndex is a sealed trait (all the implementors are in std), so you could write a macro for both implementations and use them to implement the trait for every implementor.

2 Likes