about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_resolve/src/build_reduced_graph.rs2
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs20
-rw-r--r--compiler/rustc_resolve/src/lib.rs5
-rw-r--r--tests/ui/privacy/issue-75906.stderr4
-rw-r--r--tests/ui/privacy/issue-75907.rs2
-rw-r--r--tests/ui/privacy/issue-75907.stderr8
-rw-r--r--tests/ui/resolve/issue-42944.rs2
-rw-r--r--tests/ui/resolve/issue-42944.stderr12
8 files changed, 49 insertions, 6 deletions
diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs
index 58f6fd2b006..928f372d948 100644
--- a/compiler/rustc_resolve/src/build_reduced_graph.rs
+++ b/compiler/rustc_resolve/src/build_reduced_graph.rs
@@ -331,7 +331,9 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
             .iter()
             .map(|field| respan(field.span, field.ident.map_or(kw::Empty, |ident| ident.name)))
             .collect();
+        let field_vis = vdata.fields().iter().map(|field| field.vis.span).collect();
         self.r.field_names.insert(def_id, field_names);
+        self.r.field_visibility_spans.insert(def_id, field_vis);
     }
 
     fn insert_field_names_extern(&mut self, def_id: DefId) {
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index 74522f18542..a675a1fb78b 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -1451,6 +1451,26 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
                         .collect();
 
                     if non_visible_spans.len() > 0 {
+                        if let Some(visibility_spans) = self.r.field_visibility_spans.get(&def_id) {
+                            err.multipart_suggestion_verbose(
+                                &format!(
+                                    "consider making the field{} publicly accessible",
+                                    pluralize!(visibility_spans.len())
+                                ),
+                                visibility_spans
+                                    .iter()
+                                    .map(|span| {
+                                        (
+                                            *span,
+                                            if span.lo() == span.hi() { "pub " } else { "pub" }
+                                                .to_string(),
+                                        )
+                                    })
+                                    .collect(),
+                                Applicability::MaybeIncorrect,
+                            );
+                        }
+
                         let mut m: MultiSpan = non_visible_spans.clone().into();
                         non_visible_spans
                             .into_iter()
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index 2182b736937..84d9794ccf2 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -881,6 +881,10 @@ pub struct Resolver<'a> {
     /// Used for hints during error reporting.
     field_names: FxHashMap<DefId, Vec<Spanned<Symbol>>>,
 
+    /// Span of the privacy modifier in fields of an item `DefId` accessible with dot syntax.
+    /// Used for hints during error reporting.
+    field_visibility_spans: FxHashMap<DefId, Vec<Span>>,
+
     /// All imports known to succeed or fail.
     determined_imports: Vec<&'a Import<'a>>,
 
@@ -1268,6 +1272,7 @@ impl<'a> Resolver<'a> {
 
             has_self: FxHashSet::default(),
             field_names: FxHashMap::default(),
+            field_visibility_spans: FxHashMap::default(),
 
             determined_imports: Vec::new(),
             indeterminate_imports: Vec::new(),
diff --git a/tests/ui/privacy/issue-75906.stderr b/tests/ui/privacy/issue-75906.stderr
index 4c6a68646ad..600dc7c876f 100644
--- a/tests/ui/privacy/issue-75906.stderr
+++ b/tests/ui/privacy/issue-75906.stderr
@@ -9,6 +9,10 @@ note: constructor is not visible here due to private fields
    |
 LL |     pub struct Bar(u8);
    |                    ^^ private field
+help: consider making the field publicly accessible
+   |
+LL |     pub struct Bar(pub u8);
+   |                    +++
 
 error: aborting due to previous error
 
diff --git a/tests/ui/privacy/issue-75907.rs b/tests/ui/privacy/issue-75907.rs
index 6da99cf6435..3bed841d13e 100644
--- a/tests/ui/privacy/issue-75907.rs
+++ b/tests/ui/privacy/issue-75907.rs
@@ -2,7 +2,7 @@
 
 mod foo {
     pub(crate) struct Foo(u8);
-    pub(crate) struct Bar(pub u8, u8, Foo);
+    pub(crate) struct Bar(pub u8, pub(in crate::foo) u8, Foo);
 
     pub(crate) fn make_bar() -> Bar {
         Bar(1, 12, Foo(10))
diff --git a/tests/ui/privacy/issue-75907.stderr b/tests/ui/privacy/issue-75907.stderr
index 2f89e31a31a..f7cb874c2cc 100644
--- a/tests/ui/privacy/issue-75907.stderr
+++ b/tests/ui/privacy/issue-75907.stderr
@@ -11,6 +11,10 @@ LL |     let Bar(x, y, Foo(z)) = make_bar();
    |                ^  ^^^^^^ private field
    |                |
    |                private field
+help: consider making the fields publicly accessible
+   |
+LL |     pub(crate) struct Bar(pub u8, pub u8, pub Foo);
+   |                           ~~~     ~~~     +++
 
 error[E0532]: cannot match against a tuple struct which contains private fields
   --> $DIR/issue-75907.rs:15:19
@@ -23,6 +27,10 @@ note: constructor is not visible here due to private fields
    |
 LL |     let Bar(x, y, Foo(z)) = make_bar();
    |                       ^ private field
+help: consider making the field publicly accessible
+   |
+LL |     pub(crate) struct Foo(pub u8);
+   |                           +++
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/resolve/issue-42944.rs b/tests/ui/resolve/issue-42944.rs
index a4404857a56..7e439c10b7b 100644
--- a/tests/ui/resolve/issue-42944.rs
+++ b/tests/ui/resolve/issue-42944.rs
@@ -1,5 +1,5 @@
 mod foo {
-    pub struct Bx(());
+    pub struct Bx(pub(in crate::foo) ());
 }
 
 mod bar {
diff --git a/tests/ui/resolve/issue-42944.stderr b/tests/ui/resolve/issue-42944.stderr
index 0ee9fd391fe..4ffa9402c66 100644
--- a/tests/ui/resolve/issue-42944.stderr
+++ b/tests/ui/resolve/issue-42944.stderr
@@ -7,8 +7,8 @@ LL |         Bx(());
 note: tuple struct `foo::Bx` exists but is inaccessible
   --> $DIR/issue-42944.rs:2:5
    |
-LL |     pub struct Bx(());
-   |     ^^^^^^^^^^^^^^^^^^ not accessible
+LL |     pub struct Bx(pub(in crate::foo) ());
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not accessible
 
 error[E0423]: cannot initialize a tuple struct which contains private fields
   --> $DIR/issue-42944.rs:9:9
@@ -19,8 +19,12 @@ LL |         Bx(());
 note: constructor is not visible here due to private fields
   --> $DIR/issue-42944.rs:2:19
    |
-LL |     pub struct Bx(());
-   |                   ^^ private field
+LL |     pub struct Bx(pub(in crate::foo) ());
+   |                   ^^^^^^^^^^^^^^^^^^^^^ private field
+help: consider making the field publicly accessible
+   |
+LL |     pub struct Bx(pub ());
+   |                   ~~~
 
 error: aborting due to 2 previous errors