Skip to content
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

unreachable-pub lint (as authorized by RFC 2126) #45569

Merged
merged 1 commit into from
Nov 3, 2017

Conversation

zackmdavis
Copy link
Member

@zackmdavis zackmdavis commented Oct 27, 2017

To whom it may concern:

RFC 2126 commissions the creation of a lint for pub items that are not visible from crate root (#45521). We understand (but seek confirmation from more knowledgable compiler elders) that this can be implemented by linting HIR items that are not cx.access_levels.is_exported cx.access_levels.is_reachable but have a vis (-ibility) field of hir::Visibility::Public.

The lint, tentatively called unexported-pub unreachable-pub (with the understanding that much could be written on the merits of various names, as it is said of the colors of bicycle-sheds), suggests crate as a replacement for pub if the crate_visibility_modifier feature is enabled (see #45388), and pub(crate) otherwise. We also use help messaging to suggest the other potential fix of exporting the item; feedback is desired as to whether this may be confusing or could be worded better.

As a preview of what respecting the proposed lint would look like (and to generate confirmatory evidence that this implementation doesn't issue false positives), we take its suggestions for libcore (save one, which is deferred to another pull request because it brings up an unrelated technical matter). I remain your obedient servant.

unexported_pub

r? @petrochenkov

@kennytm kennytm added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Oct 27, 2017
pub fn debug_struct_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>,
name: &str)
-> DebugStruct<'a, 'b> {
pub(crate) fn debug_struct_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>,
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd avoid changing libcore until the crate sugar for pub(crate) is available in bootstrap compiler.


impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnexportedPub {
fn check_item(&mut self, cx: &LateContext, item: &hir::Item) {
if !cx.access_levels.is_exported(item.id) && item.vis == hir::Visibility::Public {
Copy link
Contributor

Choose a reason for hiding this comment

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

As I mentioned on gitter, this should use is_reachable instead of is_exported.
With is_exported this lint will give false positives on anything that is leaked through any other means than use (type aliases, return types, field types). All these things still need to be pub to be usable from other crates.

Copy link
Contributor

Choose a reason for hiding this comment

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

Test to add:

mod m {
    pub struct S; // The lint should not fire on this struct
}

pub fn f() -> m::S { m::S }

pub struct UnexportedPub;

declare_lint! {
UNEXPORTED_PUB,
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd actually rename the lint into unreachable_pub (+ update all the comments, etc).

if !cx.access_levels.is_exported(item.id) && item.vis == hir::Visibility::Public {
let mut err = cx.struct_span_lint(UNEXPORTED_PUB, item.span, "unexported `pub` item");
err.help("consider exporting it for use by other crates");
// `pub` is three chars at start of declaration
Copy link
Contributor

Choose a reason for hiding this comment

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

This is a bold claim!
pub can be passed to an item through a $vis matcher, for example.

Copy link
Contributor

Choose a reason for hiding this comment

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

Could you add a test for this case? Something like

mod m {
    macro_rules! m {
        ($visibility: vis) => { $visibility struct S; }
    }

    m!(pub);
}

fn check_item(&mut self, cx: &LateContext, item: &hir::Item) {
if !cx.access_levels.is_exported(item.id) && item.vis == hir::Visibility::Public {
let mut err = cx.struct_span_lint(UNEXPORTED_PUB, item.span, "unexported `pub` item");
err.help("consider exporting it for use by other crates");
Copy link
Contributor

Choose a reason for hiding this comment

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

Looking at the tests, "or consider exporting it for use by other crates" would look better.

}

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnexportedPub {
fn check_item(&mut self, cx: &LateContext, item: &hir::Item) {
Copy link
Contributor

Choose a reason for hiding this comment

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

check_item doesn't cover pub on impl items, foreign items and struct fields.

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnexportedPub {
fn check_item(&mut self, cx: &LateContext, item: &hir::Item) {
if !cx.access_levels.is_exported(item.id) && item.vis == hir::Visibility::Public {
let mut err = cx.struct_span_lint(UNEXPORTED_PUB, item.span, "unexported `pub` item");
Copy link
Contributor

Choose a reason for hiding this comment

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

def_span will probably look better here (see an example of use in #44847)

@zackmdavis
Copy link
Member Author

updated (force-push)

@zackmdavis zackmdavis changed the title unexported-pub lint (as authorized by RFC 2126) unreachable-pub lint (as authorized by RFC 2126) Oct 30, 2017
Copy link
Contributor

@estebank estebank left a comment

Choose a reason for hiding this comment

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

Could you do a squash of your commits while you're at it?

// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![feature(crate_visibility_modifier)]
Copy link
Contributor

Choose a reason for hiding this comment

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

Could you add a test without this feature enabled to make sure there're no regressions going forward with the pub(crate) suggestion?

@petrochenkov
Copy link
Contributor

r=me with @estebank's comment (#45569 (comment)) addressed

@kennytm kennytm added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Nov 1, 2017
This is with deepest thanks to Vadim Petrochenkov for thorough review, and
resolves rust-lang#45521.
@zackmdavis
Copy link
Member Author

(added non-crate_visibility_modifier UI test and squashed) 🏁 💖

@petrochenkov
Copy link
Contributor

@bors r+

@bors
Copy link
Contributor

bors commented Nov 3, 2017

📌 Commit 085ec6d has been approved by petrochenkov

@bors
Copy link
Contributor

bors commented Nov 3, 2017

⌛ Testing commit 085ec6d with merge 9140b5dc5dc016024470e9ab1139c8a86cfec4b8...

@bors
Copy link
Contributor

bors commented Nov 3, 2017

💔 Test failed - status-travis

@kennytm
Copy link
Member

kennytm commented Nov 3, 2017

@bors retry

@bors
Copy link
Contributor

bors commented Nov 3, 2017

⌛ Testing commit 085ec6d with merge 59d4845...

bors added a commit that referenced this pull request Nov 3, 2017
`unreachable-pub` lint (as authorized by RFC 2126)

To whom it may concern:

RFC 2126 commissions the creation of a lint for `pub` items that are not visible from crate root (#45521). We understand (but seek confirmation from more knowledgable compiler elders) that this can be implemented by linting HIR items that are _not_ ~~`cx.access_levels.is_exported`~~ `cx.access_levels.is_reachable` but have a `vis` (-ibility) field of `hir::Visibility::Public`.

The lint, tentatively called ~~`unexported-pub`~~ `unreachable-pub` (with the understanding that much could be written on the merits of various names, as it is said of the colors of bicycle-sheds), suggests `crate` as a replacement for `pub` if the `crate_visibility_modifier` feature is enabled (see #45388), and `pub(crate)` otherwise. We also use help messaging to suggest the other potential fix of exporting the item; feedback is desired as to whether this may be confusing or could be worded better.

As a preview of what respecting the proposed lint would look like (and to generate confirmatory evidence that this implementation doesn't issue false positives), ~~we take its suggestions for `libcore`~~ (save one, which is deferred to another pull request because it brings up an unrelated technical matter). I remain your obedient servant.

![unexported_pub](https://user-images.githubusercontent.com/1076988/32089794-fbd02420-baa0-11e7-87e5-3ec01f18924a.png)

r? @petrochenkov
@bors
Copy link
Contributor

bors commented Nov 3, 2017

☀️ Test successful - status-appveyor, status-travis
Approved by: petrochenkov
Pushing 59d4845 to master...

@bors bors merged commit 085ec6d into rust-lang:master Nov 3, 2017
bors added a commit that referenced this pull request Nov 7, 2017
…hton

regenerate libcore/char_private.rs

(filed separately from the work in #45569, because of this matter of the updated Unicode data; see also #45567)

char_private.rs is generated programmatically by char_private.py, using data retrieved from the Unicode Consortium's website.

The motivation here was to make `is_printable` crate-visible (with `pub(crate)`), but it would seem that the Unicode data has changed slightly since char_private.rs was last generated.
@zackmdavis zackmdavis deleted the unexported_pub_lint branch January 13, 2018 07:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants