-
Notifications
You must be signed in to change notification settings - Fork 12.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
"error: private type in public interface" in private module #30905
Comments
This is expected, because the outer module could re-export that function. |
I couldn’t but it doesn’t. And the compiler should know that. It’s all in the same crate, a re-export can not be added without recompiling that crate. |
see #22261 for the discussion, the point is that the privacy checks don't need to reason about the entire crate, but just about the module |
I understand that fixing this bug may require doing a more complex analysis than is currently done, but i maintain that it's a bug. #22261 (comment) says the same. |
Conversely, this compile fine but should be an error: pub fn parse() -> parser::HostInternal {
unimplemented!();
}
mod parser {
pub struct HostInternal;
} |
More complex analysis (reachability by reexports, "nameability") was done before and the example with Edit: some reasons are outlined by @nikomatsakis in #28450 (comment) |
This sounds like a regression. Some git archaeology points to rust-lang/rfcs#200, I’ll read up on motivations. |
The new rules are not an improvement in any way except to make the code in rustc simpler. There's still a lot of false negatives, still a lot of false positives as well, and it will cause breaking changes to a huge amount of existing Rust code. If there's going to be breaking changes, the new system should at least have significant improvements to make the breakage worth it. |
Nah, the compiler still tracks reachability through reexports for other purposes. |
@petrochenkov So you're saying it isn't even an improvement at all and we're just breaking the world to satisfy some RFC that has been sitting around for over a year? |
@retep998 |
@retep998 Let me just say that I'm sorry your code stopped compiling -- I know that's always a pain, whatever the cause. In this case, as @petrochenkov said, there really aren't any new rules: it's just that rustc was (very) buggy and failed to enforce the rules consistently. But I know that doesn't make it any less annoying when you have to update your code. |
The changes are still only warnings for me so far, although the warnings claim they will become errors, so thankfully it isn't the end of the world yet. |
@retep998 I'd actually be interested to see the specific cases that are failing for you. In particular, I'd like to know if they fall into the category of type aliases that appear in public interfaces, or something else? |
@nikomatsakis They're all basically a private struct, and then a public typedef to a raw pointer to it. The biggest example is https://github.com/retep998/winapi-rs/blob/bb182accc1cee10ea1a6e926ca51e8ddb63154c1/src/macros.rs#L4-L9 . It's easy enough for me to just make the internal opaque type public, I just don't like knowing that all existing versions of winapi will break in the future, forcing people to cargo update. |
@retep998 OK. That particular case would not be addressed by any of the mitigating measures we considered, I think. (It's sort of the motivating example that the rules were trying to prevent, from what I understand, in that one ought to be able to assume, because it is declared priv, that the private inner struct is not accessible from outside the module.) |
This bit me as well. I defined an internal struct, and that sub modules would accept that struct as an argument to their methods. The "solution" was to trick the privacy visitor, by putting the struct into its own submodule, make the struct mod foo {
struct Buf {
inner: Vec<u8>
}
mod bar {
use super::Buf;
pub struct Encoder;
impl Encoder {
pub fn encode(&mut self, buf: &mut Buf) {
buf.inner.push(b'!');
}
}
}
} |
Oh, that’s a nice trick, thanks @seanmonstar (Through it’s still unfortunate that we have to do this to work around the lint’s incorrect algorithm.) |
Is that the right way to do it? It would be good to know, so that we don't use something that will be disallowed in the future. |
@bluss
=>
It is even mentioned in the detailed error message. |
I don't see how this can't be considered a bug: mod bar {
use super::Foo;
pub fn foo_bar(_: Foo) {}
}
struct Foo; It's trivial to see that this code doesn't actually export any private types. I strongly disagree with this being the intended behavior: it just seems wrong. |
This reverts commit 9fbcc91.
Closing as working according to the rules. |
Update E0446.md The existing error documentation did not show how to use a child module's functions if the types used in those functions are private. These are some other places this problem has popped up that did not present a solution (these are from before the solution existed, 2016-2017. The solution was released in the Rust 2018 edition. However these were the places I was pointed to when I encountered the problem myself): rust-lang#30905 https://stackoverflow.com/questions/39334430/how-to-reference-private-types-from-public-functions-in-private-modules/62374958#62374958
Update E0446.md The existing error documentation did not show how to use a child module's functions if the types used in those functions are private. These are some other places this problem has popped up that did not present a solution (these are from before the solution existed, 2016-2017. The solution was released in the Rust 2018 edition. However these were the places I was pointed to when I encountered the problem myself): rust-lang#30905 https://stackoverflow.com/questions/39334430/how-to-reference-private-types-from-public-functions-in-private-modules/62374958#62374958
…1554) Closes paritytech/polkadot-sdk-docs#55 - Changes 'current storage version' terminology to less ambiguous 'in-code storage version' (suggestion by @ggwpez) - Adds a new example pallet `pallet-example-single-block-migrations` - Adds a new reference doc to replace https://docs.substrate.io/maintain/runtime-upgrades/ (temporarily living in the pallet while we wait for developer hub PR to merge) - Adds documentation for the `storage_alias` macro - Improves `trait Hooks` docs - Improves `trait GetStorageVersion` docs - Update the suggested patterns for using `VersionedMigration`, so that version unchecked migrations are never exported - Prevents accidental usage of version unchecked migrations in runtimes paritytech/substrate#14421 (comment) - Unversioned migration code is kept inside `mod version_unchecked`, versioned code is kept in `pub mod versioned` - It is necessary to use modules to limit visibility because the inner migration must be `pub`. See rust-lang/rust#30905 and https://internals.rust-lang.org/t/lang-team-minutes-private-in-public-rules/4504/40 for more. ### todo - [x] move to reference docs to proper place within sdk-docs (now that #2102 is merged) - [x] prdoc --------- Co-authored-by: Kian Paimani <[email protected]> Co-authored-by: Juan <[email protected]> Co-authored-by: Oliver Tale-Yazdi <[email protected]> Co-authored-by: command-bot <> Co-authored-by: gupnik <[email protected]>
…aritytech#1554) Closes paritytech/polkadot-sdk-docs#55 - Changes 'current storage version' terminology to less ambiguous 'in-code storage version' (suggestion by @ggwpez) - Adds a new example pallet `pallet-example-single-block-migrations` - Adds a new reference doc to replace https://docs.substrate.io/maintain/runtime-upgrades/ (temporarily living in the pallet while we wait for developer hub PR to merge) - Adds documentation for the `storage_alias` macro - Improves `trait Hooks` docs - Improves `trait GetStorageVersion` docs - Update the suggested patterns for using `VersionedMigration`, so that version unchecked migrations are never exported - Prevents accidental usage of version unchecked migrations in runtimes paritytech/substrate#14421 (comment) - Unversioned migration code is kept inside `mod version_unchecked`, versioned code is kept in `pub mod versioned` - It is necessary to use modules to limit visibility because the inner migration must be `pub`. See rust-lang/rust#30905 and https://internals.rust-lang.org/t/lang-team-minutes-private-in-public-rules/4504/40 for more. ### todo - [x] move to reference docs to proper place within sdk-docs (now that paritytech#2102 is merged) - [x] prdoc --------- Co-authored-by: Kian Paimani <[email protected]> Co-authored-by: Juan <[email protected]> Co-authored-by: Oliver Tale-Yazdi <[email protected]> Co-authored-by: command-bot <> Co-authored-by: gupnik <[email protected]>
Reduced test case:
Output with rustc 1.7.0-nightly (1447ce7 2016-01-13)
This is incorrect: the
parse
function is not visible anywhereHostInternal
isn’t since theparser
module is not public.In my non-reduced crate I get a warning rather than an error but I haven’t managed to reproduce that in the reduced case. (Regardless, that warning is also incorrect.)
The text was updated successfully, but these errors were encountered: