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

Add warn-by-default lint when local binding shadows exported glob re-export item #111378

Merged
merged 1 commit into from
May 28, 2023

Conversation

jieyouxu
Copy link
Member

@jieyouxu jieyouxu commented May 9, 2023

This PR introduces a warn-by-default rustc lint for when a local binding (a use statement, or a type declaration) produces a name which shadows an exported glob re-export item, causing the name from the exported glob re-export to be hidden (see #111336).

Unresolved Questions

  • Is this approach correct? While it passes the UI tests, I'm not entirely convinced it is correct. Seems to be ok now.
  • What should the lint be called / how should it be worded? I don't like calling use x::*; or struct Foo; a "local binding" but they are NameBindings internally if I'm not mistaken. The lint is called local_binding_shadows_glob_reexport for now, unless a better name is suggested. hidden_glob_reexports.

Fixes #111336.

@rustbot
Copy link
Collaborator

rustbot commented May 9, 2023

r? @b-naber

(rustbot has picked a reviewer for you, use r? to override)

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels May 9, 2023
@rust-log-analyzer

This comment has been minimized.

@jieyouxu

This comment was marked as outdated.

@petrochenkov
Copy link
Contributor

r? @petrochenkov

@rustbot rustbot assigned petrochenkov and unassigned b-naber May 9, 2023
@petrochenkov
Copy link
Contributor

petrochenkov commented May 11, 2023

Similarly to #107880 it's better to run this check somewhere near finalize_imports.

At that point the main binding is available as resolution.binding and the shadowed glob binding is available as resolution.shadowed_glob.
Effective visibilities are also available there, so we'll be able to report this lint only for actually exported globs (again, similarly to #107880).

@rustbot author

@rustbot rustbot 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 May 11, 2023
@jieyouxu

This comment was marked as resolved.

@petrochenkov
Copy link
Contributor

glob_binding.res().opt_def_id() is the glob import's target, of course it's shadowed and not exported.
Instead I suggest checking effective visibility of the glob import item itself.

(But if that fails too we can always fall back to vis.is_public().)

@jieyouxu
Copy link
Member Author

Instead I suggest checking effective visibility of the glob import item itself.

Sorry how do I check this?

@petrochenkov
Copy link
Contributor

petrochenkov commented May 12, 2023

shadowed_glob -> kind: NameBindingKind::Import { import, .. } -> import.id() -> resolver.local_def_id(id)

@jieyouxu

This comment was marked as resolved.

@petrochenkov
Copy link
Contributor

but it seems self.effective_visibilities.is_exported(import_local_def_id) is still returning false

On which test case?
If you are using tests/ui/resolve/local-shadows-glob-reexport.rs then both glob imports there are indeed not exported (not usable from other crates) because upstream_a and upstream_b are private.

@jieyouxu
Copy link
Member Author

jieyouxu commented May 12, 2023

If I change upstream_a and upstream_b to pub mods

#![deny(local_binding_shadows_glob_reexport)]

pub mod upstream_a {
    mod inner {
        pub struct Foo {}
    }

    pub use self::inner::*;

    struct Foo;
    //~^ ERROR local binding shadows glob re-export
}

pub mod upstream_b {
    mod inner {
        pub struct Foo {}
    }

    mod other {
        pub struct Foo;
    }

    pub use self::inner::*;

    use self::other::Foo;
    //~^ ERROR local binding shadows glob re-export
}

// Downstream crate
// mod downstream {
//     fn proof() {
//         let _ = crate::upstream_a::Foo;
//         let _ = crate::upstream_b::Foo;
//     }
// }

pub fn main() {}

then the glob re-export items should be exported right?

@petrochenkov
Copy link
Contributor

petrochenkov commented May 12, 2023

They should be exported if you add any additional non-shadowed names to them, e.g. pub struct Bar {} to mod inner.

As written in #111378 (comment) they should not be exported and should be reported as unused because they don't reexport anything at all.
Although in ui tests lints from the unused group are allowed by default, so the unused warnings may be lost unless enabled explicitly.

@jieyouxu
Copy link
Member Author

They should be exported if you add any additional non-shadowed names to them, e.g. pub struct Bar {} to mod inner.

Ohh right that makes sense. Yeah the check works if I add additional non-shadowed names to mod inner.

@rustbot ready

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels May 12, 2023
@rust-log-analyzer

This comment has been minimized.

@jieyouxu
Copy link
Member Author

error: local binding shadows glob re-export
   --> compiler/rustc_middle/src/ty/mod.rs:148:1
    |
73  | pub use rustc_type_ir::*;
    |         ---------------- the name `sty` in the type namespace is introduced by the glob reexport here
...
148 | mod sty;
    | ^^^^^^^^ but the local binding here shadows the name `sty` in the type namespace
    |

I think the lint correctly fires here? The glob re-export item pub use rustc_type_ir::* is exported because there are other pub items apart from sty, and rustc_type_ir::sty would be shadowed by the local mod sty in rustc_middle.

@petrochenkov
Copy link
Contributor

compiler/rustc_middle/src/ty/mod.rs:148:1

Yes, looks exactly like a case which this lint is supposed to catch.

@jieyouxu
Copy link
Member Author

In this case should I just band-aid a #![allow(local_binding_shadows_glob_reexport)] for the mod sty or do I expand pub use rustc_type_ir::*; into everything needed modulo sty?

@petrochenkov
Copy link
Contributor

Probably rename the private mod sty to something else.

@jieyouxu jieyouxu force-pushed the local-shadows-glob-reexport branch 2 times, most recently from 36a2d83 to 4047827 Compare May 12, 2023 17:38
@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@petrochenkov
Copy link
Contributor

DEBUG rustc_resolve::imports check_hidden_glob_reexports: self.effective_visibilities.is_exported(glob_import_def_id) = true

Not in case of tests/ui/shadowed/shadowed-trait-methods.rs

https://play.rust-lang.org/?version=nightly&mode=debug&edition=2015&gist=e5d5a14962010be4938af1c2eec9ac16

@jieyouxu jieyouxu force-pushed the local-shadows-glob-reexport branch from f121097 to b8e4a1a Compare May 27, 2023 01:25
@rust-log-analyzer

This comment has been minimized.

@petrochenkov
Copy link
Contributor

Checking that the resolutions are not Res::Err helped with tests/ui/shadowed/shadowed-trait-methods.rs but not with tests/ui/imports/issue-55884-2.rs.

r=me after allowing the lint in tests/ui/imports/issue-55884-2.rs (just for the shadowing import, not for the whole test).

@jieyouxu jieyouxu force-pushed the local-shadows-glob-reexport branch from b8e4a1a to b960658 Compare May 27, 2023 10:49
@jieyouxu
Copy link
Member Author

@rustbot ready

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels May 27, 2023
@petrochenkov
Copy link
Contributor

@bors r+

@bors
Copy link
Contributor

bors commented May 27, 2023

📌 Commit b960658 has been approved by petrochenkov

It is now in the queue for this repository.

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels May 27, 2023
@bors
Copy link
Contributor

bors commented May 28, 2023

⌛ Testing commit b960658 with merge b9c5fdc...

@bors
Copy link
Contributor

bors commented May 28, 2023

☀️ Test successful - checks-actions
Approved by: petrochenkov
Pushing b9c5fdc to master...

@bors bors added the merged-by-bors This PR was explicitly merged by bors. label May 28, 2023
@bors bors merged commit b9c5fdc into rust-lang:master May 28, 2023
@rustbot rustbot added this to the 1.72.0 milestone May 28, 2023
@jieyouxu jieyouxu deleted the local-shadows-glob-reexport branch May 28, 2023 05:16
@rust-timer
Copy link
Collaborator

Finished benchmarking commit (b9c5fdc): comparison URL.

Overall result: ❌ regressions - no action needed

@rustbot label: -perf-regression

Instruction count

This is a highly reliable metric that was used to determine the overall result at the top of this comment.

mean range count
Regressions ❌
(primary)
0.4% [0.4%, 0.4%] 1
Regressions ❌
(secondary)
0.4% [0.4%, 0.4%] 1
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) 0.4% [0.4%, 0.4%] 1

