#Scoped visibility equivalent to friend structs in C++

26 messages · Page 1 of 1 (latest)

acoustic isle
#

I have two structs with identical fields such as the following specification

struct A { a: i8, b: i8 };
struct B { a: i8, b: i8 };

and i wish to generate an Into between them. Of course I can do this with std::mem::transmute since it is an invariant that they have the identical size following they have identical fields, but i wish to do this with destructuring to ease implementation of future features. Due to the nature of the application (proc-macro) i cannot simply add pub(self) / pub(in self) since it would violate the application scope of the macro.

My current attempt uses the in scoping to try to limit it to another path but the path must be a module. I tried

struct A { pub(in B) /* pub(in self::B) */ a: i8, pub(in B) b: i8 };
struct B { pub(in A)                       a: i8, pub(in A) b: i8 };

This does not work since A and B are not modules. The hoped for behaviour is similar to how in C++ it would be

class A {
private:
  char a;
  char b;

  friend class B;
}
class B {
private:
  char a;
  char b;

  friend class A;
}

Other ideas i have coincided include creating a module including all the desired structs (this occurs inside a proc-macro attribute so this is a power i have). This would work if the specified visibility within the struct was for example pub(self) since this would be transformed into pub(super) but it would not work if the original visibility was pub(super) since this would become pub(in super::super) which is an invalid path.

Finally the last idea i had was adding an insanely named method that destructed into an ordered tuple named something like #[inline] pub(self) fn __INTERNAL_DO_NOT_USE_PUBLIC_DESTRUCTURE(self) -> (i8,i8) and then destructing this. This is undesirable.

TL;DR: how to I expose fields to 'friend' structs without exposing them to the rest of the module.

sturdy musk
#

Of course I can do this with std::mem::transmute
these structs have an unspecified layout, transmuting between them causes undefined behavior

#

but the tl:dr is that you can't - in rust, modules are the units of privacy. Consider laying out modules in a different way

#

it might help if you explain what you're actually doing

static field
#

also pub(self) is exactly the same as without any specifier

#

which is "private"

#

in rust that means that it's only visible in the defining module

#

one possiblity would be ```rs
mod __internal {
pub(super) struct A { a: i8, b: i8 };
pub(super) struct B { a: i8, b: i8 };
}
use __internal::{A, B};

#

but I can't tell if it's valid with your setup

acoustic isle
acoustic isle
left sentinel
#

you need repr c for that

sturdy musk
#

is this code that a proc macro generates?

acoustic isle
sturdy musk
#

ah. i'm fairly sure there may be some other way to accomplish what you want, or some clever trick you can use

static field
#

what do you have to "transform"?

#

does the input have visibility specifiers?

#

and why would pub(in super::super) be invalid?

acoustic isle
#

I would expect it to work

#

But I can retry when I get home

static field
#

I still don't understand the problem tbh

sturdy musk
#

same

acoustic isle
#

I figured it out i was being dumb

sturdy musk
#

you were just undercafeinated