Compound where clause to bound impl. Why do these impl conflict?

Hello,

I'm trying to create a trait that can apply to both a String (and &str) as well as other fixed-stride types (Vec, Slice, Array), but use different behavior for Strings because they're not fixed-stride when interpreted as unicode chars.

I'm having trouble coming up with trait bounds that don't conflict.

use core::borrow::Borrow;

trait Key<KeyCharT> {
    fn get_key_chars(&self) -> Vec<KeyCharT>;
}

/// The implementation of Key for &[KeyCharT] (generic fixed-size arrays and slices)
impl <KeyT, KeyCharT>Key<KeyCharT> for KeyT
    where
    KeyCharT : 'static + Copy,
    KeyT : Borrow<[KeyCharT]>
{
    fn get_key_chars(&self) -> Vec<KeyCharT> {
        self.borrow().to_vec()
    }
}

/// The implementation of Key for String and &str, which is potentially UTF-8 encoded
impl <KeyT>Key<char> for KeyT
    where
    KeyT : Borrow<str>
{
    fn get_key_chars(&self) -> Vec<char> {
        self.borrow().chars().collect()
    }
}

fn main() {
    
    //Works, using the &str implementation
    let hello_str = "hello".to_string();
    let hello_chars : Vec<char> = hello_str.get_key_chars();
    println!("{:?}", hello_chars);
    
    //Works using the &[T] implementation
    let hello_char_array = ['h', 'e', 'l', 'l', 'o'];
    let hello_chars : Vec<char> = hello_char_array.get_key_chars();
    println!("{:?}", hello_chars);

    // //If the trait impl bounds actually overlapped, then this
    // //would work, but obviously it doesn't...
    // let hello_str = "hello".to_string();
    // let hello_chars : Vec<char> = hello_str.as_str().borrow().to_vec();
    // println!("{:?}", hello_chars);
}

Has anyone found a solution to this sort of issue?

Thank you.

There's no real solution to this problem; a type absolutely can implement Borrow<str> and Borrow<[T]> at the same time, so what you want isn't possible as-is. An immediate solution would be to implement your trait for specific types, such as slices, arrays, Vec, str, and String.

Thanks for the reply.

a type absolutely can implement Borrow<str> and Borrow<[T]> at the same time

But can a type that implements Borrow<str> also implement Borrow<[char]>? If that is possible, then that's my solution.

If that isn't possible to simultaneously implement Borrow<str> and Borrow<[char]>, it seems that any type the Borrow<str> implementation applies to must have KeyCharT == char, and therefore implement Borrow<[char]> as per impl bounds, so when the bounds are considered holistically, the two impl couldn't apply to the same type.

What am I misunderstanding?

Thanks again.

struct SomeWeirdType;

impl Borrow<[char]> for SomeWeirdType {
    fn borrow(&self) -> &[char] {
        &[]
    }
}

impl Borrow<str> for SomeWeirdType {
    fn borrow(&self) -> &str {
        ""
    }
}
1 Like

Wow. Ok. So that explains why the bounds conflict.

Rats. Unfortunately it doesn't help meaningfully get the data in the case that a reallocation and shuffle is necessary.

Thanks for the explanation!

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.