Conversation
|
r? @JohnTitor rustbot has assigned @JohnTitor. Use Why was this reviewer chosen?The reviewer was selected based on:
|
This comment has been minimized.
This comment has been minimized.
45652c2 to
73edae4
Compare
This comment has been minimized.
This comment has been minimized.
73edae4 to
3fd82be
Compare
|
These commits modify the If this was unintentional then you should revert the changes before this PR is merged. |
|
@rustbot reroll |
|
I'm not familiar either. @rustbot reroll |
|
Purely from the description, checking for how it is imported and |
|
Right, I've found some cases where this rework doesn't work, it just happened to work for the tests that were here but using fully qualified paths vs imports has effect on whether the lint fires so this is broken. I'll try to rework it so that the needed information is collected I guess in the late pass of resolve. @rustbot label +S-waiting-on-author -S-waiting-on-review |
This comment has been minimized.
This comment has been minimized.
178ef5d to
f254591
Compare
This comment has been minimized.
This comment has been minimized.
|
I've reworked it so that the information on which crate a path imported items from in resolve (last hop, not definition crate), but I still consume it in privacy where I emit the lint. From what I understand, effective visibilities are only partly constructed in resolve so I have to do the check later than that and since it was previously emitted in privacy, I put it at the same place. @rustbot label -S-waiting-on-author +S-waiting-on-review |
|
r? petrochenkov |
| @@ -339,6 +339,7 @@ pub(crate) struct CrateDep { | |||
| pub kind: CrateDepKind, | |||
| pub extra_filename: String, | |||
| pub is_private: bool, | |||
There was a problem hiding this comment.
Isn't this flag obsoleted by is_extern_private_dep?
It would be pretty bad to have the both systems in place.
There was a problem hiding this comment.
It was still used in the other privacy visitor and I wasn't sure so since it has slightly different semantics, I thought it safer to just keep it.
I'll try to see what actually uses it and if it can be safely replaced.
| } | ||
| } | ||
|
|
||
| fn entry_crate(decl: Decl<'_>) -> Option<CrateNum> { |
There was a problem hiding this comment.
Can entry_crate ever refer to an indirect dependency?
If it cannot, then we don't need to encode the dep privacy flags into metadata.
What is the behavior in this case
pub fn my_interface() -> other_crate::module::SomeType { ... }if other_crate is a public dependency, but module is actually a reexport to a module in some third crate, which is not a direct dependency?
Is that third crate considered a private or public dependency? Or it depends on the value of is_extern_private_dep encoded into the other_crate's metadata?
There was a problem hiding this comment.
And what if other_crate is a private dependency in the same situation?
There was a problem hiding this comment.
Can
entry_crateever refer to an indirect dependency?
If it cannot, then we don't need to encode the dep privacy flags into metadata.
It cannot, I'll get rid of that then.
What is the behavior in this case
pub fn my_interface() -> other_crate::module::SomeType { ... }if
other_crateis a public dependency, but module is actually a reexport to a module in some third crate, which is not a direct dependency?
Then it is considered ok. Anything other_crate exposes publicly is public regardless of what crate defined it. I think that should include the foreign module and anything accessible in there.
Assuming that other_crate (and all other transitive deps) also manages its public dependencies correctly, anything it exported publicly is from its own (transitive) public dependency so in that sense, we still require types in our public API to be from a transitive public dependency. But we additionally require that the import is through our own public dependency if there are more paths.
We don't care if any crate in the re-export chain (including our direct public dependencies) actually doesn't use public dependencies, we just trust that whatever our public dependencies have in their public API won't break in a minor release.
At least that was the design I had in mind, I don't think any test uses a type from a re-exported module so I might be describing how I tried to make it work but the implementation in this PR might do something different. So I'll add a test with that and report back if I was wrong.
Is that third crate considered a private or public dependency? Or it depends on the value of
is_extern_private_depencoded into theother_crate's metadata?
It's not considered at all in the context of the lint. We handle types imported from other_crate the same way regardless of whether they were defined or just re-exported there.
From the point of view of the new query, transitive dependencies are not passed at all with the extern flag so there is no extern priv so in that sense they're considered public (or rather they're not considered private). But that information shouldn't be ever retrieved for transitive dependencies. I think I ended with that shape instead of direct_pub_dep because it simplified some edge-cases, I think with core and std which are now considered public by that query because of that.
And what if
other_crateis a private dependency in the same situation?
Then that example should lint regardless of where SomeType is actually defined.
There was a problem hiding this comment.
I was asking because in the actual implementation decl.parent_module for SomeType will point to the indirect dependency crate.
Also, what happens in cases like this?
use other_crate::module::SomeType;
pub fn my_interface() -> SomeType { ... }
|
As I understand the reexport checking wasn't migrated to the new model yet. So this is still based on where the definition of pub use dep::Type; |
Regular resolutions are kept in paths inline after AST lowering, and not in side tables. So far the paths are checked in Could you rebase this PR so I could run benchmarks? |
f254591 to
0837b34
Compare
|
This PR was rebased onto a different main commit. Here's a range-diff highlighting what actually changed. Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers. |
|
@bors try @rust-timer queue |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Private dependencies in public interface lint rework
This comment has been minimized.
This comment has been minimized.
…public interfaces
…_id-based visitor
0837b34 to
c35759e
Compare
This comment has been minimized.
This comment has been minimized.
|
I've rebased it onto current main. I didn't change reexports, I'll do that on top of this. I somehow convinced myself that lint already works but yeah, that would be inconsistent.
Maybe constants and static variables, otherwise I don't think so. But that's based more on it not being needed for the tests currently and all other cases I could think of being covered by those two.
Do you mean putting the importing For the record, I've since found some ways to confuse the lint by having a private type alias to a foreign type from private dependency and then implementations on that alias are considered ok. There is also a similar way to implement public traits on associated types (e.g. This might end up requiring more bookkeeping regarding which types were used for aliases or associative types and how were they named. |
|
Finished benchmarking commit (56aa046): comparison URL. Overall result: ❌✅ regressions and improvements - please read:Benchmarking means the PR may be perf-sensitive. It's automatically marked not fit for rolling up. Overriding is possible but disadvised: it risks changing compiler perf. Next, please: If you can, justify the regressions found in this try perf run in writing along with @bors rollup=never rustc-perf Instruction countOur most reliable metric. Used to determine the overall result above. However, even this metric can be noisy.
Max RSS (memory usage)Results (primary 2.1%, secondary -3.3%)A less reliable metric. May be of interest, but not used to determine the overall result above.
CyclesResults (primary -2.5%, secondary -0.8%)A less reliable metric. May be of interest, but not used to determine the overall result above.
Binary sizeThis perf run didn't have relevant results for this metric. Bootstrap: 498.333s -> 498.806s (0.09%) |
| separate_provide_extern | ||
| } | ||
| /// Returns whether or not the crate with CrateNum 'cnum' | ||
| /// is marked as a direct public dependency |
There was a problem hiding this comment.
This comment should be updated (first implementation used a direct public dep query, now it's extern priv query)
|
I'm trying to understand better the perf output better and I'll see if I can replicate it locally. I tried to run the tool before the rebase and back then it showed as empty which I understood meant no perf improvements or regressions. I don't have other experience with it so I can't guarantee I just didn't use it wrong. I'll try to delete the new unnecessary crate metadata and double check if I didn't do something wrong in the rebase which included changes on how lowering state is handled. |
View all comments
Tracking issue: #44663
Closes #119428
This reworks the lint so that it does not fire based on where an item is defined but based on how it is imported. I think this is best illustrated in the following test:
tests/ui/privacy/pub-priv-dep/diamond_deps.rs
The test here is edited for brevity. Note that
Sharedis the same type and the lint fires only when imported through the private dependency.This is my first contribution of this scope and as such, I'm not sure about several things I did:
is_private_depis not enough since it handles transitively public dependencies as publicprivate_depso I just did the same things I've seen there.tcx.hir_module_items(mod_id).par_items(..)instead oftcx.hir_visit_all_item_likes_in_cratePrivateItemsInPublicInterfacesCheckerbe trimmed down more so that there are not two passes for this? It still emits hard errors for types in associated types and I'm not sure how to check for this with the visitor.@epage I'd appreciate if you could check the test changes in the first commit. The state now is how I understand the desired state based on the discussion in #119428 but I'd rather get a final ok on this.