With today's Rust nightly the following code doesn't compile anymore:
#[derive(Show)]
enum S {
A,
B
}
fn main() {
println!("{}", S::A);
}
Instead it gives me the following error message:
error: the trait `core::fmt::String` is not implemented for the type `S`
Is there a way to get the old behaviour? Surely it can't be required to implement this by hand for each type.
The old Show trait was split into Display and Debug.
Display is designed for user-facing output, and uses the blank/default format specifier (e.g. {}, {:.10} {foo:} are all using Display)
Debug is designed for debugging/internal output and uses the ? format specifier (e.g. {:?}, {:.10?}, {foo:?} are all using Debug)
Hence, to use the implementation created by #[derive(Debug)] one should write println!("{:?}", ...), instead of the old println!("{}", ...).
Only Debug can be #[derive]d since output like Foo { x: 1, y: 2 } is unlikely to be the correct user-facing output, for most situations (I'm sure it is for some, but then the programmer can write the implementation of Display to do that themselves, or even call directly into the #[derive]d Debug implementation).
This was originally described in RFC 504 and there is ongoing discussion in RFC 565, making the guidelines stated above more concrete.
The answer is to use {:?} instead of {} in format!.
Related
I am using Rust with the Rodio crate and I wanted to make a Vec of loaded sources to use whenever they are needed, so that the program doesn't need to load it every time. I've made a SoundHandler class that contains an OutputStream, an OutputStreamHandle and a Vec<Decoder<BufReader<File>>>. The first two are instanced by using OutputStream::try_default(), which returns both in a tuple. The Vec is a vector of loaded sources. Its content are, as I understand it, loaded and then pushed in the following SoundHandler method:
pub fn load_source(&mut self, file_path: PathBuf) -> SoundId {
let id = self.sources.len();
self.sources.push(
Decoder::new(
BufReader::new(
File::open(file_path).expect("file not found")
)
).expect("could not load source")
);
SoundId(id)
}
Next, the source should be played by calling the play_sound() method.
Previously, it directly loaded and played the sound:
pub fn play_sound(file_path: PathBuf) {
self.stream_handle.play_raw(
Decoder::new(
BufReader::new(
File::open(file_path).expect("file not found")
)
).expect("could not load source")
);
}
But now it must handle the sources that come from the Vec. I had trouble while trying to do that. I need help with that. I am pretty new to the language so knowing how to solve that problem in more than one way would be even better, but my priority is really the path I've chosen to do it, because knowing how to solve that would undoubtedly increase my Rust problem solving skills. Keep in mind my main goal here is to learn the language, and the snippets below are not at all an urgent problem to be solved for a company.
Ok, so I tried the most straightforward thing possible. I directly changed the old method to do the same thing but with the Vec:
pub fn play_sound(&self, sound_id: SoundId) {
self.stream_handle
.play_raw(self.sources.get(sound_id.0).unwrap().convert_samples()).unwrap();
}
But the compiler won't compile that method, because, according to it,
error[E0507]: cannot move out of a shared reference
self.stream_handle.play_raw(self.sources.get(sound_id.0).unwrap().convert_samples()).unwrap();
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------------
| |
| value moved due to this method call
move occurs because value has type `rodio::Decoder<std::io::BufReader<std::fs::File>>`, which does not implement the `Copy` trait
note: this function takes ownership of the receiver `self`, which moves value
I understand what the compiler is saying. Of course that can't be possible. convert_samples() tries to make the value inside the Vec invalid, and thus it could make the Vec unsafe. So I naively tried to clone the Decoder, but the struct does not implement the Clone trait, and apparently does not have any method to do so. Finally, I found a way to get the value and own it through the Vec::remove() method, but I do not want to remove it, and I do want it to be fallible.
So my question is: in this situation, how can I make that Vec of loaded sources? Maybe I could even make a Vec out of SamplesConverter. But then the name of the type gets huge, so that is probably not an intended way to do it: Vec<SamplesConverter<Decoder<BufReader<File>>, f32>>. But it has the same problems of the other implementation.
Decoders can't be cloned because the underlying data source may not be clonable (and in fact BufReader isn't). So in order to clone the audio sources you will need to ensure that the data is stored in memory. This can be accomplished by the buffered method, which returns a Buffered source, which can be cloned. So something like this should work:
pub fn load_source(&mut self, file_path: PathBuf) -> SoundId {
let id = self.sources.len();
self.sources.push(
Decoder::new(
BufReader::new(
File::open(file_path).expect("file not found")
)
).expect("could not load source")
.buffered()
);
SoundId(id)
}
pub fn play_sound(&self, sound_id: SoundId) {
self.stream_handle.play_raw(
self.sources.get(sound_id.0).unwrap().clone().convert_samples()).unwrap();
}
Is there an attribute like #[warn(redundant_result_as_return_type)] to show a warning that Result is redundant as a return type?
#[derive(Debug)]
struct SomeError();
fn process_some() -> Result<(), SomeError> {
Ok(())
}
fn main() {
process_some().unwrap();
}
(playground)
This code produces no warnings despite the fact that Result is not needed as the return type at all.
I've been deciding how to properly implement error handling of a function from the crate used in my project. After digging into the function implementation, it turned out that no errors are generated.
Since then, I want to prevent such cases in my own code. Ideally it would be great to get such warnings from inside of imported crates too, when utilizing methods with redundant Results, but as far as I understand such checking is impossible for used crates without adjusting their code.
The question is in some way the opposite of Possible to declare functions that will warn on unused results in Rust?.
No, there is no such warning, either in the compiler or in Clippy. You could submit an issue to Clippy suggesting they add it, of course.
I challenge that this is a common occurrence or even one that is actually a problem. Even if it was, I'd believe such a warning will have many disadvantages:
I use this pattern to scaffold out functions that I'm pretty sure will return an error once I've implemented them.
A method that is part of a trait cannot change the return type.
You might be passing the function as a function pointer or closure argument and the return type cannot be changed.
Changing the return type breaks API backwards compatibility, so you have to wait until a major version bump.
I'm trying to understand the need for the Trait:: and <T as Trait>:: method invocation syntax. In particular, I'm looking at the following function from this answer:
fn clone_into_array<A, T>(slice: &[T]) -> A
where
A: Default + AsMut<[T]>,
T: Clone,
{
assert_eq!(
slice.len(),
std::mem::size_of::<A>() / std::mem::size_of::<T>()
);
let mut a = Default::default();
<A as AsMut<[T]>>::as_mut(&mut a).clone_from_slice(slice);
a
}
It seems that the middle two method invocation lines can be rewritten as:
let mut a = A::default();
a.as_mut().clone_from_slice(slice);
I believe this is more readable, as we already know that A implements Default and AsMut<[T]> and we can invoke as_mut directly as a method instead of having to pass a to it explicitly.
However, am I missing a good reason for the linked answer to have written it more verbosely? Is it considered good style? Are the two semantically different under certain conditions?
I agree with your rewrites — they are more clear and are what I would recommend for that function.
am I missing a good reason for the linked answer to have written it more verbosely?
My guess is that the author simply was tired of writing that function and stopped. If they took a look at it again, they might refine it to be shorter.
Is it considered good style?
I don't think there's a general community stylistic preference around this yet, other than the general "shorter is better until it isn't".
Are the two semantically different under certain conditions?
They shouldn't be.
There are times where the <>:: syntax is needed because otherwise it would be ambiguous. One example from a recent question:
let array = <&mut [u8; 3]>::try_from(slice);
Another time is when you don't have a nicely-named intermediate type or the intermediate type is ambiguous across multiple traits. One gross example is from a where clause but shows the same issue as an expression would:
<<Tbl as OrderDsl<Desc<Expr>>>::Output as LimitDsl>::Output: QueryId,
See also:
How to call a method when a trait and struct use the same name?
I have been watching Rust for the past few months but I just started into an actual project. I am not sure if the terminology in the title is correct. Please let me know how it can be corrected.
I am writing a rust wrapper around the ENet library (http://enet.bespin.org). My goal is to keep the rust API as similar to the C API as possible except to refactor functions that take C style handle pointers into member functions of structure objects. I want to keep the API similar so that the official C documentation will apply equally well to the rust wrapper.
ENet exposes a single function to create either a client host or a server host. When creating a server you pass a pointer to an IP Address structure to the function. When creating a client you pass NULL.
I am trying to emulate that behavior using the ToSocketAddr trait and Option but I am running into problems using them in conjunction.
This is a reduced example of what I am trying to do:
use std::io::net::ip::ToSocketAddr;
fn create_host<A: ToSocketAddr>(addr: Option<A>) {
match addr {
Some(a) => println!("Address is {}. Return a server host object.",a.to_socket_addr()),
None => println!("no address... Return a client.")
};
}
fn main() {
create_host(Some("localhost:12345"));
create_host(None);
}
The first call to create_host() works like a charm. The second call however will not compile.
Rustc returns
error: unable to infer enough type information about `_`; type annotations required
I am guessing that error is occurring because None doesn't provide any resolution to the generic A. I tried the following but this doesn't work either because ToSocketAddr does not implement the trait core::kinds::Sized.
fn create_host(addr: Option<ToSocketAddr>) {
...
}
Is there a way I can do this or do I need to take a different approach?
fn main() {
create_host(Some("localhost:12345"));
create_host(None::<&str>);
}
I've chosen &str here as it is the same type as on the first call, so that the compiler wouldn't generate another monomorphized version of the generic function. You could choose any type that implements ToSocketAddr.
Given a situation like this one :
trait Basic {
// Some functions
}
trait Derived : Basic {
// some other functions
}
fn do_someting<T : Basic>(target: &mut T) {
// do stuff
}
Is it possible to have the do_something function behave differently depending on whether target implements the trait Derived or not (the information being known at compilation time) ?
I guess something similar could be achieved in C++ using template specialization, but I don't see a Rust equivalent.
AFAIK this is not currently possible. Defining fn do_something<T : Derived> alongside your existing function leads to compilation error:
error: duplicate definition of value `do_someting`
because both versions can be used for Basic.
There are some proposals to allow explicit bounds like <T: Basic + !Derived> that will allow you to resolve this conflict.
But I personally hope that impl overloading/specialization will be possible some day after 1.0 version is released.