@@ -30,75 +30,131 @@ impl<T: ?Sized> CastToken<T> {
3030}
3131
3232/// Supporting trait for autoderef specialization on mutable references to lifetime-free
33- /// types.
33+ /// target types.
3434pub trait TryCastMutLifetimeFree < ' a , T : ?Sized , U : LifetimeFree + ?Sized > {
3535 #[ inline( always) ]
3636 fn try_cast ( & self , value : & ' a mut T ) -> Result < & ' a mut U , & ' a mut T > {
37- // SAFETY: See comments on safety in `TryCastLifetimeFree`.
38-
39- if type_eq_non_static :: < T , U > ( ) {
40- // Pointer casts are not allowed here since the compiler can't prove
41- // that `&mut T` and `&mut U` have the same kind of associated
42- // pointer data if they are fat pointers. But we know they are
43- // identical, so we use a transmute.
44- Ok ( unsafe { transmute_unchecked :: < & mut T , & mut U > ( value) } )
45- } else {
46- Err ( value)
47- }
37+ try_cast_mut_lifetime_free ( value)
4838 }
4939}
5040
5141impl < ' a , T : ?Sized , U : LifetimeFree + ?Sized > TryCastMutLifetimeFree < ' a , T , U >
52- for & & & & & & & ( CastToken < & ' a mut T > , CastToken < & ' a mut U > )
42+ for & & & & & & & & & & ( CastToken < & ' a mut T > , CastToken < & ' a mut U > )
43+ {
44+ }
45+
46+ /// Supporting trait for autoderef specialization on mutable references to lifetime-free
47+ /// source types.
48+ pub trait TryCastMutLifetimeFreeBack < ' a , T : LifetimeFree + ?Sized , U : ?Sized > {
49+ #[ inline( always) ]
50+ fn try_cast ( & self , value : & ' a mut T ) -> Result < & ' a mut U , & ' a mut T > {
51+ try_cast_mut_lifetime_free ( value)
52+ }
53+ }
54+
55+ impl < ' a , T : LifetimeFree + ?Sized , U : ?Sized > TryCastMutLifetimeFreeBack < ' a , T , U >
56+ for & & & & & & & & & ( CastToken < & ' a mut T > , CastToken < & ' a mut U > )
5357{
5458}
5559
60+ // SAFETY: Requires at least one of `T` or `U` to be `LifetimeFree`.
61+ #[ inline( always) ]
62+ fn try_cast_mut_lifetime_free < T : ?Sized , U : ?Sized > ( value : & mut T ) -> Result < & mut U , & mut T > {
63+ // SAFETY: See comments on safety in `try_cast_owned_lifetime_free`.
64+
65+ if type_eq_non_static :: < T , U > ( ) {
66+ // Pointer casts are not allowed here since the compiler can't prove
67+ // that `&mut T` and `&mut U` have the same kind of associated
68+ // pointer data if they are fat pointers. But we know they are
69+ // identical, so we use a transmute.
70+ Ok ( unsafe { transmute_unchecked :: < & mut T , & mut U > ( value) } )
71+ } else {
72+ Err ( value)
73+ }
74+ }
75+
5676/// Supporting trait for autoderef specialization on references to lifetime-free
57- /// types.
77+ /// target types.
5878pub trait TryCastRefLifetimeFree < ' a , T : ?Sized , U : LifetimeFree + ?Sized > {
5979 #[ inline( always) ]
6080 fn try_cast ( & self , value : & ' a T ) -> Result < & ' a U , & ' a T > {
61- // SAFETY: See comments on safety in `TryCastLifetimeFree`.
62-
63- if type_eq_non_static :: < T , U > ( ) {
64- // Pointer casts are not allowed here since the compiler can't prove
65- // that `&T` and `&U` have the same kind of associated pointer data if
66- // they are fat pointers. But we know they are identical, so we use
67- // a transmute.
68- Ok ( unsafe { transmute_unchecked :: < & T , & U > ( value) } )
69- } else {
70- Err ( value)
71- }
81+ try_cast_ref_lifetime_free ( value)
7282 }
7383}
7484
7585impl < ' a , T : ?Sized , U : LifetimeFree + ?Sized > TryCastRefLifetimeFree < ' a , T , U >
76- for & & & & & & ( CastToken < & ' a T > , CastToken < & ' a U > )
86+ for & & & & & & & & ( CastToken < & ' a T > , CastToken < & ' a U > )
87+ {
88+ }
89+
90+ /// Supporting trait for autoderef specialization on references to lifetime-free
91+ /// source types.
92+ pub trait TryCastRefLifetimeFreeBack < ' a , T : LifetimeFree + ?Sized , U : ?Sized > {
93+ #[ inline( always) ]
94+ fn try_cast ( & self , value : & ' a T ) -> Result < & ' a U , & ' a T > {
95+ try_cast_ref_lifetime_free ( value)
96+ }
97+ }
98+
99+ impl < ' a , T : LifetimeFree + ?Sized , U : ?Sized > TryCastRefLifetimeFreeBack < ' a , T , U >
100+ for & & & & & & & ( CastToken < & ' a T > , CastToken < & ' a U > )
77101{
78102}
79103
80- /// Supporting trait for autoderef specialization on lifetime-free types.
104+ // SAFETY: Requires at least one of `T` or `U` to be `LifetimeFree`.
105+ #[ inline( always) ]
106+ fn try_cast_ref_lifetime_free < T : ?Sized , U : ?Sized > ( value : & T ) -> Result < & U , & T > {
107+ // SAFETY: See comments on safety in `try_cast_owned_lifetime_free`.
108+
109+ if type_eq_non_static :: < T , U > ( ) {
110+ // Pointer casts are not allowed here since the compiler can't prove
111+ // that `&T` and `&U` have the same kind of associated pointer data if
112+ // they are fat pointers. But we know they are identical, so we use
113+ // a transmute.
114+ Ok ( unsafe { transmute_unchecked :: < & T , & U > ( value) } )
115+ } else {
116+ Err ( value)
117+ }
118+ }
119+
120+ /// Supporting trait for autoderef specialization on lifetime-free target types.
81121pub trait TryCastOwnedLifetimeFree < T , U : LifetimeFree > {
82122 #[ inline( always) ]
83123 fn try_cast ( & self , value : T ) -> Result < U , T > {
84- // SAFETY: If `U` is lifetime-free, and the base types of `T` and `U`
85- // are equal, then `T` is also lifetime-free. Therefore `T` and `U` are
86- // strictly identical and it is safe to cast a `T` into a `U`.
87- //
88- // We know that `U` is lifetime-free because of the `LifetimeFree` trait
89- // checked statically. `LifetimeFree` is an unsafe trait implemented for
90- // individual types, so the burden of verifying that a type is indeed
91- // lifetime-free is on the implementer.
92-
93- if type_eq_non_static :: < T , U > ( ) {
94- Ok ( unsafe { transmute_unchecked :: < T , U > ( value) } )
95- } else {
96- Err ( value)
97- }
124+ try_cast_owned_lifetime_free ( value)
98125 }
99126}
100127
101- impl < T , U : LifetimeFree > TryCastOwnedLifetimeFree < T , U > for & & & & & ( CastToken < T > , CastToken < U > ) { }
128+ impl < T , U : LifetimeFree > TryCastOwnedLifetimeFree < T , U > for & & & & & & ( CastToken < T > , CastToken < U > ) { }
129+
130+ /// Supporting trait for autoderef specialization on lifetime-free source types.
131+ pub trait TryCastOwnedLifetimeFreeBack < T : LifetimeFree , U > {
132+ #[ inline( always) ]
133+ fn try_cast ( & self , value : T ) -> Result < U , T > {
134+ try_cast_owned_lifetime_free ( value)
135+ }
136+ }
137+
138+ impl < T : LifetimeFree , U > TryCastOwnedLifetimeFreeBack < T , U > for & & & & & ( CastToken < T > , CastToken < U > ) { }
139+
140+ // SAFETY: Requires at least one of `T` or `U` to be `LifetimeFree`.
141+ #[ inline( always) ]
142+ fn try_cast_owned_lifetime_free < T , U > ( value : T ) -> Result < U , T > {
143+ // SAFETY: If `U` is lifetime-free, and the base types of `T` and `U`
144+ // are equal, then `T` is also lifetime-free. Therefore `T` and `U` are
145+ // strictly identical and it is safe to cast a `T` into a `U`.
146+ //
147+ // We know that `U` is lifetime-free because of the `LifetimeFree` trait
148+ // checked statically. `LifetimeFree` is an unsafe trait implemented for
149+ // individual types, so the burden of verifying that a type is indeed
150+ // lifetime-free is on the implementer.
151+
152+ if type_eq_non_static :: < T , U > ( ) {
153+ Ok ( unsafe { transmute_unchecked :: < T , U > ( value) } )
154+ } else {
155+ Err ( value)
156+ }
157+ }
102158
103159/// Supporting trait for autoderef specialization on mutable slices.
104160pub trait TryCastSliceMut < ' a , T : ' static , U : ' static > {
0 commit comments