rust-lang / rust-lang/rust

`private_interfaces` lint needs to perform type resolution to avoid false positives

Open
#149,284 0 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

A-lints A-visibility C-bug L-false-positive L-private_interfaces T-compiler
Dominant language
Rust
Stars
119k
Forks
16.1k
PR merge metrics
PR metrics pending

Description

The private_interfaces lint incorrectly fires for cases where a type is declared via a private interface but nevertheless fully resolves to an equally (or more) public type.

trait Service {
    type Output;
    
    fn process() -> Self::Output;
}

pub struct SomeService;
impl Service for SomeService {
    type Output = ();
    
    fn process() -> Self::Output {
        todo!();
    }
}

// False positive on return type here:
pub fn exposed_method() -> <SomeService as Service>::Output {
    SomeService::process()
}

Currently produces the following error on both 1.91.1 stable and 1.93.0-nightly:

warning: associated type `Service::Output` is more private than the item `exposed_method`
  --> src/lib.rs:16:1
   |
16 | pub fn exposed_method() -> <SomeService as Service>::Output {
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function `exposed_method` is reachable at visibility `pub`
   |
note: but associated type `Service::Output` is only usable at visibility `pub(crate)`
  --> src/lib.rs:2:5
   |
 2 |     type Output;
   |     ^^^^^^^^^^^
   = note: `#[warn(private_interfaces)]` on by default

warning: trait `Service` is more private than the item `exposed_method`
  --> src/lib.rs:16:1
   |
16 | pub fn exposed_method() -> <SomeService as Service>::Output {
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function `exposed_method` is reachable at visibility `pub`
   |
note: but trait `Service` is only usable at visibility `pub(crate)`
  --> src/lib.rs:1:1
   |
 1 | trait Service {
   | ^^^^^^^^^^^^^

Playground link: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2024&gist=4756e3d350f5f0bdd90086f76d043a89

As you can see, the private_interfaces lint is automatically fired when a less-public type is encountered in the type signature, but if type resolution were performed it would be obvious that this actually resolves to a very much public and accessible type (in this case, ()).

(This is a very much contrived example; in my actual code I have a trait that exposes blocking methods via a non-blocking async interface and the trait's associated type is the shortest and least error-prone method of expressing the type of a pub static)

@rustbot label +T-compiler +L-private_interfaces +L-false-positive +A-visibility +A-lints +C-bug

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Reproduce the false positive from the linked Rust Playground example, then trace the compiler's private_interfaces lint and its type-resolution handling. The work is done when the shown () return type no longer triggers warnings for the private trait or associated type, with regression coverage for the example.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.