Skip to content

Commit 25fd633

Browse files
authored
Rollup merge of #106579 - estebank:issue-52144, r=Nilstrieb
Suggest making private tuple struct field public Fix #52144.
2 parents 35cf81d + 41e66d9 commit 25fd633

14 files changed

+246
-7
lines changed

Diff for: compiler/rustc_resolve/src/build_reduced_graph.rs

+14
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,15 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
334334
self.r.field_names.insert(def_id, field_names);
335335
}
336336

337+
fn insert_field_visibilities_local(&mut self, def_id: DefId, vdata: &ast::VariantData) {
338+
let field_vis = vdata
339+
.fields()
340+
.iter()
341+
.map(|field| field.vis.span.until(field.ident.map_or(field.ty.span, |i| i.span)))
342+
.collect();
343+
self.r.field_visibility_spans.insert(def_id, field_vis);
344+
}
345+
337346
fn insert_field_names_extern(&mut self, def_id: DefId) {
338347
let field_names =
339348
self.r.cstore().struct_field_names_untracked(def_id, self.r.session).collect();
@@ -737,6 +746,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
737746

738747
// Record field names for error reporting.
739748
self.insert_field_names_local(def_id, vdata);
749+
self.insert_field_visibilities_local(def_id, vdata);
740750

741751
// If this is a tuple or unit struct, define a name
742752
// in the value namespace as well.
@@ -770,6 +780,8 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
770780
Res::Def(DefKind::Ctor(CtorOf::Struct, ctor_kind), ctor_def_id.to_def_id());
771781
self.r.define(parent, ident, ValueNS, (ctor_res, ctor_vis, sp, expansion));
772782
self.r.visibilities.insert(ctor_def_id, ctor_vis);
783+
// We need the field visibility spans also for the constructor for E0603.
784+
self.insert_field_visibilities_local(ctor_def_id.to_def_id(), vdata);
773785

774786
self.r
775787
.struct_constructors
@@ -783,6 +795,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
783795

784796
// Record field names for error reporting.
785797
self.insert_field_names_local(def_id, vdata);
798+
self.insert_field_visibilities_local(def_id, vdata);
786799
}
787800

788801
ItemKind::Trait(..) => {
@@ -1510,6 +1523,7 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> {
15101523

15111524
// Record field names for error reporting.
15121525
self.insert_field_names_local(def_id.to_def_id(), &variant.data);
1526+
self.insert_field_visibilities_local(def_id.to_def_id(), &variant.data);
15131527

15141528
visit::walk_variant(self, variant);
15151529
}

Diff for: compiler/rustc_resolve/src/diagnostics.rs

+13-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ use rustc_ast::{self as ast, Crate, ItemKind, ModKind, NodeId, Path, CRATE_NODE_
66
use rustc_ast_pretty::pprust;
77
use rustc_data_structures::fx::FxHashSet;
88
use rustc_errors::struct_span_err;
9-
use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan};
9+
use rustc_errors::{
10+
pluralize, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan,
11+
};
1012
use rustc_feature::BUILTIN_ATTRIBUTES;
1113
use rustc_hir::def::Namespace::{self, *};
1214
use rustc_hir::def::{self, CtorKind, CtorOf, DefKind, NonMacroAttrKind, PerNS};
@@ -1604,6 +1606,16 @@ impl<'a> Resolver<'a> {
16041606
err.span_label(ident.span, &format!("private {}", descr));
16051607
if let Some(span) = ctor_fields_span {
16061608
err.span_label(span, "a constructor is private if any of the fields is private");
1609+
if let Res::Def(_, d) = res && let Some(fields) = self.field_visibility_spans.get(&d) {
1610+
err.multipart_suggestion_verbose(
1611+
&format!(
1612+
"consider making the field{} publicly accessible",
1613+
pluralize!(fields.len())
1614+
),
1615+
fields.iter().map(|span| (*span, "pub ".to_string())).collect(),
1616+
Applicability::MaybeIncorrect,
1617+
);
1618+
}
16071619
}
16081620

16091621
// Print the whole import chain to make it easier to see what happens.

Diff for: compiler/rustc_resolve/src/late/diagnostics.rs

+11
Original file line numberDiff line numberDiff line change
@@ -1451,6 +1451,17 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
14511451
.collect();
14521452

14531453
if non_visible_spans.len() > 0 {
1454+
if let Some(fields) = self.r.field_visibility_spans.get(&def_id) {
1455+
err.multipart_suggestion_verbose(
1456+
&format!(
1457+
"consider making the field{} publicly accessible",
1458+
pluralize!(fields.len())
1459+
),
1460+
fields.iter().map(|span| (*span, "pub ".to_string())).collect(),
1461+
Applicability::MaybeIncorrect,
1462+
);
1463+
}
1464+
14541465
let mut m: MultiSpan = non_visible_spans.clone().into();
14551466
non_visible_spans
14561467
.into_iter()

Diff for: compiler/rustc_resolve/src/lib.rs

+5
Original file line numberDiff line numberDiff line change
@@ -881,6 +881,10 @@ pub struct Resolver<'a> {
881881
/// Used for hints during error reporting.
882882
field_names: FxHashMap<DefId, Vec<Spanned<Symbol>>>,
883883

884+
/// Span of the privacy modifier in fields of an item `DefId` accessible with dot syntax.
885+
/// Used for hints during error reporting.
886+
field_visibility_spans: FxHashMap<DefId, Vec<Span>>,
887+
884888
/// All imports known to succeed or fail.
885889
determined_imports: Vec<&'a Import<'a>>,
886890

@@ -1268,6 +1272,7 @@ impl<'a> Resolver<'a> {
12681272

12691273
has_self: FxHashSet::default(),
12701274
field_names: FxHashMap::default(),
1275+
field_visibility_spans: FxHashMap::default(),
12711276

12721277
determined_imports: Vec::new(),
12731278
indeterminate_imports: Vec::new(),

Diff for: tests/ui/privacy/issue-75906.stderr

+4
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ note: constructor is not visible here due to private fields
99
|
1010
LL | pub struct Bar(u8);
1111
| ^^ private field
12+
help: consider making the field publicly accessible
13+
|
14+
LL | pub struct Bar(pub u8);
15+
| +++
1216

1317
error: aborting due to previous error
1418

Diff for: tests/ui/privacy/issue-75907.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
mod foo {
44
pub(crate) struct Foo(u8);
5-
pub(crate) struct Bar(pub u8, u8, Foo);
5+
pub(crate) struct Bar(pub u8, pub(in crate::foo) u8, Foo);
66

77
pub(crate) fn make_bar() -> Bar {
88
Bar(1, 12, Foo(10))

Diff for: tests/ui/privacy/issue-75907.stderr

+8
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ LL | let Bar(x, y, Foo(z)) = make_bar();
1111
| ^ ^^^^^^ private field
1212
| |
1313
| private field
14+
help: consider making the fields publicly accessible
15+
|
16+
LL | pub(crate) struct Bar(pub u8, pub u8, pub Foo);
17+
| ~~~ ~~~ +++
1418

1519
error[E0532]: cannot match against a tuple struct which contains private fields
1620
--> $DIR/issue-75907.rs:15:19
@@ -23,6 +27,10 @@ note: constructor is not visible here due to private fields
2327
|
2428
LL | let Bar(x, y, Foo(z)) = make_bar();
2529
| ^ private field
30+
help: consider making the field publicly accessible
31+
|
32+
LL | pub(crate) struct Foo(pub u8);
33+
| +++
2634

2735
error: aborting due to 2 previous errors
2836

0 commit comments

Comments
 (0)