1
Fork 0

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
```
This commit is contained in:
Esteban Küber 2025-01-18 01:56:22 +00:00
parent 3e99055c40
commit bbcf26fc33
5 changed files with 44 additions and 4 deletions

View file

@ -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,

View file

@ -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(),
);
}
}