I want to use the write_fmt method on two different types of object:
use std::fmt::Write;
use std::io::Write;
fn main() {
let mut a = String::new();
let mut b = std::fs::File::create("test").unwrap();
a.write_fmt(format_args!("hello"));
b.write_fmt(format_args!("hello"));
}
I get an error when using Write because they are both named the same:
error[E0252]: a trait named `Write` has already been imported in this module
--> src/main.rs:8:5
|
7 | use std::fmt::Write;
| --------------- previous import of `Write` here
8 | use std::io::Write;
| ^^^^^^^^^^^^^^ `Write` already imported
a.write_fmt(format_args!("hello"));
b.write_fmt(format_args!("hello"));
Or I get an error saying the trait is not available:
error[E0599]: no method named `write_fmt` found for type `std::fs::File` in the current scope
--> src/main.rs:76:4
|
76 | b.write_fmt(format_args!("hello"));
| ^^^^^^^^^
|
= help: items from traits can only be used if the trait is in scope; the following trait is implemented but not in scope, perhaps add a `use` for it:
= help: candidate #1: `use std::io::Write;`
You can call the trait method directly:
fn main() {
let mut a = String::new();
let mut b = std::fs::File::create("test").unwrap();
std::fmt::Write::write_fmt(&mut a, format_args!("hello"));
std::io::Write::write_fmt(&mut b, format_args!("hello"));
}
You can also choose to only import the trait in a smaller scope:
fn main() {
let mut a = String::new();
let mut b = std::fs::File::create("test").unwrap();
{
use std::fmt::Write;
a.write_fmt(format_args!("hello"));
}
{
use std::io::Write;
b.write_fmt(format_args!("hello"));
}
}
Note that if you choose to use a smaller scope, you can also use the write! macro directly:
fn main() {
let mut a = String::new();
let mut b = std::fs::File::create("test").unwrap();
{
use std::fmt::Write;
write!(a, "hello");
}
{
use std::io::Write;
write!(b, "hello");
}
}
In either case, you should handle the Result return value.
See also:
How to call a method when a trait and struct use the same name?
You can specify an alias for use:
use std::fmt::Write as FmtWrite;
use std::io::Write;
fn main() {
let mut a = String::new();
let mut b = std::fs::File::create("test").unwrap();
a.write_fmt(format_args!("hello"));
b.write_fmt(format_args!("hello"));
}
If you just want to call the traits method, you can even just bring them in scope:
use std::fmt::Write as _;
use std::io::Write as _;
fn main() {
let mut a = String::new();
let mut b = std::fs::File::create("test").unwrap();
a.write_fmt(format_args!("hello"));
b.write_fmt(format_args!("hello"));
}
Be careful, this solution works when different types implement different traits with the same name. If the same type implements different traits with the same name, you must use Shepmaster's answer:
mod foo {
pub trait Trait {
fn do_something(&self) {}
}
}
mod bar {
pub trait Trait {
fn do_something(&self) {}
}
}
pub struct Concrete {}
impl foo::Trait for Concrete {}
impl bar::Trait for Concrete {}
fn main() {
let x = Concrete {};
{
use foo::Trait; // use limited to scope
x.do_something(); // call foo::Trait::do_something
}
{
foo::Trait::do_something(&x); // complete path to disambiguate
bar::Trait::do_something(&x); // complete path to disambiguate
}
{
use foo::Trait as FooTrait;
use bar::Trait;
x.do_something(&x); // ERROR: multiple applicable items in scope
}
}
Related
I got a Box<Rc<RefCell<T>>> from FFI. How can I get the &mut T based on it?
I can not compile it. Compiler tells me:
47 | let mut r: &mut Server = server.borrow_mut();
| ^^^^^^^^^^ the trait BorrowMut<Server> is not implemented for Box<Rc<RefCell<Server>>>
|
= help: the trait BorrowMut<T> is implemented for Box<T, A>
For more information about this error, try rustc --explain E0277.
#[derive(Debug)]
struct Server {
id: i32,
}
impl Server {
pub fn change_id(&mut self) {
self.id = self.id + 1;
}
}
#[no_mangle]
pub extern "C" fn server_change_id(server: *mut Rc<RefCell<Server>>) -> isize {
let server: Box<Rc<RefCell<Server>>> = unsafe { Box::from_raw(server) };
let mut r: &mut Server = server.borrow_mut();
r.change_id();
return 0;
}
Auto-deref will make borrow_mut() directly accessible.
use std::{cell::RefCell, cell::RefMut, ops::DerefMut, rc::Rc};
fn main() {
let a = Box::new(Rc::new(RefCell::new("aaa".to_owned())));
//
println!("{:?}", a);
{
let mut r: RefMut<String> = a.borrow_mut();
r.push_str("bbb"); // via RefMut
let r2: &mut String = r.deref_mut();
r2.push_str("ccc"); // via exclusive-reference
}
println!("{:?}", a);
}
/*
RefCell { value: "aaa" }
RefCell { value: "aaabbbccc" }
*/
In your code, let mut r = server.borrow_mut(); should be enough to invoke r.change_id().
let mut r = server.borrow_mut();
r.change_id();
If you absolutely want a &mut, then use let r2 = r.deref_mut() and invoke r2.change_id().
let mut r = server.borrow_mut();
let r2 = r.deref_mut();
r2.change_id();
T gets wrapped inside the RefCell<T> must implement the Deref or DerefMut trait in order to be borrowed mutably or reference borrowed. In your case, Server must implement a deref method.
use std::ops::DerefMut;
impl DerefMut for Server {
fn deref_mut(&mut self) -> &mut Self {
*self // this assumes your server has more than just one i32 field.
}
}
After this implementation, you should be able to call server.borrow_mut() should work perfectly and return you a mutable server object.
When I implement a trait for a given struct, I can obviously only use it by bringing the trait into scope. For example:
// file1.rs
pub struct MyStruct {
value: u64;
}
impl MyStruct {
pub fn new(value: u64) -> MyStruct {
MyStruct { value }
}
}
impl BitOr<MyStruct> for MyStruct {
type Output = Self;
fn bitor(self, rhs: Self) -> Self {
Self::new(self.value | rhs.value)
}
}
// main.rs
use file1::MyStruct;
let t1 = MyStruct::new(10u64);
let t2 = MyStruct::new(15u64);
let t3 = t1.bitor(t2); // This gives a compilation error unless std::ops::BitOr is in scope
The compiler has some useful warnings about this behaviour:
= help: items from traits can only be used if the trait is in scope
help: the following trait is implemented but not in scope; perhaps add a `use` for it:
|
1 | use std::ops::BitOr;
|
However, if I replace let t3 = t1.bitor(t2); with let t3 = t1 | t2;, then the code compiles without errors even if std::ops::BitOr is not in scope. Why is that?
I want to implement a function that takes an immutable &Vec reference, makes a copy, sorts the values and prints them.
This is the main code.
trait Foo {
fn value(&self) -> i32;
}
struct Bar {
x: i32,
}
impl Foo for Bar {
fn value(&self) -> i32 {
self.x
}
}
fn main() {
let mut a: Vec<Box<dyn Foo>> = Vec::new();
a.push(Box::new(Bar { x: 3 }));
a.push(Box::new(Bar { x: 5 }));
a.push(Box::new(Bar { x: 4 }));
let b = &a;
sort_and_print(&b);
}
The only way I was able to make it work was this
fn sort_and_print(v: &Vec<Box<dyn Foo>>) {
let mut v_copy = Vec::new();
for val in v {
v_copy.push(val);
}
v_copy.sort_by_key(|o| o.value());
for val in v_copy {
println!("{}", val.value());
}
}
However I want to understand what's happening here and also to make the code shorter.
Question 1
If I try to change let mut v_copy = Vec::new(); to let mut v_copy: Vec<Box<dyn Foo>> = Vec::new(); however that results in various errors that I don't know how to fix.
How do I make this version work and why is it different than the first version?
Attempt 2
Something closer to what I'm looking for is something like this.
let mut v_copy = v.clone(); but this doesn't work. Can this version be fixed?
First, let's annotate the types:
fn sort_and_print(v: &Vec<Box<dyn Foo>>) {
let mut v_copy: Vec<&Box<dyn Foo>> = Vec::new();
for val /* : &Box<dyn Foo> */ in v {
v_copy.push(val);
}
v_copy.sort_by_key(|o: &&Box<dyn Foo>| <dyn Foo>::value(&***o));
for val /* : &Box<dyn Foo> */ in v_copy {
println!("{}", <dyn Foo>::value(&**val));
}
}
Iterating over &Vec<T> produces an iterator over &T (the same as the .iter() method).
Now we can see we can convert it into iterator, by either calling .into_iter() on v and then .collect() (which is what the for loop does), or replace into_iter() with iter() (which is more idiomatic since we're iterating over references):
fn sort_and_print(v: &Vec<Box<dyn Foo>>) {
let mut v_copy: Vec<&Box<dyn Foo>> = v.iter().collect(); // You can omit the `&Box<dyn Foo>` and replace it with `_`, I put it here for clarity.
v_copy.sort_by_key(|o| o.value());
for val in v_copy {
println!("{}", val.value());
}
}
However, we still only have a copy of the reference (&Box<dyn Foo>). Why can't we just clone the vector?
If we try...
fn sort_and_print(v: &Vec<Box<dyn Foo>>) {
let mut v_copy = v.clone();
v_copy.sort_by_key(|o| o.value());
for val in v_copy {
println!("{}", val.value());
}
}
...the compiler yell at us:
warning: variable does not need to be mutable
--> src/main.rs:45:9
|
45 | let mut v_copy = v.clone();
| ----^^^^^^
| |
| help: remove this `mut`
|
= note: `#[warn(unused_mut)]` on by default
error[E0596]: cannot borrow `*v_copy` as mutable, as it is behind a `&` reference
--> src/main.rs:46:5
|
45 | let mut v_copy = v.clone();
| ---------- help: consider changing this to be a mutable reference: `&mut Vec<Box<dyn Foo>>`
46 | v_copy.sort_by_key(|o| o.value());
| ^^^^^^ `v_copy` is a `&` reference, so the data it refers to cannot be borrowed as mutable
WHAT???????????
Well, let's try to specify the type. It can make the compiler smarter.
fn sort_and_print(v: &Vec<Box<dyn Foo>>) {
let mut v_copy: Vec<Box<dyn Foo>> = v.clone();
v_copy.sort_by_key(|o| o.value());
for val in v_copy {
println!("{}", val.value());
}
}
Nope.
error[E0308]: mismatched types
--> src/main.rs:45:41
|
45 | let mut v_copy: Vec<Box<dyn Foo>> = v.clone();
| ----------------- ^^^^^^^^^
| | |
| | expected struct `Vec`, found reference
| | help: try using a conversion method: `v.to_vec()`
| expected due to this
|
= note: expected struct `Vec<Box<dyn Foo>>`
found reference `&Vec<Box<dyn Foo>>`
Well, let's use the compiler's suggestion:
fn sort_and_print(v: &Vec<Box<dyn Foo>>) {
let mut v_copy: Vec<Box<dyn Foo>> = v.to_vec();
v_copy.sort_by_key(|o| o.value());
for val in v_copy {
println!("{}", val.value());
}
}
Grrr!!
error[E0277]: the trait bound `dyn Foo: Clone` is not satisfied
--> src/main.rs:45:43
|
45 | let mut v_copy: Vec<Box<dyn Foo>> = v.to_vec();
| ^^^^^^ the trait `Clone` is not implemented for `dyn Foo`
|
= note: required because of the requirements on the impl of `Clone` for `Box<dyn Foo>`
At least we now have some clues.
What happened here?
Well, like the compiler said, dyn Foo does not implement the Clone trait. Which means that neither does Box<dyn Foo>, and so is Vec<Box<dyn Foo>>.
However, &Vec<Box<dyn Foo>> actually does impl Clone. This is because you can have as many shared references as you want - shared (non-mutable) references are Copy, and every Copy is also Clone. Try it:
fn main() {
let i: i32 = 123;
let r0: &i32 = &i;
let r1: &i32 = <&i32 as Clone>::clone(&r0);
}
So, when we write v.clone(), the compiler asks "is there a method named clone() that takes self of type &Vec<Box<dyn Foo>> (v)?" it first looks for such method on the Clone impl for Vec<Box<dyn Foo>> (because the Clone::clone() takes &self, so for Vec<Box<dyn Foo>> it takes &Vec<Box<dyn Foo>>). Unfortunately, such impl doesn't exist, so it does the magic of autoref (part the process of trying to adjust a method receiver in Rust, you can read more here), and asks the same question for &&Vec<Box<dyn Foo>>. Now we did find a match - <&Vec<Box<dyn Foo>> as Clone>::clone()! So this is what the compiler calls.
What is the return type of the method? Well, &Vec<Box<dyn Foo>>. This will be the type of v_copy. Now we understand why when we specified another type, the compiler got crazy! We can also decrypt the error message when we didn't specify a type: we asked the compiler to call sort_by_key() on a &Vec<Box<dyn Foo>>, but this method requires a &mut Vec<Box<dyn Foo>> (&mut [Box<dyn Foo>], to be precise, but it doesn't matter because Vec<T> can coerce to [T])!
We can also understand the warning about a redundant mut: we never change the reference, so no need to declare it as mutable!
When we called to_vec(), OTOH, the compiler didn't get confused: to_vec() requires the vector's item to implement Clone (where T: Clone), which doesn't happen for Box<dyn Foo>. BOOM.
Now the solution should be clear: we just need Box<dyn Foo> to impl Clone.
Just?...
The first thing we may think about is to give Foo a supertrait Clone:
trait Foo: Clone {
fn value(&self) -> i32;
}
#[derive(Clone)]
struct Bar { /* ... */ }
Not working:
error[E0038]: the trait `Foo` cannot be made into an object
--> src/main.rs:33:31
|
33 | fn sort_and_print(v: &Vec<Box<dyn Foo>>) {
| ^^^^^^^ `Foo` cannot be made into an object
|
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> src/main.rs:1:12
|
1 | trait Foo: Clone {
| --- ^^^^^ ...because it requires `Self: Sized`
| |
| this trait cannot be made into an object...
Hmm, looks like Clone indeed requires Sized. Why?
Well, because in order to clone something, we need to return itself. Can we return dyn Foo? No, because it can be of any size.
So, let's try to impl Clone for Box<dyn Foo> by hand (we can do that even though Box is not defined in our crate because it is a fundamental type and Foo is local (defined in our crate)).
impl Clone for Box<dyn Foo> {
fn clone(self: &Box<dyn Foo>) -> Box<dyn Foo> {
// Now... What, actually?
}
}
How can we even clone something that can be anything? Clearly we need to forward it to someone else. Who else? Someone who knows how to clone this thing. A method on Foo?
trait Foo {
fn value(&self) -> i32;
fn clone_dyn(&self) -> Box<dyn Foo>;
}
impl Foo for Bar {
fn value(&self) -> i32 {
self.x
}
fn clone_dyn(&self) -> Box<dyn Foo> {
Box::new(self.clone()) // Forward to the derive(Clone) impl
}
}
NOW!
impl Clone for Box<dyn Foo> {
fn clone(&self) -> Self {
self.clone_dyn()
}
}
IT WORKS!!
fn sort_and_print(v: &Vec<Box<dyn Foo>>) {
let mut v_copy = v.clone();
v_copy.sort_by_key(|o| o.value());
for val in v_copy {
println!("{}", val.value());
}
}
https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=d6e871711146bc3f34d9710211b4a1dd
Note: The dyn-clone crate from #dtonlay generalizes this idea.
You can make sort_and_print() shorter using Iterator::collect():
fn sort_and_print(v: &[Box<dyn Foo>]) {
let mut v_copy: Vec<_> = v.iter().collect();
v_copy.sort_by_key(|o| o.value());
for val in v_copy {
println!("{}", val.value());
}
}
Playground
As an aside, accepting a vector by reference is usually better expressed as accepting a slice, as explained here, so the above answer accepts a slice.
You can make it even shorter by using the sorted() method from the itertools crate, or in this case its cousin sorted_by_key():
use itertools::Itertools;
fn sort_and_print(v: &[Box<dyn Foo>]) {
for val in v.iter().sorted_by_key(|o| o.value()) {
println!("{}", val.value());
}
}
You almost certainly don't want to clone the vector because it would involve a deep copy, i.e. cloning each Box<dyn Foo>, which is unnecessary, potentially expensive, as well as complicated (as explained in the other answer).
I'm trying to get a procedural macro to print out information about variables in my function inputs. When I test the macro in a separate crate, I get an error from the compiler that I'm not implementing the trait functions even though the trait functions are clearly implemented.
Please ignore that the attr isn't returning anything yet; I'm building it together but ran into this issue first.
The procedural macro definition:
extern crate proc_macro;
use self::proc_macro::TokenStream;
use syn::{parse_macro_input, ItemFn};
#[proc_macro_attribute]
pub fn my_macro(attr: proc_macro::TokenStream, item: proc_macro::TokenStream) -> proc_macro::TokenStream {
println!("item: \"{}\"", item.to_string());
let func = parse_macro_input!(item as ItemFn);
let input_funcs = func.sig.inputs
.iter()
.map(|item| println!("{:?}", try_me(item)));
//input_funcs
attr
}
fn try_me(arg: &syn::FnArg) -> String {
match arg {
syn::FnArg::Receiver(_r) => "is receiver".to_string(),
syn::FnArg::Typed(_p) => "is pattern type".to_string()
}
}
the testing crate:
use my_macro::{my_macro};
pub trait TestTrait {
#[my_macro]
fn my_func(&self, x: u8, y: String) -> u32 {
return 0;
}
#[my_macro]
fn empty_func(&mut self);
}
#[cfg(test)]
mod tests {
// Note this useful idiom: importing names from outer (for mod tests) scope.
use super::*;
#[derive(Default)]
struct MyStruct{
pub a: u8
}
impl TestTrait for MyStruct{
#[my_macro]
fn my_func(&self, _x: u8, _y: String) -> u32 {
return 0;
}
#[my_macro]
fn empty_func(&mut self) {
self.a = 5;
}
}
#[test]
fn test_empty_func() {
let mut struc = MyStruct::default();
let interface = &mut struc as &mut dyn TestTrait;
interface.empty_func();
assert_eq!(5, contract.a);
}
#[test]
fn test_macros() {
let mut struct = MyStruct::default();
let interface = &mut struc as &mut dyn TestTrait;
let zero = interface.my_func(8, "hello".to_string());
}
}
yields errors such as:
item: "fn my_func(&self, x: u8, y: String) -> u32 { return 0; }"
item: "fn my_func(&self, x: u8, y: String) -> u32 { return 0; }"
item: "fn empty_func(&mut self);"
item: "fn empty_func(&mut self);"
error: expected curly braces
|
9 | fn empty_func(&mut self);
| ^
error: expected curly braces
|
9 | fn empty_func(&mut self);
and
error[E0599]: no method named `empty_func` found for mutable reference `&mut dyn TestTrait` in the current scope
|
34 | interface.empty_func();
| ^^^^^^^^^^ method not found in `&mut dyn TestTrait`
error[E0599]: no method named `my_func` found for mutable reference `&mut dyn TestTrait` in the current scope
|
42 | let zero = interface.my_func(8, "hello".to_string());
| ^^^^^^^ method not found in `&mut dyn TestTrait`
If I take off the procedural macro attribute, this compiles. What is going on here and what should I do differently?
Found this out after discussion in the Rust Discord. Props to Jebrosen. The problem is that I'm returning attr and attr currently has nothing assigned to it. Thus when the compiler goes to expand the code it actually shrinks the code to...nothing. I am essentially deleting my code at compile time. Instead of doing this to test out the proc macro, I should instead use quote and quote the function as is while testing things out with printlns. Hope this helps someone in the future.
I have an Option<T> that is shared by several structures and that must be mutable. I'm using a RefCell since, as I understand, it is the tool for that job. How do I access (and alter) the content of that Option<T> ?
I tried the following:
use std::cell::RefCell;
#[derive(Debug)]
struct S {
val: i32
}
fn main() {
let rc: RefCell<Option<S>> = RefCell::new(Some(S{val: 0}));
if let Some(ref mut s2) = rc.borrow_mut() {
s2.val += 1;
}
println!("{:?}", rc);
}
But the compiler won't let me do it:
error[E0308]: mismatched types
--> <anon>:10:12
|
10 | if let Some(ref mut s2) = rc.borrow_mut() {
| ^^^^^^^^^^^^^^^^ expected struct `std::cell::RefMut`, found enum `std::option::Option`
|
= note: expected type `std::cell::RefMut<'_, std::option::Option<S>, >`
found type `std::option::Option<_>`
When you borrow_mut the RefCell, you get a RefMut, as the compiler says. To get the value inside it, just use the operator deref_mut:
use std::cell::RefCell;
#[derive(Debug)]
struct S {
val: i32
}
fn main() {
let rc: RefCell<Option<S>> = RefCell::new(Some(S{val: 0}));
if let Some(ref mut s2) = *rc.borrow_mut() { // deref_mut
s2.val += 1;
}
println!("{:?}", rc);
}