Why does T not implement AsRef<T>? - rust

This code does not compile:
fn ref_on_int<T>(_: T) where T: AsRef<i32> {}
fn main() {
ref_on_int(&0_i32)
}
because
the trait bound `i32: std::convert::AsRef<i32>` is not satisfied
Why is it so?
This could be useful for example with a newtype like
struct MyInt(i32);
impl AsRef<i32> for MyInt {
/* etc. */
}
then you could indifferently pass a reference on an i32 or a reference on a MyInt, because in the memory we have in both cases an i32.

AsRef and Borrow are pretty similar at first glance, but they are used for different things. The Book describes the difference between them pretty well:
Choose Borrow when you want to abstract over different kinds of
borrowing, or when you’re building a data structure that treats owned
and borrowed values in equivalent ways, such as hashing and
comparison.
Choose AsRef when you want to convert something to a reference
directly, and you’re writing generic code.
In your case Borrow is a more reasonable choice because there is no conversion involved.
As for the question of why AsRef is not implemented between different integral types, I guess this would go against the intent of Rust to be expressive about casts; I think it's similar to the question Why can't I compare two integers of different types?.

Here's an authoritative answer by Aaron Turon:
Borrow provides a blanket implementation T: Borrow<T>, which is essential for making the above collections work well. AsRef provides a different blanket implementation, basically &T: AsRef<U> whenever T: AsRef<U>, which is important for APIs like fs::open that can use a simpler and more flexible signature as a result. You can't have both blanket implementations due to coherence, so each trait is making the choice that's appropriate for its use case.

I think that is one of the differences of AsRef and Borrow.
That is, Borrow<T> is implemented directly for &T, while AsRef<T> is not implemented for &T.
Funny thing is that AsRef<U> is implemented for &T if T implements AsRef<U>. That is, if you can use AsRef with a type, you can use it with a reference to the same time.
And another funny thing is that Borrow<T> is implemented for &T but also for T!

Related

Why does the Rust standard library implement traits for both Thing and &Thing?

I was reading the question The trait `std::fmt::Write` is not implemented for `Stdout` when it should be where the asker noted that the rust documentation shows that the std::io::Write trait is implemented for both &Stdout and Stdout.
I don't understand why this is necessary or how you would use it. Isn't everything you define for Thing always implemented for &Thing? Why would you implement something for &Thing without implementing it for it's definition?
Isn't everything you define for Thing always implemented for &Thing?
No, an implementation for a type T will not automatically implement anything for &T. Now, sometimes blanket implementations can kick in, and if you pass a &&T to a function expecting a &T, then Rust will insert dereferences for you, but that does not mean the trait was implemented for &T, just that Rust helped you out a bit.
Why would you implement something for &Thing without implementing it for it's definition?
There's a very good example of that which we use all the time: String::from.
impl From<&str> for String {
fn from(value: &str) -> String {
...
}
}
From::<T>::from takes an argument, by value. No references or anything, just straight-up a value of type T. So we can never write a From<str> implementation for anything, since str is unsized and hence cannot be a function argument on its own. But it makes perfect sense to convert a &str to a String: that's just making an owned copy of the string.
Building on #Silvio-Mayolo's answer: in this particular case, there was originally just an implementation for Stdout; and the more-flexible implementation for &Stdout was added later, which provides a strict superset of functionality, notably allowing you to share the reference between threads. The original implementation can't be removed without breaking backwards compatibility with existing code using the by-value implementation (auto-deref isn't perfect, you would still need to go back and add an & in some situations).

What are "Blanket Implementations" in Rust?

