Skip to content

Commit fefaed2

Browse files
committed
Stop relying on impl Deref { type Target = Self; ...
... this has a tendency to cause `reached the recursion limit while auto-dereferencing` errors, and even a dumb struct copy suffices to avoid it.
1 parent 05c3f9d commit fefaed2

File tree

1 file changed

+13
-3
lines changed

1 file changed

+13
-3
lines changed

c-bindings-gen/src/main.rs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -646,12 +646,22 @@ fn writeln_trait<'a, 'b, W: std::io::Write>(w: &mut W, t: &'a syn::ItemTrait, ty
646646
writeln!(w, " for {} {{", trait_name).unwrap();
647647
impl_trait_for_c!(t, "", types, &syn::PathArguments::None);
648648
writeln!(w, "}}\n").unwrap();
649+
650+
writeln!(w, "struct {}Ref({});", trait_name, trait_name).unwrap();
651+
write!(w, "impl").unwrap();
652+
maybe_write_lifetime_generics(w, &t.generics, types);
653+
write!(w, " rust{}", t.ident).unwrap();
654+
maybe_write_generics(w, &t.generics, &syn::PathArguments::None, types, false);
655+
writeln!(w, " for {}Ref {{", trait_name).unwrap();
656+
impl_trait_for_c!(t, ".0", types, &syn::PathArguments::None);
657+
writeln!(w, "}}\n").unwrap();
658+
649659
writeln!(w, "// We're essentially a pointer already, or at least a set of pointers, so allow us to be used").unwrap();
650660
writeln!(w, "// directly as a Deref trait in higher-level structs:").unwrap();
651-
writeln!(w, "impl core::ops::Deref for {} {{\n\ttype Target = Self;", trait_name).unwrap();
652-
writeln!(w, "\tfn deref(&self) -> &Self {{\n\t\tself\n\t}}\n}}").unwrap();
661+
writeln!(w, "impl core::ops::Deref for {} {{\n\ttype Target = {}Ref;", trait_name, trait_name).unwrap();
662+
writeln!(w, "\tfn deref(&self) -> &Self::Target {{\n\t\tunsafe {{ &*(self as *const _ as *const {}Ref) }}\n\t}}\n}}", trait_name).unwrap();
653663
writeln!(w, "impl core::ops::DerefMut for {} {{", trait_name).unwrap();
654-
writeln!(w, "\tfn deref_mut(&mut self) -> &mut Self {{\n\t\tself\n\t}}\n}}").unwrap();
664+
writeln!(w, "\tfn deref_mut(&mut self) -> &mut {}Ref {{\n\t\tunsafe {{ &mut *(self as *mut _ as *mut {}Ref) }}\n\t}}\n}}", trait_name, trait_name).unwrap();
655665
}
656666

657667
writeln!(w, "/// Calls the free function if one is set").unwrap();

0 commit comments

Comments
 (0)