Skip to content

Latest commit

 

History

History
109 lines (88 loc) · 3.75 KB

0000-more-visibilities.md

File metadata and controls

109 lines (88 loc) · 3.75 KB
  • Feature Name: more_visibilities, or variant_visibilities and trait_item_visibilities separately
  • Start Date: 2017-06-12
  • RFC PR: (leave this empty)
  • Rust Issue: (leave this empty)

Summary

Support pub/pub(restricted) on enum variants and trait items.

Motivation

Enum variant and trait items already have visibilities internally in the compiler, but they are always inherited from their enums and traits respectively, this RFC supports specifying them explicitly in source code. This can be useful for several reasons.

If variant is marked with smaller visibility than enum itself, for example

pub enum E {
    // This variant can be named only in the current crate.
    pub(crate) V1,
    // This variant can be named only in the current module.
    pub(self) V2,
}

, then it can restrict exhaustiveness of matching performed on values of enum E. If enum has a pub(crate) variant, it can be exhaustively matched only in the current crate because the restricted variant cannot be named from other crates. If enum has a pub(self) variant, it can be exhaustively matched only in the current module, i.e. the exhaustiveness control is fine-grained.

If trait item is marked with smaller visibility than trait itself, for example

pub trait Trait1 {
    fn method1();
    pub(crate) fn method_without_default();
}
pub trait Trait2 {
    fn method2();
    pub(crate) fn method_with_default() {}
}

, then Trait1 can be used in other crates (e.g. it can be imported, the method method1 can be called), but it cannot be implemented, because method_without_default cannot be accessed from other crates. Trait2 can be used and implemented in other crates, it just have a private helper method that can be used only locally (possibly for default implementations of other methods).

Detailed design

Visibilities can be specified for enum variants and trait items at the beginning of their declaration, but after attributes.

If visibility of a variant or trait item is not specified explicitly it's inherited from its enum or trait respectively.

Variants / trait items with visibilities larger than visibilities of their enums / traits are permitted (similarly to private structs with private fields, or public inherent methods of private structs) but don't make much sense, they won't be usable anyway due to type privacy.

Visibilities on trait impl items (impl Tr for Ty { pub fn .... }) are still prohibited like before.

How We Teach This

pub should be already familiar from existing teaching materials and pub(restricted) was documented during stabilization as well. Reference should mention that visibilities can be applied to variants and trait items.

The book or rust-by-example should show that visibilities can be used for controlling enum exhaustiveness and trait implementability, because these idioms may not be immediately obvious.

Drawbacks

None known.

Alternatives

Enum exhaustiveness and trait implementability can be controlled by specialized language additions instead, new attributes and .. were previously proposed (see for example rust-lang#2008 or rust-lang#757). These alternatives spend more "language budget" than reusing visibilities, and are more coarse-grained (e.g. distinction pub(crate) vs pub(self) is not supported), but may be more concize / naturally looking.

Visibilities can also be supported on variant fields, because why not.

pub enum E {
    V1 { pub(self) a: u8, b: u16 },
    V2(pub(self) u8, b: u16),
}

Unresolved questions

None known.