diff --git a/derive/src/lib.rs b/derive/src/lib.rs index 19f3c48..a56512b 100644 --- a/derive/src/lib.rs +++ b/derive/src/lib.rs @@ -352,6 +352,9 @@ fn expand_function_body(function: Function) -> TokenStream2 { } } + // Do not apply the caller's span to our "unsafe" token. Otherwise + // `forbid(unsafe_code)` at caller would reject the expanded code. + let our_unsafe = quote!(unsafe); quote_spanned! {semi_token.span=> #(#attrs)* #inline_attr @@ -366,7 +369,7 @@ fn expand_function_body(function: Function) -> TokenStream2 { let _ = ::ref_cast::__private::CurrentCrate::<#from_type, #to_type> {}; #allow_unused_unsafe // in case they are building with deny(unsafe_op_in_unsafe_fn) - unsafe { + #our_unsafe { ::ref_cast::__private::transmute::<#from_type, #to_type>(#arg) } } diff --git a/tests/test_trivial.rs b/tests/test_trivial.rs index c5ec85a..d96959c 100644 --- a/tests/test_trivial.rs +++ b/tests/test_trivial.rs @@ -42,6 +42,20 @@ pub struct Unsized<'a> { pub value: str, } +#[forbid(unsafe_code)] +mod forbid_unsafe { + use ref_cast::{ref_cast_custom, RefCastCustom}; + + #[derive(RefCastCustom)] + #[repr(transparent)] + pub struct Custom(str); + + impl Custom { + #[ref_cast_custom] + pub fn new(s: &str) -> &Custom; + } +} + #[test] fn test_trivial() { ImplicitUnit::ref_cast(&0); @@ -49,4 +63,5 @@ fn test_trivial() { ExplicitTrivial::ref_cast(&0); Override::::ref_cast(&PhantomData::); Unsized::ref_cast("..."); + forbid_unsafe::Custom::new("..."); }