Skip to content

Commit 77dba22

Browse files
committed
Auto merge of #111801 - Bryanskiy:lints1, r=petrochenkov
Private-in-public lints implementation Next part of RFC #48054. r? `@petrochenkov`
2 parents 37998ab + 6d46382 commit 77dba22

24 files changed

+893
-85
lines changed

compiler/rustc_lint_defs/src/builtin.rs

+95
Original file line numberDiff line numberDiff line change
@@ -3372,7 +3372,9 @@ declare_lint_pass! {
33723372
OVERLAPPING_RANGE_ENDPOINTS,
33733373
PATTERNS_IN_FNS_WITHOUT_BODY,
33743374
POINTER_STRUCTURAL_MATCH,
3375+
PRIVATE_BOUNDS,
33753376
PRIVATE_IN_PUBLIC,
3377+
PRIVATE_INTERFACES,
33763378
PROC_MACRO_BACK_COMPAT,
33773379
PROC_MACRO_DERIVE_RESOLUTION_FALLBACK,
33783380
PUB_USE_OF_PRIVATE_EXTERN_CRATE,
@@ -3399,6 +3401,7 @@ declare_lint_pass! {
33993401
UNINHABITED_STATIC,
34003402
UNKNOWN_CRATE_TYPES,
34013403
UNKNOWN_LINTS,
3404+
UNNAMEABLE_TYPES,
34023405
UNREACHABLE_CODE,
34033406
UNREACHABLE_PATTERNS,
34043407
UNSAFE_OP_IN_UNSAFE_FN,
@@ -4251,3 +4254,95 @@ declare_lint! {
42514254
Warn,
42524255
"\"invalid_parameter\" isn't a valid argument for `#[macro_export]`",
42534256
}
4257+
4258+
declare_lint! {
4259+
/// The `private_interfaces` lint detects types in a primary interface of an item,
4260+
/// that are more private than the item itself. Primary interface of an item is all
4261+
/// its interface except for bounds on generic parameters and where clauses.
4262+
///
4263+
/// ### Example
4264+
///
4265+
/// ```rust,compile_fail
4266+
/// # #![allow(unused)]
4267+
/// # #![allow(private_in_public)]
4268+
/// #![deny(private_interfaces)]
4269+
/// struct SemiPriv;
4270+
///
4271+
/// mod m1 {
4272+
/// struct Priv;
4273+
/// impl crate::SemiPriv {
4274+
/// pub fn f(_: Priv) {}
4275+
/// }
4276+
/// }
4277+
///
4278+
/// # fn main() {}
4279+
/// ```
4280+
///
4281+
/// {{produces}}
4282+
///
4283+
/// ### Explanation
4284+
///
4285+
/// Having something private in primary interface guarantees that
4286+
/// the item will be unusable from outer modules due to type privacy.
4287+
pub PRIVATE_INTERFACES,
4288+
Allow,
4289+
"private type in primary interface of an item",
4290+
}
4291+
4292+
declare_lint! {
4293+
/// The `private_bounds` lint detects types in a secondary interface of an item,
4294+
/// that are more private than the item itself. Secondary interface of an item consists of
4295+
/// bounds on generic parameters and where clauses, including supertraits for trait items.
4296+
///
4297+
/// ### Example
4298+
///
4299+
/// ```rust,compile_fail
4300+
/// # #![allow(private_in_public)]
4301+
/// # #![allow(unused)]
4302+
/// #![deny(private_bounds)]
4303+
///
4304+
/// struct PrivTy;
4305+
/// pub struct S
4306+
/// where PrivTy:
4307+
/// {}
4308+
/// # fn main() {}
4309+
/// ```
4310+
///
4311+
/// {{produces}}
4312+
///
4313+
/// ### Explanation
4314+
///
4315+
/// Having private types or traits in item bounds makes it less clear what interface
4316+
/// the item actually provides.
4317+
pub PRIVATE_BOUNDS,
4318+
Allow,
4319+
"private type in secondary interface of an item"
4320+
}
4321+
4322+
declare_lint! {
4323+
/// The `unnameable_types` lint detects types for which you can get objects of that type,
4324+
/// but cannot name the type itself.
4325+
///
4326+
/// ### Example
4327+
///
4328+
/// ```rust,compile_fail
4329+
/// # #![allow(unused)]
4330+
/// #![deny(unnameable_types)]
4331+
/// mod m {
4332+
/// pub struct S;
4333+
/// }
4334+
///
4335+
/// pub fn get_voldemort() -> m::S { m::S }
4336+
/// # fn main() {}
4337+
/// ```
4338+
///
4339+
/// {{produces}}
4340+
///
4341+
/// ### Explanation
4342+
///
4343+
/// It is often expected that if you can obtain an object of type `T`, then
4344+
/// you can name the type `T` as well, this lint attempts to enforce this rule.
4345+
pub UNNAMEABLE_TYPES,
4346+
Allow,
4347+
"effective visibility of a type is larger than the area in which it can be named"
4348+
}

compiler/rustc_privacy/messages.ftl

+7
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,14 @@ privacy_private_in_public_lint =
1717
*[other] E0446
1818
})
1919
20+
privacy_private_interface_or_bounds_lint = {$ty_kind} `{$ty_descr}` is more private than the item `{$item_descr}`
21+
.item_note = {$item_kind} `{$item_descr}` is reachable at visibility `{$item_vis_descr}`
22+
.ty_note = but {$ty_kind} `{$ty_descr}` is only usable at visibility `{$ty_vis_descr}`
23+
2024
privacy_report_effective_visibility = {$descr}
2125
26+
privacy_unnameable_types_lint = {$kind} `{$descr}` is reachable but cannot be named
27+
.label = reachable at visibility `{$reachable_vis}`, but can only be named at visibility `{$reexported_vis}`
28+
2229
privacy_unnamed_item_is_private = {$kind} is private
2330
.label = private {$kind}

compiler/rustc_privacy/src/errors.rs

+29
Original file line numberDiff line numberDiff line change
@@ -98,3 +98,32 @@ pub struct PrivateInPublicLint<'a> {
9898
pub kind: &'a str,
9999
pub descr: DiagnosticArgFromDisplay<'a>,
100100
}
101+
102+
#[derive(LintDiagnostic)]
103+
#[diag(privacy_unnameable_types_lint)]
104+
pub struct UnnameableTypesLint<'a> {
105+
#[label]
106+
pub span: Span,
107+
pub kind: &'a str,
108+
pub descr: DiagnosticArgFromDisplay<'a>,
109+
pub reachable_vis: &'a str,
110+
pub reexported_vis: &'a str,
111+
}
112+
113+
// Used for `private_interfaces` and `private_bounds` lints.
114+
// They will replace private-in-public errors and compatibility lints in future.
115+
// See https://rust-lang.github.io/rfcs/2145-type-privacy.html for more details.
116+
#[derive(LintDiagnostic)]
117+
#[diag(privacy_private_interface_or_bounds_lint)]
118+
pub struct PrivateInterfacesOrBoundsLint<'a> {
119+
#[note(privacy_item_note)]
120+
pub item_span: Span,
121+
pub item_kind: &'a str,
122+
pub item_descr: DiagnosticArgFromDisplay<'a>,
123+
pub item_vis_descr: &'a str,
124+
#[note(privacy_ty_note)]
125+
pub ty_span: Span,
126+
pub ty_kind: &'a str,
127+
pub ty_descr: DiagnosticArgFromDisplay<'a>,
128+
pub ty_vis_descr: &'a str,
129+
}

0 commit comments

Comments
 (0)