Skip to content

Commit 57f285d

Browse files
bors[bot]edwin0chengedwin0minv
authored
Merge #4283
4283: Support macro for trait items r=matklad a=edwin0cheng Fixed #4039 r? @flodiebold Co-authored-by: Edwin Cheng <edwin0cheng@gmail.com> Co-authored-by: Edwin Cheng <edwin@m-inverse.com>
2 parents b1a5dc8 + 5899c8e commit 57f285d

File tree

2 files changed

+80
-104
lines changed

2 files changed

+80
-104
lines changed

crates/ra_hir_def/src/data.rs

Lines changed: 60 additions & 86 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_items(
165+
db,
166+
&mut expander,
167+
item_list.impl_items(),
168+
src.file_id,
169+
container,
170+
));
171+
items.extend(collect_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,22 @@ 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_items(db, &mut expander, item_list.impl_items(), src.file_id, container)
223+
.into_iter()
224+
.map(|(_, item)| item),
225+
);
226+
items.extend(
227+
collect_items_in_macros(db, &mut expander, &src.with_value(item_list), container)
228+
.into_iter()
229+
.map(|(_, item)| item),
230+
);
253231
}
254232

255233
let res = ImplData { target_trait, target_type, items, is_negative };
@@ -292,49 +270,50 @@ impl ConstData {
292270
}
293271
}
294272

295-
fn collect_impl_items_in_macros(
273+
fn collect_items_in_macros(
296274
db: &dyn DefDatabase,
297275
expander: &mut Expander,
298276
impl_def: &InFile<ast::ItemList>,
299-
id: ImplId,
300-
) -> Vec<AssocItemId> {
277+
container: AssocContainerId,
278+
) -> Vec<(Name, AssocItemId)> {
301279
let mut res = Vec::new();
302280

303281
// We set a limit to protect against infinite recursion
304282
let limit = 100;
305283

306284
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))
285+
res.extend(collect_items_in_macro(db, expander, m, container, limit))
308286
}
309287

310288
res
311289
}
312290

313-
fn collect_impl_items_in_macro(
291+
fn collect_items_in_macro(
314292
db: &dyn DefDatabase,
315293
expander: &mut Expander,
316294
m: ast::MacroCall,
317-
id: ImplId,
295+
container: AssocContainerId,
318296
limit: usize,
319-
) -> Vec<AssocItemId> {
297+
) -> Vec<(Name, AssocItemId)> {
320298
if limit == 0 {
321299
return Vec::new();
322300
}
323301

324302
if let Some((mark, items)) = expander.enter_expand(db, None, m) {
325303
let items: InFile<ast::MacroItems> = expander.to_source(items);
326-
let mut res = collect_impl_items(
304+
let mut res = collect_items(
327305
db,
328306
expander,
329307
items.value.items().filter_map(|it| ImplItem::cast(it.syntax().clone())),
330308
items.file_id,
331-
id,
309+
container,
332310
);
311+
333312
// Recursive collect macros
334313
// Note that ast::ModuleItem do not include ast::MacroCall
335314
// We cannot use ModuleItemOwner::items here
336315
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))
316+
res.extend(collect_items_in_macro(db, expander, it, container, limit - 1))
338317
}
339318
expander.exit(db, mark);
340319
res
@@ -343,44 +322,39 @@ fn collect_impl_items_in_macro(
343322
}
344323
}
345324

346-
fn collect_impl_items(
325+
fn collect_items(
347326
db: &dyn DefDatabase,
348327
expander: &mut Expander,
349328
impl_items: impl Iterator<Item = ImplItem>,
350329
file_id: crate::HirFileId,
351-
id: ImplId,
352-
) -> Vec<AssocItemId> {
330+
container: AssocContainerId,
331+
) -> Vec<(Name, AssocItemId)> {
353332
let items = db.ast_id_map(file_id);
354333

355334
impl_items
356335
.filter_map(|item_node| match item_node {
357336
ast::ImplItem::FnDef(it) => {
337+
let name = it.name().map_or_else(Name::missing, |it| it.as_name());
358338
let attrs = expander.parse_attrs(&it);
359339
if !expander.is_cfg_enabled(&attrs) {
360340
return None;
361341
}
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())
342+
let def = FunctionLoc { container, ast_id: AstId::new(file_id, items.ast_id(&it)) }
343+
.intern(db);
344+
Some((name, def.into()))
368345
}
369346
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())
347+
let name = it.name().map_or_else(Name::missing, |it| it.as_name());
348+
let def = ConstLoc { container, ast_id: AstId::new(file_id, items.ast_id(&it)) }
349+
.intern(db);
350+
Some((name, def.into()))
376351
}
377352
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())
353+
let name = it.name().map_or_else(Name::missing, |it| it.as_name());
354+
let def =
355+
TypeAliasLoc { container, ast_id: AstId::new(file_id, items.ast_id(&it)) }
356+
.intern(db);
357+
Some((name, def.into()))
384358
}
385359
})
386360
.collect()

crates/ra_hir_ty/src/tests/traits.rs

Lines changed: 20 additions & 18 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
}
21072109
}
2108-
"#, true),
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)