Skip to content

librustc: Require that types mentioned anywhere in public signatures be #16467

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

Closed
wants to merge 1 commit into from

Conversation

pcwalton
Copy link
Contributor

public, including in trait bounds and typedefs.

There are three main patterns that this breaks. First is code that uses
private trait bounds in public APIs:

pub mod a {
    trait Trait { ... }
    pub fn f<T:Trait>() { ... }
}

Change that code to export the trait. For example:

pub mod a {
    pub trait Trait { ... }     // note `pub`
    pub fn f<T:Trait>() { ... }
}

Second, this change breaks code that was relying on
#[allow(visible_private_types)]. That lint is now a hard error, and
cannot be overridden. For example:

mod helper {
    pub struct Foo { ... }
}
pub mod public {
    use helper::Foo;
    pub fn f() -> Foo;
}

Because there is no way for code that uses public::f to name Foo,
this is no longer allowed. Change affected code to look like this:

pub mod helper {    // note `pub`
    pub struct Foo { ... }
}
pub mod public {
    use helper::Foo;
    pub fn f() -> Foo;
}

Third, this change breaks code that was relying on being able to
reference private typedefs in public APIs. For example:

pub mod b {
    type Foo = int;
    pub fn f(_: Foo) { ... }
}

Change this code to:

pub mod b {
    pub type Foo = int; // note `pub`
    pub fn f(_: Foo) { ... }
}

This implements RFC #48.

Closes #16463.

[breaking-change]

r? @alexcrichton

@lilyball
Copy link
Contributor

The RFC says this is supposed to be a feature gate.

@pcwalton
Copy link
Contributor Author

Feature gates for this kind of thing are to ease deprecation per the discussion in the imports RFC. Because I've removed all offending code this simply fast tracks deprecation. So I don't believe a gate is warranted here.

@lilyball
Copy link
Contributor

@pcwalton The RFC was very clear that this would introduce a feature gate. I don't care what you think the motivation was, not adding the feature gate means you're not following the RFC. Personally, I think the feature gate is important because it allows anyone who discovers that they cannot reasonably update their code to do what they want after this change a way to still make their code compile, while they raise an issue here regarding the breakage.

@pcwalton
Copy link
Contributor Author

You are free to submit a PR to add the feature gate.

@lilyball
Copy link
Contributor

@pcwalton That's not at all appropriate. You are violating the RFC process if you aren't implementing the RFC as merged. It's not my responsibility to clean up after you.

@pcwalton
Copy link
Contributor Author

Fine, I'll put in the feature gate. It's ridiculous cruft and nobody will ever use it, but you can have broken features if you want them.

@lilyball
Copy link
Contributor

@pcwalton I don't understand your approach here. If you think the feature gate isn't necessary, then you should have had it removed during the RFC process. Furthermore, the adoption path that the feature gate provides isn't just for rustc, it's also for any third-party code that is impacted by this. And it's also more important with this change than with most, because this change is very deliberately removing functionality from Rust with no replacement (notably, because private supertraits are disallowed despite the expectation of nearly everyone who responded to the RFC, AFAIK there's no way to expose a trait that cannot be implemented by third-parties).

It's also important to note that this is a very controversial change to begin with. Not just because there was not a clear community consensus, but also because you have chosen to merge in the RFC despite the majority of the feedback being negative. You should be trying to avoid giving the community any more cause to be unhappy with this change.

@pcwalton
Copy link
Contributor Author

Updated with feature gate.

@sfackler
Copy link
Member

@kballard it is true that this should be feature gated (as it now is), but it is not true that there is no workaround for this change:

pub struct Privatizer<T> { t: marker::InvariantType<T> }

pub trait InternalImplsOnly {
    fn force_internal() -> Privatizer<T>;
}

pub trait Foo: InternalImplsOnly {}

Privatizer::t is a private field so Privatizer can't be instantiated by code outside of its crate, which prevents cross-crate implementations of InternalImplsOnly.

@lilyball
Copy link
Contributor

Any code that has access to an existing value that confirms to Foo can use it to construct that private value. Granted, that's awkward and not necessarily doable, but it is a hole.

@sfackler
Copy link
Member

Oops, should be Privatizer<Self>.

@alexcrichton
Copy link
Member

From the technical side of things, could you opt-in all non-syntax/rustc libs into the feature gate for now? Almost everything that was made public is intentionally not-public, and I'd like to take some time to analyze why they need to be public (unless you'd like to do it of course!). Once this lands I'll do a follow up patch to remove all the feature gates soon after.

Otherwise this looks good to me, thanks @pcwalton!

type TypedArenaChunkRef<T> = Option<Box<TypedArenaChunk<T>>>;

struct TypedArenaChunk<T> {
pub struct TypedArenaChunk<T> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pretty sure this is due to a bug. I don't see why this ought to be publicly accessible.

@nikomatsakis
Copy link
Contributor

I did a read through of the first half or so of the changes. The majority I looked at did not appear to be things that must be made public by my understanding of the rules. I think though that we do need to amend the rules in two ways:

