Skip to content

Instantly share code, notes, and snippets.

@rbran
Created May 14, 2023 11:38
Show Gist options
  • Save rbran/9feec2bf4bc42dfcc2e08b3220e6aafd to your computer and use it in GitHub Desktop.
Save rbran/9feec2bf4bc42dfcc2e08b3220e6aafd to your computer and use it in GitHub Desktop.
Avoid using a blanket implementations by using Borrow instead.
use std::borrow::{Borrow, Cow};
/// A trait for things that can speak.
trait Speaker {
fn speak(&self);
}
/// BasicSpeaker is an empty struct that exists only to implement Speaker.
#[derive(Clone)]
struct BasicSpeaker;
/// BasicSpeakers must be able to speak.
impl Speaker for BasicSpeaker {
fn speak(&self) {
println!("Hello!");
}
}
fn speak_to<S>(s: impl Borrow<S>)
where
S: Speaker,
{
// borrow allow us to get a reference from lots of types, such:
// Box, Cow, Rc, Arc, &T, T, etc
let s: &S = s.borrow();
s.speak();
}
fn main() {
// Create a BasicSpeaker struct:
let speaker = BasicSpeaker;
speaker.speak();
speak_to(speaker);
// Take a reference to the BasicSpeaker:
let speaker = BasicSpeaker;
let speaker_ref: &BasicSpeaker = &speaker;
speaker_ref.speak();
speak_to::<BasicSpeaker>(speaker_ref);
// Maybe take a refernce to the BasicSpeaker, maybe own it.
let speaker = BasicSpeaker;
let speaker_cow = if std::env::args().len() == 1 {
Cow::Borrowed(&speaker)
} else {
Cow::Owned(speaker.clone())
};
speaker_cow.speak();
speak_to::<BasicSpeaker>(speaker_cow);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment