Skip to content

Commit 7ade4d4

Browse files
committed
Auto merge of rust-lang#12517 - xuhongxu96:master, r=Veykril
fix methods in pub trait generated by macro cannot be completed Fix rust-lang#12483 Check if the container is trait and inherit the visibility to associate items during collection.
2 parents 519d748 + 534d71a commit 7ade4d4

File tree

6 files changed

+252
-84
lines changed

6 files changed

+252
-84
lines changed

crates/hir-def/src/data.rs

+18-3
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,11 @@ impl FunctionData {
4040
let cfg_options = &crate_graph[krate].cfg_options;
4141
let item_tree = loc.id.item_tree(db);
4242
let func = &item_tree[loc.id.value];
43+
let visibility = if let ItemContainerId::TraitId(trait_id) = loc.container {
44+
db.trait_data(trait_id).visibility.clone()
45+
} else {
46+
item_tree[func.visibility].clone()
47+
};
4348

4449
let enabled_params = func
4550
.params
@@ -93,7 +98,7 @@ impl FunctionData {
9398
ret_type: func.ret_type.clone(),
9499
async_ret_type: func.async_ret_type.clone(),
95100
attrs: item_tree.attrs(db, krate, ModItem::from(loc.id.value).into()),
96-
visibility: item_tree[func.visibility].clone(),
101+
visibility,
97102
abi: func.abi.clone(),
98103
legacy_const_generics_indices,
99104
flags,
@@ -171,11 +176,16 @@ impl TypeAliasData {
171176
let loc = typ.lookup(db);
172177
let item_tree = loc.id.item_tree(db);
173178
let typ = &item_tree[loc.id.value];
179+
let visibility = if let ItemContainerId::TraitId(trait_id) = loc.container {
180+
db.trait_data(trait_id).visibility.clone()
181+
} else {
182+
item_tree[typ.visibility].clone()
183+
};
174184

175185
Arc::new(TypeAliasData {
176186
name: typ.name.clone(),
177187
type_ref: typ.type_ref.clone(),
178-
visibility: item_tree[typ.visibility].clone(),
188+
visibility,
179189
is_extern: matches!(loc.container, ItemContainerId::ExternBlockId(_)),
180190
bounds: typ.bounds.to_vec(),
181191
})
@@ -385,11 +395,16 @@ impl ConstData {
385395
let loc = konst.lookup(db);
386396
let item_tree = loc.id.item_tree(db);
387397
let konst = &item_tree[loc.id.value];
398+
let visibility = if let ItemContainerId::TraitId(trait_id) = loc.container {
399+
db.trait_data(trait_id).visibility.clone()
400+
} else {
401+
item_tree[konst.visibility].clone()
402+
};
388403

389404
Arc::new(ConstData {
390405
name: konst.name.clone(),
391406
type_ref: konst.type_ref.clone(),
392-
visibility: item_tree[konst.visibility].clone(),
407+
visibility,
393408
})
394409
}
395410
}

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

+14-38
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! AST -> `ItemTree` lowering code.
22
3-
use std::{collections::hash_map::Entry, mem, sync::Arc};
3+
use std::{collections::hash_map::Entry, sync::Arc};
44

55
use hir_expand::{ast_id_map::AstIdMap, hygiene::Hygiene, HirFileId};
66
use syntax::ast::{self, HasModuleItem};
@@ -21,7 +21,6 @@ pub(super) struct Ctx<'a> {
2121
tree: ItemTree,
2222
source_ast_id_map: Arc<AstIdMap>,
2323
body_ctx: crate::body::LowerCtx<'a>,
24-
forced_visibility: Option<RawVisibilityId>,
2524
}
2625

2726
impl<'a> Ctx<'a> {
@@ -31,7 +30,6 @@ impl<'a> Ctx<'a> {
3130
tree: ItemTree::default(),
3231
source_ast_id_map: db.ast_id_map(file),
3332
body_ctx: crate::body::LowerCtx::new(db, file),
34-
forced_visibility: None,
3533
}
3634
}
3735

@@ -225,11 +223,10 @@ impl<'a> Ctx<'a> {
225223
let visibility = self.lower_visibility(enum_);
226224
let name = enum_.name()?.as_name();
227225
let generic_params = self.lower_generic_params(GenericsOwner::Enum, enum_);
228-
let variants =
229-
self.with_inherited_visibility(visibility, |this| match &enum_.variant_list() {
230-
Some(variant_list) => this.lower_variants(variant_list),
231-
None => IdxRange::new(this.next_variant_idx()..this.next_variant_idx()),
232-
});
226+
let variants = match &enum_.variant_list() {
227+
Some(variant_list) => self.lower_variants(variant_list),
228+
None => IdxRange::new(self.next_variant_idx()..self.next_variant_idx()),
229+
};
233230
let ast_id = self.source_ast_id_map.ast_id(enum_);
234231
let res = Enum { name, visibility, generic_params, variants, ast_id };
235232
Some(id(self.data().enums.alloc(res)))
@@ -440,18 +437,15 @@ impl<'a> Ctx<'a> {
440437
let is_auto = trait_def.auto_token().is_some();
441438
let is_unsafe = trait_def.unsafe_token().is_some();
442439
let items = trait_def.assoc_item_list().map(|list| {
443-
let db = self.db;
444-
self.with_inherited_visibility(visibility, |this| {
445-
list.assoc_items()
446-
.filter_map(|item| {
447-
let attrs = RawAttrs::new(db, &item, this.hygiene());
448-
this.lower_assoc_item(&item).map(|item| {
449-
this.add_attrs(ModItem::from(item).into(), attrs);
450-
item
451-
})
440+
list.assoc_items()
441+
.filter_map(|item| {
442+
let attrs = RawAttrs::new(self.db, &item, self.hygiene());
443+
self.lower_assoc_item(&item).map(|item| {
444+
self.add_attrs(ModItem::from(item).into(), attrs);
445+
item
452446
})
453-
.collect()
454-
})
447+
})
448+
.collect()
455449
});
456450
let ast_id = self.source_ast_id_map.ast_id(trait_def);
457451
let res = Trait {
@@ -622,13 +616,7 @@ impl<'a> Ctx<'a> {
622616
}
623617

624618
fn lower_visibility(&mut self, item: &dyn ast::HasVisibility) -> RawVisibilityId {
625-
let vis = match self.forced_visibility {
626-
Some(vis) => return vis,
627-
None => {
628-
RawVisibility::from_ast_with_hygiene(self.db, item.visibility(), self.hygiene())
629-
}
630-
};
631-
619+
let vis = RawVisibility::from_ast_with_hygiene(self.db, item.visibility(), self.hygiene());
632620
self.data().vis.alloc(vis)
633621
}
634622

@@ -649,18 +637,6 @@ impl<'a> Ctx<'a> {
649637
}
650638
}
651639

652-
/// Forces the visibility `vis` to be used for all items lowered during execution of `f`.
653-
fn with_inherited_visibility<R>(
654-
&mut self,
655-
vis: RawVisibilityId,
656-
f: impl FnOnce(&mut Self) -> R,
657-
) -> R {
658-
let old = mem::replace(&mut self.forced_visibility, Some(vis));
659-
let res = f(self);
660-
self.forced_visibility = old;
661-
res
662-
}
663-
664640
fn next_field_idx(&self) -> Idx<Field> {
665641
Idx::from_raw(RawIdx::from(
666642
self.tree.data.as_ref().map_or(0, |data| data.fields.len() as u32),

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

-37
Original file line numberDiff line numberDiff line change
@@ -358,40 +358,3 @@ trait Tr<'a, T: 'a>: Super where Self: for<'a> Tr<'a, T> {}
358358
"#]],
359359
)
360360
}
361-
362-
#[test]
363-
fn inherit_visibility() {
364-
check(
365-
r#"
366-
pub(crate) enum En {
367-
Var1(u8),
368-
Var2 {
369-
fld: u8,
370-
},
371-
}
372-
373-
pub(crate) trait Tr {
374-
fn f();
375-
fn method(&self) {}
376-
}
377-
"#,
378-
expect![[r#"
379-
pub(crate) enum En {
380-
Var1(
381-
pub(crate) 0: u8,
382-
),
383-
Var2 {
384-
pub(crate) fld: u8,
385-
},
386-
}
387-
388-
pub(crate) trait Tr<Self> {
389-
pub(crate) fn f() -> ();
390-
391-
pub(crate) fn method(
392-
_: &Self, // self
393-
) -> () { ... }
394-
}
395-
"#]],
396-
)
397-
}

crates/ide-completion/src/completions/dot.rs

+107-5
Original file line numberDiff line numberDiff line change
@@ -117,13 +117,20 @@ fn complete_methods(
117117
mod tests {
118118
use expect_test::{expect, Expect};
119119

120-
use crate::tests::{check_edit, completion_list_no_kw};
120+
use crate::tests::{
121+
check_edit, completion_list_no_kw, completion_list_no_kw_with_private_editable,
122+
};
121123

122124
fn check(ra_fixture: &str, expect: Expect) {
123125
let actual = completion_list_no_kw(ra_fixture);
124126
expect.assert_eq(&actual);
125127
}
126128

129+
fn check_with_private_editable(ra_fixture: &str, expect: Expect) {
130+
let actual = completion_list_no_kw_with_private_editable(ra_fixture);
131+
expect.assert_eq(&actual);
132+
}
133+
127134
#[test]
128135
fn test_struct_field_and_method_completion() {
129136
check(
@@ -200,6 +207,101 @@ pub mod m {
200207
}
201208
//- /main.rs crate:main deps:lib new_source_root:local
202209
fn foo(a: lib::m::A) { a.$0 }
210+
"#,
211+
expect![[r#"
212+
fd pub_field u32
213+
"#]],
214+
);
215+
216+
check(
217+
r#"
218+
//- /lib.rs crate:lib new_source_root:library
219+
pub mod m {
220+
pub struct A {
221+
private_field: u32,
222+
pub pub_field: u32,
223+
pub(crate) crate_field: u32,
224+
pub(super) super_field: u32,
225+
}
226+
}
227+
//- /main.rs crate:main deps:lib new_source_root:local
228+
fn foo(a: lib::m::A) { a.$0 }
229+
"#,
230+
expect![[r#"
231+
fd pub_field u32
232+
"#]],
233+
);
234+
235+
check(
236+
r#"
237+
//- /lib.rs crate:lib new_source_root:library
238+
pub mod m {
239+
pub struct A(
240+
i32,
241+
pub f64,
242+
);
243+
}
244+
//- /main.rs crate:main deps:lib new_source_root:local
245+
fn foo(a: lib::m::A) { a.$0 }
246+
"#,
247+
expect![[r#"
248+
fd 1 f64
249+
"#]],
250+
);
251+
252+
check(
253+
r#"
254+
//- /lib.rs crate:lib new_source_root:local
255+
pub struct A {}
256+
mod m {
257+
impl super::A {
258+
fn private_method(&self) {}
259+
pub(crate) fn crate_method(&self) {}
260+
pub fn pub_method(&self) {}
261+
}
262+
}
263+
//- /main.rs crate:main deps:lib new_source_root:local
264+
fn foo(a: lib::A) { a.$0 }
265+
"#,
266+
expect![[r#"
267+
me pub_method() fn(&self)
268+
"#]],
269+
);
270+
check(
271+
r#"
272+
//- /lib.rs crate:lib new_source_root:library
273+
pub struct A {}
274+
mod m {
275+
impl super::A {
276+
fn private_method(&self) {}
277+
pub(crate) fn crate_method(&self) {}
278+
pub fn pub_method(&self) {}
279+
}
280+
}
281+
//- /main.rs crate:main deps:lib new_source_root:local
282+
fn foo(a: lib::A) { a.$0 }
283+
"#,
284+
expect![[r#"
285+
me pub_method() fn(&self)
286+
"#]],
287+
);
288+
}
289+
290+
#[test]
291+
fn test_visibility_filtering_with_private_editable_enabled() {
292+
check_with_private_editable(
293+
r#"
294+
//- /lib.rs crate:lib new_source_root:local
295+
pub mod m {
296+
pub struct A {
297+
private_field: u32,
298+
pub pub_field: u32,
299+
pub(crate) crate_field: u32,
300+
pub(super) super_field: u32,
301+
}
302+
}
303+
//- /main.rs crate:main deps:lib new_source_root:local
304+
fn foo(a: lib::m::A) { a.$0 }
203305
"#,
204306
expect![[r#"
205307
fd crate_field u32
@@ -209,7 +311,7 @@ fn foo(a: lib::m::A) { a.$0 }
209311
"#]],
210312
);
211313

212-
check(
314+
check_with_private_editable(
213315
r#"
214316
//- /lib.rs crate:lib new_source_root:library
215317
pub mod m {
@@ -228,7 +330,7 @@ fn foo(a: lib::m::A) { a.$0 }
228330
"#]],
229331
);
230332

231-
check(
333+
check_with_private_editable(
232334
r#"
233335
//- /lib.rs crate:lib new_source_root:library
234336
pub mod m {
@@ -245,7 +347,7 @@ fn foo(a: lib::m::A) { a.$0 }
245347
"#]],
246348
);
247349

248-
check(
350+
check_with_private_editable(
249351
r#"
250352
//- /lib.rs crate:lib new_source_root:local
251353
pub struct A {}
@@ -265,7 +367,7 @@ fn foo(a: lib::A) { a.$0 }
265367
me pub_method() fn(&self)
266368
"#]],
267369
);
268-
check(
370+
check_with_private_editable(
269371
r#"
270372
//- /lib.rs crate:lib new_source_root:library
271373
pub struct A {}

crates/ide-completion/src/tests.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ pub(crate) const TEST_CONFIG: CompletionConfig = CompletionConfig {
6565
enable_postfix_completions: true,
6666
enable_imports_on_the_fly: true,
6767
enable_self_on_the_fly: true,
68-
enable_private_editable: true,
68+
enable_private_editable: false,
6969
callable: Some(CallableSnippets::FillArguments),
7070
snippet_cap: SnippetCap::new(true),
7171
insert_use: InsertUseConfig {
@@ -86,6 +86,12 @@ pub(crate) fn completion_list_no_kw(ra_fixture: &str) -> String {
8686
completion_list_with_config(TEST_CONFIG, ra_fixture, false, None)
8787
}
8888

89+
pub(crate) fn completion_list_no_kw_with_private_editable(ra_fixture: &str) -> String {
90+
let mut config = TEST_CONFIG.clone();
91+
config.enable_private_editable = true;
92+
completion_list_with_config(config, ra_fixture, false, None)
93+
}
94+
8995
pub(crate) fn completion_list_with_trigger_character(
9096
ra_fixture: &str,
9197
trigger_character: Option<char>,

0 commit comments

Comments
 (0)