Can't Implement AsRef<f32> for [Point] Because of Orphan Trait Rules

I have a type Point that is just 4 f32 values and I'd like to be able to cheaply convert between &[Point] and &[f32]. I would expect to be able to use the AsRef trait for this, but when I do

impl AsRef<[f32]> for [Point] { ... }

I get the error:

error: the impl does not reference any types defined in this crate; only traits defined in the current crate can be implemented for arbitrary types

This seems wrong. The impl clearly references Point, does the compiler treat [Point] as not coming from my crate? Or am I missing something?

See Rust Compiler Error Index / https://github.com/rust-lang/rfcs/blob/master/text/1023-rebalancing-coherence.md . [Point] doesn't count as a local type, the same way Vec<Point> doesn't count as a local type.

2 Likes

I get why Vec<Point> isn't considered a local type (Vec is defined in another crate), but why not [Point]? According to the RFC you linked &Point would be considered a local type, so it seems intuitive (at least to me) that [Point] would fall in the same category.

&T is a reference to a T. It has a fixed size regardless of the T it points to, doesn't own it and cannot do anything with the T except pointing to it. When you do something to a &T, you actually end up doing it to the T it points to due to Deref coercion.

Vec<T> owns the contained Ts. It has to manage the memory where the Ts live. You can take a T out of a Vec by removeing it and get the actual object, not just a reference to it.

[T] is a slice of Ts. It's a region of memory that's inhabited by Ts, not unlike the memory Vec keeps its contents in. You usually don't handle such a thing in code directly, only (immutable or mutable) references to it. It's a special type (and marked as such in std).

1 Like

[quote="llogiq, post:4, topic:3190"]
[T] is a slice of Ts.
[/quote]More precisely a &[T] is a slice and trying to implement AsRef<[T]>, which returns &[T], is dealing with a slice. [T] owns its contents as well as Vec<T>.

1 Like