rust-lang / rust

Empowering everyone to build reliable and efficient software.
https://www.rust-lang.org
Other
95.68k stars 12.33k forks source link

rustc ignores first exposed private type / span incorrect #127124

Open MolotovCherry opened 1 month ago

MolotovCherry commented 1 month ago

I tried to look for an existing issue but could not find any. Apologies if this has been reported already.

It should be reporting the private error for Wants_X, but instead it completely skips the error on builder() and displays error for finish()

Code

mod something {
    pub struct S {
        x: u32,
    }
    impl S {
        pub fn builder() -> Wants_X {
            Wants_X
        }
    }
    struct Wants_X;
    pub struct Data_X(u32);
    impl Wants_X {
        pub fn next_number(self, number: u32) -> Wants_Finish {
            Wants_Finish(Data_X(number))
        }
    }
    struct Wants_Finish(Data_X);
    impl Wants_Finish {
        pub fn finish(self) -> S {
            S {
                x: self.0.0
            }
        }
    }
}

fn main() {
    {
        use something::*;
        let s = S::builder()
            .next_number(32)
            .finish();
    }
}

Current output

error: type `Wants_Finish` is private
  --> src\bin\test_private.rs:32:14
   |
32 |             .finish();
   |              ^^^^^^ private type

If you remove the finish() line, the output is still wrong (span appears to be incorrect).

error: type `Wants_Finish` is private
  --> src/main.rs:30:17
   |
30 |           let s = S::builder()
   |  _________________^
31 | |             .next_number(32);
   | |____________________________^ private type

If you make Wants_Finish pub, you get this (span definitely wrong)

error: type `Wants_X` is private
  --> src/main.rs:31:14
   |
31 |             .next_number(32)
   |              ^^^^^^^^^^^ private type

Desired output

error: type `Wants_X` is private
  --> src/main.rs:30:17
   |
30 |         let s = S::builder()
   |                 ^^^^^^^^^^^^ private type

Rationale and extra context

No response

Other cases

No response

Rust Version

1.81.0-nightly
(2024-06-24 6b0f4b5ec3aa707ecaa7)

Anything else?

No response

theemathas commented 1 month ago

Slightly minimized:

mod something {
    pub fn builder() -> WantsNext {
        WantsNext
    }

    struct WantsNext;
    impl WantsNext {
        pub fn next(self) -> WantsFinish {
            WantsFinish
        }
    }

    struct WantsFinish;
    impl WantsFinish {
        pub fn finish(self) {}
    }
}

fn main() {
    something::builder().next().finish();
}

Output:

   Compiling playground v0.0.1 (/playground)
warning: type `WantsNext` is more private than the item `builder`
 --> src/main.rs:2:5
  |
2 |     pub fn builder() -> WantsNext {
  |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function `builder` is reachable at visibility `pub(crate)`
  |
note: but type `WantsNext` is only usable at visibility `pub(self)`
 --> src/main.rs:6:5
  |
6 |     struct WantsNext;
  |     ^^^^^^^^^^^^^^^^
  = note: `#[warn(private_interfaces)]` on by default

error: type `WantsFinish` is private
  --> src/main.rs:20:33
   |
20 |     something::builder().next().finish();
   |                                 ^^^^^^ private type

warning: `playground` (bin "playground") generated 1 warning
error: could not compile `playground` (bin "playground") due to 1 previous error; 1 warning emitted

The issue is that all 3 function calls in main() should be errors, since they all involve private types. However, only the last function call is displayed as an error. Ideally, only the first function call would be displayed as an error.