Skip to content

Commit 0fa822d

Browse files
committed
Auto merge of rust-lang#15418 - oxalica:fix/sig-from-macro, r=Veykril
Fix signature help of methods from macros Currently the receiver type is copied from AST instead re-formatting through `HirDisplay`. Macro generated functions seem to have no spaces and their signature help are rendered like `fn foo(&'amutself)` instead of `fn foo(&'a mut self)`.
2 parents 2fbe69d + de86444 commit 0fa822d

File tree

4 files changed

+63
-42
lines changed

4 files changed

+63
-42
lines changed

crates/hir/src/display.rs

+36-27
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ use hir_def::{
88
type_ref::{TypeBound, TypeRef},
99
AdtId, GenericDefId,
1010
};
11-
use hir_expand::name;
1211
use hir_ty::{
1312
display::{
1413
write_bounds_like_dyn_trait_with_prefix, write_visibility, HirDisplay, HirDisplayError,
@@ -19,8 +18,9 @@ use hir_ty::{
1918

2019
use crate::{
2120
Adt, AsAssocItem, AssocItemContainer, Const, ConstParam, Enum, ExternCrateDecl, Field,
22-
Function, GenericParam, HasCrate, HasVisibility, LifetimeParam, Macro, Module, Static, Struct,
23-
Trait, TraitAlias, TyBuilder, Type, TypeAlias, TypeOrConstParam, TypeParam, Union, Variant,
21+
Function, GenericParam, HasCrate, HasVisibility, LifetimeParam, Macro, Module, SelfParam,
22+
Static, Struct, Trait, TraitAlias, TyBuilder, Type, TypeAlias, TypeOrConstParam, TypeParam,
23+
Union, Variant,
2424
};
2525

2626
impl HirDisplay for Function {
@@ -57,37 +57,21 @@ impl HirDisplay for Function {
5757

5858
f.write_char('(')?;
5959

60-
let write_self_param = |ty: &TypeRef, f: &mut HirFormatter<'_>| match ty {
61-
TypeRef::Path(p) if p.is_self_type() => f.write_str("self"),
62-
TypeRef::Reference(inner, lifetime, mut_) if matches!(&**inner, TypeRef::Path(p) if p.is_self_type()) =>
63-
{
64-
f.write_char('&')?;
65-
if let Some(lifetime) = lifetime {
66-
write!(f, "{} ", lifetime.name.display(f.db.upcast()))?;
67-
}
68-
if let hir_def::type_ref::Mutability::Mut = mut_ {
69-
f.write_str("mut ")?;
70-
}
71-
f.write_str("self")
72-
}
73-
_ => {
74-
f.write_str("self: ")?;
75-
ty.hir_fmt(f)
76-
}
77-
};
78-
7960
let mut first = true;
61+
let mut skip_self = 0;
62+
if let Some(self_param) = self.self_param(db) {
63+
self_param.hir_fmt(f)?;
64+
first = false;
65+
skip_self = 1;
66+
}
67+
8068
// FIXME: Use resolved `param.ty` once we no longer discard lifetimes
81-
for (type_ref, param) in data.params.iter().zip(self.assoc_fn_params(db)) {
69+
for (type_ref, param) in data.params.iter().zip(self.assoc_fn_params(db)).skip(skip_self) {
8270
let local = param.as_local(db).map(|it| it.name(db));
8371
if !first {
8472
f.write_str(", ")?;
8573
} else {
8674
first = false;
87-
if local == Some(name!(self)) {
88-
write_self_param(type_ref, f)?;
89-
continue;
90-
}
9175
}
9276
match local {
9377
Some(name) => write!(f, "{}: ", name.display(f.db.upcast()))?,
@@ -137,6 +121,31 @@ impl HirDisplay for Function {
137121
}
138122
}
139123

124+
impl HirDisplay for SelfParam {
125+
fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
126+
let data = f.db.function_data(self.func);
127+
let param = data.params.first().unwrap();
128+
match &**param {
129+
TypeRef::Path(p) if p.is_self_type() => f.write_str("self"),
130+
TypeRef::Reference(inner, lifetime, mut_) if matches!(&**inner, TypeRef::Path(p) if p.is_self_type()) =>
131+
{
132+
f.write_char('&')?;
133+
if let Some(lifetime) = lifetime {
134+
write!(f, "{} ", lifetime.name.display(f.db.upcast()))?;
135+
}
136+
if let hir_def::type_ref::Mutability::Mut = mut_ {
137+
f.write_str("mut ")?;
138+
}
139+
f.write_str("self")
140+
}
141+
ty => {
142+
f.write_str("self: ")?;
143+
ty.hir_fmt(f)
144+
}
145+
}
146+
}
147+
}
148+
140149
impl HirDisplay for Adt {
141150
fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
142151
match self {

crates/hir/src/lib.rs

+3-12
Original file line numberDiff line numberDiff line change
@@ -2090,14 +2090,6 @@ impl SelfParam {
20902090
.unwrap_or(Access::Owned)
20912091
}
20922092

2093-
pub fn display(self, db: &dyn HirDatabase) -> &'static str {
2094-
match self.access(db) {
2095-
Access::Shared => "&self",
2096-
Access::Exclusive => "&mut self",
2097-
Access::Owned => "self",
2098-
}
2099-
}
2100-
21012093
pub fn source(&self, db: &dyn HirDatabase) -> Option<InFile<ast::SelfParam>> {
21022094
let InFile { file_id, value } = Function::from(self.func).source(db)?;
21032095
value
@@ -4406,14 +4398,13 @@ impl Callable {
44064398
Other => CallableKind::Other,
44074399
}
44084400
}
4409-
pub fn receiver_param(&self, db: &dyn HirDatabase) -> Option<(ast::SelfParam, Type)> {
4401+
pub fn receiver_param(&self, db: &dyn HirDatabase) -> Option<(SelfParam, Type)> {
44104402
let func = match self.callee {
44114403
Callee::Def(CallableDefId::FunctionId(it)) if self.is_bound_method => it,
44124404
_ => return None,
44134405
};
4414-
let src = func.lookup(db.upcast()).source(db.upcast());
4415-
let param_list = src.value.param_list()?;
4416-
Some((param_list.self_param()?, self.ty.derived(self.sig.params()[0].clone())))
4406+
let func = Function { id: func };
4407+
Some((func.self_param(db)?, self.ty.derived(self.sig.params()[0].clone())))
44174408
}
44184409
pub fn n_params(&self) -> usize {
44194410
self.sig.params().len() - if self.is_bound_method { 1 } else { 0 }

crates/ide-ssr/src/matching.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -560,8 +560,10 @@ impl<'db, 'sema> Matcher<'db, 'sema> {
560560
placeholder_value.autoref_kind = self
561561
.sema
562562
.resolve_method_call_as_callable(code)
563-
.and_then(|callable| callable.receiver_param(self.sema.db))
564-
.map(|(self_param, _)| self_param.kind())
563+
.and_then(|callable| {
564+
let (self_param, _) = callable.receiver_param(self.sema.db)?;
565+
Some(self_param.source(self.sema.db)?.value.kind())
566+
})
565567
.unwrap_or(ast::SelfParamKind::Owned);
566568
}
567569
}

crates/ide/src/signature_help.rs

+20-1
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ fn signature_help_for_call(
202202
res.signature.push('(');
203203
{
204204
if let Some((self_param, _)) = callable.receiver_param(db) {
205-
format_to!(res.signature, "{}", self_param)
205+
format_to!(res.signature, "{}", self_param.display(db))
206206
}
207207
let mut buf = String::new();
208208
for (idx, (pat, ty)) in callable.params(db).into_iter().enumerate() {
@@ -1314,6 +1314,25 @@ id! {
13141314
);
13151315
}
13161316

1317+
#[test]
1318+
fn fn_signature_for_method_call_defined_in_macro() {
1319+
check(
1320+
r#"
1321+
macro_rules! id { ($($tt:tt)*) => { $($tt)* } }
1322+
struct S;
1323+
id! {
1324+
impl S {
1325+
fn foo<'a>(&'a mut self) {}
1326+
}
1327+
}
1328+
fn test() { S.foo($0); }
1329+
"#,
1330+
expect![[r#"
1331+
fn foo(&'a mut self)
1332+
"#]],
1333+
);
1334+
}
1335+
13171336
#[test]
13181337
fn call_info_for_lambdas() {
13191338
check(

0 commit comments

Comments
 (0)