New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tracking issue for `legacy_constructor_visibility` compatibility lint #39207

Open
petrochenkov opened this Issue Jan 20, 2017 · 0 comments

Comments

Projects
None yet
3 participants
@petrochenkov
Contributor

petrochenkov commented Jan 20, 2017

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

  • #38932 introduces the legacy_constructor_visibility lint as deny-by-default
  • PR ? makes the legacy_constructor_visibility lint a hard error
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment