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_visibility
lint as deny-by-default - PR ? makes the
legacy_constructor_visibility
lint a hard error