Skip to content

Commit 8b6216d

Browse files
committed
Support macro for trait items
1 parent 2474f42 commit 8b6216d

File tree

2 files changed

+88
-101
lines changed

2 files changed

+88
-101
lines changed

crates/ra_hir_def/src/data.rs

Lines changed: 67 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -150,51 +150,31 @@ pub struct TraitData {
150150

151151
impl TraitData {
152152
pub(crate) fn trait_data_query(db: &dyn DefDatabase, tr: TraitId) -> Arc<TraitData> {
153-
let src = tr.lookup(db).source(db);
153+
let tr_loc = tr.lookup(db);
154+
let src = tr_loc.source(db);
154155
let name = src.value.name().map_or_else(Name::missing, |n| n.as_name());
155156
let auto = src.value.auto_token().is_some();
156-
let ast_id_map = db.ast_id_map(src.file_id);
157+
let module_id = tr_loc.container.module(db);
157158

158159
let container = AssocContainerId::TraitId(tr);
159-
let items = if let Some(item_list) = src.value.item_list() {
160-
item_list
161-
.impl_items()
162-
.map(|item_node| match item_node {
163-
ast::ImplItem::FnDef(it) => {
164-
let name = it.name().map_or_else(Name::missing, |it| it.as_name());
165-
let def = FunctionLoc {
166-
container,
167-
ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)),
168-
}
169-
.intern(db)
170-
.into();
171-
(name, def)
172-
}
173-
ast::ImplItem::ConstDef(it) => {
174-
let name = it.name().map_or_else(Name::missing, |it| it.as_name());
175-
let def = ConstLoc {
176-
container,
177-
ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)),
178-
}
179-
.intern(db)
180-
.into();
181-
(name, def)
182-
}
183-
ast::ImplItem::TypeAliasDef(it) => {
184-
let name = it.name().map_or_else(Name::missing, |it| it.as_name());
185-
let def = TypeAliasLoc {
186-
container,
187-
ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)),
188-
}
189-
.intern(db)
190-
.into();
191-
(name, def)
192-
}
193-
})
194-
.collect()
195-
} else {
196-
Vec::new()
197-
};
160+
let mut items = Vec::new();
161+
162+
if let Some(item_list) = src.value.item_list() {
163+
let mut expander = Expander::new(db, tr_loc.ast_id.file_id, module_id);
164+
items.extend(collect_impl_items(
165+
db,
166+
&mut expander,
167+
item_list.impl_items(),
168+
src.file_id,
169+
container,
170+
));
171+
items.extend(collect_impl_items_in_macros(
172+
db,
173+
&mut expander,
174+
&src.with_value(item_list),
175+
container,
176+
));
177+
}
198178
Arc::new(TraitData { name, items, auto })
199179
}
200180

