Continuing the discussion from How to (idiomatically) borrow a str from a String (using the "as" keyword?), I have another issue with coercions:
use std::any::Any;
use std::sync::Arc;
macro_rules! coerce {
($x:expr) => ( { let t: _ = $x; t } );
}
fn takes_any_arc(_arg: Arc<dyn Any + Send + Sync>) {}
fn takes_any_arc_ref(_arg: &Arc<dyn Any + Send + Sync>) {}
fn main() {
let x = Arc::new(1);
takes_any_arc(x.clone());
// These don't work:
//takes_any_arc_ref(&x.clone());
//takes_any_arc_ref(&x.clone() as &Arc<dyn Any + Send + Sync>);
//takes_any_arc_ref(&x.clone() as _);
//takes_any_arc_ref(&(x.clone() as Arc<dyn _));
//let t: _ = x.clone();
//takes_any_arc_ref(&t);
// But these work:
takes_any_arc_ref(&{ let t: _ = x.clone(); t });
takes_any_arc_ref(&coerce!(x.clone()));
takes_any_arc_ref(&(x.clone() as Arc<dyn Any + Send + Sync>));
takes_any_arc_ref(&(x.clone() as Arc<_>));
takes_any_arc_ref(&(x.clone() as _));
}
What's the best way to go? I dislike having to write dyn Any + Send + Sync
, especially because changing Send
ness and Sync
edness would have to be redundantly noted everywhere I do this coercion. Writing as _
is a bit vague, and as Vec<_>
sort of misses the point here (but works).
I feel like as _
is the best way to go here. But apart from allowing coercion here, it would also enable primitive type casts (which is what's neither needed nor intended here).
Why doesn't takes_any_arc_ref(&x.clone());
work here? Wouldn't it be good if it was allowed and would perform the coercion of x.clone()
here? I guess this doesn't work because it's not a coercion site here (and &x.clone()
can't be coerced).
I tried to work around this by writing a coerce!
macro which basically inserts an artificial coercion site. Is there some less-messy (or already existing) way to achieve this?
Note that coerce!(x)
isn't the same as x as _
:
#![allow(unused_macros)]
macro_rules! coerce {
($x:expr) => ( { let t: _ = $x; t } );
}
fn takes_byte(byte: u8) {
println!("Got {byte}")
}
fn main() {
let i: i32 = 1000;
//takes_byte(i); // compile-time error, of course
takes_byte(i as _); // danger!
//takes_byte(coerce!(i)); // gives a compile-time error
}
Output:
Got 232