]> git.lizzy.rs Git - rust.git/blob - crates/hir_def/src/item_tree/lower.rs
Merge #10372
[rust.git] / crates / hir_def / src / item_tree / lower.rs
1 //! AST -> `ItemTree` lowering code.
2
3 use std::{collections::hash_map::Entry, mem, sync::Arc};
4
5 use hir_expand::{ast_id_map::AstIdMap, hygiene::Hygiene, name::known, HirFileId};
6 use syntax::{
7     ast::{self, HasModuleItem},
8     SyntaxNode, WalkEvent,
9 };
10
11 use crate::{
12     generics::{GenericParams, TypeParamData, TypeParamProvenance},
13     type_ref::{LifetimeRef, TraitBoundModifier, TraitRef},
14 };
15
16 use super::*;
17
18 fn id<N: ItemTreeNode>(index: Idx<N>) -> FileItemTreeId<N> {
19     FileItemTreeId { index, _p: PhantomData }
20 }
21
22 pub(super) struct Ctx<'a> {
23     db: &'a dyn DefDatabase,
24     tree: ItemTree,
25     hygiene: Hygiene,
26     source_ast_id_map: Arc<AstIdMap>,
27     body_ctx: crate::body::LowerCtx<'a>,
28     forced_visibility: Option<RawVisibilityId>,
29 }
30
31 impl<'a> Ctx<'a> {
32     pub(super) fn new(db: &'a dyn DefDatabase, hygiene: Hygiene, file: HirFileId) -> Self {
33         Self {
34             db,
35             tree: ItemTree::default(),
36             hygiene,
37             source_ast_id_map: db.ast_id_map(file),
38             body_ctx: crate::body::LowerCtx::new(db, file),
39             forced_visibility: None,
40         }
41     }
42
43     pub(super) fn lower_module_items(mut self, item_owner: &dyn HasModuleItem) -> ItemTree {
44         self.tree.top_level =
45             item_owner.items().flat_map(|item| self.lower_mod_item(&item, false)).collect();
46         self.tree
47     }
48
49     pub(super) fn lower_macro_stmts(mut self, stmts: ast::MacroStmts) -> ItemTree {
50         self.tree.top_level = stmts
51             .statements()
52             .filter_map(|stmt| match stmt {
53                 ast::Stmt::Item(item) => Some(item),
54                 // Macro calls can be both items and expressions. The syntax library always treats
55                 // them as expressions here, so we undo that.
56                 ast::Stmt::ExprStmt(es) => match es.expr()? {
57                     ast::Expr::MacroCall(call) => {
58                         cov_mark::hit!(macro_call_in_macro_stmts_is_added_to_item_tree);
59                         Some(call.into())
60                     }
61                     _ => None,
62                 },
63                 _ => None,
64             })
65             .flat_map(|item| self.lower_mod_item(&item, false))
66             .collect();
67
68         // Non-items need to have their inner items collected.
69         for stmt in stmts.statements() {
70             match stmt {
71                 ast::Stmt::ExprStmt(_) | ast::Stmt::LetStmt(_) => {
72                     self.collect_inner_items(stmt.syntax())
73                 }
74                 _ => {}
75             }
76         }
77         if let Some(expr) = stmts.expr() {
78             self.collect_inner_items(expr.syntax());
79         }
80         self.tree
81     }
82
83     pub(super) fn lower_inner_items(mut self, within: &SyntaxNode) -> ItemTree {
84         self.collect_inner_items(within);
85         self.tree
86     }
87
88     fn data(&mut self) -> &mut ItemTreeData {
89         self.tree.data_mut()
90     }
91
92     fn lower_mod_item(&mut self, item: &ast::Item, inner: bool) -> Option<ModItem> {
93         // Collect inner items for 1-to-1-lowered items.
94         match item {
95             ast::Item::Struct(_)
96             | ast::Item::Union(_)
97             | ast::Item::Enum(_)
98             | ast::Item::Fn(_)
99             | ast::Item::TypeAlias(_)
100             | ast::Item::Const(_)
101             | ast::Item::Static(_) => {
102                 // Skip this if we're already collecting inner items. We'll descend into all nodes
103                 // already.
104                 if !inner {
105                     self.collect_inner_items(item.syntax());
106                 }
107             }
108
109             // These are handled in their respective `lower_X` method (since we can't just blindly
110             // walk them).
111             ast::Item::Trait(_) | ast::Item::Impl(_) | ast::Item::ExternBlock(_) => {}
112
113             // These don't have inner items.
114             ast::Item::Module(_)
115             | ast::Item::ExternCrate(_)
116             | ast::Item::Use(_)
117             | ast::Item::MacroCall(_)
118             | ast::Item::MacroRules(_)
119             | ast::Item::MacroDef(_) => {}
120         };
121
122         let attrs = RawAttrs::new(self.db, item, &self.hygiene);
123         let item: ModItem = match item {
124             ast::Item::Struct(ast) => self.lower_struct(ast)?.into(),
125             ast::Item::Union(ast) => self.lower_union(ast)?.into(),
126             ast::Item::Enum(ast) => self.lower_enum(ast)?.into(),
127             ast::Item::Fn(ast) => self.lower_function(ast)?.into(),
128             ast::Item::TypeAlias(ast) => self.lower_type_alias(ast)?.into(),
129             ast::Item::Static(ast) => self.lower_static(ast)?.into(),
130             ast::Item::Const(ast) => self.lower_const(ast).into(),
131             ast::Item::Module(ast) => self.lower_module(ast)?.into(),
132             ast::Item::Trait(ast) => self.lower_trait(ast)?.into(),
133             ast::Item::Impl(ast) => self.lower_impl(ast)?.into(),
134             ast::Item::Use(ast) => self.lower_use(ast)?.into(),
135             ast::Item::ExternCrate(ast) => self.lower_extern_crate(ast)?.into(),
136             ast::Item::MacroCall(ast) => self.lower_macro_call(ast)?.into(),
137             ast::Item::MacroRules(ast) => self.lower_macro_rules(ast)?.into(),
138             ast::Item::MacroDef(ast) => self.lower_macro_def(ast)?.into(),
139             ast::Item::ExternBlock(ast) => self.lower_extern_block(ast).into(),
140         };
141
142         self.add_attrs(item.into(), attrs);
143
144         Some(item)
145     }
146
147     fn add_attrs(&mut self, item: AttrOwner, attrs: RawAttrs) {
148         match self.tree.attrs.entry(item) {
149             Entry::Occupied(mut entry) => {
150                 *entry.get_mut() = entry.get().merge(attrs);
151             }
152             Entry::Vacant(entry) => {
153                 entry.insert(attrs);
154             }
155         }
156     }
157
158     fn collect_inner_items(&mut self, container: &SyntaxNode) {
159         let forced_vis = self.forced_visibility.take();
160
161         let mut block_stack = Vec::new();
162
163         // if container itself is block, add it to the stack
164         if let Some(block) = ast::BlockExpr::cast(container.clone()) {
165             block_stack.push(self.source_ast_id_map.ast_id(&block));
166         }
167
168         for event in container.preorder().skip(1) {
169             match event {
170                 WalkEvent::Enter(node) => {
171                     match_ast! {
172                         match node {
173                             ast::BlockExpr(block) => {
174                                 block_stack.push(self.source_ast_id_map.ast_id(&block));
175                             },
176                             ast::Item(item) => {
177                                 // FIXME: This triggers for macro calls in expression/pattern/type position
178                                 let mod_item = self.lower_mod_item(&item, true);
179                                 let current_block = block_stack.last();
180                                 if let (Some(mod_item), Some(block)) = (mod_item, current_block) {
181                                         self.data().inner_items.entry(*block).or_default().push(mod_item);
182                                 }
183                             },
184                             _ => {}
185                         }
186                     }
187                 }
188                 WalkEvent::Leave(node) => {
189                     if ast::BlockExpr::cast(node).is_some() {
190                         block_stack.pop();
191                     }
192                 }
193             }
194         }
195
196         self.forced_visibility = forced_vis;
197     }
198
199     fn lower_assoc_item(&mut self, item: &ast::AssocItem) -> Option<AssocItem> {
200         match item {
201             ast::AssocItem::Fn(ast) => self.lower_function(ast).map(Into::into),
202             ast::AssocItem::TypeAlias(ast) => self.lower_type_alias(ast).map(Into::into),
203             ast::AssocItem::Const(ast) => Some(self.lower_const(ast).into()),
204             ast::AssocItem::MacroCall(ast) => self.lower_macro_call(ast).map(Into::into),
205         }
206     }
207
208     fn lower_struct(&mut self, strukt: &ast::Struct) -> Option<FileItemTreeId<Struct>> {
209         let visibility = self.lower_visibility(strukt);
210         let name = strukt.name()?.as_name();
211         let generic_params = self.lower_generic_params(GenericsOwner::Struct, strukt);
212         let fields = self.lower_fields(&strukt.kind());
213         let ast_id = self.source_ast_id_map.ast_id(strukt);
214         let res = Struct { name, visibility, generic_params, fields, ast_id };
215         Some(id(self.data().structs.alloc(res)))
216     }
217
218     fn lower_fields(&mut self, strukt_kind: &ast::StructKind) -> Fields {
219         match strukt_kind {
220             ast::StructKind::Record(it) => {
221                 let range = self.lower_record_fields(it);
222                 Fields::Record(range)
223             }
224             ast::StructKind::Tuple(it) => {
225                 let range = self.lower_tuple_fields(it);
226                 Fields::Tuple(range)
227             }
228             ast::StructKind::Unit => Fields::Unit,
229         }
230     }
231
232     fn lower_record_fields(&mut self, fields: &ast::RecordFieldList) -> IdRange<Field> {
233         let start = self.next_field_idx();
234         for field in fields.fields() {
235             if let Some(data) = self.lower_record_field(&field) {
236                 let idx = self.data().fields.alloc(data);
237                 self.add_attrs(idx.into(), RawAttrs::new(self.db, &field, &self.hygiene));
238             }
239         }
240         let end = self.next_field_idx();
241         IdRange::new(start..end)
242     }
243
244     fn lower_record_field(&mut self, field: &ast::RecordField) -> Option<Field> {
245         let name = field.name()?.as_name();
246         let visibility = self.lower_visibility(field);
247         let type_ref = self.lower_type_ref_opt(field.ty());
248         let res = Field { name, type_ref, visibility };
249         Some(res)
250     }
251
252     fn lower_tuple_fields(&mut self, fields: &ast::TupleFieldList) -> IdRange<Field> {
253         let start = self.next_field_idx();
254         for (i, field) in fields.fields().enumerate() {
255             let data = self.lower_tuple_field(i, &field);
256             let idx = self.data().fields.alloc(data);
257             self.add_attrs(idx.into(), RawAttrs::new(self.db, &field, &self.hygiene));
258         }
259         let end = self.next_field_idx();
260         IdRange::new(start..end)
261     }
262
263     fn lower_tuple_field(&mut self, idx: usize, field: &ast::TupleField) -> Field {
264         let name = Name::new_tuple_field(idx);
265         let visibility = self.lower_visibility(field);
266         let type_ref = self.lower_type_ref_opt(field.ty());
267         Field { name, type_ref, visibility }
268     }
269
270     fn lower_union(&mut self, union: &ast::Union) -> Option<FileItemTreeId<Union>> {
271         let visibility = self.lower_visibility(union);
272         let name = union.name()?.as_name();
273         let generic_params = self.lower_generic_params(GenericsOwner::Union, union);
274         let fields = match union.record_field_list() {
275             Some(record_field_list) => self.lower_fields(&StructKind::Record(record_field_list)),
276             None => Fields::Record(IdRange::new(self.next_field_idx()..self.next_field_idx())),
277         };
278         let ast_id = self.source_ast_id_map.ast_id(union);
279         let res = Union { name, visibility, generic_params, fields, ast_id };
280         Some(id(self.data().unions.alloc(res)))
281     }
282
283     fn lower_enum(&mut self, enum_: &ast::Enum) -> Option<FileItemTreeId<Enum>> {
284         let visibility = self.lower_visibility(enum_);
285         let name = enum_.name()?.as_name();
286         let generic_params = self.lower_generic_params(GenericsOwner::Enum, enum_);
287         let variants =
288             self.with_inherited_visibility(visibility, |this| match &enum_.variant_list() {
289                 Some(variant_list) => this.lower_variants(variant_list),
290                 None => IdRange::new(this.next_variant_idx()..this.next_variant_idx()),
291             });
292         let ast_id = self.source_ast_id_map.ast_id(enum_);
293         let res = Enum { name, visibility, generic_params, variants, ast_id };
294         Some(id(self.data().enums.alloc(res)))
295     }
296
297     fn lower_variants(&mut self, variants: &ast::VariantList) -> IdRange<Variant> {
298         let start = self.next_variant_idx();
299         for variant in variants.variants() {
300             if let Some(data) = self.lower_variant(&variant) {
301                 let idx = self.data().variants.alloc(data);
302                 self.add_attrs(idx.into(), RawAttrs::new(self.db, &variant, &self.hygiene));
303             }
304         }
305         let end = self.next_variant_idx();
306         IdRange::new(start..end)
307     }
308
309     fn lower_variant(&mut self, variant: &ast::Variant) -> Option<Variant> {
310         let name = variant.name()?.as_name();
311         let fields = self.lower_fields(&variant.kind());
312         let res = Variant { name, fields };
313         Some(res)
314     }
315
316     fn lower_function(&mut self, func: &ast::Fn) -> Option<FileItemTreeId<Function>> {
317         let visibility = self.lower_visibility(func);
318         let name = func.name()?.as_name();
319
320         let mut has_self_param = false;
321         let start_param = self.next_param_idx();
322         if let Some(param_list) = func.param_list() {
323             if let Some(self_param) = param_list.self_param() {
324                 let self_type = match self_param.ty() {
325                     Some(type_ref) => TypeRef::from_ast(&self.body_ctx, type_ref),
326                     None => {
327                         let self_type = TypeRef::Path(name![Self].into());
328                         match self_param.kind() {
329                             ast::SelfParamKind::Owned => self_type,
330                             ast::SelfParamKind::Ref => TypeRef::Reference(
331                                 Box::new(self_type),
332                                 self_param.lifetime().as_ref().map(LifetimeRef::new),
333                                 Mutability::Shared,
334                             ),
335                             ast::SelfParamKind::MutRef => TypeRef::Reference(
336                                 Box::new(self_type),
337                                 self_param.lifetime().as_ref().map(LifetimeRef::new),
338                                 Mutability::Mut,
339                             ),
340                         }
341                     }
342                 };
343                 let ty = Interned::new(self_type);
344                 let idx = self.data().params.alloc(Param::Normal(ty));
345                 self.add_attrs(idx.into(), RawAttrs::new(self.db, &self_param, &self.hygiene));
346                 has_self_param = true;
347             }
348             for param in param_list.params() {
349                 let idx = match param.dotdotdot_token() {
350                     Some(_) => self.data().params.alloc(Param::Varargs),
351                     None => {
352                         let type_ref = TypeRef::from_ast_opt(&self.body_ctx, param.ty());
353                         let ty = Interned::new(type_ref);
354                         self.data().params.alloc(Param::Normal(ty))
355                     }
356                 };
357                 self.add_attrs(idx.into(), RawAttrs::new(self.db, &param, &self.hygiene));
358             }
359         }
360         let end_param = self.next_param_idx();
361         let params = IdRange::new(start_param..end_param);
362
363         let ret_type = match func.ret_type().and_then(|rt| rt.ty()) {
364             Some(type_ref) => TypeRef::from_ast(&self.body_ctx, type_ref),
365             _ => TypeRef::unit(),
366         };
367
368         let (ret_type, async_ret_type) = if func.async_token().is_some() {
369             let async_ret_type = ret_type.clone();
370             let future_impl = desugar_future_path(ret_type);
371             let ty_bound = Interned::new(TypeBound::Path(future_impl, TraitBoundModifier::None));
372             (TypeRef::ImplTrait(vec![ty_bound]), Some(async_ret_type))
373         } else {
374             (ret_type, None)
375         };
376
377         let abi = func.abi().map(lower_abi);
378
379         let ast_id = self.source_ast_id_map.ast_id(func);
380
381         let mut flags = FnFlags::default();
382         if func.body().is_some() {
383             flags.bits |= FnFlags::HAS_BODY;
384         }
385         if has_self_param {
386             flags.bits |= FnFlags::HAS_SELF_PARAM;
387         }
388         if func.default_token().is_some() {
389             flags.bits |= FnFlags::IS_DEFAULT;
390         }
391         if func.const_token().is_some() {
392             flags.bits |= FnFlags::IS_CONST;
393         }
394         if func.async_token().is_some() {
395             flags.bits |= FnFlags::IS_ASYNC;
396         }
397         if func.unsafe_token().is_some() {
398             flags.bits |= FnFlags::IS_UNSAFE;
399         }
400
401         let mut res = Function {
402             name,
403             visibility,
404             generic_params: Interned::new(GenericParams::default()),
405             abi,
406             params,
407             ret_type: Interned::new(ret_type),
408             async_ret_type: async_ret_type.map(Interned::new),
409             ast_id,
410             flags,
411         };
412         res.generic_params = self.lower_generic_params(GenericsOwner::Function(&res), func);
413
414         Some(id(self.data().functions.alloc(res)))
415     }
416
417     fn lower_type_alias(
418         &mut self,
419         type_alias: &ast::TypeAlias,
420     ) -> Option<FileItemTreeId<TypeAlias>> {
421         let name = type_alias.name()?.as_name();
422         let type_ref = type_alias.ty().map(|it| self.lower_type_ref(&it));
423         let visibility = self.lower_visibility(type_alias);
424         let bounds = self.lower_type_bounds(type_alias);
425         let generic_params = self.lower_generic_params(GenericsOwner::TypeAlias, type_alias);
426         let ast_id = self.source_ast_id_map.ast_id(type_alias);
427         let res = TypeAlias {
428             name,
429             visibility,
430             bounds: bounds.into_boxed_slice(),
431             generic_params,
432             type_ref,
433             ast_id,
434             is_extern: false,
435         };
436         Some(id(self.data().type_aliases.alloc(res)))
437     }
438
439     fn lower_static(&mut self, static_: &ast::Static) -> Option<FileItemTreeId<Static>> {
440         let name = static_.name()?.as_name();
441         let type_ref = self.lower_type_ref_opt(static_.ty());
442         let visibility = self.lower_visibility(static_);
443         let mutable = static_.mut_token().is_some();
444         let ast_id = self.source_ast_id_map.ast_id(static_);
445         let res = Static { name, visibility, mutable, type_ref, ast_id, is_extern: false };
446         Some(id(self.data().statics.alloc(res)))
447     }
448
449     fn lower_const(&mut self, konst: &ast::Const) -> FileItemTreeId<Const> {
450         let mut name = konst.name().map(|it| it.as_name());
451         if name.as_ref().map_or(false, |n| n.to_string().starts_with("_DERIVE_")) {
452             // FIXME: this is a hack to treat consts generated by synstructure as unnamed
453             // remove this some time in the future
454             name = None;
455         }
456         let type_ref = self.lower_type_ref_opt(konst.ty());
457         let visibility = self.lower_visibility(konst);
458         let ast_id = self.source_ast_id_map.ast_id(konst);
459         let res = Const { name, visibility, type_ref, ast_id };
460         id(self.data().consts.alloc(res))
461     }
462
463     fn lower_module(&mut self, module: &ast::Module) -> Option<FileItemTreeId<Mod>> {
464         let name = module.name()?.as_name();
465         let visibility = self.lower_visibility(module);
466         let kind = if module.semicolon_token().is_some() {
467             ModKind::Outline {}
468         } else {
469             ModKind::Inline {
470                 items: module
471                     .item_list()
472                     .map(|list| {
473                         list.items().flat_map(|item| self.lower_mod_item(&item, false)).collect()
474                     })
475                     .unwrap_or_else(|| {
476                         cov_mark::hit!(name_res_works_for_broken_modules);
477                         Box::new([]) as Box<[_]>
478                     }),
479             }
480         };
481         let ast_id = self.source_ast_id_map.ast_id(module);
482         let res = Mod { name, visibility, kind, ast_id };
483         Some(id(self.data().mods.alloc(res)))
484     }
485
486     fn lower_trait(&mut self, trait_def: &ast::Trait) -> Option<FileItemTreeId<Trait>> {
487         let name = trait_def.name()?.as_name();
488         let visibility = self.lower_visibility(trait_def);
489         let generic_params =
490             self.lower_generic_params_and_inner_items(GenericsOwner::Trait(trait_def), trait_def);
491         let is_auto = trait_def.auto_token().is_some();
492         let is_unsafe = trait_def.unsafe_token().is_some();
493         let items = trait_def.assoc_item_list().map(|list| {
494             let db = self.db;
495             self.with_inherited_visibility(visibility, |this| {
496                 list.assoc_items()
497                     .filter_map(|item| {
498                         let attrs = RawAttrs::new(db, &item, &this.hygiene);
499                         this.collect_inner_items(item.syntax());
500                         this.lower_assoc_item(&item).map(|item| {
501                             this.add_attrs(ModItem::from(item).into(), attrs);
502                             item
503                         })
504                     })
505                     .collect()
506             })
507         });
508         let ast_id = self.source_ast_id_map.ast_id(trait_def);
509         let res = Trait {
510             name,
511             visibility,
512             generic_params,
513             is_auto,
514             is_unsafe,
515             items: items.unwrap_or_default(),
516             ast_id,
517         };
518         Some(id(self.data().traits.alloc(res)))
519     }
520
521     fn lower_impl(&mut self, impl_def: &ast::Impl) -> Option<FileItemTreeId<Impl>> {
522         let generic_params =
523             self.lower_generic_params_and_inner_items(GenericsOwner::Impl, impl_def);
524         // FIXME: If trait lowering fails, due to a non PathType for example, we treat this impl
525         // as if it was an non-trait impl. Ideally we want to create a unique missing ref that only
526         // equals itself.
527         let target_trait = impl_def.trait_().and_then(|tr| self.lower_trait_ref(&tr));
528         let self_ty = self.lower_type_ref(&impl_def.self_ty()?);
529         let is_negative = impl_def.excl_token().is_some();
530
531         // We cannot use `assoc_items()` here as that does not include macro calls.
532         let items = impl_def
533             .assoc_item_list()
534             .into_iter()
535             .flat_map(|it| it.assoc_items())
536             .filter_map(|item| {
537                 self.collect_inner_items(item.syntax());
538                 let assoc = self.lower_assoc_item(&item)?;
539                 let attrs = RawAttrs::new(self.db, &item, &self.hygiene);
540                 self.add_attrs(ModItem::from(assoc).into(), attrs);
541                 Some(assoc)
542             })
543             .collect();
544         let ast_id = self.source_ast_id_map.ast_id(impl_def);
545         let res = Impl { generic_params, target_trait, self_ty, is_negative, items, ast_id };
546         Some(id(self.data().impls.alloc(res)))
547     }
548
549     fn lower_use(&mut self, use_item: &ast::Use) -> Option<FileItemTreeId<Import>> {
550         let visibility = self.lower_visibility(use_item);
551         let ast_id = self.source_ast_id_map.ast_id(use_item);
552         let (use_tree, _) = lower_use_tree(self.db, &self.hygiene, use_item.use_tree()?)?;
553
554         let res = Import { visibility, ast_id, use_tree };
555         Some(id(self.data().imports.alloc(res)))
556     }
557
558     fn lower_extern_crate(
559         &mut self,
560         extern_crate: &ast::ExternCrate,
561     ) -> Option<FileItemTreeId<ExternCrate>> {
562         let name = extern_crate.name_ref()?.as_name();
563         let alias = extern_crate.rename().map(|a| {
564             a.name().map(|it| it.as_name()).map_or(ImportAlias::Underscore, ImportAlias::Alias)
565         });
566         let visibility = self.lower_visibility(extern_crate);
567         let ast_id = self.source_ast_id_map.ast_id(extern_crate);
568
569         let res = ExternCrate { name, alias, visibility, ast_id };
570         Some(id(self.data().extern_crates.alloc(res)))
571     }
572
573     fn lower_macro_call(&mut self, m: &ast::MacroCall) -> Option<FileItemTreeId<MacroCall>> {
574         let path = Interned::new(ModPath::from_src(self.db, m.path()?, &self.hygiene)?);
575         let ast_id = self.source_ast_id_map.ast_id(m);
576         let expand_to = hir_expand::ExpandTo::from_call_site(m);
577         let res = MacroCall { path, ast_id, expand_to };
578         Some(id(self.data().macro_calls.alloc(res)))
579     }
580
581     fn lower_macro_rules(&mut self, m: &ast::MacroRules) -> Option<FileItemTreeId<MacroRules>> {
582         let name = m.name().map(|it| it.as_name())?;
583         let ast_id = self.source_ast_id_map.ast_id(m);
584
585         let res = MacroRules { name, ast_id };
586         Some(id(self.data().macro_rules.alloc(res)))
587     }
588
589     fn lower_macro_def(&mut self, m: &ast::MacroDef) -> Option<FileItemTreeId<MacroDef>> {
590         let name = m.name().map(|it| it.as_name())?;
591
592         let ast_id = self.source_ast_id_map.ast_id(m);
593         let visibility = self.lower_visibility(m);
594
595         let res = MacroDef { name, ast_id, visibility };
596         Some(id(self.data().macro_defs.alloc(res)))
597     }
598
599     fn lower_extern_block(&mut self, block: &ast::ExternBlock) -> FileItemTreeId<ExternBlock> {
600         let ast_id = self.source_ast_id_map.ast_id(block);
601         let abi = block.abi().map(lower_abi);
602         let children: Box<[_]> = block.extern_item_list().map_or(Box::new([]), |list| {
603             list.extern_items()
604                 .filter_map(|item| {
605                     self.collect_inner_items(item.syntax());
606                     let attrs = RawAttrs::new(self.db, &item, &self.hygiene);
607                     let id: ModItem = match item {
608                         ast::ExternItem::Fn(ast) => {
609                             let func_id = self.lower_function(&ast)?;
610                             let func = &mut self.data().functions[func_id.index];
611                             if is_intrinsic_fn_unsafe(&func.name) {
612                                 func.flags.bits |= FnFlags::IS_UNSAFE;
613                             }
614                             func.flags.bits |= FnFlags::IS_IN_EXTERN_BLOCK;
615                             func_id.into()
616                         }
617                         ast::ExternItem::Static(ast) => {
618                             let statik = self.lower_static(&ast)?;
619                             self.data().statics[statik.index].is_extern = true;
620                             statik.into()
621                         }
622                         ast::ExternItem::TypeAlias(ty) => {
623                             let foreign_ty = self.lower_type_alias(&ty)?;
624                             self.data().type_aliases[foreign_ty.index].is_extern = true;
625                             foreign_ty.into()
626                         }
627                         ast::ExternItem::MacroCall(call) => {
628                             // FIXME: we need some way of tracking that the macro call is in an
629                             // extern block
630                             self.lower_macro_call(&call)?.into()
631                         }
632                     };
633                     self.add_attrs(id.into(), attrs);
634                     Some(id)
635                 })
636                 .collect()
637         });
638
639         let res = ExternBlock { abi, ast_id, children };
640         id(self.data().extern_blocks.alloc(res))
641     }
642
643     /// Lowers generics defined on `node` and collects inner items defined within.
644     fn lower_generic_params_and_inner_items(
645         &mut self,
646         owner: GenericsOwner<'_>,
647         node: &impl ast::HasGenericParams,
648     ) -> Interned<GenericParams> {
649         // Generics are part of item headers and may contain inner items we need to collect.
650         if let Some(params) = node.generic_param_list() {
651             self.collect_inner_items(params.syntax());
652         }
653         if let Some(clause) = node.where_clause() {
654             self.collect_inner_items(clause.syntax());
655         }
656
657         self.lower_generic_params(owner, node)
658     }
659
660     fn lower_generic_params(
661         &mut self,
662         owner: GenericsOwner<'_>,
663         node: &impl ast::HasGenericParams,
664     ) -> Interned<GenericParams> {
665         let mut generics = GenericParams::default();
666         match owner {
667             GenericsOwner::Function(func) => {
668                 generics.fill(&self.body_ctx, node);
669                 // lower `impl Trait` in arguments
670                 for id in func.params.clone() {
671                     if let Param::Normal(ty) = &self.data().params[id] {
672                         generics.fill_implicit_impl_trait_args(ty);
673                     }
674                 }
675             }
676             GenericsOwner::Struct
677             | GenericsOwner::Enum
678             | GenericsOwner::Union
679             | GenericsOwner::TypeAlias => {
680                 generics.fill(&self.body_ctx, node);
681             }
682             GenericsOwner::Trait(trait_def) => {
683                 // traits get the Self type as an implicit first type parameter
684                 generics.types.alloc(TypeParamData {
685                     name: Some(name![Self]),
686                     default: None,
687                     provenance: TypeParamProvenance::TraitSelf,
688                 });
689                 // add super traits as bounds on Self
690                 // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar
691                 let self_param = TypeRef::Path(name![Self].into());
692                 generics.fill_bounds(&self.body_ctx, trait_def, Either::Left(self_param));
693                 generics.fill(&self.body_ctx, node);
694             }
695             GenericsOwner::Impl => {
696                 // Note that we don't add `Self` here: in `impl`s, `Self` is not a
697                 // type-parameter, but rather is a type-alias for impl's target
698                 // type, so this is handled by the resolver.
699                 generics.fill(&self.body_ctx, node);
700             }
701         }
702
703         generics.shrink_to_fit();
704         Interned::new(generics)
705     }
706
707     fn lower_type_bounds(&mut self, node: &impl ast::HasTypeBounds) -> Vec<Interned<TypeBound>> {
708         match node.type_bound_list() {
709             Some(bound_list) => bound_list
710                 .bounds()
711                 .map(|it| Interned::new(TypeBound::from_ast(&self.body_ctx, it)))
712                 .collect(),
713             None => Vec::new(),
714         }
715     }
716
717     fn lower_visibility(&mut self, item: &impl ast::HasVisibility) -> RawVisibilityId {
718         let vis = match self.forced_visibility {
719             Some(vis) => return vis,
720             None => RawVisibility::from_ast_with_hygiene(self.db, item.visibility(), &self.hygiene),
721         };
722
723         self.data().vis.alloc(vis)
724     }
725
726     fn lower_trait_ref(&mut self, trait_ref: &ast::Type) -> Option<Interned<TraitRef>> {
727         let trait_ref = TraitRef::from_ast(&self.body_ctx, trait_ref.clone())?;
728         Some(Interned::new(trait_ref))
729     }
730
731     fn lower_type_ref(&mut self, type_ref: &ast::Type) -> Interned<TypeRef> {
732         let tyref = TypeRef::from_ast(&self.body_ctx, type_ref.clone());
733         Interned::new(tyref)
734     }
735
736     fn lower_type_ref_opt(&mut self, type_ref: Option<ast::Type>) -> Interned<TypeRef> {
737         match type_ref.map(|ty| self.lower_type_ref(&ty)) {
738             Some(it) => it,
739             None => Interned::new(TypeRef::Error),
740         }
741     }
742
743     /// Forces the visibility `vis` to be used for all items lowered during execution of `f`.
744     fn with_inherited_visibility<R>(
745         &mut self,
746         vis: RawVisibilityId,
747         f: impl FnOnce(&mut Self) -> R,
748     ) -> R {
749         let old = mem::replace(&mut self.forced_visibility, Some(vis));
750         let res = f(self);
751         self.forced_visibility = old;
752         res
753     }
754
755     fn next_field_idx(&self) -> Idx<Field> {
756         Idx::from_raw(RawIdx::from(
757             self.tree.data.as_ref().map_or(0, |data| data.fields.len() as u32),
758         ))
759     }
760     fn next_variant_idx(&self) -> Idx<Variant> {
761         Idx::from_raw(RawIdx::from(
762             self.tree.data.as_ref().map_or(0, |data| data.variants.len() as u32),
763         ))
764     }
765     fn next_param_idx(&self) -> Idx<Param> {
766         Idx::from_raw(RawIdx::from(
767             self.tree.data.as_ref().map_or(0, |data| data.params.len() as u32),
768         ))
769     }
770 }
771
772 fn desugar_future_path(orig: TypeRef) -> Path {
773     let path = path![core::future::Future];
774     let mut generic_args: Vec<_> =
775         std::iter::repeat(None).take(path.segments().len() - 1).collect();
776     let mut last = GenericArgs::empty();
777     let binding =
778         AssociatedTypeBinding { name: name![Output], type_ref: Some(orig), bounds: Vec::new() };
779     last.bindings.push(binding);
780     generic_args.push(Some(Interned::new(last)));
781
782     Path::from_known_path(path, generic_args)
783 }
784
785 enum GenericsOwner<'a> {
786     /// We need access to the partially-lowered `Function` for lowering `impl Trait` in argument
787     /// position.
788     Function(&'a Function),
789     Struct,
790     Enum,
791     Union,
792     /// The `TraitDef` is needed to fill the source map for the implicit `Self` parameter.
793     Trait(&'a ast::Trait),
794     TypeAlias,
795     Impl,
796 }
797
798 /// Returns `true` if the given intrinsic is unsafe to call, or false otherwise.
799 fn is_intrinsic_fn_unsafe(name: &Name) -> bool {
800     // Should be kept in sync with https://github.com/rust-lang/rust/blob/0cd0709f19d316c4796fa71c5f52c8612a5f3771/compiler/rustc_typeck/src/check/intrinsic.rs#L72-L105
801     ![
802         known::abort,
803         known::add_with_overflow,
804         known::bitreverse,
805         known::bswap,
806         known::caller_location,
807         known::ctlz,
808         known::ctpop,
809         known::cttz,
810         known::discriminant_value,
811         known::forget,
812         known::likely,
813         known::maxnumf32,
814         known::maxnumf64,
815         known::min_align_of,
816         known::minnumf32,
817         known::minnumf64,
818         known::mul_with_overflow,
819         known::needs_drop,
820         known::ptr_guaranteed_eq,
821         known::ptr_guaranteed_ne,
822         known::rotate_left,
823         known::rotate_right,
824         known::rustc_peek,
825         known::saturating_add,
826         known::saturating_sub,
827         known::size_of,
828         known::sub_with_overflow,
829         known::type_id,
830         known::type_name,
831         known::unlikely,
832         known::variant_count,
833         known::wrapping_add,
834         known::wrapping_mul,
835         known::wrapping_sub,
836     ]
837     .contains(name)
838 }
839
840 fn lower_abi(abi: ast::Abi) -> Interned<str> {
841     // FIXME: Abi::abi() -> Option<SyntaxToken>?
842     match abi.syntax().last_token() {
843         Some(tok) if tok.kind() == SyntaxKind::STRING => {
844             // FIXME: Better way to unescape?
845             Interned::new_str(tok.text().trim_matches('"'))
846         }
847         _ => {
848             // `extern` default to be `extern "C"`.
849             Interned::new_str("C")
850         }
851     }
852 }
853
854 struct UseTreeLowering<'a> {
855     db: &'a dyn DefDatabase,
856     hygiene: &'a Hygiene,
857     mapping: Arena<ast::UseTree>,
858 }
859
860 impl UseTreeLowering<'_> {
861     fn lower_use_tree(&mut self, tree: ast::UseTree) -> Option<UseTree> {
862         if let Some(use_tree_list) = tree.use_tree_list() {
863             let prefix = match tree.path() {
864                 // E.g. use something::{{{inner}}};
865                 None => None,
866                 // E.g. `use something::{inner}` (prefix is `None`, path is `something`)
867                 // or `use something::{path::{inner::{innerer}}}` (prefix is `something::path`, path is `inner`)
868                 Some(path) => {
869                     match ModPath::from_src(self.db, path, self.hygiene) {
870                         Some(it) => Some(it),
871                         None => return None, // FIXME: report errors somewhere
872                     }
873                 }
874             };
875
876             let list =
877                 use_tree_list.use_trees().filter_map(|tree| self.lower_use_tree(tree)).collect();
878
879             Some(
880                 self.use_tree(
881                     UseTreeKind::Prefixed { prefix: prefix.map(Interned::new), list },
882                     tree,
883                 ),
884             )
885         } else {
886             let is_glob = tree.star_token().is_some();
887             let path = match tree.path() {
888                 Some(path) => Some(ModPath::from_src(self.db, path, self.hygiene)?),
889                 None => None,
890             };
891             let alias = tree.rename().map(|a| {
892                 a.name().map(|it| it.as_name()).map_or(ImportAlias::Underscore, ImportAlias::Alias)
893             });
894             if alias.is_some() && is_glob {
895                 return None;
896             }
897
898             match (path, alias, is_glob) {
899                 (path, None, true) => {
900                     if path.is_none() {
901                         cov_mark::hit!(glob_enum_group);
902                     }
903                     Some(self.use_tree(UseTreeKind::Glob { path: path.map(Interned::new) }, tree))
904                 }
905                 // Globs can't be renamed
906                 (_, Some(_), true) | (None, None, false) => None,
907                 // `bla::{ as Name}` is invalid
908                 (None, Some(_), false) => None,
909                 (Some(path), alias, false) => Some(
910                     self.use_tree(UseTreeKind::Single { path: Interned::new(path), alias }, tree),
911                 ),
912             }
913         }
914     }
915
916     fn use_tree(&mut self, kind: UseTreeKind, ast: ast::UseTree) -> UseTree {
917         let index = self.mapping.alloc(ast);
918         UseTree { index, kind }
919     }
920 }
921
922 pub(super) fn lower_use_tree(
923     db: &dyn DefDatabase,
924     hygiene: &Hygiene,
925     tree: ast::UseTree,
926 ) -> Option<(UseTree, Arena<ast::UseTree>)> {
927     let mut lowering = UseTreeLowering { db, hygiene, mapping: Arena::new() };
928     let tree = lowering.lower_use_tree(tree)?;
929     Some((tree, lowering.mapping))
930 }