  1. Associated items in an impl count as public if the impl is implemented for a public type (when multidispatch comes around: if impl for only public types).
  2. pub use requires that its end point be public and reachable, but not that each individual step along the way be public.

The intution for point 1 is that, if these rules are doing their job, you the outsider cannot get your hands on an instance of a private type, nor can you name it, therefore you could not trigger the impl nor invoke its methods etc if any of the types are private.

@pcwalton
Copy link
Contributor Author

@nikomatsakis Since these changes would require an RFC, can we land this for now with the feature gate that @alexcrichton suggested, as well as the types you audited and determined to be public-due-to-a-bug made private again?

@pcwalton
Copy link
Contributor Author

re-r? @alexcrichton

public, including in trait bounds and typedefs.

There are three main patterns that this breaks. First is code that uses
private trait bounds in public APIs:

    pub mod a {
        trait Trait { ... }
        pub fn f<T:Trait>() { ... }
    }

Change that code to export the trait. For example:

    pub mod a {
        pub trait Trait { ... }     // note `pub`
        pub fn f<T:Trait>() { ... }
    }

Second, this change breaks code that was relying on
`#[allow(visible_private_types)]`. That lint is now a hard error, and
cannot be overridden. For example:

    mod helper {
        pub struct Foo { ... }
    }
    pub mod public {
        use helper::Foo;
        pub fn f() -> Foo;
    }

Because there is no way for code that uses `public::f` to name `Foo`,
this is no longer allowed. Change affected code to look like this:

    pub mod helper {    // note `pub`
        pub struct Foo { ... }
    }
    pub mod public {
        use helper::Foo;
        pub fn f() -> Foo;
    }

Third, this change breaks code that was relying on being able to
reference private typedefs in public APIs. For example:

    pub mod b {
        type Foo = int;
        pub fn f(_: Foo) { ... }
    }

Change this code to:

    pub mod b {
        pub type Foo = int; // note `pub`
        pub fn f(_: Foo) { ... }
    }

For now, the old behavior can be obtained with
`#[feature(visible_private_types)]`. However, the preciase semantics of
this feature gate may be unstable.

This implements RFC rust-lang#48.

Closes rust-lang#16463.

[breaking-change]
@nikomatsakis
Copy link
Contributor

@pcwalton I don't object to landing the code with feature gate, but I'd prefer not to make things public until we settle on the rules we want. Some of the items I see in the current commit, for example, don't seem like they should be public (e.g., Scope in the resolve_lifetimes module).

@pcwalton
Copy link
Contributor Author

@nikomatsakis Would you prefer opting librustc and friends into the feature gate too?

@nikomatsakis
Copy link
Contributor

I'm still confused as to why some of those changes were needed, even under the rules as accepted. I think I'd prefer not to land the patch, actually, until that is better understood (and ideally until we have a chance to discuss which rules we wanted). Alternatively we could change feature gate to opt IN to the new rules for time being until they are settled (and then only use it in tests). I just don't want people to start getting errors for rules that are under active debate. 

Niko

-------- Original message --------
From: Patrick Walton [email protected]
Date:08/15/2014 22:40 (GMT-05:00)
To: rust-lang/rust [email protected]
Cc: Niko Matsakis [email protected]
Subject: Re: [rust] librustc: Require that types mentioned anywhere in public
signatures be (#16467)

@nikomatsakis Would you prefer opting librustc and friends into the feature gate too?


Reply to this email directly or view it on GitHub.

@pcwalton
Copy link
Contributor Author

@nikomatsakis Works for me. Do you mind if I close the issue/nominate it for removal from 1.0 until such time as we come up with a workable set of rules? I don't like having 1.0 blocker issues that we can't implement

@pcwalton
Copy link
Contributor Author

Closing per @nikomatsakis' request.

@pcwalton pcwalton closed this Aug 16, 2014
@nikomatsakis
Copy link
Contributor

No objection.

Niko

-------- Original message --------
From: Patrick Walton [email protected]
Date:08/16/2014 00:16 (GMT-05:00)
To: rust-lang/rust [email protected]
Cc: Niko Matsakis [email protected]
Subject: Re: [rust] librustc: Require that types mentioned anywhere in public
signatures be (#16467)

@nikomatsakis Works for me. Do you mind if I close the issue/nominate it for removal from 1.0 until such time as we come up with a workable set of rules? I don't like having 1.0 blocker issues that we can't implement


Reply to this email directly or view it on GitHub.

matthiaskrgr pushed a commit to matthiaskrgr/rust that referenced this pull request Feb 11, 2024
…e-6, r=DropDemBits

internal: Migrate assists to the structured snippet API, part 6/7

Continuing from rust-lang#16082

Migrates the following assists:

- `extract_function`
- `generate_getter_or_setter`
- `generate_impl`
- `generate_new`
- `replace_derive_with_manual_impl`

Would've been the final PR in the structured snippet migration series, but I didn't notice that `generate_trait_from_impl` started to use `{insert,replace}_snippet` when I first started the migration 😅. This appears to be a pretty self-contained change, so I'll leave that for a separate future PR.

This also removes the last usages of `render_snippet`, which was a follow up goal of rust-lang#11638. 🎉
bors added a commit to rust-lang-ci/rust that referenced this pull request Feb 18, 2024
…e-7, r=Veykril

internal: Migrate assists to the structured snippet API, part 7/7

Continuing from rust-lang#16467

Migrates the following assists:

- `generate_trait_from_impl`

This adds `add_placeholder_snippet_group`, which adds a group of placeholder snippets which are linked together and allows for renaming generated items without going through a separate rename step.

This also removes the last usages of `SourceChangeBuilder::{insert,replace}_snippet`, as all assists have finally been migrated to the structured snippet versions of those methods.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Feature gate public items in private APIs
6 participants