Referencing private struct

Hey there,
I’m try to get the synth crate working with rodio.
synth provides a public Synth struct, which has a method, frames(), which returns a private Frames struct.
In order to adapt this to the Source trait from rodio, i have to store this Frames struct in my adapter.
But since this struct is private, I can’t reference it in my struct. How can I solve this problem?
Why is it even allowed to return private module members from a public function, as this seems to destroy composability… :confused:

1 Like

Looks like Frames is public here. I don’t think you’re allowed to return a private struct. Did you try it as synth::Frames? Nevermind, I see it is not exported in lib.rs… I wouldn’t expect that to work.

Rust-the-language is not going to be of help in gaining access to a private struct from the outside;
The fact that you can’t access a private struct means Rust is doing its job in that regard :slight_smile:

The easiest and most practical fix is to file a bug report with the project and explain the situation to the maintainer(s). In the meantime I suggest you fork the project and make the necessary changes, so you 1. have something to work with in the meantime and 2. have a pull request ready to go if the maintainers are willing to make the struct public. Doing all this is a few minutes of work at most, and will lower the barrier to them saying yes to your request.

2 Likes

Thanks for clarifying, I almost expected this to be the case.
In the meantime, I stumbled accross even bigger differences in design that makes it impossible (at least for me) to use these two crates together (One only operates on 'static objects while the other builds dynamic ones, so they seem to be incompatible by design)
This being said, I don’t think a pull request is necessary, as my usecase was pretty unique (i think) and when using synth the way it’s supposed to be used, I think this change is unnecessary.
Thank you a lot anyways :slight_smile:

Having a publicly callable method/function return something private seems like a clear bug to me in the library. In fact, it almost seems like a compiler bug as well. I can’t imagine how it could be useful or why the compiler even allows it. This sounds like something that should be brought up on the internals forum.

1 Like

You’re right, I created a pull request to the crate, but while doing so, i saw the last update was 2 years ago, so we can only hope this will get merged :confused:
(my first pull request ever by the way, I’m quite excited ^^)

2 Likes

If it is not a bug and it is intended, I don’t like it very much :confused:
I think that the following is a simple example that shows the problem:

mod parent {
    mod private {
        pub fn test() -> Test {
            Test
        }
        
        #[derive(Debug)]
        pub struct Test;
    }
    
    pub use self::private::test;
}

use parent::test;

fn main() {
   println!("{:?}", test());
   // The following does not compile
   // println!("{:?}", parent::private::Test);
}

Should this situation be posted in the internal forum?
EDIT: posted on the internals forum

3 Likes

I think there’s some wonkiness with privacy, modules, and re-exports. I’ve definitely seen cases before where a private type made its way into a public API, after some amount of re-exporting took place (just recently something of similar ilk was fixed in tokio, IIRC). I suspect there’re existing GH issues on it, but if not, yeah, I think it should be filed.

Edit: found the tokio issue I was thinking of: https://github.com/tokio-rs/tokio/pull/604

2 Likes

The semantics are that the privacy is that at the definition site.

If you wrote pub struct Foo, anyone can use it even from outside your crate (e.g. by calling a function returning it) even if you didn’t reexport it yourself out of a private module.

I think the question is whether that should actually be allowed, whether it’s the desired semantics. To me, it seems not. At a minimum, it should be a warning that there’s a “more public” API that exposes a “less public” type, particularly if “more public” means “exposed to consumes of the crate”. These types of scenarios are usually mistakes, people simply losing track of what’s exposed how and where.

3 Likes

This was discussed at length, years ago, and the current design was chosen, as a tradeoff. @petrochenkov might be able to offer more information.

From what I can remember, we were going to add that lint, but I’m not sure what happened.

EDIT: @petrochenkov commented on https://internals.rust-lang.org/t/private-struct-returned-by-public-fn/8448/13

4 Likes