Skip to content

Commit 8c2ea71

Browse files
committed
Use field ident spans directly instead of the full field span in diagnostics on local fields
1 parent 28cc0b6 commit 8c2ea71

9 files changed

+49
-45
lines changed

compiler/rustc_resolve/src/build_reduced_graph.rs

+8-2
Original file line numberDiff line numberDiff line change
@@ -321,8 +321,14 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
321321
// The fields are not expanded yet.
322322
return;
323323
}
324-
let def_ids = fields.iter().map(|field| self.r.local_def_id(field.id).to_def_id());
325-
self.r.field_def_ids.insert(def_id, self.r.tcx.arena.alloc_from_iter(def_ids));
324+
let fields = fields
325+
.iter()
326+
.enumerate()
327+
.map(|(i, field)| {
328+
field.ident.unwrap_or_else(|| Ident::from_str_and_span(&format!("{i}"), field.span))
329+
})
330+
.collect();
331+
self.r.field_names.insert(def_id, fields);
326332
}
327333

328334
fn insert_field_visibilities_local(&mut self, def_id: DefId, fields: &[ast::FieldDef]) {

compiler/rustc_resolve/src/diagnostics.rs

+1-5
Original file line numberDiff line numberDiff line change
@@ -1726,11 +1726,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
17261726
)) = binding.kind
17271727
{
17281728
let def_id = self.tcx.parent(ctor_def_id);
1729-
return self
1730-
.field_def_ids(def_id)?
1731-
.iter()
1732-
.map(|&field_id| self.def_span(field_id))
1733-
.reduce(Span::to); // None for `struct Foo()`
1729+
return self.field_idents(def_id)?.iter().map(|&f| f.span).reduce(Span::to); // None for `struct Foo()`
17341730
}
17351731
None
17361732
}

compiler/rustc_resolve/src/late/diagnostics.rs

