about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEsteban Küber <esteban@kuber.com.ar>2025-01-18 01:56:22 +0000
committerEsteban Küber <esteban@kuber.com.ar>2025-01-18 01:56:22 +0000
commitbbcf26fc33afb4695014aff22fa77dcb7d9eb715 (patch)
tree89fa7b0b3844f81b310ee203fa1f3ff445756e62
parent3e99055c4099f0ccb3e5ce5768c32af57d48c79b (diff)
downloadrust-bbcf26fc33afb4695014aff22fa77dcb7d9eb715.tar.gz
rust-bbcf26fc33afb4695014aff22fa77dcb7d9eb715.zip
Add context on private fields that are not on the same line as the struct name
```
error[E0451]: field `x` of struct `S` is private
  --> $DIR/visibility.rs:24:9
   |
LL |     let a = baz::S {
   |             ------ in this type
LL |         ..
   |         ^^ field `x` is private
```
-rw-r--r--compiler/rustc_privacy/messages.ftl1
-rw-r--r--compiler/rustc_privacy/src/errors.rs2
-rw-r--r--compiler/rustc_privacy/src/lib.rs38
-rw-r--r--tests/ui/deprecation/deprecation-lint.stderr3
-rw-r--r--tests/ui/structs/default-field-values/visibility.stderr4
5 files changed, 44 insertions, 4 deletions
diff --git a/compiler/rustc_privacy/messages.ftl b/compiler/rustc_privacy/messages.ftl
index 7785f1a7f81..5b5c10d448a 100644
--- a/compiler/rustc_privacy/messages.ftl
+++ b/compiler/rustc_privacy/messages.ftl
@@ -1,4 +1,5 @@
 privacy_field_is_private = field `{$field_name}` of {$variant_descr} `{$def_path_str}` is private
+    .label = in this type
 privacy_field_is_private_is_update_syntax_label = field `{$field_name}` is private
 privacy_field_is_private_label = private field
 
diff --git a/compiler/rustc_privacy/src/errors.rs b/compiler/rustc_privacy/src/errors.rs
index f5e641eb642..23181f63a28 100644
--- a/compiler/rustc_privacy/src/errors.rs
+++ b/compiler/rustc_privacy/src/errors.rs
@@ -8,6 +8,8 @@ use rustc_span::{Span, Symbol};
 pub(crate) struct FieldIsPrivate {
     #[primary_span]
     pub span: Span,
+    #[label]
+    pub struct_span: Option<Span>,
     pub field_name: Symbol,
     pub variant_descr: &'static str,
     pub def_path_str: String,
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index e484cfed06b..6ec73599005 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -925,6 +925,7 @@ impl<'tcx> NamePrivacyVisitor<'tcx> {
         def: ty::AdtDef<'tcx>, // definition of the struct or enum
         field: &'tcx ty::FieldDef,
         in_update_syntax: bool,
+        struct_span: Span,
     ) {
         if def.is_enum() {
             return;
@@ -936,6 +937,11 @@ impl<'tcx> NamePrivacyVisitor<'tcx> {
         if !field.vis.is_accessible_from(def_id, self.tcx) {
             self.tcx.dcx().emit_err(FieldIsPrivate {
                 span,
+                struct_span: if self.tcx.sess.source_map().is_multiline(span.between(struct_span)) {
+                    Some(struct_span)
+                } else {
+                    None
+                },
                 field_name: field.name,
                 variant_descr: def.variant_descr(),
                 def_path_str: self.tcx.def_path_str(def.did()),
@@ -955,6 +961,7 @@ impl<'tcx> NamePrivacyVisitor<'tcx> {
         fields: &[hir::ExprField<'tcx>],
         hir_id: hir::HirId,
         span: Span,
+        struct_span: Span,
     ) {
         for (vf_index, variant_field) in variant.fields.iter_enumerated() {
             let field =
@@ -963,7 +970,7 @@ impl<'tcx> NamePrivacyVisitor<'tcx> {
                 Some(field) => (field.hir_id, field.ident.span, field.span),
                 None => (hir_id, span, span),
             };
-            self.check_field(hir_id, use_ctxt, span, adt, variant_field, true);
+            self.check_field(hir_id, use_ctxt, span, adt, variant_field, true, struct_span);
         }
     }
 }
@@ -990,10 +997,24 @@ impl<'tcx> Visitor<'tcx> for NamePrivacyVisitor<'tcx> {
                     // If the expression uses FRU we need to make sure all the unmentioned fields
                     // are checked for privacy (RFC 736). Rather than computing the set of
                     // unmentioned fields, just check them all.
-                    self.check_expanded_fields(adt, variant, fields, base.hir_id, base.span);
+                    self.check_expanded_fields(
+                        adt,
+                        variant,
+                        fields,
+                        base.hir_id,
+                        base.span,
+                        qpath.span(),
+                    );
                 }
                 hir::StructTailExpr::DefaultFields(span) => {
-                    self.check_expanded_fields(adt, variant, fields, expr.hir_id, span);
+                    self.check_expanded_fields(
+                        adt,
+                        variant,
+                        fields,
+                        expr.hir_id,
+                        span,
+                        qpath.span(),
+                    );
                 }
                 hir::StructTailExpr::None => {
                     for field in fields {
@@ -1006,6 +1027,7 @@ impl<'tcx> Visitor<'tcx> for NamePrivacyVisitor<'tcx> {
                             adt,
                             &variant.fields[index],
                             false,
+                            qpath.span(),
                         );
                     }
                 }
@@ -1023,7 +1045,15 @@ impl<'tcx> Visitor<'tcx> for NamePrivacyVisitor<'tcx> {
             for field in fields {
                 let (hir_id, use_ctxt, span) = (field.hir_id, field.ident.span, field.span);
                 let index = self.typeck_results().field_index(field.hir_id);
-                self.check_field(hir_id, use_ctxt, span, adt, &variant.fields[index], false);
+                self.check_field(
+                    hir_id,
+                    use_ctxt,
+                    span,
+                    adt,
+                    &variant.fields[index],
+                    false,
+                    qpath.span(),
+                );
             }
         }
 
diff --git a/tests/ui/deprecation/deprecation-lint.stderr b/tests/ui/deprecation/deprecation-lint.stderr
index 2098073409d..075bb42fa9a 100644
--- a/tests/ui/deprecation/deprecation-lint.stderr
+++ b/tests/ui/deprecation/deprecation-lint.stderr
@@ -739,6 +739,9 @@ LL |              _)
 error[E0451]: field `i` of struct `this_crate::nested::DeprecatedStruct` is private
   --> $DIR/deprecation-lint.rs:280:13
    |
+LL |         let _ = nested::DeprecatedStruct {
+   |                 ------------------------ in this type
+LL |
 LL |             i: 0
    |             ^^^^ private field
 
diff --git a/tests/ui/structs/default-field-values/visibility.stderr b/tests/ui/structs/default-field-values/visibility.stderr
index 63721d79be5..666782933d3 100644
--- a/tests/ui/structs/default-field-values/visibility.stderr
+++ b/tests/ui/structs/default-field-values/visibility.stderr
@@ -1,12 +1,16 @@
 error[E0451]: field `x` of struct `S` is private
   --> $DIR/visibility.rs:24:9
    |
+LL |     let a = baz::S {
+   |             ------ in this type
 LL |         ..
    |         ^^ field `x` is private
 
 error[E0451]: field `x` of struct `S` is private
   --> $DIR/visibility.rs:27:9
    |
+LL |     let b = baz::S {
+   |             ------ in this type
 LL |         x: 0,
    |         ^^^^ private field