Skip to content

Commit c423738

Browse files
Merge #6189
6189: adt: correctly inherit field visibility from enum r=jonas-schievink a=jonas-schievink Previously, "find all references" on a variant field wouldn't find any references outside the defining module. This is because variant fields were incorrectly assumed to be private, like struct fields without explicit visibility, but they actually inherit the enum's visibility. bors r+ 🤖 Co-authored-by: Jonas Schievink <[email protected]>
2 parents cde189c + 5dcbf03 commit c423738

File tree

3 files changed

+47
-15
lines changed

3 files changed

+47
-15
lines changed

crates/assists/src/handlers/fix_visibility.rs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -324,23 +324,21 @@ pub struct Foo { pub bar: () }
324324

325325
#[test]
326326
fn fix_visibility_of_enum_variant_field() {
327-
check_assist(
327+
// Enum variants, as well as their fields, always get the enum's visibility. In fact, rustc
328+
// rejects any visibility specifiers on them, so this assist should never fire on them.
329+
check_assist_not_applicable(
328330
fix_visibility,
329331
r"mod foo { pub enum Foo { Bar { bar: () } } }
330332
fn main() { foo::Foo::Bar { <|>bar: () }; } ",
331-
r"mod foo { pub enum Foo { Bar { $0pub(crate) bar: () } } }
332-
fn main() { foo::Foo::Bar { bar: () }; } ",
333333
);
334-
check_assist(
334+
check_assist_not_applicable(
335335
fix_visibility,
336336
r"
337337
//- /lib.rs
338338
mod foo;
339339
fn main() { foo::Foo::Bar { <|>bar: () }; }
340340
//- /foo.rs
341341
pub enum Foo { Bar { bar: () } }
342-
",
343-
r"pub enum Foo { Bar { $0pub(crate) bar: () } }
344342
",
345343
);
346344
check_assist_not_applicable(

crates/hir_def/src/adt.rs

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use tt::{Delimiter, DelimiterKind, Leaf, Subtree, TokenTree};
1414
use crate::{
1515
body::{CfgExpander, LowerCtx},
1616
db::DefDatabase,
17-
item_tree::{AttrOwner, Field, Fields, ItemTree, ModItem},
17+
item_tree::{AttrOwner, Field, Fields, ItemTree, ModItem, RawVisibilityId},
1818
src::HasChildSource,
1919
src::HasSource,
2020
trace::Trace,
@@ -91,7 +91,7 @@ impl StructData {
9191
let cfg_options = db.crate_graph()[loc.container.module(db).krate].cfg_options.clone();
9292

9393
let strukt = &item_tree[loc.id.value];
94-
let variant_data = lower_fields(&item_tree, &cfg_options, &strukt.fields);
94+
let variant_data = lower_fields(&item_tree, &cfg_options, &strukt.fields, None);
9595
Arc::new(StructData {
9696
name: strukt.name.clone(),
9797
variant_data: Arc::new(variant_data),
@@ -105,7 +105,7 @@ impl StructData {
105105
let cfg_options = db.crate_graph()[loc.container.module(db).krate].cfg_options.clone();
106106

107107
let union = &item_tree[loc.id.value];
108-
let variant_data = lower_fields(&item_tree, &cfg_options, &union.fields);
108+
let variant_data = lower_fields(&item_tree, &cfg_options, &union.fields, None);
109109

110110
Arc::new(StructData {
111111
name: union.name.clone(),
@@ -126,7 +126,8 @@ impl EnumData {
126126
for var_id in enum_.variants.clone() {
127127
if item_tree.attrs(var_id.into()).is_cfg_enabled(&cfg_options) {
128128
let var = &item_tree[var_id];
129-
let var_data = lower_fields(&item_tree, &cfg_options, &var.fields);
129+
let var_data =
130+
lower_fields(&item_tree, &cfg_options, &var.fields, Some(enum_.visibility));
130131

131132
variants.alloc(EnumVariantData {
132133
name: var.name.clone(),
@@ -296,13 +297,18 @@ fn lower_struct(
296297
}
297298
}
298299

299-
fn lower_fields(item_tree: &ItemTree, cfg_options: &CfgOptions, fields: &Fields) -> VariantData {
300+
fn lower_fields(
301+
item_tree: &ItemTree,
302+
cfg_options: &CfgOptions,
303+
fields: &Fields,
304+
override_visibility: Option<RawVisibilityId>,
305+
) -> VariantData {
300306
match fields {
301307
Fields::Record(flds) => {
302308
let mut arena = Arena::new();
303309
for field_id in flds.clone() {
304310
if item_tree.attrs(field_id.into()).is_cfg_enabled(cfg_options) {
305-
arena.alloc(lower_field(item_tree, &item_tree[field_id]));
311+
arena.alloc(lower_field(item_tree, &item_tree[field_id], override_visibility));
306312
}
307313
}
308314
VariantData::Record(arena)
@@ -311,7 +317,7 @@ fn lower_fields(item_tree: &ItemTree, cfg_options: &CfgOptions, fields: &Fields)
311317
let mut arena = Arena::new();
312318
for field_id in flds.clone() {
313319
if item_tree.attrs(field_id.into()).is_cfg_enabled(cfg_options) {
314-
arena.alloc(lower_field(item_tree, &item_tree[field_id]));
320+
arena.alloc(lower_field(item_tree, &item_tree[field_id], override_visibility));
315321
}
316322
}
317323
VariantData::Tuple(arena)
@@ -320,10 +326,14 @@ fn lower_fields(item_tree: &ItemTree, cfg_options: &CfgOptions, fields: &Fields)
320326
}
321327
}
322328

323-
fn lower_field(item_tree: &ItemTree, field: &Field) -> FieldData {
329+
fn lower_field(
330+
item_tree: &ItemTree,
331+
field: &Field,
332+
override_visibility: Option<RawVisibilityId>,
333+
) -> FieldData {
324334
FieldData {
325335
name: field.name.clone(),
326336
type_ref: field.type_ref.clone(),
327-
visibility: item_tree[field.visibility].clone(),
337+
visibility: item_tree[override_visibility.unwrap_or(field.visibility)].clone(),
328338
}
329339
}

crates/ide/src/references.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -732,6 +732,30 @@ fn f(e: En) {
732732
);
733733
}
734734

735+
#[test]
736+
fn test_find_all_refs_enum_var_privacy() {
737+
check(
738+
r#"
739+
mod m {
740+
pub enum En {
741+
Variant {
742+
field<|>: u8,
743+
}
744+
}
745+
}
746+
747+
fn f() -> m::En {
748+
m::En::Variant { field: 0 }
749+
}
750+
"#,
751+
expect![[r#"
752+
field RECORD_FIELD FileId(0) 56..65 56..61 Other
753+
754+
FileId(0) 125..130 Other Read
755+
"#]],
756+
);
757+
}
758+
735759
fn check(ra_fixture: &str, expect: Expect) {
736760
check_with_scope(ra_fixture, None, expect)
737761
}

0 commit comments

Comments
 (0)