When looking through the documentation of Rust structs, I often come across a section with the title "Blanket Implementations". I have heard that it can be used to implement a trait for all types or all types that match some condition but I am not sure why this is needed.
So what really are Blanket Implementations and why are they useful in Rust?
A blanket implementation is an implementation of a trait on a generic parameter:
impl<T> Trait for T
They usually also have where clauses involved since it is very hard to do anything useful to an unconstrained T. This does not cover things like impl<T> Trait for Vec<T>, which is a generic implementation but not a blanket implementation.
They are documented separately since they are applied without any particularity and may or may not be relevant to the type you're looking at. Whereas for the normal "Trait Implementations" section, all those traits at least had some thought for the specific type in mind (usually).
They are patently useful since it implements the trait for anything, in the entire ecosystem! If something satisfies the constraints, then it is able to take advantage of the implementation without needing to implement it themselves. You do not need to do anything to "opt-in" besides bringing the trait into scope.
Some notable ones:
From<T> is implemented for all T (the identity implementation)
Into<U> is implemented for all T where T: From<U> (the reflexive implementation that allows you to call .into() when a matching From implementation exists)
Any is implemented for all T where T: 'static
They are also needed to implement "trait aliases" where you create a trait that is constrained over multiple other traits (handy for reducing boilerplate and needed for multi-trait trait objects). You use a blanket implementation that the trait is implemented for any type satisfying the super-traits:
trait MyCoolAsyncTrait: AsyncRead + AsyncWrite + AsyncSeek + 'static {}
impl<T> MyCoolAsyncTrait for T
where
T: AsyncRead + AsyncWrite + AsyncSeek + 'static
{ }
Be careful when adding them to your types though. Because of their extensive scope, they can easily conflict with other trait implementations that may be desirable. You can only define one blanket implementation per type (even if the constraints are non-overlapping).
See also:
What are blanket implementations? (Rust forum)
Traits: Defining Shared Behavior in the Rust book
Is there any way to create a type alias for multiple traits?
How is there a conflicting implementation of `From` when using a generic type?
Why do blanket implementations for two different traits conflict?

In Rust, how to define a generic function for converting Vec<T> to Vec<U>

