From 757a009db418ee4a0e534a68e98e0fee2f92b194 Mon Sep 17 00:00:00 2001 From: Takayuki Maeda Date: Wed, 26 Feb 2025 00:37:31 +0900 Subject: [PATCH 1/2] suggest dotdot for ignoring fields with private types --- compiler/rustc_privacy/messages.ftl | 1 + compiler/rustc_privacy/src/errors.rs | 2 ++ compiler/rustc_privacy/src/lib.rs | 35 ++++++++++++++++++++++++---- 3 files changed, 33 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_privacy/messages.ftl b/compiler/rustc_privacy/messages.ftl index 43c34a109d721..b71d5a5889da2 100644 --- a/compiler/rustc_privacy/messages.ftl +++ b/compiler/rustc_privacy/messages.ftl @@ -25,6 +25,7 @@ privacy_in_public_interface = {$vis_descr} {$kind} `{$descr}` in public interfac privacy_item_is_private = {$kind} `{$descr}` is private .label = private {$kind} + .suggestion = consider using `..` to ignore fields with private types privacy_private_interface_or_bounds_lint = {$ty_kind} `{$ty_descr}` is more private than the item `{$item_descr}` .item_label = {$item_kind} `{$item_descr}` is reachable at visibility `{$item_vis_descr}` diff --git a/compiler/rustc_privacy/src/errors.rs b/compiler/rustc_privacy/src/errors.rs index 4d1d58c08528c..ba70e7938e768 100644 --- a/compiler/rustc_privacy/src/errors.rs +++ b/compiler/rustc_privacy/src/errors.rs @@ -42,6 +42,8 @@ pub(crate) struct ItemIsPrivate<'a> { pub span: Span, pub kind: &'a str, pub descr: DiagArgFromDisplay<'a>, + #[suggestion(style = "verbose", code = "..", applicability = "maybe-incorrect")] + pub pat_span: Option, } #[derive(Diagnostic)] diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 3842b7035e537..c4b4862d475b1 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -1117,6 +1117,7 @@ struct TypePrivacyVisitor<'tcx> { module_def_id: LocalModDefId, maybe_typeck_results: Option<&'tcx ty::TypeckResults<'tcx>>, span: Span, + hir_id: Option, } impl<'tcx> TypePrivacyVisitor<'tcx> { @@ -1124,9 +1125,24 @@ impl<'tcx> TypePrivacyVisitor<'tcx> { self.tcx.visibility(did).is_accessible_from(self.module_def_id, self.tcx) } + fn tuple_struct_field_with_private_type_span(&self) -> Option { + if let Some(hir_id) = self.hir_id + && let hir::Node::Pat(pat) = self.tcx.hir_node(hir_id) + && let hir::PatKind::Wild = pat.kind + && let hir::Node::Pat(pat) = self.tcx.parent_hir_node(hir_id) + && let hir::PatKind::TupleStruct(_, pat_arr, _) = pat.kind + && pat_arr.len() == 1 + { + Some(self.tcx.hir().span(hir_id)) + } else { + None + } + } + // Take node-id of an expression or pattern and check its type for privacy. fn check_expr_pat_type(&mut self, id: hir::HirId, span: Span) -> bool { self.span = span; + self.hir_id = Some(id); let typeck_results = self .maybe_typeck_results .unwrap_or_else(|| span_bug!(span, "`hir::Expr` or `hir::Pat` outside of a body")); @@ -1143,7 +1159,12 @@ impl<'tcx> TypePrivacyVisitor<'tcx> { fn check_def_id(&mut self, def_id: DefId, kind: &str, descr: &dyn fmt::Display) -> bool { let is_error = !self.item_is_accessible(def_id); if is_error { - self.tcx.dcx().emit_err(ItemIsPrivate { span: self.span, kind, descr: descr.into() }); + self.tcx.dcx().emit_err(ItemIsPrivate { + span: self.span, + kind, + descr: descr.into(), + pat_span: self.tuple_struct_field_with_private_type_span(), + }); } is_error } @@ -1278,9 +1299,12 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> { let kind = self.tcx.def_descr(def_id); let sess = self.tcx.sess; let _ = match name { - Some(name) => { - sess.dcx().emit_err(ItemIsPrivate { span, kind, descr: (&name).into() }) - } + Some(name) => sess.dcx().emit_err(ItemIsPrivate { + span, + kind, + descr: (&name).into(), + pat_span: None, + }), None => sess.dcx().emit_err(UnnamedItemIsPrivate { span, kind }), }; return; @@ -1776,7 +1800,8 @@ fn check_mod_privacy(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) { // Check privacy of explicitly written types and traits as well as // inferred types of expressions and patterns. let span = tcx.def_span(module_def_id); - let mut visitor = TypePrivacyVisitor { tcx, module_def_id, maybe_typeck_results: None, span }; + let mut visitor = + TypePrivacyVisitor { tcx, module_def_id, maybe_typeck_results: None, span, hir_id: None }; let module = tcx.hir_module_items(module_def_id); for def_id in module.definitions() { From 7e35070a8dfd525700ea953090ac381154270a90 Mon Sep 17 00:00:00 2001 From: Takayuki Maeda Date: Wed, 26 Feb 2025 00:51:05 +0900 Subject: [PATCH 2/2] add ui test for #135903 fix error message --- compiler/rustc_privacy/messages.ftl | 2 +- tests/ui/privacy/private-pat-field-types.rs | 14 ++++++++++++++ tests/ui/privacy/private-pat-field-types.stderr | 14 ++++++++++++++ 3 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 tests/ui/privacy/private-pat-field-types.rs create mode 100644 tests/ui/privacy/private-pat-field-types.stderr diff --git a/compiler/rustc_privacy/messages.ftl b/compiler/rustc_privacy/messages.ftl index b71d5a5889da2..de9e26cb82665 100644 --- a/compiler/rustc_privacy/messages.ftl +++ b/compiler/rustc_privacy/messages.ftl @@ -25,7 +25,7 @@ privacy_in_public_interface = {$vis_descr} {$kind} `{$descr}` in public interfac privacy_item_is_private = {$kind} `{$descr}` is private .label = private {$kind} - .suggestion = consider using `..` to ignore fields with private types + .suggestion = consider using `..` to ignore the field with private type privacy_private_interface_or_bounds_lint = {$ty_kind} `{$ty_descr}` is more private than the item `{$item_descr}` .item_label = {$item_kind} `{$item_descr}` is reachable at visibility `{$item_vis_descr}` diff --git a/tests/ui/privacy/private-pat-field-types.rs b/tests/ui/privacy/private-pat-field-types.rs new file mode 100644 index 0000000000000..9ebaaf4ebe4ac --- /dev/null +++ b/tests/ui/privacy/private-pat-field-types.rs @@ -0,0 +1,14 @@ +mod foo { + struct Bar; + pub enum Foo { + #[allow(private_interfaces)] + A(Bar), + } +} +fn foo_bar(v: foo::Foo) { + match v { + foo::Foo::A(_) => {} //~ ERROR type `Bar` is private + } +} + +fn main() {} diff --git a/tests/ui/privacy/private-pat-field-types.stderr b/tests/ui/privacy/private-pat-field-types.stderr new file mode 100644 index 0000000000000..723ba8f9ac20f --- /dev/null +++ b/tests/ui/privacy/private-pat-field-types.stderr @@ -0,0 +1,14 @@ +error: type `Bar` is private + --> $DIR/private-pat-field-types.rs:10:21 + | +LL | foo::Foo::A(_) => {} + | ^ private type + | +help: consider using `..` to ignore the field with private type + | +LL - foo::Foo::A(_) => {} +LL + foo::Foo::A(..) => {} + | + +error: aborting due to 1 previous error +