Skip to content

Commit b01cdd8

Browse files
committed
Auto merge of rust-lang#13189 - unexge:unconfigured-diagnostics-for-fields, r=Veykril
Emit unconfigured code diagnostics for enum variants and struct/union fields Fixes rust-lang/rust-analyzer#12664
2 parents f972cdd + 7e5e517 commit b01cdd8

File tree

13 files changed

+255
-57
lines changed

13 files changed

+255
-57
lines changed

crates/hir-def/src/adt.rs

Lines changed: 129 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use base_db::CrateId;
66
use either::Either;
77
use hir_expand::{
88
name::{AsName, Name},
9-
InFile,
9+
HirFileId, InFile,
1010
};
1111
use la_arena::{Arena, ArenaMap};
1212
use syntax::ast::{self, HasName, HasVisibility};
@@ -17,13 +17,15 @@ use crate::{
1717
builtin_type::{BuiltinInt, BuiltinUint},
1818
db::DefDatabase,
1919
intern::Interned,
20-
item_tree::{AttrOwner, Field, Fields, ItemTree, ModItem, RawVisibilityId},
20+
item_tree::{AttrOwner, Field, FieldAstId, Fields, ItemTree, ModItem, RawVisibilityId},
21+
nameres::diagnostics::DefDiagnostic,
2122
src::HasChildSource,
2223
src::HasSource,
2324
trace::Trace,
2425
type_ref::TypeRef,
2526
visibility::RawVisibility,
26-
EnumId, LocalEnumVariantId, LocalFieldId, Lookup, ModuleId, StructId, UnionId, VariantId,
27+
EnumId, LocalEnumVariantId, LocalFieldId, LocalModuleId, Lookup, ModuleId, StructId, UnionId,
28+
VariantId,
2729
};
2830
use cfg::CfgOptions;
2931

