I'm working on a library that has a function that I would like to be able to accept a HashMap of any hashing algorithm. But when I try to call it with a particular type of HashMap, such as a FnvHashMap, the compiler complains.
pub fn func(map: HashMap<u32, u32>) {}
let map: FnvHashMap<u32, u32> = FnvHashMap::default();
func(map);
error[E0308]: mismatched types
--> lib.rs:42:10
|
42 | func(map);
| ^^^ expected struct `RandomState`, found struct `BuildHasherDefault`
|
= note: expected struct `HashMap<_, _, RandomState>`
found struct `HashMap<_, _, BuildHasherDefault<FnvHasher>>`
As FnvHashMap is only a type alias I thought this wouldn't be a problem.
I'm sure there's a way to do this, but I haven't found it yet. What's the correct way?
The definition of HashMap in the docs is:
pub struct HashMap<K, V, S = RandomState> { /* fields omitted */ }
RandomState is the default type, but it can be overridden with another type, including a generic. It may not be immediately clear, but most of the HashMap methods are declared in an impl block that constraints S: BuildHasher, which is the trait you need to bound it by:
use std::hash::BuildHasher;
pub fn func<S: BuildHasher>(map: HashMap<u32, u32, S>) {}
Related
I have the following Rust code
use std::{
cell::{Ref, RefCell},
rc::Rc,
};
trait TraitA {
fn data(&self) -> Ref<Vec<Rc<dyn TraitB>>>;
}
struct A {
data: RefCell<Vec<Rc<B>>>,
}
impl TraitA for A {
fn data(&self) -> Ref<Vec<Rc<dyn TraitB>>> {
self.data.borrow()
}
}
trait TraitB {}
struct B {}
impl TraitB for B {}
However I get the following error
error[E0308]: mismatched types
--> src/lib.rs:16:9
|
15 | fn data(&self) -> Ref<Vec<Rc<dyn TraitB>>> {
| ------------------------ expected `Ref<'_, Vec<Rc<(dyn TraitB + 'static)>>>` because of return type
16 | self.data.borrow()
| ^^^^^^^^^^^^^^^^^^ expected trait object `dyn TraitB`, found struct `B`
|
= note: expected struct `Ref<'_, Vec<Rc<(dyn TraitB + 'static)>>>`
found struct `Ref<'_, Vec<Rc<B>>>`
I have tried setting the data field in A to have type RefCell<Vec<Rc<dyn TraitB>>>. That will work.
However in my implementation I want to have the field contain the type B as I want the Vec to store only type B, not any implementation of TraitB.
My understanding is that Rust should be able to coerce the B type as required as long as it implements the trait TraitB, which in the example above, B does indeed implement TraitB.
For example, in the following snippet, Rc<dyn TraitB> is successfully coerced to Rc<B> no problem.
struct C {
weak_ref: Weak<B>,
}
impl C {
fn upgrade_weak_ref(&self) -> Rc<dyn TraitB> {
self.weak_ref.upgrade().unwrap()
}
}
So my question is, why is the coercion not working in the first example above. Is it because it's contained in a Ref? Is there a workaround or some way to make it work without changing the type of the data field in struct A?
Rc<dyn TraitB> is twice the size of Rc<B> (two usizes versus one). Therefore, there cannot be a way to coerce a Vec<Rc<B>> to Vec<Rc<dyn TraitB>> without rebuilding the vector.
You can store Vec<Rc<dyn TraitB>>, but have only methods that push Bs and therefore protect against misuse.
It seems that when deriving Clone, Rust forwards the Clone trait requirement to Generics that do not require the trait, like if they are wrapped inside an Arc.
Do I misunderstand how Clone works or is this a compiler mistake?
Consider the following code, where a.clone() works, but b.clone() does not.
Also note that without the b.clone() call, the code compiles fine, indicating that #[derive(Clone)] worked.
use std::sync::Arc;
struct Unclonable {}
struct A<T>(Arc<T>);
impl<T> Clone for A<T> {
fn clone(&self) -> Self {
Self(self.0.clone())
}
}
#[derive(Clone)]
struct B<T>(Arc<T>);
fn main() {
let a = A(Arc::new(Unclonable {}));
let b = B(Arc::new(Unclonable {}));
// Works
a.clone();
// Fails
b.clone();
}
|
3 | struct Unclonable {}
| ----------------- doesn't satisfy `Unclonable: Clone`
...
13 | struct B<T>(Arc<T>);
| --------------------
| |
| method `clone` not found for this
| doesn't satisfy `B<Unclonable>: Clone`
...
22 | b.clone();
| ^^^^^ method cannot be called on `B<Unclonable>` due to unsatisfied trait bounds
|
= note: the following trait bounds were not satisfied:
`Unclonable: Clone`
which is required by `B<Unclonable>: Clone`
= help: items from traits can only be used if the trait is implemented and in scope
= note: the following trait defines an item `clone`, perhaps you need to implement it:
candidate #1: `Clone`
help: consider annotating `Unclonable` with `#[derive(Clone)]`
|
3 | #[derive(Clone)]
|
When I expand the macros, I see the following generated code:
#![feature(prelude_import)]
#[prelude_import]
use std::prelude::rust_2018::*;
#[macro_use]
extern crate std;
use std::sync::Arc;
struct Unclonable {}
struct A<T>(Arc<T>);
impl<T> Clone for A<T> {
fn clone(&self) -> Self {
Self(self.0.clone())
}
}
struct B<T>(Arc<T>);
#[automatically_derived]
#[allow(unused_qualifications)]
impl<T: ::core::clone::Clone> ::core::clone::Clone for B<T> {
#[inline]
fn clone(&self) -> B<T> {
match *self {
B(ref __self_0_0) => B(::core::clone::Clone::clone(&(*__self_0_0))),
}
}
}
fn main() {
let a = A(Arc::new(Unclonable {}));
let b = B(Arc::new(Unclonable {}));
a.clone();
b.clone();
}
What is going on?
Why would the Rust compiler add <T: ::core::clone::Clone>??
Or is this just one of those cases where the intended way is to implement Clone manually?
This is not a compiler bug, in the sense that it's a documented behavior, even though one might find it weird. The compiler will automatically add constraints to generic types when deriving, even if those constraints are not actually required in the implementation. For instance, deriving Clone for B<T> will only implement Clone for B<T> where T: Clone, even though it would be possibly to implement that regardless of whether T is Clone.
So, for the time being (maybe the compiler will get smarter about these cases in the future), yes, it's one of those cases where you have to implement manually.
If you don't mind a smallo dependency, you can avoid the drudgery1 of manual implementation using the derivative crate:
#[derive(Derivative)]
#[derivative(Clone(bound = ""))]
struct B<T>(Arc<T>);
Playground
1 In the case of a small struct the drudgery is not that bad, but in case of an enum with many variants, the implementation gets quite large.
I am learning Rust and don't understand why the following doesnt work. I gather we are unable to clone an Rc pointer over a trait object? How am I to pass such a reference to an function defined only by a trait, as attempted in some_function?
use std::rc::Rc;
trait SomeTrait {}
struct SomeThing {}
impl SomeTrait for SomeThing {}
fn some_function(s: Rc<dyn SomeTrait>) {}
fn another_function(s: &Rc<dyn SomeTrait>) {}
fn main() {
let s = Rc::new(SomeThing{});
// This doesnt work
some_function(Rc::clone(&s));
// I could do this
some_function(s);
// But then I could not do this
some_function(s);
// For that matter, neither can I do this
another_function(&s);
}
If you look at the error messages of the compiler you will see this:
error[E0308]: mismatched types
|
14 | some_function(Rc::clone(&s));
| ^^ expected trait object `dyn SomeTrait`, found struct `SomeThing`
|
= note: expected reference `&Rc<dyn SomeTrait>`
found reference `&Rc<SomeThing>`
That means the compiler mis-infers the type of s to Rc<SomeThing> instead of the Rc<dyn SomeTrait> you were looking for, which can be confirmed by the usual trick of providing a blatantly incorrect type to let s:
error[E0308]: mismatched types
--> src/main.rs:11:17
|
11 | let s: () = Rc::new(SomeThing{});
| -- ^^^^^^^^^^^^^^^^^^^^ expected `()`, found struct `Rc`
| |
| expected due to this
|
= note: expected unit type `()`
found struct `Rc<SomeThing>`
Since Rust wrappers are invariant, an Rc<SomeThing> and an Rc<dyn SomeTrait> are completely incompatible values, there is no way to just use one for the other.
The solution is to simply explicitely type s correctly:
use std::rc::Rc;
trait SomeTrait {}
struct SomeThing {}
impl SomeTrait for SomeThing {}
fn some_function(s: Rc<dyn SomeTrait>) {}
fn another_function(s: &Rc<dyn SomeTrait>) {}
fn main() {
let s: Rc<dyn SomeTrait> = Rc::new(SomeThing{});
// This doesnt work
some_function(Rc::clone(&s));
// For that matter, neither can I do this
another_function(&s);
}
Obviously the two calls in the middle can't work, as the first one will move the local Rc, which the second one (and the final call) still want.
I have this simple snippet of code, which uses an arena for memory allocation and a trait CloneInto whose purpose is to clone a structure from unknown origins into an Arena, adjusting the lifetimes as it goes:
struct Arena;
impl Arena {
fn insert<'a, T: 'a>(&'a self, _: T) -> &'a mut T { unimplemented!() }
}
trait CloneInto<'a> {
type Output: 'a;
fn clone_into(&self, arena: &'a Arena) -> Self::Output;
}
It can be used as is:
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Eq, Ord, Hash)]
struct Simple<'a> { a: &'a usize }
impl<'a, 'target> CloneInto<'target> for Simple<'a> {
type Output = Simple<'target>;
fn clone_into(&self, arena: &'target Arena) -> Simple<'target> {
Simple { a: arena.insert(*self.a) }
}
}
fn main() {
let arena = Arena;
let _ = Simple { a: &1 }.clone_into(&arena);
}
Or could, until the update to Rust 1.18. Now the compiler emits this error:
error[E0034]: multiple applicable items in scope
--> <anon>:25:30
|
25 | let _ = Simple { a: &1 }.clone_into(&arena);
| ^^^^^^^^^^ multiple `clone_into` found
|
note: candidate #1 is defined in an impl of the trait `CloneInto` for the type `Simple<'_>`
--> <anon>:18:5
|
18 | / fn clone_into(&self, arena: &'target Arena) -> Simple<'target> {
19 | | Simple { a: arena.insert(*self.a) }
20 | | }
| |_____^
= note: candidate #2 is defined in an impl of the trait `std::borrow::ToOwned` for the type `_`
even though I do not even import std or ToOwned!
This is an unfortunate effect of how method resolution works in Rust. Unlike other languages which feature overloading, in Rust the exact function to be called must be resolved unambiguously with no regard for its arguments.
In this specific case, Rust 1.18 brings a new nightly method called clone_into on the ToOwned trait, and the ToOwned trait is implemented unconditionally for all types implementing Clone and imported automatically (via the prelude).
The fact that this method cannot be called on stable has no bearing; the method is first considered for resolution, and an error will be emitted if it is actually used.
Note that even though irking, there are benefits to this method of resolution: it is often unclear to a human being which overload is selected when several appear to be available, or why the expected overload is NOT being selected. By erring on the side of explicitness, Rust makes it a no-brainer.
Unfortunately, in this case this results in Simple::clone_into() becoming ambiguous.
There is no way to opt out of the ToOwned implementation (not without giving up Clone and Copy), so instead one must switch to an unambiguous call to clone_into using Fully Qualified Syntax (FQS):
fn main() {
let arena = Arena;
let _ = CloneInto::clone_into(&Simple { a: &1 }, &arena);
}
If I have a trait, and a function that accepts a generic type constrained to that type, everything works fine. If I try to pass in a reference to that type, I get a compilation error.
trait Trait {
fn hello(&self) -> u32;
}
struct Struct(u32);
impl Trait for Struct {
fn hello(&self) -> u32 {
self.0
}
}
fn runner<T: Trait>(t: T) {
println!("{}", t.hello())
}
fn main() {
let s = Struct(42);
// Works
runner(s);
// Doesn't work
runner(&s);
}
error[E0277]: the trait bound `&Struct: Trait` is not satisfied
--> src/main.rs:24:5
|
24 | runner(&s);
| ^^^^^^ the trait `Trait` is not implemented for `&Struct`
|
= help: the following implementations were found:
<Struct as Trait>
note: required by `runner`
--> src/main.rs:13:1
|
13 | fn runner<T: Trait>(t: T) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^
I can fix the issue by implementing the trait for any reference to a type that implements the trait:
impl<'a, T> Trait for &'a T
where
T: Trait,
{
fn hello(&self) -> u32 {
(*self).hello()
}
}
The piece of information that I'm missing is when shouldn't I implement this? Asked another way, why doesn't the compiler automatically implement this for me? Since it currently doesn't, I assume there must be cases where having this implementation would be disadvantageous.
when shouldn't I implement this? Asked another way, why doesn't the compiler automatically implement this for me? Since it currently doesn't, I assume there must be cases where having this implementation would be disadvantageous.
As an example, the Default trait immediately came to mind.
pub trait Default {
fn default() -> Self;
}
I could implement it for T, but there is no way to automatically implement it for &T.
The particular trait you are writing here only takes self by reference, and that is the only reason it is possible to write the additional implementation you did.
For this reason, taking the parameter to runner() by value is probably undesirable; you should instead be taking it by reference. This guideline can apply generally: if it is possible to implement the trait for a reference then rather than wondering “should I implement it?” you should wonder “why would I implement it?” for the only cases where you would use it should probably be altered to take the object by reference in the first place.