-
-
Notifications
You must be signed in to change notification settings - Fork 37
/
main.rs
74 lines (62 loc) · 1.97 KB
/
main.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
/////////////////////////////////////////////////////////////////////
// Suppose these are the real traits from Serde.
trait Querializer {}
trait Generic {
// Not object safe because of this generic method.
fn generic_fn<Q: Querializer>(&self, querializer: Q);
}
impl<'a, T> Querializer for &'a T where T: ?Sized + Querializer {}
impl<'a, T> Generic for Box<T>
where
T: ?Sized + Generic,
{
fn generic_fn<Q: Querializer>(&self, querializer: Q) {
(**self).generic_fn(querializer)
}
}
/////////////////////////////////////////////////////////////////////
// This is an object-safe equivalent that interoperates seamlessly.
trait ErasedGeneric {
fn erased_fn(&self, querializer: &dyn Querializer);
}
impl Generic for dyn ErasedGeneric {
// Depending on the trait method signatures and the upstream
// impls, could also implement for:
//
// - &'a dyn ErasedGeneric
// - &'a (dyn ErasedGeneric + Send)
// - &'a (dyn ErasedGeneric + Sync)
// - &'a (dyn ErasedGeneric + Send + Sync)
// - Box<dyn ErasedGeneric>
// - Box<dyn ErasedGeneric + Send>
// - Box<dyn ErasedGeneric + Sync>
// - Box<dyn ErasedGeneric + Send + Sync>
fn generic_fn<Q: Querializer>(&self, querializer: Q) {
self.erased_fn(&querializer)
}
}
impl<T> ErasedGeneric for T
where
T: Generic,
{
fn erased_fn(&self, querializer: &dyn Querializer) {
self.generic_fn(querializer)
}
}
fn main() {
struct T;
impl Querializer for T {}
struct S;
impl Generic for S {
fn generic_fn<Q: Querializer>(&self, _querializer: Q) {
println!("querying the real S");
}
}
// Construct a trait object.
let trait_object: Box<dyn ErasedGeneric> = Box::new(S);
// Seamlessly invoke the generic method on the trait object.
//
// THIS LINE LOOKS LIKE MAGIC. We have a value of type trait
// object and we are invoking a generic method on it.
trait_object.generic_fn(T);
}