@@ -143,43 +145,87 @@ fn parse_repr_tt(tt: &Subtree) -> Option<ReprData> {
143145

144146
impl StructData {
145147
pub(crate) fn struct_data_query(db: &dyn DefDatabase, id: StructId) -> Arc<StructData> {
148+
db.struct_data_with_diagnostics(id).0
149+
}
150+
151+
pub(crate) fn struct_data_with_diagnostics_query(
152+
db: &dyn DefDatabase,
153+
id: StructId,
154+
) -> (Arc<StructData>, Arc<[DefDiagnostic]>) {
146155
let loc = id.lookup(db);
147156
let krate = loc.container.krate;
148157
let item_tree = loc.id.item_tree(db);
149158
let repr = repr_from_value(db, krate, &item_tree, ModItem::from(loc.id.value).into());
150159
let cfg_options = db.crate_graph()[loc.container.krate].cfg_options.clone();
151160

152161
let strukt = &item_tree[loc.id.value];
153-
let variant_data = lower_fields(db, krate, &item_tree, &cfg_options, &strukt.fields, None);
154-
Arc::new(StructData {
155-
name: strukt.name.clone(),
156-
variant_data: Arc::new(variant_data),
157-
repr,
158-
visibility: item_tree[strukt.visibility].clone(),
159-
})
162+
let (variant_data, diagnostics) = lower_fields(
163+
db,
164+
krate,
165+
loc.id.file_id(),
166+
loc.container.local_id,
167+
&item_tree,
168+
&cfg_options,
169+
&strukt.fields,
170+
None,
171+
);
172+
(
173+
Arc::new(StructData {
174+
name: strukt.name.clone(),
175+
variant_data: Arc::new(variant_data),
176+
repr,
177+
visibility: item_tree[strukt.visibility].clone(),
178+
}),
179+
diagnostics.into(),
180+
)
160181
}
161182

162183
pub(crate) fn union_data_query(db: &dyn DefDatabase, id: UnionId) -> Arc<StructData> {
184+
db.union_data_with_diagnostics(id).0
185+
}
186+
187+
pub(crate) fn union_data_with_diagnostics_query(
188+
db: &dyn DefDatabase,
189+
id: UnionId,
190+
) -> (Arc<StructData>, Arc<[DefDiagnostic]>) {
163191
let loc = id.lookup(db);
164192
let krate = loc.container.krate;
165193
let item_tree = loc.id.item_tree(db);
166194
let repr = repr_from_value(db, krate, &item_tree, ModItem::from(loc.id.value).into());
167195
let cfg_options = db.crate_graph()[loc.container.krate].cfg_options.clone();
168196

169197
let union = &item_tree[loc.id.value];
170-
let variant_data = lower_fields(db, krate, &item_tree, &cfg_options, &union.fields, None);
171-
172-
Arc::new(StructData {
173-
name: union.name.clone(),
174-
variant_data: Arc::new(variant_data),
175-
repr,
176-
visibility: item_tree[union.visibility].clone(),
177-
})
198+
let (variant_data, diagnostics) = lower_fields(
199+
db,
200+
krate,
201+
loc.id.file_id(),
202+
loc.container.local_id,
203+
&item_tree,
204+
&cfg_options,
205+
&union.fields,
206+
None,
207+
);
208+
(
209+
Arc::new(StructData {
210+
name: union.name.clone(),
211+
variant_data: Arc::new(variant_data),
212+
repr,
213+
visibility: item_tree[union.visibility].clone(),
214+
}),
215+
diagnostics.into(),
216+
)
178217
}
179218
}
180219

181220
impl EnumData {
182221
pub(crate) fn enum_data_query(db: &dyn DefDatabase, e: EnumId) -> Arc<EnumData> {
222+
db.enum_data_with_diagnostics(e).0
223+
}
224+
225+
pub(crate) fn enum_data_with_diagnostics_query(
226+
db: &dyn DefDatabase,
227+
e: EnumId,
228+
) -> (Arc<EnumData>, Arc<[DefDiagnostic]>) {
183229
let loc = e.lookup(db);
184230
let krate = loc.container.krate;
185231
let item_tree = loc.id.item_tree(db);
@@ -188,31 +234,46 @@ impl EnumData {
188234

189235
let enum_ = &item_tree[loc.id.value];
190236
let mut variants = Arena::new();
237+
let mut diagnostics = Vec::new();
191238
for tree_id in enum_.variants.clone() {
192-
if item_tree.attrs(db, krate, tree_id.into()).is_cfg_enabled(&cfg_options) {
193-
let var = &item_tree[tree_id];
194-
let var_data = lower_fields(
239+
let attrs = item_tree.attrs(db, krate, tree_id.into());
240+
let var = &item_tree[tree_id];
241+
if attrs.is_cfg_enabled(&cfg_options) {
242+
let (var_data, field_diagnostics) = lower_fields(
195243
db,
196244
krate,
245+
loc.id.file_id(),
246+
loc.container.local_id,
197247
&item_tree,
198248
&cfg_options,
199249
&var.fields,
200250
Some(enum_.visibility),
201251
);
252+
diagnostics.extend(field_diagnostics);
202253

203254
variants.alloc(EnumVariantData {
204255
name: var.name.clone(),
205256
variant_data: Arc::new(var_data),
206257
});
258+
} else {
259+
diagnostics.push(DefDiagnostic::unconfigured_code(
260+
loc.container.local_id,
261+
InFile::new(loc.id.file_id(), var.ast_id.upcast()),
262+
attrs.cfg().unwrap(),
263+
cfg_options.clone(),
264+
))
207265
}
208266
}
209267

210-
Arc::new(EnumData {
211-
name: enum_.name.clone(),
212-
variants,
213-
repr,
214-
visibility: item_tree[enum_.visibility].clone(),
215-
})
268+
(
269+
Arc::new(EnumData {
270+
name: enum_.name.clone(),
271+
variants,
272+
repr,
273+
visibility: item_tree[enum_.visibility].clone(),
274+
}),
275+
diagnostics.into(),
276+
)
216277
}
217278

218279
pub fn variant(&self, name: &Name) -> Option<LocalEnumVariantId> {
@@ -384,31 +445,64 @@ fn lower_struct(
384445
fn lower_fields(
385446
db: &dyn DefDatabase,
386447
krate: CrateId,
448+
current_file_id: HirFileId,
449+
container: LocalModuleId,
387450
item_tree: &ItemTree,
388451
cfg_options: &CfgOptions,
389452
fields: &Fields,
390453
override_visibility: Option<RawVisibilityId>,
391-
) -> VariantData {
454+
) -> (VariantData, Vec<DefDiagnostic>) {
455+
let mut diagnostics = Vec::new();
392456
match fields {
393457
Fields::Record(flds) => {
394458
let mut arena = Arena::new();
395459
for field_id in flds.clone() {
396-
if item_tree.attrs(db, krate, field_id.into()).is_cfg_enabled(cfg_options) {
397-
arena.alloc(lower_field(item_tree, &item_tree[field_id], override_visibility));
460+
let attrs = item_tree.attrs(db, krate, field_id.into());
461+
let field = &item_tree[field_id];
462+
if attrs.is_cfg_enabled(cfg_options) {
463+
arena.alloc(lower_field(item_tree, field, override_visibility));
464+
} else {
465+
diagnostics.push(DefDiagnostic::unconfigured_code(
466+
container,
467+
InFile::new(
468+
current_file_id,
469+
match field.ast_id {
470+
FieldAstId::Record(it) => it.upcast(),
471+
FieldAstId::Tuple(it) => it.upcast(),
472+
},
473+
),
474+
attrs.cfg().unwrap(),
475+
cfg_options.clone(),
476+
))
398477
}
399478
}
400-
VariantData::Record(arena)
479+
(VariantData::Record(arena), diagnostics)
401480
}
402481
Fields::Tuple(flds) => {
403482
let mut arena = Arena::new();
404483
for field_id in flds.clone() {
405-
if item_tree.attrs(db, krate, field_id.into()).is_cfg_enabled(cfg_options) {
406-
arena.alloc(lower_field(item_tree, &item_tree[field_id], override_visibility));
484+
let attrs = item_tree.attrs(db, krate, field_id.into());
485+
let field = &item_tree[field_id];
486+
if attrs.is_cfg_enabled(cfg_options) {
487+
arena.alloc(lower_field(item_tree, field, override_visibility));
488+
} else {
489+
diagnostics.push(DefDiagnostic::unconfigured_code(
490+
container,
491+
InFile::new(
492+
current_file_id,
493+
match field.ast_id {
494+
FieldAstId::Record(it) => it.upcast(),
495+
FieldAstId::Tuple(it) => it.upcast(),
496+
},
497+
),
498+
attrs.cfg().unwrap(),
499+
cfg_options.clone(),
500+
))
407501
}
408502
}
409-
VariantData::Tuple(arena)
503+
(VariantData::Tuple(arena), diagnostics)
410504
}
411-
Fields::Unit => VariantData::Unit,
505+
Fields::Unit => (VariantData::Unit, diagnostics),
412506
}
413507
}
414508

crates/hir-def/src/data.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ impl TraitData {
219219
pub(crate) fn trait_data_with_diagnostics_query(
220220
db: &dyn DefDatabase,
221221
tr: TraitId,
222-
) -> (Arc<TraitData>, Arc<Vec<DefDiagnostic>>) {
222+
) -> (Arc<TraitData>, Arc<[DefDiagnostic]>) {
223223
let tr_loc @ ItemLoc { container: module_id, id: tree_id } = tr.lookup(db);
224224
let item_tree = tree_id.item_tree(db);
225225
let tr_def = &item_tree[tree_id.value];
@@ -251,7 +251,7 @@ impl TraitData {
251251
visibility,
252252
skip_array_during_method_dispatch,
253253
}),
254-
Arc::new(diagnostics),
254+
diagnostics.into(),
255255
)
256256
}
257257

@@ -299,7 +299,7 @@ impl ImplData {
299299
pub(crate) fn impl_data_with_diagnostics_query(
300300
db: &dyn DefDatabase,
301301
id: ImplId,
302-
) -> (Arc<ImplData>, Arc<Vec<DefDiagnostic>>) {
302+
) -> (Arc<ImplData>, Arc<[DefDiagnostic]>) {
303303
let _p = profile::span("impl_data_with_diagnostics_query");
304304
let ItemLoc { container: module_id, id: tree_id } = id.lookup(db);
305305

@@ -318,7 +318,7 @@ impl ImplData {
318318

319319
(
320320
Arc::new(ImplData { target_trait, self_ty, items, is_negative, attribute_calls }),
321-
Arc::new(diagnostics),
321+
diagnostics.into(),
322322
)
323323
}
324324

crates/hir-def/src/db.rs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -97,24 +97,33 @@ pub trait DefDatabase: InternDatabase + AstDatabase + Upcast<dyn AstDatabase> {
9797
#[salsa::invoke(StructData::struct_data_query)]
9898
fn struct_data(&self, id: StructId) -> Arc<StructData>;
9999

100+
#[salsa::invoke(StructData::struct_data_with_diagnostics_query)]
101+
fn struct_data_with_diagnostics(&self, id: StructId)
102+
-> (Arc<StructData>, Arc<[DefDiagnostic]>);
103+
100104
#[salsa::invoke(StructData::union_data_query)]
101105
fn union_data(&self, id: UnionId) -> Arc<StructData>;
102106

107+
#[salsa::invoke(StructData::union_data_with_diagnostics_query)]
108+
fn union_data_with_diagnostics(&self, id: UnionId) -> (Arc<StructData>, Arc<[DefDiagnostic]>);
109+
103110
#[salsa::invoke(EnumData::enum_data_query)]
104111
fn enum_data(&self, e: EnumId) -> Arc<EnumData>;
105112

113+
#[salsa::invoke(EnumData::enum_data_with_diagnostics_query)]
114+
fn enum_data_with_diagnostics(&self, e: EnumId) -> (Arc<EnumData>, Arc<[DefDiagnostic]>);
115+
106116
#[salsa::invoke(ImplData::impl_data_query)]
107117
fn impl_data(&self, e: ImplId) -> Arc<ImplData>;
108118

109119
#[salsa::invoke(ImplData::impl_data_with_diagnostics_query)]
110-
fn impl_data_with_diagnostics(&self, e: ImplId) -> (Arc<ImplData>, Arc<Vec<DefDiagnostic>>);
120+
fn impl_data_with_diagnostics(&self, e: ImplId) -> (Arc<ImplData>, Arc<[DefDiagnostic]>);
111121

112122
#[salsa::invoke(TraitData::trait_data_query)]
113123
fn trait_data(&self, e: TraitId) -> Arc<TraitData>;
114124

115125
#[salsa::invoke(TraitData::trait_data_with_diagnostics_query)]
116-
fn trait_data_with_diagnostics(&self, tr: TraitId)
117-
-> (Arc<TraitData>, Arc<Vec<DefDiagnostic>>);
126+
fn trait_data_with_diagnostics(&self, tr: TraitId) -> (Arc<TraitData>, Arc<[DefDiagnostic]>);
118127

119128
#[salsa::invoke(TypeAliasData::type_alias_data_query)]
120129
fn type_alias_data(&self, e: TypeAliasId) -> Arc<TypeAliasData>;

crates/hir-def/src/item_tree.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -943,6 +943,7 @@ impl AssocItem {
943943
pub struct Variant {
944944
pub name: Name,
945945
pub fields: Fields,
946+
pub ast_id: FileAstId<ast::Variant>,
946947
}
947948

948949
#[derive(Debug, Clone, PartialEq, Eq)]
@@ -952,10 +953,17 @@ pub enum Fields {
952953
Unit,
953954
}
954955

956+
#[derive(Debug, Clone, PartialEq, Eq)]
957+
pub enum FieldAstId {
958+
Record(FileAstId<ast::RecordField>),
959+
Tuple(FileAstId<ast::TupleField>),
960+
}
961+
955962
/// A single field of an enum variant or struct
956963
#[derive(Debug, Clone, PartialEq, Eq)]
957964
pub struct Field {
958965
pub name: Name,
959966
pub type_ref: Interned<TypeRef>,
960967
pub visibility: RawVisibilityId,
968+
pub ast_id: FieldAstId,
961969
}

crates/hir-def/src/item_tree/lower.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,8 @@ impl<'a> Ctx<'a> {
184184
let name = field.name()?.as_name();
185185
let visibility = self.lower_visibility(field);
186186
let type_ref = self.lower_type_ref_opt(field.ty());
187-
let res = Field { name, type_ref, visibility };
187+
let ast_id = FieldAstId::Record(self.source_ast_id_map.ast_id(field));
188+
let res = Field { name, type_ref, visibility, ast_id };
188189
Some(res)
189190
}
190191

@@ -203,7 +204,8 @@ impl<'a> Ctx<'a> {
203204
let name = Name::new_tuple_field(idx);
204205
let visibility = self.lower_visibility(field);
205206
let type_ref = self.lower_type_ref_opt(field.ty());
206-
Field { name, type_ref, visibility }
207+
let ast_id = FieldAstId::Tuple(self.source_ast_id_map.ast_id(field));
208+
Field { name, type_ref, visibility, ast_id }
207209
}
208210

209211
fn lower_union(&mut self, union: &ast::Union) -> Option<FileItemTreeId<Union>> {
@@ -247,7 +249,8 @@ impl<'a> Ctx<'a> {
247249
fn lower_variant(&mut self, variant: &ast::Variant) -> Option<Variant> {
248250
let name = variant.name()?.as_name();
249251
let fields = self.lower_fields(&variant.kind());
250-
let res = Variant { name, fields };
252+
let ast_id = self.source_ast_id_map.ast_id(variant);
253+
let res = Variant { name, fields, ast_id };
251254
Some(res)
252255
}
253256

0 commit comments

Comments
 (0)