@@ -232,24 +212,33 @@ impl ImplData {
232212
let target_type = TypeRef::from_ast_opt(&lower_ctx, src.value.target_type());
233213
let is_negative = src.value.excl_token().is_some();
234214
let module_id = impl_loc.container.module(db);
215+
let container = AssocContainerId::ImplId(id);
235216

236-
let mut items = Vec::new();
217+
let mut items: Vec<AssocItemId> = Vec::new();
237218

238219
if let Some(item_list) = src.value.item_list() {
239220
let mut expander = Expander::new(db, impl_loc.ast_id.file_id, module_id);
240-
items.extend(collect_impl_items(
241-
db,
242-
&mut expander,
243-
item_list.impl_items(),
244-
src.file_id,
245-
id,
246-
));
247-
items.extend(collect_impl_items_in_macros(
248-
db,
249-
&mut expander,
250-
&src.with_value(item_list),
251-
id,
252-
));
221+
items.extend(
222+
collect_impl_items(
223+
db,
224+
&mut expander,
225+
item_list.impl_items(),
226+
src.file_id,
227+
container,
228+
)
229+
.into_iter()
230+
.map(|(_, item)| item),
231+
);
232+
items.extend(
233+
collect_impl_items_in_macros(
234+
db,
235+
&mut expander,
236+
&src.with_value(item_list),
237+
container,
238+
)
239+
.into_iter()
240+
.map(|(_, item)| item),
241+
);
253242
}
254243

255244
let res = ImplData { target_trait, target_type, items, is_negative };
@@ -296,15 +285,15 @@ fn collect_impl_items_in_macros(
296285
db: &dyn DefDatabase,
297286
expander: &mut Expander,
298287
impl_def: &InFile<ast::ItemList>,
299-
id: ImplId,
300-
) -> Vec<AssocItemId> {
288+
container: AssocContainerId,
289+
) -> Vec<(Name, AssocItemId)> {
301290
let mut res = Vec::new();
302291

303292
// We set a limit to protect against infinite recursion
304293
let limit = 100;
305294

306295
for m in impl_def.value.syntax().children().filter_map(ast::MacroCall::cast) {
307-
res.extend(collect_impl_items_in_macro(db, expander, m, id, limit))
296+
res.extend(collect_impl_items_in_macro(db, expander, m, container, limit))
308297
}
309298

310299
res
@@ -314,9 +303,9 @@ fn collect_impl_items_in_macro(
314303
db: &dyn DefDatabase,
315304
expander: &mut Expander,
316305
m: ast::MacroCall,
317-
id: ImplId,
306+
container: AssocContainerId,
318307
limit: usize,
319-
) -> Vec<AssocItemId> {
308+
) -> Vec<(Name, AssocItemId)> {
320309
if limit == 0 {
321310
return Vec::new();
322311
}
@@ -328,13 +317,14 @@ fn collect_impl_items_in_macro(
328317
expander,
329318
items.value.items().filter_map(|it| ImplItem::cast(it.syntax().clone())),
330319
items.file_id,
331-
id,
320+
container,
332321
);
322+
333323
// Recursive collect macros
334324
// Note that ast::ModuleItem do not include ast::MacroCall
335325
// We cannot use ModuleItemOwner::items here
336326
for it in items.value.syntax().children().filter_map(ast::MacroCall::cast) {
337-
res.extend(collect_impl_items_in_macro(db, expander, it, id, limit - 1))
327+
res.extend(collect_impl_items_in_macro(db, expander, it, container, limit - 1))
338328
}
339329
expander.exit(db, mark);
340330
res
@@ -348,39 +338,34 @@ fn collect_impl_items(
348338
expander: &mut Expander,
349339
impl_items: impl Iterator<Item = ImplItem>,
350340
file_id: crate::HirFileId,
351-
id: ImplId,
352-
) -> Vec<AssocItemId> {
341+
container: AssocContainerId,
342+
) -> Vec<(Name, AssocItemId)> {
353343
let items = db.ast_id_map(file_id);
354344

355345
impl_items
356346
.filter_map(|item_node| match item_node {
357347
ast::ImplItem::FnDef(it) => {
348+
let name = it.name().map_or_else(Name::missing, |it| it.as_name());
358349
let attrs = expander.parse_attrs(&it);
359350
if !expander.is_cfg_enabled(&attrs) {
360351
return None;
361352
}
362-
let def = FunctionLoc {
363-
container: AssocContainerId::ImplId(id),
364-
ast_id: AstId::new(file_id, items.ast_id(&it)),
365-
}
366-
.intern(db);
367-
Some(def.into())
353+
let def = FunctionLoc { container, ast_id: AstId::new(file_id, items.ast_id(&it)) }
354+
.intern(db);
355+
Some((name, def.into()))
368356
}
369357
ast::ImplItem::ConstDef(it) => {
370-
let def = ConstLoc {
371-
container: AssocContainerId::ImplId(id),
372-
ast_id: AstId::new(file_id, items.ast_id(&it)),
373-
}
374-
.intern(db);
375-
Some(def.into())
358+
let name = it.name().map_or_else(Name::missing, |it| it.as_name());
359+
let def = ConstLoc { container, ast_id: AstId::new(file_id, items.ast_id(&it)) }
360+
.intern(db);
361+
Some((name, def.into()))
376362
}
377363
ast::ImplItem::TypeAliasDef(it) => {
378-
let def = TypeAliasLoc {
379-
container: AssocContainerId::ImplId(id),
380-
ast_id: AstId::new(file_id, items.ast_id(&it)),
381-
}
382-
.intern(db);
383-
Some(def.into())
364+
let name = it.name().map_or_else(Name::missing, |it| it.as_name());
365+
let def =
366+
TypeAliasLoc { container, ast_id: AstId::new(file_id, items.ast_id(&it)) }
367+
.intern(db);
368+
Some((name, def.into()))
384369
}
385370
})
386371
.collect()

crates/ra_hir_ty/src/tests/traits.rs

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2055,7 +2055,7 @@ fn test<I: Iterator<Item: Iterator<Item = u32>>>() {
20552055
#[test]
20562056
fn proc_macro_server_types() {
20572057
assert_snapshot!(
2058-
infer_with_mismatches(r#"
2058+
infer(r#"
20592059
macro_rules! with_api {
20602060
($S:ident, $self:ident, $m:ident) => {
20612061
$m! {
@@ -2069,9 +2069,9 @@ macro_rules! with_api {
20692069
}
20702070
macro_rules! associated_item {
20712071
(type TokenStream) =>
2072-
(type TokenStream: 'static + Clone;);
2072+
(type TokenStream: 'static;);
20732073
(type Group) =>
2074-
(type Group: 'static + Clone;);
2074+
(type Group: 'static;);
20752075
($($item:tt)*) => ($($item)*;)
20762076
}
20772077
macro_rules! declare_server_traits {
@@ -2083,39 +2083,41 @@ macro_rules! declare_server_traits {
20832083
}
20842084
20852085
$(pub trait $name: Types {
2086-
$(associated_item!(fn $method(&mut self, $($arg: $arg_ty),*) $(-> $ret_ty)?);)*
2086+
$(associated_item!(fn $method($($arg: $arg_ty),*) $(-> $ret_ty)?);)*
20872087
})*
20882088
20892089
pub trait Server: Types $(+ $name)* {}
20902090
impl<S: Types $(+ $name)*> Server for S {}
20912091
}
20922092
}
2093+
20932094
with_api!(Self, self_, declare_server_traits);
2094-
struct Group {}
2095-
struct TokenStream {}
2095+
struct G {}
2096+
struct T {}
20962097
struct Rustc;
20972098
impl Types for Rustc {
2098-
type TokenStream = TokenStream;
2099-
type Group = Group;
2099+
type TokenStream = T;
2100+
type Group = G;
21002101
}
2102+
21012103
fn make<T>() -> T { loop {} }
21022104
impl TokenStream for Rustc {
21032105
fn new() -> Self::TokenStream {
21042106
let group: Self::Group = make();
21052107
make()
21062108
}
2107-
}
2108-
"#, true),
2109+
}
2110+
"#),
21092111
@r###"
2110-
1115..1126 '{ loop {} }': T
2111-
1117..1124 'loop {}': !
2112-
1122..1124 '{}': ()
2113-
1190..1253 '{ ... }': {unknown}
2114-
1204..1209 'group': {unknown}
2115-
1225..1229 'make': fn make<{unknown}>() -> {unknown}
2116-
1225..1231 'make()': {unknown}
2117-
1241..1245 'make': fn make<{unknown}>() -> {unknown}
2118-
1241..1247 'make()': {unknown}
2112+
1062..1073 '{ loop {} }': T
2113+
1064..1071 'loop {}': !
2114+
1069..1071 '{}': ()
2115+
1137..1200 '{ ... }': T
2116+
1151..1156 'group': G
2117+
1172..1176 'make': fn make<G>() -> G
2118+
1172..1178 'make()': G
2119+
1188..1192 'make': fn make<T>() -> T
2120+
1188..1194 'make()': T
21192121
"###
21202122
);
21212123
}

0 commit comments

Comments
 (0)