Max RSS (memory usage)

Results

This is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.

mean range count
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
2.3% [2.0%, 2.5%] 2
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) - - 0

Cycles

Results

This is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.

mean range count
Regressions ❌
(primary)
2.0% [2.0%, 2.0%] 1
Regressions ❌
(secondary)
- - 0
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) 2.0% [2.0%, 2.0%] 1

Binary size

This benchmark run did not return any relevant results for this metric.

Bootstrap: 645.492s -> 645.767s (0.04%)

@petrochenkov
Copy link
Contributor

@jieyouxu
I've just noticed that the labels here go in a span order, but they should go in a fixed order instead ("supposed to be publicly re-exported" first, and "but the private" second).

If the order is not fixed, then it looks weird, see for example https://crater-reports.s3.amazonaws.com/pr-111505/try%23590af02d982816cfb2e4e43f8c54065e816581ce/reg/assemble-std-0.2.0/log.txt

[INFO] [stdout] warning: private item shadows public glob re-export
[INFO] [stdout]   --> src/lib.rs:20:5
[INFO] [stdout]    |
[INFO] [stdout] 20 | use assemble_core::Project;
[INFO] [stdout]    |     ^^^^^^^^^^^^^^^^^^^^^^ but the private item here shadows it
[INFO] [stdout] ...
[INFO] [stdout] 26 | pub use assemble_core::*;
[INFO] [stdout]    |         ---------------- the name `Project` in the type namespace is supposed to be publicly re-exported here

@jieyouxu
Copy link
Member Author

jieyouxu commented Jun 7, 2023

Thanks for the heads up, I'll fix this tomorrow. EDIT: Currently trying to find out how I can sort them in fixed order and not span order.

matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request Jun 10, 2023
…-span-order, r=petrochenkov

Adjust span labels for `HIDDEN_GLOB_REEXPORTS`

Addresses rust-lang#111378 (comment).

### Before This PR

The possibility that the private item comes before the glob re-export was not account for, causing the span label messages to say "but private item here shadows it" before "the name `Foo` in the type namespace is supposed to be publicly re-exported here".

### After This PR

```rust
warning: private item shadows public glob re-export
  --> $DIR/hidden_glob_reexports.rs:9:5
   |
LL |     struct Foo;
   |     ^^^^^^^^^^^ the private item here shadows the name `Foo` in the type namespace
...
LL |     pub use self::inner::*;
   |             -------------- but it is supposed to be publicly re-exported here
   |
   = note: `#[warn(hidden_glob_reexports)]` on by default

warning: private item shadows public glob re-export
  --> $DIR/hidden_glob_reexports.rs:27:9
   |
LL |     pub use self::inner::*;
   |             -------------- the name `Foo` in the type namespace is supposed to be publicly re-exported here
LL |
LL |     use self::other::Foo;
   |         ^^^^^^^^^^^^^^^^ but the private item here shadows it
```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
merged-by-bors This PR was explicitly merged by bors. S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Lint when shadowing a glob-reexported item with a local declaration
8 participants