+19-25
Original file line numberDiff line numberDiff line change
@@ -1532,17 +1532,17 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
15321532
if !this.has_private_fields(def_id) {
15331533
// If the fields of the type are private, we shouldn't be suggesting using
15341534
// the struct literal syntax at all, as that will cause a subsequent error.
1535-
let field_ids = this.r.field_def_ids(def_id);
1536-
let (fields, applicability) = match field_ids {
1537-
Some(field_ids) => {
1538-
let fields = field_ids.iter().map(|&id| this.r.tcx.item_name(id));
1539-
1535+
let fields = this.r.field_idents(def_id);
1536+
let has_fields = fields.as_ref().is_some_and(|f| !f.is_empty());
1537+
let (fields, applicability) = match fields {
1538+
Some(fields) => {
15401539
let fields = if let Some(old_fields) = old_fields {
15411540
fields
1541+
.iter()
15421542
.enumerate()
15431543
.map(|(idx, new)| (new, old_fields.get(idx)))
15441544
.map(|(new, old)| {
1545-
let new = new.to_ident_string();
1545+
let new = new.name.to_ident_string();
15461546
if let Some(Some(old)) = old
15471547
&& new != *old
15481548
{
@@ -1553,17 +1553,17 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
15531553
})
15541554
.collect::<Vec<String>>()
15551555
} else {
1556-
fields.map(|f| format!("{f}{tail}")).collect::<Vec<String>>()
1556+
fields
1557+
.iter()
1558+
.map(|f| format!("{f}{tail}"))
1559+
.collect::<Vec<String>>()
15571560
};
15581561

15591562
(fields.join(", "), applicability)
15601563
}
15611564
None => ("/* fields */".to_string(), Applicability::HasPlaceholders),
15621565
};
1563-
let pad = match field_ids {
1564-
Some([]) => "",
1565-
_ => " ",
1566-
};
1566+
let pad = if has_fields { " " } else { "" };
15671567
err.span_suggestion(
15681568
span,
15691569
format!("use struct {descr} syntax instead"),
@@ -1723,12 +1723,9 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
17231723
&args[..],
17241724
);
17251725
// Use spans of the tuple struct definition.
1726-
self.r.field_def_ids(def_id).map(|field_ids| {
1727-
field_ids
1728-
.iter()
1729-
.map(|&field_id| self.r.def_span(field_id))
1730-
.collect::<Vec<_>>()
1731-
})
1726+
self.r
1727+
.field_idents(def_id)
1728+
.map(|fields| fields.iter().map(|f| f.span).collect::<Vec<_>>())
17321729
}
17331730
_ => None,
17341731
};
@@ -1791,7 +1788,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
17911788
(Res::Def(DefKind::Ctor(_, CtorKind::Fn), ctor_def_id), _) if ns == ValueNS => {
17921789
let def_id = self.r.tcx.parent(ctor_def_id);
17931790
err.span_label(self.r.def_span(def_id), format!("`{path_str}` defined here"));
1794-
let fields = self.r.field_def_ids(def_id).map_or_else(
1791+
let fields = self.r.field_idents(def_id).map_or_else(
17951792
|| "/* fields */".to_string(),
17961793
|field_ids| vec!["_"; field_ids.len()].join(", "),
17971794
);
@@ -2017,12 +2014,9 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
20172014
if let Some(Res::Def(DefKind::Struct | DefKind::Union, did)) =
20182015
resolution.full_res()
20192016
{
2020-
if let Some(field_ids) = self.r.field_def_ids(did) {
2021-
if let Some(field_id) = field_ids
2022-
.iter()
2023-
.find(|&&field_id| ident.name == self.r.tcx.item_name(field_id))
2024-
{
2025-
return Some(AssocSuggestion::Field(self.r.def_span(*field_id)));
2017+
if let Some(fields) = self.r.field_idents(did) {
2018+
if let Some(field) = fields.iter().find(|id| ident.name == id.name) {
2019+
return Some(AssocSuggestion::Field(field.span));
20262020
}
20272021
}
20282022
}
@@ -2418,7 +2412,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
24182412
match kind {
24192413
CtorKind::Const => false,
24202414
CtorKind::Fn => {
2421-
!self.r.field_def_ids(def_id).is_some_and(|field_ids| field_ids.is_empty())
2415+
!self.r.field_idents(def_id).is_some_and(|field_ids| field_ids.is_empty())
24222416
}
24232417
}
24242418
};

compiler/rustc_resolve/src/lib.rs

+13-5
Original file line numberDiff line numberDiff line change
@@ -991,7 +991,7 @@ pub struct Resolver<'a, 'tcx> {
991991
extern_prelude: FxHashMap<Ident, ExternPreludeEntry<'a>>,
992992

993993
/// N.B., this is used only for better diagnostics, not name resolution itself.
994-
field_def_ids: LocalDefIdMap<&'tcx [DefId]>,
994+
field_names: LocalDefIdMap<Vec<Ident>>,
995995

996996
/// Span of the privacy modifier in fields of an item `DefId` accessible with dot syntax.
997997
/// Used for hints during error reporting.
@@ -1406,7 +1406,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
14061406
prelude: None,
14071407
extern_prelude,
14081408

1409-
field_def_ids: Default::default(),
1409+
field_names: Default::default(),
14101410
field_visibility_spans: FxHashMap::default(),
14111411

14121412
determined_imports: Vec::new(),
@@ -2127,10 +2127,18 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
21272127
}
21282128
}
21292129

2130-
fn field_def_ids(&self, def_id: DefId) -> Option<&'tcx [DefId]> {
2130+
fn field_idents(&self, def_id: DefId) -> Option<Vec<Ident>> {
21312131
match def_id.as_local() {
2132-
Some(def_id) => self.field_def_ids.get(&def_id).copied(),
2133-
None => Some(self.tcx.associated_item_def_ids(def_id)),
2132+
Some(def_id) => self.field_names.get(&def_id).cloned(),
2133+
None => Some(
2134+
self.tcx
2135+
.associated_item_def_ids(def_id)
2136+
.iter()
2137+
.map(|&def_id| {
2138+
Ident::new(self.tcx.item_name(def_id), self.tcx.def_span(def_id))
2139+
})
2140+
.collect(),
2141+
),
21342142
}
21352143
}
21362144

tests/ui/resolve/field-and-method-in-self-not-available-in-assoc-fn.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error[E0425]: cannot find value `field` in this scope
22
--> $DIR/field-and-method-in-self-not-available-in-assoc-fn.rs:11:9
33
|
44
LL | field: u32,
5-
| ---------- a field by that name exists in `Self`
5+
| ----- a field by that name exists in `Self`
66
...
77
LL | fn field(&self) -> u32 {
88
| ----- a method by that name is available on `Self` here
@@ -14,7 +14,7 @@ error[E0425]: cannot find value `field` in this scope
1414
--> $DIR/field-and-method-in-self-not-available-in-assoc-fn.rs:12:15
1515
|
1616
LL | field: u32,
17-
| ---------- a field by that name exists in `Self`
17+
| ----- a field by that name exists in `Self`
1818
...
1919
LL | fn field(&self) -> u32 {
2020
| ----- a method by that name is available on `Self` here

tests/ui/resolve/issue-2356.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error[E0425]: cannot find value `whiskers` in this scope
22
--> $DIR/issue-2356.rs:39:5
33
|
44
LL | whiskers: isize,
5-
| --------------- a field by that name exists in `Self`
5+
| -------- a field by that name exists in `Self`
66
...
77
LL | whiskers -= other;
88
| ^^^^^^^^
@@ -35,7 +35,7 @@ error[E0425]: cannot find value `whiskers` in this scope
3535
--> $DIR/issue-2356.rs:84:5
3636
|
3737
LL | whiskers: isize,
38-
| --------------- a field by that name exists in `Self`
38+
| -------- a field by that name exists in `Self`
3939
...
4040
LL | whiskers = 4;
4141
| ^^^^^^^^

tests/ui/resolve/issue-60057.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error[E0425]: cannot find value `banana` in this scope
22
--> $DIR/issue-60057.rs:8:21
33
|
44
LL | banana: u8,
5-
| ---------- a field by that name exists in `Self`
5+
| ------ a field by that name exists in `Self`
66
...
77
LL | banana: banana
88
| ^^^^^^

tests/ui/resolve/typo-suggestion-for-variable-with-name-similar-to-struct-field.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error[E0425]: cannot find value `config` in this scope
22
--> $DIR/typo-suggestion-for-variable-with-name-similar-to-struct-field.rs:7:16
33
|
44
LL | config: String,
5-
| -------------- a field by that name exists in `Self`
5+
| ------ a field by that name exists in `Self`
66
...
77
LL | Self { config }
88
| ^^^^^^ help: a local variable with a similar name exists: `cofig`
@@ -11,7 +11,7 @@ error[E0425]: cannot find value `config` in this scope
1111
--> $DIR/typo-suggestion-for-variable-with-name-similar-to-struct-field.rs:11:20
1212
|
1313
LL | config: String,
14-
| -------------- a field by that name exists in `Self`
14+
| ------ a field by that name exists in `Self`
1515
...
1616
LL | println!("{config}");
1717
| ^^^^^^ help: a local variable with a similar name exists: `cofig`

tests/ui/resolve/unresolved_static_type_field.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error[E0425]: cannot find value `cx` in this scope
22
--> $DIR/unresolved_static_type_field.rs:9:11
33
|
44
LL | cx: bool,
5-
| -------- a field by that name exists in `Self`
5+
| -- a field by that name exists in `Self`
66
...
77
LL | f(cx);
88
| ^^

0 commit comments

Comments
 (0)