I have a function that can take a &[&str] or a &[String] and return different values based on the slice. It works fine using == if I add a PartialEq constraint:
You can't match a String against a string slice directly, and you can't do it on the other side of a trait or generic either. Rust's pattern matching mechanism requires you to be able to write out the constructor for the type in the pattern, so you can't match a trait, a generic parameter, or the internal structure of a type with private internals, because the constructor is abstracted away.
Your .as_foo() idea is the best way to do this, because it allows you to convert the type into something you can construct.
Alternatively, you can do something like this, but it does an allocation:
pub fn info1<'a, S>(path: &[S]) -> Option<String>
where
S: AsRef<str>,
{
match &path.iter().map(|s| s.as_ref()).collect::<Vec<_>>()[..] {
["a", "b"] => Some("It's a b!".to_string()),
_ => None,
}
}
Can you explain this a little bit more? I can't find any documentation on what exactly Rust does when you match against something like ["a", _, "b"]. It obviously doesn't desugar to something like
[ ] is the Rust syntax for constructing an array or slice, so you can use that syntax in a pattern to match an array's or slice's internals. Likewise, (,) constructs tuples, Enum::Variant ... constructs enums, Struct {...} constructs structs, etc., and you can use those in patterns to match the internals of tuples, enums, etc., respectively. The only way to pattern match a String's internals is to write String { ... }. So you need to write the constructor of the type to match the internal structure of that type.
Essentially, the language knows how to construct these types, so it can 'deconstruct' them into pattern bindings. If you are dealing with data that can't be constructed trivially and unambiguously, like generics, traits, or private data, then you can't pattern match its internal structure.
(I keep saying 'internal structure', because you can match anything with a simple variable, like let x = ....)
The == operator calls user-defined (arbitrary) code, so it cannot be used to create patterns either. Nor can anything constructed through a function call. Only language builtin constructors can be used. So if you need to pattern match something more complex, you have to convert it into something constructable first.
Ah ok so basically you can only match on primitive types (or struct/enum/slices of primitive types) because it uses built in comparison logic rather than ==?