Skip to content

Cannot detect glob re-export's shadowed items in rustdoc JSON #111338

Open
@obi1kenobi

Description

@obi1kenobi

I tried this code:

mod inner {
    pub struct Foo {};
}

mod other {
    struct Foo;
}

pub use inner::*;

// Adding either of the following two lines
// would shadow `inner::Foo` and
// hide the name `Foo` from the public API.
//
// (1)
// struct Foo;
//
// (2)
// use other::Foo;

I expected to see this happen: when either line (1) or (2) is added, rustdoc JSON files should offer some way to detect that the name Foo is no longer part of the crate's public API.

Instead, this happened:

  • With default settings, rustdoc generates identical JSON regardless of whether either or none of (1) or (2) is included.
  • With --document-private-items and --document-hidden-items, rustdoc generates identical JSON whether or not (2) is included.

Just like using a private type in (1), the same problem can be caused by using a #[doc(hidden)] public type, which will also not be emitted in rustdoc JSON unless --document-hidden-items is set.

This means that shadowing glob re-exported items is in general currently impossible to reliably detect via rustdoc JSON, even with --document-private-items and --document-hidden-items. As a result, cargo-semver-checks cannot detect breaking changes caused by such shadowing, which have happened in real life: around a year ago, the opencl3 crate seems to have suffered a regression when a large number of its items were accidentally shadowed.

Relatedly, in #111336 I'm arguing that such shadowing should trigger a lint since it's essentially never what one wants: anything it can productively accomplish can be better accomplished in another way.

I plan to publish a blog post with more details about this in a few hours, it will be available at the following link: https://predr.ag/blog/breaking-semver-in-rust-by-adding-private-type-or-import/

Meta

rustc --version --verbose:

rustc 1.71.0-nightly (39c6804b9 2023-04-19)
binary: rustc
commit-hash: 39c6804b92aa202369e402525cee329556bc1db0
commit-date: 2023-04-19
host: x86_64-unknown-linux-gnu
release: 1.71.0-nightly
LLVM version: 16.0.2

That version of rustc emits rustdoc JSON format version v24.

Possible solution

One option I thought of would be to tweak the rustdoc format to include a list of shadowed names in glob re-exports. This would allow proper name resolution in all cases, and without requiring --document-private-items and --document-hidden-items to be set.

Another option would be to include non-pub imports when --document-private-items is set. This only allows proper name resolution in rustdoc JSON generated with both --document-private-items and --document-hidden-items set.

Perhaps there are other options as well.

Personally, I'd prefer the former option over the latter, since it seems reasonable to expect that rustdoc JSON shouldn't require flags that document explicitly non-public-API components in order to fully describe the public API.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-resolveArea: Name/path resolution done by `rustc_resolve` specificallyA-rustdoc-jsonArea: Rustdoc JSON backendC-bugCategory: This is a bug.T-rustdocRelevant to the rustdoc team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions