- 
                Notifications
    You must be signed in to change notification settings 
- Fork 13.9k
Description
What is this lint about
#38932 introduces new rules for privacy of tuple struct constructors. Constructor is a function automatically created by a tuple struct having the same name as the struct itself.
struct S(u8); // defines `struct S { ... }` and `fn S(u8) -> S` 
See RFC 1506 for more details.
With these new rules constructor function of a public struct S(....) is defined as private if at least one of the fields is private.
More precisely, visibility(constructor_fn) = min(visibility(struct), visibility(field_1), ..., visibility(field_N)) (this definition takes RFC 1422 into account).
This change is done to make a struct with private fields being a tuple struct an implementation detail. So libraries can freely change it into non-tuple struct and back, and nothing breaks.
This change is mostly backward compatible due to some ad-hoc privacy checks existing previously (e.g. error[E0450]: cannot invoke tuple struct constructor with private fields), however there's one pattern that is broken by it:
mod m {
    // Tuple struct with a private field.
    // Type S is pub(pub).
    // The field S::0 is pub(m).
    // Constructor S is min(pub(pub), pub(m)) -> pub(m).
    pub struct S(u8);
    
    fn f() {
        // Try to use S from the root module in value namespace.
        // No success, ::S exists only in type namespace.
        // How to fix: use S from this module instead of ::S from the root module.
        ::S;
    }
}
// This imports S only in type namespace, value S is too private.
// This is expected filtering behavior of imports described in RFC 1560.
use m::S;
fn main() {}
legacy_constructor_visibility lint tries to detect this patterns and make name resolution succeed with a warning to keep backward compatibility. However, this detection is pretty hacky and not entirely precise, so it will need to go away eventually.
How to fix this warning/error
Use the constructor from its original location X and not through reexports in modules outer to X.
Current status
-  Privatize constructors of tuple structs with private fields #38932 introduces the legacy_constructor_visibilitylint as deny-by-default
-  PR ? makes the legacy_constructor_visibilitylint a hard error