Skip to content

Commit

Permalink
Auto merge of rust-lang#111801 - Bryanskiy:lints1, r=petrochenkov
Browse files Browse the repository at this point in the history
Private-in-public lints implementation

Next part of RFC rust-lang#48054.

r? `@petrochenkov`
  • Loading branch information
bors committed Jun 11, 2023
2 parents 37998ab + 6d46382 commit 77dba22
Show file tree
Hide file tree
Showing 24 changed files with 893 additions and 85 deletions.
95 changes: 95 additions & 0 deletions compiler/rustc_lint_defs/src/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3372,7 +3372,9 @@ declare_lint_pass! {
OVERLAPPING_RANGE_ENDPOINTS,
PATTERNS_IN_FNS_WITHOUT_BODY,
POINTER_STRUCTURAL_MATCH,
PRIVATE_BOUNDS,
PRIVATE_IN_PUBLIC,
PRIVATE_INTERFACES,
PROC_MACRO_BACK_COMPAT,
PROC_MACRO_DERIVE_RESOLUTION_FALLBACK,
PUB_USE_OF_PRIVATE_EXTERN_CRATE,
Expand All @@ -3399,6 +3401,7 @@ declare_lint_pass! {
UNINHABITED_STATIC,
UNKNOWN_CRATE_TYPES,
UNKNOWN_LINTS,
UNNAMEABLE_TYPES,
UNREACHABLE_CODE,
UNREACHABLE_PATTERNS,
UNSAFE_OP_IN_UNSAFE_FN,
Expand Down Expand Up @@ -4251,3 +4254,95 @@ declare_lint! {
Warn,
"\"invalid_parameter\" isn't a valid argument for `#[macro_export]`",
}

declare_lint! {
/// The `private_interfaces` lint detects types in a primary interface of an item,
/// that are more private than the item itself. Primary interface of an item is all
/// its interface except for bounds on generic parameters and where clauses.
///
/// ### Example
///
/// ```rust,compile_fail
/// # #![allow(unused)]
/// # #![allow(private_in_public)]
/// #![deny(private_interfaces)]
/// struct SemiPriv;
///
/// mod m1 {
/// struct Priv;
/// impl crate::SemiPriv {
/// pub fn f(_: Priv) {}
/// }
/// }
///
/// # fn main() {}
/// ```
///
/// {{produces}}
///
/// ### Explanation
///
/// Having something private in primary interface guarantees that
/// the item will be unusable from outer modules due to type privacy.
pub PRIVATE_INTERFACES,
Allow,
"private type in primary interface of an item",
}

declare_lint! {
/// The `private_bounds` lint detects types in a secondary interface of an item,
/// that are more private than the item itself. Secondary interface of an item consists of
/// bounds on generic parameters and where clauses, including supertraits for trait items.
///
/// ### Example
///
/// ```rust,compile_fail
/// # #![allow(private_in_public)]
/// # #![allow(unused)]
/// #![deny(private_bounds)]
///
/// struct PrivTy;
/// pub struct S
/// where PrivTy:
/// {}
/// # fn main() {}
/// ```
///
/// {{produces}}
///
/// ### Explanation
///
/// Having private types or traits in item bounds makes it less clear what interface
/// the item actually provides.
pub PRIVATE_BOUNDS,
Allow,
"private type in secondary interface of an item"
}

declare_lint! {
/// The `unnameable_types` lint detects types for which you can get objects of that type,
/// but cannot name the type itself.
///
/// ### Example
///
/// ```rust,compile_fail
/// # #![allow(unused)]
/// #![deny(unnameable_types)]
/// mod m {
/// pub struct S;
/// }
///
/// pub fn get_voldemort() -> m::S { m::S }
/// # fn main() {}
/// ```
///
/// {{produces}}
///
/// ### Explanation
///
/// It is often expected that if you can obtain an object of type `T`, then
/// you can name the type `T` as well, this lint attempts to enforce this rule.
pub UNNAMEABLE_TYPES,
Allow,
"effective visibility of a type is larger than the area in which it can be named"
}
7 changes: 7 additions & 0 deletions compiler/rustc_privacy/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,14 @@ privacy_private_in_public_lint =
*[other] E0446
})
privacy_private_interface_or_bounds_lint = {$ty_kind} `{$ty_descr}` is more private than the item `{$item_descr}`
.item_note = {$item_kind} `{$item_descr}` is reachable at visibility `{$item_vis_descr}`
.ty_note = but {$ty_kind} `{$ty_descr}` is only usable at visibility `{$ty_vis_descr}`
privacy_report_effective_visibility = {$descr}
privacy_unnameable_types_lint = {$kind} `{$descr}` is reachable but cannot be named
.label = reachable at visibility `{$reachable_vis}`, but can only be named at visibility `{$reexported_vis}`
privacy_unnamed_item_is_private = {$kind} is private
.label = private {$kind}
29 changes: 29 additions & 0 deletions compiler/rustc_privacy/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,3 +98,32 @@ pub struct PrivateInPublicLint<'a> {
pub kind: &'a str,
pub descr: DiagnosticArgFromDisplay<'a>,
}

#[derive(LintDiagnostic)]
#[diag(privacy_unnameable_types_lint)]
pub struct UnnameableTypesLint<'a> {
#[label]
pub span: Span,
pub kind: &'a str,
pub descr: DiagnosticArgFromDisplay<'a>,
pub reachable_vis: &'a str,
pub reexported_vis: &'a str,
}

// Used for `private_interfaces` and `private_bounds` lints.
// They will replace private-in-public errors and compatibility lints in future.
// See https://rust-lang.github.io/rfcs/2145-type-privacy.html for more details.
#[derive(LintDiagnostic)]
#[diag(privacy_private_interface_or_bounds_lint)]
pub struct PrivateInterfacesOrBoundsLint<'a> {
#[note(privacy_item_note)]
pub item_span: Span,
pub item_kind: &'a str,
pub item_descr: DiagnosticArgFromDisplay<'a>,
pub item_vis_descr: &'a str,
#[note(privacy_ty_note)]
pub ty_span: Span,
pub ty_kind: &'a str,
pub ty_descr: DiagnosticArgFromDisplay<'a>,
pub ty_vis_descr: &'a str,
}
Loading

0 comments on commit 77dba22

Please sign in to comment.