Rollup merge of #127431 - oli-obk:feed_item_attrs, r=compiler-errors
Use field ident spans directly instead of the full field span in diagnostics on local fields This improves diagnostics and avoids having to store the `DefId`s of fields
This commit is contained in:
commit
bd4ab30e9c
@ -321,8 +321,14 @@ fn insert_field_def_ids(&mut self, def_id: LocalDefId, fields: &[ast::FieldDef])
|
|||||||
// The fields are not expanded yet.
|
// The fields are not expanded yet.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let def_ids = fields.iter().map(|field| self.r.local_def_id(field.id).to_def_id());
|
let fields = fields
|
||||||
self.r.field_def_ids.insert(def_id, self.r.tcx.arena.alloc_from_iter(def_ids));
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(i, field)| {
|
||||||
|
field.ident.unwrap_or_else(|| Ident::from_str_and_span(&format!("{i}"), field.span))
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
self.r.field_names.insert(def_id, fields);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn insert_field_visibilities_local(&mut self, def_id: DefId, fields: &[ast::FieldDef]) {
|
fn insert_field_visibilities_local(&mut self, def_id: DefId, fields: &[ast::FieldDef]) {
|
||||||
|
@ -1726,11 +1726,7 @@ fn ctor_fields_span(&self, binding: NameBinding<'_>) -> Option<Span> {
|
|||||||
)) = binding.kind
|
)) = binding.kind
|
||||||
{
|
{
|
||||||
let def_id = self.tcx.parent(ctor_def_id);
|
let def_id = self.tcx.parent(ctor_def_id);
|
||||||
return self
|
return self.field_idents(def_id)?.iter().map(|&f| f.span).reduce(Span::to); // None for `struct Foo()`
|
||||||
.field_def_ids(def_id)?
|
|
||||||
.iter()
|
|
||||||
.map(|&field_id| self.def_span(field_id))
|
|
||||||
.reduce(Span::to); // None for `struct Foo()`
|
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -1532,17 +1532,17 @@ fn smart_resolve_context_dependent_help(
|
|||||||
if !this.has_private_fields(def_id) {
|
if !this.has_private_fields(def_id) {
|
||||||
// If the fields of the type are private, we shouldn't be suggesting using
|
// If the fields of the type are private, we shouldn't be suggesting using
|
||||||
// the struct literal syntax at all, as that will cause a subsequent error.
|
// the struct literal syntax at all, as that will cause a subsequent error.
|
||||||
let field_ids = this.r.field_def_ids(def_id);
|
let fields = this.r.field_idents(def_id);
|
||||||
let (fields, applicability) = match field_ids {
|
let has_fields = fields.as_ref().is_some_and(|f| !f.is_empty());
|
||||||
Some(field_ids) => {
|
let (fields, applicability) = match fields {
|
||||||
let fields = field_ids.iter().map(|&id| this.r.tcx.item_name(id));
|
Some(fields) => {
|
||||||
|
|
||||||
let fields = if let Some(old_fields) = old_fields {
|
let fields = if let Some(old_fields) = old_fields {
|
||||||
fields
|
fields
|
||||||
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(idx, new)| (new, old_fields.get(idx)))
|
.map(|(idx, new)| (new, old_fields.get(idx)))
|
||||||
.map(|(new, old)| {
|
.map(|(new, old)| {
|
||||||
let new = new.to_ident_string();
|
let new = new.name.to_ident_string();
|
||||||
if let Some(Some(old)) = old
|
if let Some(Some(old)) = old
|
||||||
&& new != *old
|
&& new != *old
|
||||||
{
|
{
|
||||||
@ -1553,17 +1553,17 @@ fn smart_resolve_context_dependent_help(
|
|||||||
})
|
})
|
||||||
.collect::<Vec<String>>()
|
.collect::<Vec<String>>()
|
||||||
} else {
|
} else {
|
||||||
fields.map(|f| format!("{f}{tail}")).collect::<Vec<String>>()
|
fields
|
||||||
|
.iter()
|
||||||
|
.map(|f| format!("{f}{tail}"))
|
||||||
|
.collect::<Vec<String>>()
|
||||||
};
|
};
|
||||||
|
|
||||||
(fields.join(", "), applicability)
|
(fields.join(", "), applicability)
|
||||||
}
|
}
|
||||||
None => ("/* fields */".to_string(), Applicability::HasPlaceholders),
|
None => ("/* fields */".to_string(), Applicability::HasPlaceholders),
|
||||||
};
|
};
|
||||||
let pad = match field_ids {
|
let pad = if has_fields { " " } else { "" };
|
||||||
Some([]) => "",
|
|
||||||
_ => " ",
|
|
||||||
};
|
|
||||||
err.span_suggestion(
|
err.span_suggestion(
|
||||||
span,
|
span,
|
||||||
format!("use struct {descr} syntax instead"),
|
format!("use struct {descr} syntax instead"),
|
||||||
@ -1723,12 +1723,9 @@ fn smart_resolve_context_dependent_help(
|
|||||||
&args[..],
|
&args[..],
|
||||||
);
|
);
|
||||||
// Use spans of the tuple struct definition.
|
// Use spans of the tuple struct definition.
|
||||||
self.r.field_def_ids(def_id).map(|field_ids| {
|
self.r
|
||||||
field_ids
|
.field_idents(def_id)
|
||||||
.iter()
|
.map(|fields| fields.iter().map(|f| f.span).collect::<Vec<_>>())
|
||||||
.map(|&field_id| self.r.def_span(field_id))
|
|
||||||
.collect::<Vec<_>>()
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
@ -1791,7 +1788,7 @@ fn smart_resolve_context_dependent_help(
|
|||||||
(Res::Def(DefKind::Ctor(_, CtorKind::Fn), ctor_def_id), _) if ns == ValueNS => {
|
(Res::Def(DefKind::Ctor(_, CtorKind::Fn), ctor_def_id), _) if ns == ValueNS => {
|
||||||
let def_id = self.r.tcx.parent(ctor_def_id);
|
let def_id = self.r.tcx.parent(ctor_def_id);
|
||||||
err.span_label(self.r.def_span(def_id), format!("`{path_str}` defined here"));
|
err.span_label(self.r.def_span(def_id), format!("`{path_str}` defined here"));
|
||||||
let fields = self.r.field_def_ids(def_id).map_or_else(
|
let fields = self.r.field_idents(def_id).map_or_else(
|
||||||
|| "/* fields */".to_string(),
|
|| "/* fields */".to_string(),
|
||||||
|field_ids| vec!["_"; field_ids.len()].join(", "),
|
|field_ids| vec!["_"; field_ids.len()].join(", "),
|
||||||
);
|
);
|
||||||
@ -2017,12 +2014,9 @@ fn extract_node_id(t: &Ty) -> Option<NodeId> {
|
|||||||
if let Some(Res::Def(DefKind::Struct | DefKind::Union, did)) =
|
if let Some(Res::Def(DefKind::Struct | DefKind::Union, did)) =
|
||||||
resolution.full_res()
|
resolution.full_res()
|
||||||
{
|
{
|
||||||
if let Some(field_ids) = self.r.field_def_ids(did) {
|
if let Some(fields) = self.r.field_idents(did) {
|
||||||
if let Some(field_id) = field_ids
|
if let Some(field) = fields.iter().find(|id| ident.name == id.name) {
|
||||||
.iter()
|
return Some(AssocSuggestion::Field(field.span));
|
||||||
.find(|&&field_id| ident.name == self.r.tcx.item_name(field_id))
|
|
||||||
{
|
|
||||||
return Some(AssocSuggestion::Field(self.r.def_span(*field_id)));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2418,7 +2412,7 @@ fn suggest_using_enum_variant(
|
|||||||
match kind {
|
match kind {
|
||||||
CtorKind::Const => false,
|
CtorKind::Const => false,
|
||||||
CtorKind::Fn => {
|
CtorKind::Fn => {
|
||||||
!self.r.field_def_ids(def_id).is_some_and(|field_ids| field_ids.is_empty())
|
!self.r.field_idents(def_id).is_some_and(|field_ids| field_ids.is_empty())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -991,7 +991,7 @@ pub struct Resolver<'a, 'tcx> {
|
|||||||
extern_prelude: FxHashMap<Ident, ExternPreludeEntry<'a>>,
|
extern_prelude: FxHashMap<Ident, ExternPreludeEntry<'a>>,
|
||||||
|
|
||||||
/// N.B., this is used only for better diagnostics, not name resolution itself.
|
/// N.B., this is used only for better diagnostics, not name resolution itself.
|
||||||
field_def_ids: LocalDefIdMap<&'tcx [DefId]>,
|
field_names: LocalDefIdMap<Vec<Ident>>,
|
||||||
|
|
||||||
/// Span of the privacy modifier in fields of an item `DefId` accessible with dot syntax.
|
/// Span of the privacy modifier in fields of an item `DefId` accessible with dot syntax.
|
||||||
/// Used for hints during error reporting.
|
/// Used for hints during error reporting.
|
||||||
@ -1407,7 +1407,7 @@ pub fn new(
|
|||||||
prelude: None,
|
prelude: None,
|
||||||
extern_prelude,
|
extern_prelude,
|
||||||
|
|
||||||
field_def_ids: Default::default(),
|
field_names: Default::default(),
|
||||||
field_visibility_spans: FxHashMap::default(),
|
field_visibility_spans: FxHashMap::default(),
|
||||||
|
|
||||||
determined_imports: Vec::new(),
|
determined_imports: Vec::new(),
|
||||||
@ -2128,10 +2128,18 @@ fn def_span(&self, def_id: DefId) -> Span {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn field_def_ids(&self, def_id: DefId) -> Option<&'tcx [DefId]> {
|
fn field_idents(&self, def_id: DefId) -> Option<Vec<Ident>> {
|
||||||
match def_id.as_local() {
|
match def_id.as_local() {
|
||||||
Some(def_id) => self.field_def_ids.get(&def_id).copied(),
|
Some(def_id) => self.field_names.get(&def_id).cloned(),
|
||||||
None => Some(self.tcx.associated_item_def_ids(def_id)),
|
None => Some(
|
||||||
|
self.tcx
|
||||||
|
.associated_item_def_ids(def_id)
|
||||||
|
.iter()
|
||||||
|
.map(|&def_id| {
|
||||||
|
Ident::new(self.tcx.item_name(def_id), self.tcx.def_span(def_id))
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ error[E0425]: cannot find value `field` in this scope
|
|||||||
--> $DIR/field-and-method-in-self-not-available-in-assoc-fn.rs:11:9
|
--> $DIR/field-and-method-in-self-not-available-in-assoc-fn.rs:11:9
|
||||||
|
|
|
|
||||||
LL | field: u32,
|
LL | field: u32,
|
||||||
| ---------- a field by that name exists in `Self`
|
| ----- a field by that name exists in `Self`
|
||||||
...
|
...
|
||||||
LL | fn field(&self) -> u32 {
|
LL | fn field(&self) -> u32 {
|
||||||
| ----- a method by that name is available on `Self` here
|
| ----- a method by that name is available on `Self` here
|
||||||
@ -14,7 +14,7 @@ error[E0425]: cannot find value `field` in this scope
|
|||||||
--> $DIR/field-and-method-in-self-not-available-in-assoc-fn.rs:12:15
|
--> $DIR/field-and-method-in-self-not-available-in-assoc-fn.rs:12:15
|
||||||
|
|
|
|
||||||
LL | field: u32,
|
LL | field: u32,
|
||||||
| ---------- a field by that name exists in `Self`
|
| ----- a field by that name exists in `Self`
|
||||||
...
|
...
|
||||||
LL | fn field(&self) -> u32 {
|
LL | fn field(&self) -> u32 {
|
||||||
| ----- a method by that name is available on `Self` here
|
| ----- a method by that name is available on `Self` here
|
||||||
|
@ -2,7 +2,7 @@ error[E0425]: cannot find value `whiskers` in this scope
|
|||||||
--> $DIR/issue-2356.rs:39:5
|
--> $DIR/issue-2356.rs:39:5
|
||||||
|
|
|
|
||||||
LL | whiskers: isize,
|
LL | whiskers: isize,
|
||||||
| --------------- a field by that name exists in `Self`
|
| -------- a field by that name exists in `Self`
|
||||||
...
|
...
|
||||||
LL | whiskers -= other;
|
LL | whiskers -= other;
|
||||||
| ^^^^^^^^
|
| ^^^^^^^^
|
||||||
@ -35,7 +35,7 @@ error[E0425]: cannot find value `whiskers` in this scope
|
|||||||
--> $DIR/issue-2356.rs:84:5
|
--> $DIR/issue-2356.rs:84:5
|
||||||
|
|
|
|
||||||
LL | whiskers: isize,
|
LL | whiskers: isize,
|
||||||
| --------------- a field by that name exists in `Self`
|
| -------- a field by that name exists in `Self`
|
||||||
...
|
...
|
||||||
LL | whiskers = 4;
|
LL | whiskers = 4;
|
||||||
| ^^^^^^^^
|
| ^^^^^^^^
|
||||||
|
@ -2,7 +2,7 @@ error[E0425]: cannot find value `banana` in this scope
|
|||||||
--> $DIR/issue-60057.rs:8:21
|
--> $DIR/issue-60057.rs:8:21
|
||||||
|
|
|
|
||||||
LL | banana: u8,
|
LL | banana: u8,
|
||||||
| ---------- a field by that name exists in `Self`
|
| ------ a field by that name exists in `Self`
|
||||||
...
|
...
|
||||||
LL | banana: banana
|
LL | banana: banana
|
||||||
| ^^^^^^
|
| ^^^^^^
|
||||||
|
@ -2,7 +2,7 @@ error[E0425]: cannot find value `config` in this scope
|
|||||||
--> $DIR/typo-suggestion-for-variable-with-name-similar-to-struct-field.rs:7:16
|
--> $DIR/typo-suggestion-for-variable-with-name-similar-to-struct-field.rs:7:16
|
||||||
|
|
|
|
||||||
LL | config: String,
|
LL | config: String,
|
||||||
| -------------- a field by that name exists in `Self`
|
| ------ a field by that name exists in `Self`
|
||||||
...
|
...
|
||||||
LL | Self { config }
|
LL | Self { config }
|
||||||
| ^^^^^^ help: a local variable with a similar name exists: `cofig`
|
| ^^^^^^ help: a local variable with a similar name exists: `cofig`
|
||||||
@ -11,7 +11,7 @@ error[E0425]: cannot find value `config` in this scope
|
|||||||
--> $DIR/typo-suggestion-for-variable-with-name-similar-to-struct-field.rs:11:20
|
--> $DIR/typo-suggestion-for-variable-with-name-similar-to-struct-field.rs:11:20
|
||||||
|
|
|
|
||||||
LL | config: String,
|
LL | config: String,
|
||||||
| -------------- a field by that name exists in `Self`
|
| ------ a field by that name exists in `Self`
|
||||||
...
|
...
|
||||||
LL | println!("{config}");
|
LL | println!("{config}");
|
||||||
| ^^^^^^ help: a local variable with a similar name exists: `cofig`
|
| ^^^^^^ help: a local variable with a similar name exists: `cofig`
|
||||||
|
@ -2,7 +2,7 @@ error[E0425]: cannot find value `cx` in this scope
|
|||||||
--> $DIR/unresolved_static_type_field.rs:9:11
|
--> $DIR/unresolved_static_type_field.rs:9:11
|
||||||
|
|
|
|
||||||
LL | cx: bool,
|
LL | cx: bool,
|
||||||
| -------- a field by that name exists in `Self`
|
| -- a field by that name exists in `Self`
|
||||||
...
|
...
|
||||||
LL | f(cx);
|
LL | f(cx);
|
||||||
| ^^
|
| ^^
|
||||||
|
Loading…
Reference in New Issue
Block a user