Skip to content

Commit d416623

Browse files
committed
Adjust block-local impl item visibility rendering
1 parent 83e24fe commit d416623

File tree

3 files changed

+216
-9
lines changed

3 files changed

+216
-9
lines changed

crates/hir/src/display.rs

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,23 @@ use hir_ty::{
1717
};
1818

1919
use crate::{
20-
Adt, Const, ConstParam, Enum, Field, Function, GenericParam, HasCrate, HasVisibility,
21-
LifetimeParam, Macro, Module, Static, Struct, Trait, TyBuilder, Type, TypeAlias,
22-
TypeOrConstParam, TypeParam, Union, Variant,
20+
Adt, AsAssocItem, AssocItemContainer, Const, ConstParam, Enum, Field, Function, GenericParam,
21+
HasCrate, HasVisibility, LifetimeParam, Macro, Module, Static, Struct, Trait, TyBuilder, Type,
22+
TypeAlias, TypeOrConstParam, TypeParam, Union, Variant,
2323
};
2424

2525
impl HirDisplay for Function {
2626
fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
27-
let data = f.db.function_data(self.id);
28-
write_visibility(self.module(f.db).id, self.visibility(f.db), f)?;
27+
let db = f.db;
28+
let data = db.function_data(self.id);
29+
let container = self.as_assoc_item(db).map(|it| it.container(db));
30+
let mut module = self.module(db);
31+
if let Some(AssocItemContainer::Impl(_)) = container {
32+
// Block-local impls are "hoisted" to the nearest (non-block) module.
33+
module = module.nearest_non_block_module(db);
34+
}
35+
let module_id = module.id;
36+
write_visibility(module_id, self.visibility(db), f)?;
2937
if data.has_default_kw() {
3038
f.write_str("default ")?;
3139
}
@@ -35,7 +43,7 @@ impl HirDisplay for Function {
3543
if data.has_async_kw() {
3644
f.write_str("async ")?;
3745
}
38-
if self.is_unsafe_to_call(f.db) {
46+
if self.is_unsafe_to_call(db) {
3947
f.write_str("unsafe ")?;
4048
}
4149
if let Some(abi) = &data.abi {
@@ -442,8 +450,15 @@ fn write_where_clause(def: GenericDefId, f: &mut HirFormatter<'_>) -> Result<(),
442450

443451
impl HirDisplay for Const {
444452
fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
445-
write_visibility(self.module(f.db).id, self.visibility(f.db), f)?;
446-
let data = f.db.const_data(self.id);
453+
let db = f.db;
454+
let container = self.as_assoc_item(db).map(|it| it.container(db));
455+
let mut module = self.module(db);
456+
if let Some(AssocItemContainer::Impl(_)) = container {
457+
// Block-local impls are "hoisted" to the nearest (non-block) module.
458+
module = module.nearest_non_block_module(db);
459+
}
460+
write_visibility(module.id, self.visibility(db), f)?;
461+
let data = db.const_data(self.id);
447462
f.write_str("const ")?;
448463
match &data.name {
449464
Some(name) => write!(f, "{name}: ")?,

crates/hir/src/lib.rs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ use hir_def::{
4646
item_tree::ItemTreeNode,
4747
lang_item::{LangItem, LangItemTarget},
4848
layout::{Layout, LayoutError, ReprOptions},
49-
nameres::{self, diagnostics::DefDiagnostic},
49+
nameres::{self, diagnostics::DefDiagnostic, ModuleOrigin},
5050
per_ns::PerNs,
5151
resolver::{HasResolver, Resolver},
5252
src::HasSource as _,
@@ -488,6 +488,20 @@ impl Module {
488488
Some(Module { id: def_map.module_id(parent_id) })
489489
}
490490

491+
/// Finds nearest non-block ancestor `Module` (`self` included).
492+
fn nearest_non_block_module(self, db: &dyn HirDatabase) -> Module {
493+
let mut id = self.id;
494+
loop {
495+
let def_map = id.def_map(db.upcast());
496+
let origin = def_map[id.local_id].origin;
497+
if matches!(origin, ModuleOrigin::BlockExpr { .. }) {
498+
id = id.containing_module(db.upcast()).expect("block without parent module")
499+
} else {
500+
return Module { id };
501+
}
502+
}
503+
}
504+
491505
pub fn path_to_root(self, db: &dyn HirDatabase) -> Vec<Module> {
492506
let mut res = vec![self];
493507
let mut curr = self;

crates/ide/src/hover/tests.rs

Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5647,3 +5647,181 @@ fn main() {
56475647
"#]],
56485648
);
56495649
}
5650+
5651+
#[test]
5652+
fn assoc_fn_in_block_local_impl() {
5653+
check(
5654+
r#"
5655+
struct S;
5656+
mod m {
5657+
const _: () = {
5658+
impl crate::S {
5659+
pub(crate) fn foo() {}
5660+
}
5661+
};
5662+
}
5663+
fn test() {
5664+
S::foo$0();
5665+
}
5666+
"#,
5667+
expect![[r#"
5668+
*foo*
5669+
5670+
```rust
5671+
test::S
5672+
```
5673+
5674+
```rust
5675+
pub(crate) fn foo()
5676+
```
5677+
"#]],
5678+
);
5679+
5680+
check(
5681+
r#"
5682+
struct S;
5683+
mod m {
5684+
const _: () = {
5685+
const _: () = {
5686+
impl crate::S {
5687+
pub(crate) fn foo() {}
5688+
}
5689+
};
5690+
};
5691+
}
5692+
fn test() {
5693+
S::foo$0();
5694+
}
5695+
"#,
5696+
expect![[r#"
5697+
*foo*
5698+
5699+
```rust
5700+
test::S
5701+
```
5702+
5703+
```rust
5704+
pub(crate) fn foo()
5705+
```
5706+
"#]],
5707+
);
5708+
5709+
check(
5710+
r#"
5711+
struct S;
5712+
mod m {
5713+
mod inner {
5714+
const _: () = {
5715+
impl crate::S {
5716+
pub(super) fn foo() {}
5717+
}
5718+
};
5719+
}
5720+
5721+
fn test() {
5722+
crate::S::foo$0();
5723+
}
5724+
}
5725+
"#,
5726+
expect![[r#"
5727+
*foo*
5728+
5729+
```rust
5730+
test::S
5731+
```
5732+
5733+
```rust
5734+
pub(super) fn foo()
5735+
```
5736+
"#]],
5737+
);
5738+
}
5739+
5740+
#[test]
5741+
fn assoc_const_in_block_local_impl() {
5742+
check(
5743+
r#"
5744+
struct S;
5745+
mod m {
5746+
const _: () = {
5747+
impl crate::S {
5748+
pub(crate) const A: () = ();
5749+
}
5750+
};
5751+
}
5752+
fn test() {
5753+
S::A$0;
5754+
}
5755+
"#,
5756+
expect![[r#"
5757+
*A*
5758+
5759+
```rust
5760+
test
5761+
```
5762+
5763+
```rust
5764+
pub(crate) const A: () = ()
5765+
```
5766+
"#]],
5767+
);
5768+
5769+
check(
5770+
r#"
5771+
struct S;
5772+
mod m {
5773+
const _: () = {
5774+
const _: () = {
5775+
impl crate::S {
5776+
pub(crate) const A: () = ();
5777+
}
5778+
};
5779+
};
5780+
}
5781+
fn test() {
5782+
S::A$0;
5783+
}
5784+
"#,
5785+
expect![[r#"
5786+
*A*
5787+
5788+
```rust
5789+
test
5790+
```
5791+
5792+
```rust
5793+
pub(crate) const A: () = ()
5794+
```
5795+
"#]],
5796+
);
5797+
5798+
check(
5799+
r#"
5800+
struct S;
5801+
mod m {
5802+
mod inner {
5803+
const _: () = {
5804+
impl crate::S {
5805+
pub(super) const A: () = ();
5806+
}
5807+
};
5808+
}
5809+
5810+
fn test() {
5811+
crate::S::A$0;
5812+
}
5813+
}
5814+
"#,
5815+
expect![[r#"
5816+
*A*
5817+
5818+
```rust
5819+
test
5820+
```
5821+
5822+
```rust
5823+
pub(super) const A: () = ()
5824+
```
5825+
"#]],
5826+
);
5827+
}

0 commit comments

Comments
 (0)