@@ -10,11 +10,13 @@ use alloc::boxed::Box;
1010///
1111/// # Safety
1212///
13- /// `Outer` is `repr(transparent)` and has one non-zero-sized field
14- /// of type `Inner`.
13+ /// `Outer` is `repr(transparent)` and has one non-zero-sized field of type `Inner`.
14+ ///
15+ /// Suggestion: explicitly setting the generic parameters to two types satisfying this invariant
16+ /// makes the fn safe to call.
1517#[ cfg( feature = "alloc" ) ]
1618#[ inline( always) ]
17- pub unsafe fn cast_transparent_box < Outer , Inner > ( inner : Box < Inner > ) -> Box < Outer > {
19+ pub unsafe fn cast_transparent_box < Inner , Outer > ( inner : Box < Inner > ) -> Box < Outer > {
1820 // Safety:
1921 //
2022 // - Both boxes have the same allocator (the global allocator).
@@ -82,29 +84,28 @@ macro_rules! transparent {
8284 $(
8385 impl <' zf> $crate:: ZeroFrom <' zf, $inner_zf> for & ' zf $outer {
8486 fn zero_from( inner: & ' zf $inner) -> Self {
85- unsafe { core:: mem:: transmute( inner) }
87+ unsafe { core:: mem:: transmute:: < & $inner , & $outer> ( inner) }
8688 }
8789 }
8890 ) ?
8991 $( impl $outer {
9092 $(
9193 $( #[ $meta_ref] ) *
9294 $vis_ref fn $fn_ref( inner: & $inner_ref) -> & Self {
93- unsafe { core:: mem:: transmute( inner) }
95+ unsafe { core:: mem:: transmute:: < & $inner , & $outer> ( inner) }
9496 }
9597 ) ?
9698 $(
9799 $( #[ $meta_slice] ) *
98100 $vis_slice fn $fn_slice( inner: & [ $inner_slice] ) -> & [ Self ] {
99- unsafe { core:: mem:: transmute( inner) }
101+ unsafe { core:: mem:: transmute:: < & [ $inner ] , & [ $outer ] > ( inner) }
100102 }
101103 ) ?
102104 $(
103105 $( #[ $meta_box] ) *
104106 $vis_box fn $fn_box( inner: $crate:: internal:: Box <$inner_box>) -> $crate:: internal:: Box <Self > {
105107 // Safety: $outer is repr(transparent) over $inner.
106- // TODO: Enforce that $inner is the same as $inner_box
107- unsafe { $crate:: internal:: cast_transparent_box( inner) }
108+ unsafe { $crate:: internal:: cast_transparent_box:: <$inner, $outer>( inner) }
108109 }
109110 ) ?
110111 $(
@@ -116,3 +117,41 @@ macro_rules! transparent {
116117 } ) ?
117118 } ;
118119}
120+
121+ /// Additional tests for failure modes.
122+ ///
123+ /// ```compile_fail,E0053
124+ /// zerofrom::transparent! {
125+ /// #[repr(transparent)]
126+ /// pub struct Foo(String);
127+ /// // Wrong types in these positions!
128+ /// impl ZeroFrom<&Foo> for &String;
129+ /// };
130+ /// ```
131+ ///
132+ /// ```compile_fail,E0308
133+ /// zerofrom::transparent! {
134+ /// #[repr(transparent)]
135+ /// pub struct Foo(String);
136+ /// impl {
137+ /// @ref
138+ /// // Wrong type in this position!
139+ /// pub fn from(&Foo) -> &Self;
140+ /// }
141+ /// };
142+ /// ```
143+ ///
144+ /// ```compile_fail,E0308
145+ /// zerofrom::transparent! {
146+ /// #[repr(transparent)]
147+ /// pub struct Foo(String);
148+ /// impl {
149+ /// @slice
150+ /// // Wrong type in this position!
151+ /// pub fn from(&[Foo]) -> &[Self];
152+ /// }
153+ /// };
154+ /// ```
155+ ///
156+ /// TODO: Rc
157+ mod _tests { }
0 commit comments