I need something like:
fn my_convert<T, U>(v: &Vec<U>)->Vec<T>{
v.iter().map(|&t|t).collect()
}
Of course, I suppose that only vector of builtin numeric types could be passed to the function.
The compiler tells me that I need to give the trait FromIterator for Vec
the trait std::iter::FromIterator<U> is not implemented for `std::vec::Vec
then, I added
impl<T, U> std::iter::FromIterator<U> for Vec<T>{
fn from_iter<I>(iter:I)->Self where I: IntoIterator<Item=U>{
Vec::<T>::new() // just for test
}
}
conflicting implementations of trait std::iter::FromIterator<_> for type std::vec::Vec<_>:
note: conflicting implementation in crate alloc:
- impl std::iter::FromIterator for std::vec::Vec;rustc(E0119)
As we all known, in C++, this kind of conversion is straight forward and intutive. I am a beginner of Rust. I don't know how to define a function like above. I even don't known if it is could be achieved in Rust because of the complexity of the trait for generic type.
Thanks!
The Rust From trait is your general purpose "how to get from A to B". If there's a reasonable way to go from U to T, then T: From<U> will be implemented. Consider
fn my_convert<T, U>(v: Vec<U>) -> Vec<T>
where T: From<U> {
v.into_iter().map(T::from).collect()
}
Note that I do take ownership of the v vector. the From::from function consumes its argument, so we should also consume the vector. You could write a completely general version of this function that works with arbitrary iterators, and then it'll be easier to go back and forth between iterators which own their data and those that only borrow.
fn my_convert1<T, U, I>(v: I) -> Vec<T>
where T: From<U>,
I: Iterator<Item=U> {
v.map(T::from).collect()
}
But at that point, you'd be better off just writing v.map(T::from).collect() directly, and any reasonably proficient Rust programmer will instantly know what you're doing.
One point to note here, since you've mentioned that you're a C++ programmer. In C++, template functions can simply be written as-is, and then, when the caller instantiates a version of it, the compiler checks whether it's okay or not. So your proposed function in the OP works fine, since the compiler only checks it when it's called. Rust (and indeed most languages with generics) isn't like that.
In Rust, on the other hand, when you write the my_convert function, Rust checks at that time that all of the types line up. You can't write a function that only works some of the time. If you say my_convert works for all T and U, then it had better work for all of them, and Rust's type checker and borrow checker are going to verify that immediately. If not, then you'd better do as I did above and restrict the type signature. If you've used C++20 at all, you can think of traits as being somewhat similar to the "concepts" feature in C++20.

Should trait bounds be duplicated in struct and impl?

The following code uses a struct with generic type. While its implementation is only valid for the given trait bound, the struct can be defined with or without the same bound. The struct's fields are private so no other code could create an instance anyway.
trait Trait {
fn foo(&self);
}
struct Object<T: Trait> {
value: T,
}
impl<T: Trait> Object<T> {
fn bar(object: Object<T>) {
object.value.foo();
}
}
Should the trait bound for the structure should be omitted to conform to the DRY principle, or should it be given to clarify the dependency? Or are there circumstances one solution should be preferred over the other?
I believe that the existing answers are misleading. In most cases, you should not put a bound on a struct unless the struct literally will not compile without it.
tl;dr
Bounds on structs express the wrong thing for most people. They are infectious, redundant, sometimes nearsighted, and often confusing. Even when a bound feels right, you should usually leave it off until it's proven necessary.
(In this answer, anything I say about structs applies equally to enums.)
0. Bounds on structs have to be repeated everywhere the struct is
This is the most obvious, but (to me) least compelling reason to avoid writing bounds on structs. As of this writing (Rust 1.65), you have to repeat every struct's bounds on every impl that touches it, which is a good enough reason not to put bounds on structs for now. However, there is an accepted RFC (implied_bounds) which, when implemented and stabilized, will change this by inferring the redundant bounds. But even then, bounds on structs are still usually wrong:
1. Bounds on structs leak out of abstractions.
Your data structure is special. "Object<T> only makes sense if T is Trait," you say. And perhaps you are right. But the decision affects not just Object, but any other data structure that contains an Object<T>, even if it does not always contain an Object<T>. Consider a programmer who wants to wrap your Object in an enum:
enum MyThing<T> { // error[E0277]: the trait bound `T: Trait` is not satisfied
Wrapped(your::Object<T>),
Plain(T),
}
Within the downstream code this makes sense because MyThing::Wrapped is only used with Ts that do implement Thing, while Plain can be used with any type. But if your::Object<T> has a bound on T, this enum can't be compiled without that same bound, even if there are lots of uses for a Plain(T) that don't require such a bound. Not only does this not work, but even if adding the bound doesn't make it entirely useless, it also exposes the bound in the public API of any struct that happens to use MyThing.
Bounds on structs limit what other people can do with them. Bounds on code (impls and functions) do too, of course, but those constraints are (presumably) required by your own code, while bounds on structs are a preemptive strike against anyone downstream who might use your struct in an innovative way. This may be useful, but unnecessary bounds are particularly annoying for innovators because they constrain what can compile without usefully constraining what can actually run (more on that in a moment).
2. Bounds on structs are redundant with bounds on code.
So you don't think downstream innovation is possible? That doesn't mean the struct itself needs a bound. To make it impossible to construct an Object<T> without T: Trait, it is enough to put that bound on the impl that contains Object's constructor(s); if it's impossible to call a_method on an Object<T> without T: Trait you can say that on the impl that contains a_method, or perhaps on a_method itself. (Until implied_bounds is implemented, you have to, anyway, so you don't even have the weak justification of "saving keystrokes.")
Even and especially when you can't think of any way for downstream to use an un-bounded Object<T>, you should not forbid it a priori, because...
3. Bounds on structs mean something different to the type system than bounds on code.
A T: Trait bound on Object<T> means more than "all Object<T>s have to have T: Trait"; it actually means something like "the concept of Object<T> itself does not make sense unless T: Trait", which is a more abstract idea. Think about natural language: I've never seen a purple elephant, but I can easily name the concept of "purple elephant" despite the fact that it corresponds to no real-world animal. Types are a kind of language and it can make sense to refer to the idea of Elephant<Purple>, even when you don't know how to create one and you certainly have no use for one. Similarly, it can make sense to express the type Object<NotTrait> in the abstract even if you don't and can't have one in hand right now. Especially when NotTrait is a type parameter, which may not be known in this context to implement Trait but in some other context does.
Case study: Cell<T>
For one example of a struct that originally had a trait bound which was eventually removed, look no farther than Cell<T>, which originally had a T: Copy bound. In the RFC to remove the bound many people initially made the same kinds of arguments you may be thinking of right now, but the eventual consensus was that "Cell requires Copy" was always the wrong way to think about Cell. The RFC was merged, paving the way for innovations like Cell::as_slice_of_cells, which lets you do things you couldn't before in safe code, including temporarily opt-in to shared mutation. The point is that T: Copy was never a useful bound on Cell<T>, and it would have done no harm (and possibly some good) to leave it off from the beginning.
This kind of abstract constraint can be hard to wrap one's head around, which is probably one reason why it's so often misused. Which relates to my last point:
4. Unnecessary bounds invite unnecessary parameters (which are worse).
This does not apply to all cases of bounds on structs, but it is a common point of confusion. You may, for instance, have a struct with a type parameter that should implement a generic trait, but not know what parameter(s) the trait should take. In such cases it is tempting to use PhantomData to add a type parameter to the main struct, but this is usually a mistake, not least because PhantomData is hard to use correctly. Here are some examples of unnecessary parameters added because of unnecessary bounds: 1 2 3 4 5 In the majority of such cases, the correct solution is simply to remove the bound.
Exceptions to the rule
Okay, when do you need a bound on a struct? I can think of two possible reasons.
In Shepmaster's answer, the struct will simply not compile without a bound, because the Iterator implementation for I actually defines what the struct contains. One other way that a struct won't compile without a bound is when its implementation of Drop has to use the trait somehow. Drop can't have bounds that aren't on the struct, for soundness reasons, so you have to write them on the struct as well.
When you're writing unsafe code and you want it to rely on a bound (T: Send, for example), you might need to put that bound on the struct. unsafe code is special because it can rely on invariants that are guaranteed by non-unsafe code, so just putting the bound on the impl that contains the unsafe is not necessarily enough.
But in all other cases, unless you really know what you're doing, you should avoid bounds on structs entirely.
Trait bounds that apply to every instance of the struct should be applied to the struct:
struct IteratorThing<I>
where
I: Iterator,
{
a: I,
b: Option<I::Item>,
}
Trait bounds that only apply to certain instances should only be applied to the impl block they pertain to:
struct Pair<T> {
a: T,
b: T,
}
impl<T> Pair<T>
where
T: std::ops::Add<T, Output = T>,
{
fn sum(self) -> T {
self.a + self.b
}
}
impl<T> Pair<T>
where
T: std::ops::Mul<T, Output = T>,
{
fn product(self) -> T {
self.a * self.b
}
}
to conform to the DRY principle
The redundancy will be removed by RFC 2089:
Eliminate the need for “redundant” bounds on functions and impls where
those bounds can be inferred from the input types and other trait
bounds. For example, in this simple program, the impl would no longer
require a bound, because it can be inferred from the Foo<T> type:
struct Foo<T: Debug> { .. }
impl<T: Debug> Foo<T> {
// ^^^^^ this bound is redundant
...
}
It really depends on what the type is for. If it is only intended to hold values which implement the trait, then yes, it should have the trait bound e.g.
trait Child {
fn name(&self);
}
struct School<T: Child> {
pupil: T,
}
impl<T: Child> School<T> {
fn role_call(&self) -> bool {
// check everyone is here
}
}
In this example, only children are allowed in the school so we have the bound on the struct.
If the struct is intended to hold any value but you want to offer extra behaviour when the trait is implemented, then no, the bound shouldn't be on the struct e.g.
trait GoldCustomer {
fn get_store_points(&self) -> i32;
}
struct Store<T> {
customer: T,
}
impl<T: GoldCustomer> Store {
fn choose_reward(customer: T) {
// Do something with the store points
}
}
In this example, not all customers are gold customers and it doesn't make sense to have the bound on the struct.

How to idiomatically require a trait to retrieve a slice

I'm working on a library that operates on [T] slices. I would like the library user to specify a type that can retrieve a slice in a mutable or immutable way.
My current lib defines 2 traits
pub trait SliceWrapper<T> {
fn slice(&self) -> &[T];
}
pub trait SliceWrapperMut<T> {
fn slice_mut (&mut self) -> &mut [T];
}
But the names slice and slice_mut seem arbitrary and not somewhere in the core Rust libs.
Is there a trait I should be requiring instead, like Into::<&mut [T]> ?
I'm afraid that Into consumes the type rather than just referencing it, so I can't simply demand the caller type implements core::convert::Into, can I?
The simplest way to answer this is to look at the documentation for existing types that more or less do what you want. This sounds like something Vec would do, so why not look at the documentation for Vec?
If you search through it looking for -> &, you'll find numerous methods that return borrowed slices:
Vec::as_slice
Borrow::borrow
Index::<Range<usize>>::index (plus for RangeTo<usize>, RangeFrom<usize>, RangeFull, RangeInclusive<usize>, and RangeToInclusive<usize>)
Deref::deref
AsRef::<[T]>::as_ref
Which of these should you implement? I don't know; which ones make sense? Read the documentation on each method (and the associated trait) and see if what it describes is what you want to permit. You say "that can retrieve a slice", but you don't really explain what that means. A big part of traits is not just abstracting out common interfaces, but giving those interfaces meaning beyond what the code strictly allows.
If the methods listed aren't right; if none of them quite convey the correct semantics, then make a new trait. Don't feel compelled to implement a trait just because you technically can.
As for Into, again, read the documentation:
A conversion that consumes self, which may or may not be expensive.
Emphasis mine. Implementing Into in this context makes no sense: if you consume the value, you can't borrow from it. Oh, also:
Library authors should not directly implement this trait, but should prefer implementing the From trait, which offers greater flexibility and provides an equivalent Into implementation for free, thanks to a blanket implementation in the standard library.
So yeah, I wouldn't use Into for this. Or From.

Resources