diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_hir_def/src/item_tree.rs | 517 | ||||
-rw-r--r-- | crates/ra_hir_def/src/item_tree/lower.rs | 501 |
2 files changed, 513 insertions, 505 deletions
diff --git a/crates/ra_hir_def/src/item_tree.rs b/crates/ra_hir_def/src/item_tree.rs index 245ee5e62..a13a989dd 100644 --- a/crates/ra_hir_def/src/item_tree.rs +++ b/crates/ra_hir_def/src/item_tree.rs | |||
@@ -1,13 +1,23 @@ | |||
1 | //! A simplified AST that only contains items. | 1 | //! A simplified AST that only contains items. |
2 | 2 | ||
3 | mod lower; | ||
4 | |||
5 | use std::{ | ||
6 | ops::{Index, Range}, | ||
7 | sync::Arc, | ||
8 | }; | ||
9 | |||
10 | use ast::{AstNode, AttrsOwner, ModuleItemOwner, NameOwner, StructKind, TypeAscriptionOwner}; | ||
11 | use either::Either; | ||
3 | use hir_expand::{ | 12 | use hir_expand::{ |
4 | ast_id_map::{AstIdMap, FileAstId}, | 13 | ast_id_map::FileAstId, |
5 | hygiene::Hygiene, | 14 | hygiene::Hygiene, |
6 | name::{name, AsName, Name}, | 15 | name::{name, AsName, Name}, |
7 | HirFileId, InFile, | 16 | HirFileId, InFile, |
8 | }; | 17 | }; |
9 | use ra_arena::{Arena, Idx, RawId}; | 18 | use ra_arena::{Arena, Idx, RawId}; |
10 | use ra_syntax::{ast, match_ast}; | 19 | use ra_syntax::{ast, match_ast}; |
20 | use rustc_hash::FxHashMap; | ||
11 | use test_utils::mark; | 21 | use test_utils::mark; |
12 | 22 | ||
13 | use crate::{ | 23 | use crate::{ |
@@ -18,14 +28,6 @@ use crate::{ | |||
18 | type_ref::{Mutability, TypeBound, TypeRef}, | 28 | type_ref::{Mutability, TypeBound, TypeRef}, |
19 | visibility::RawVisibility, | 29 | visibility::RawVisibility, |
20 | }; | 30 | }; |
21 | use ast::{AstNode, AttrsOwner, ModuleItemOwner, NameOwner, StructKind, TypeAscriptionOwner}; | ||
22 | use either::Either; | ||
23 | use rustc_hash::FxHashMap; | ||
24 | use smallvec::SmallVec; | ||
25 | use std::{ | ||
26 | ops::{Index, Range}, | ||
27 | sync::Arc, | ||
28 | }; | ||
29 | 31 | ||
30 | /// The item tree of a source file. | 32 | /// The item tree of a source file. |
31 | #[derive(Debug, Default, Eq, PartialEq)] | 33 | #[derive(Debug, Default, Eq, PartialEq)] |
@@ -80,7 +82,7 @@ impl ItemTree { | |||
80 | }; | 82 | }; |
81 | 83 | ||
82 | let map = db.ast_id_map(file_id); | 84 | let map = db.ast_id_map(file_id); |
83 | let mut ctx = Ctx { | 85 | let mut ctx = lower::Ctx { |
84 | tree: ItemTree::default(), | 86 | tree: ItemTree::default(), |
85 | hygiene, | 87 | hygiene, |
86 | file: file_id, | 88 | file: file_id, |
@@ -366,498 +368,3 @@ pub struct Field { | |||
366 | pub type_ref: TypeRef, | 368 | pub type_ref: TypeRef, |
367 | pub visibility: RawVisibility, | 369 | pub visibility: RawVisibility, |
368 | } | 370 | } |
369 | |||
370 | struct ModItems(SmallVec<[ModItem; 1]>); | ||
371 | |||
372 | impl<T> From<T> for ModItems | ||
373 | where | ||
374 | T: Into<ModItem>, | ||
375 | { | ||
376 | fn from(t: T) -> Self { | ||
377 | ModItems(SmallVec::from_buf([t.into(); 1])) | ||
378 | } | ||
379 | } | ||
380 | |||
381 | struct Ctx { | ||
382 | tree: ItemTree, | ||
383 | hygiene: Hygiene, | ||
384 | file: HirFileId, | ||
385 | source_ast_id_map: Arc<AstIdMap>, | ||
386 | body_ctx: crate::body::LowerCtx, | ||
387 | } | ||
388 | |||
389 | impl Ctx { | ||
390 | fn lower(mut self, item_owner: &dyn ModuleItemOwner) -> ItemTree { | ||
391 | self.tree.top_level = item_owner | ||
392 | .items() | ||
393 | .flat_map(|item| self.lower_mod_item(&item)) | ||
394 | .flat_map(|items| items.0) | ||
395 | .collect(); | ||
396 | self.tree | ||
397 | } | ||
398 | |||
399 | fn lower_mod_item(&mut self, item: &ast::ModuleItem) -> Option<ModItems> { | ||
400 | let attrs = Attrs::new(item, &self.hygiene); | ||
401 | let items = match item { | ||
402 | ast::ModuleItem::StructDef(ast) => { | ||
403 | self.lower_struct(ast).map(|data| self.tree.structs.alloc(data).into()) | ||
404 | } | ||
405 | ast::ModuleItem::UnionDef(ast) => { | ||
406 | self.lower_union(ast).map(|data| self.tree.unions.alloc(data).into()) | ||
407 | } | ||
408 | ast::ModuleItem::EnumDef(ast) => { | ||
409 | self.lower_enum(ast).map(|data| self.tree.enums.alloc(data).into()) | ||
410 | } | ||
411 | ast::ModuleItem::FnDef(ast) => { | ||
412 | self.lower_function(ast).map(|data| self.tree.functions.alloc(data).into()) | ||
413 | } | ||
414 | ast::ModuleItem::TypeAliasDef(ast) => { | ||
415 | self.lower_type_alias(ast).map(|data| self.tree.type_aliases.alloc(data).into()) | ||
416 | } | ||
417 | ast::ModuleItem::StaticDef(ast) => { | ||
418 | self.lower_static(ast).map(|data| self.tree.statics.alloc(data).into()) | ||
419 | } | ||
420 | ast::ModuleItem::ConstDef(ast) => { | ||
421 | let data = self.lower_const(ast); | ||
422 | Some(self.tree.consts.alloc(data).into()) | ||
423 | } | ||
424 | ast::ModuleItem::Module(ast) => { | ||
425 | self.lower_module(ast).map(|data| self.tree.mods.alloc(data).into()) | ||
426 | } | ||
427 | ast::ModuleItem::TraitDef(ast) => { | ||
428 | self.lower_trait(ast).map(|data| self.tree.traits.alloc(data).into()) | ||
429 | } | ||
430 | ast::ModuleItem::ImplDef(ast) => { | ||
431 | self.lower_impl(ast).map(|data| self.tree.impls.alloc(data).into()) | ||
432 | } | ||
433 | ast::ModuleItem::UseItem(ast) => Some(ModItems( | ||
434 | self.lower_use(ast) | ||
435 | .into_iter() | ||
436 | .map(|data| self.tree.imports.alloc(data).into()) | ||
437 | .collect::<SmallVec<_>>(), | ||
438 | )), | ||
439 | ast::ModuleItem::ExternCrateItem(ast) => { | ||
440 | self.lower_extern_crate(ast).map(|data| self.tree.imports.alloc(data).into()) | ||
441 | } | ||
442 | ast::ModuleItem::MacroCall(ast) => { | ||
443 | self.lower_macro_call(ast).map(|data| self.tree.macro_calls.alloc(data).into()) | ||
444 | } | ||
445 | ast::ModuleItem::ExternBlock(ast) => Some(ModItems( | ||
446 | self.lower_extern_block(ast) | ||
447 | .into_iter() | ||
448 | .map(|item| match item { | ||
449 | Either::Left(func) => self.tree.functions.alloc(func).into(), | ||
450 | Either::Right(statik) => self.tree.statics.alloc(statik).into(), | ||
451 | }) | ||
452 | .collect::<SmallVec<_>>(), | ||
453 | )), | ||
454 | }; | ||
455 | |||
456 | if !attrs.is_empty() { | ||
457 | for item in items.iter().flat_map(|items| &items.0) { | ||
458 | self.tree.attrs.insert(*item, attrs.clone()); | ||
459 | } | ||
460 | } | ||
461 | |||
462 | items | ||
463 | } | ||
464 | |||
465 | fn lower_assoc_item(&mut self, item: &ast::AssocItem) -> Option<AssocItem> { | ||
466 | match item { | ||
467 | ast::AssocItem::FnDef(ast) => { | ||
468 | self.lower_function(ast).map(|data| self.tree.functions.alloc(data).into()) | ||
469 | } | ||
470 | ast::AssocItem::TypeAliasDef(ast) => { | ||
471 | self.lower_type_alias(ast).map(|data| self.tree.type_aliases.alloc(data).into()) | ||
472 | } | ||
473 | ast::AssocItem::ConstDef(ast) => { | ||
474 | let data = self.lower_const(ast); | ||
475 | Some(self.tree.consts.alloc(data).into()) | ||
476 | } | ||
477 | } | ||
478 | } | ||
479 | |||
480 | fn lower_struct(&mut self, strukt: &ast::StructDef) -> Option<Struct> { | ||
481 | let attrs = self.lower_attrs(strukt); | ||
482 | let visibility = self.lower_visibility(strukt); | ||
483 | let name = strukt.name()?.as_name(); | ||
484 | let generic_params = self.lower_generic_params(strukt); | ||
485 | let fields = self.lower_fields(&strukt.kind()); | ||
486 | let ast_id = self.source_ast_id_map.ast_id(strukt); | ||
487 | let kind = match strukt.kind() { | ||
488 | ast::StructKind::Record(_) => StructDefKind::Record, | ||
489 | ast::StructKind::Tuple(_) => StructDefKind::Tuple, | ||
490 | ast::StructKind::Unit => StructDefKind::Unit, | ||
491 | }; | ||
492 | let res = Struct { name, attrs, visibility, generic_params, fields, ast_id, kind }; | ||
493 | Some(res) | ||
494 | } | ||
495 | |||
496 | fn lower_fields(&mut self, strukt_kind: &ast::StructKind) -> Fields { | ||
497 | match strukt_kind { | ||
498 | ast::StructKind::Record(it) => { | ||
499 | let range = self.lower_record_fields(it); | ||
500 | Fields::Record(range) | ||
501 | } | ||
502 | ast::StructKind::Tuple(it) => { | ||
503 | let range = self.lower_tuple_fields(it); | ||
504 | Fields::Tuple(range) | ||
505 | } | ||
506 | ast::StructKind::Unit => Fields::Unit, | ||
507 | } | ||
508 | } | ||
509 | |||
510 | fn lower_record_fields(&mut self, fields: &ast::RecordFieldDefList) -> Range<Idx<Field>> { | ||
511 | let start = self.next_field_idx(); | ||
512 | for field in fields.fields() { | ||
513 | if let Some(data) = self.lower_record_field(&field) { | ||
514 | self.tree.fields.alloc(data); | ||
515 | } | ||
516 | } | ||
517 | let end = self.next_field_idx(); | ||
518 | start..end | ||
519 | } | ||
520 | |||
521 | fn lower_record_field(&self, field: &ast::RecordFieldDef) -> Option<Field> { | ||
522 | let name = field.name()?.as_name(); | ||
523 | let visibility = self.lower_visibility(field); | ||
524 | let type_ref = self.lower_type_ref(&field.ascribed_type()?); | ||
525 | let res = Field { name, type_ref, visibility }; | ||
526 | Some(res) | ||
527 | } | ||
528 | |||
529 | fn lower_tuple_fields(&mut self, fields: &ast::TupleFieldDefList) -> Range<Idx<Field>> { | ||
530 | let start = self.next_field_idx(); | ||
531 | for (i, field) in fields.fields().enumerate() { | ||
532 | if let Some(data) = self.lower_tuple_field(i, &field) { | ||
533 | self.tree.fields.alloc(data); | ||
534 | } | ||
535 | } | ||
536 | let end = self.next_field_idx(); | ||
537 | start..end | ||
538 | } | ||
539 | |||
540 | fn lower_tuple_field(&self, idx: usize, field: &ast::TupleFieldDef) -> Option<Field> { | ||
541 | let name = Name::new_tuple_field(idx); | ||
542 | let visibility = self.lower_visibility(field); | ||
543 | let type_ref = self.lower_type_ref(&field.type_ref()?); | ||
544 | let res = Field { name, type_ref, visibility }; | ||
545 | Some(res) | ||
546 | } | ||
547 | |||
548 | fn lower_union(&mut self, union: &ast::UnionDef) -> Option<Union> { | ||
549 | let attrs = self.lower_attrs(union); | ||
550 | let visibility = self.lower_visibility(union); | ||
551 | let name = union.name()?.as_name(); | ||
552 | let generic_params = self.lower_generic_params(union); | ||
553 | let fields = match union.record_field_def_list() { | ||
554 | Some(record_field_def_list) => { | ||
555 | self.lower_fields(&StructKind::Record(record_field_def_list)) | ||
556 | } | ||
557 | None => Fields::Record(self.next_field_idx()..self.next_field_idx()), | ||
558 | }; | ||
559 | let ast_id = self.source_ast_id_map.ast_id(union); | ||
560 | let res = Union { name, attrs, visibility, generic_params, fields, ast_id }; | ||
561 | Some(res) | ||
562 | } | ||
563 | |||
564 | fn lower_enum(&mut self, enum_: &ast::EnumDef) -> Option<Enum> { | ||
565 | let attrs = self.lower_attrs(enum_); | ||
566 | let visibility = self.lower_visibility(enum_); | ||
567 | let name = enum_.name()?.as_name(); | ||
568 | let generic_params = self.lower_generic_params(enum_); | ||
569 | let variants = match &enum_.variant_list() { | ||
570 | Some(variant_list) => self.lower_variants(variant_list), | ||
571 | None => self.next_variant_idx()..self.next_variant_idx(), | ||
572 | }; | ||
573 | let ast_id = self.source_ast_id_map.ast_id(enum_); | ||
574 | let res = Enum { name, attrs, visibility, generic_params, variants, ast_id }; | ||
575 | Some(res) | ||
576 | } | ||
577 | |||
578 | fn lower_variants(&mut self, variants: &ast::EnumVariantList) -> Range<Idx<Variant>> { | ||
579 | let start = self.next_variant_idx(); | ||
580 | for variant in variants.variants() { | ||
581 | if let Some(data) = self.lower_variant(&variant) { | ||
582 | self.tree.variants.alloc(data); | ||
583 | } | ||
584 | } | ||
585 | let end = self.next_variant_idx(); | ||
586 | start..end | ||
587 | } | ||
588 | |||
589 | fn lower_variant(&mut self, variant: &ast::EnumVariant) -> Option<Variant> { | ||
590 | let name = variant.name()?.as_name(); | ||
591 | let fields = self.lower_fields(&variant.kind()); | ||
592 | let res = Variant { name, fields }; | ||
593 | Some(res) | ||
594 | } | ||
595 | |||
596 | fn lower_function(&mut self, func: &ast::FnDef) -> Option<Function> { | ||
597 | let attrs = self.lower_attrs(func); | ||
598 | let visibility = self.lower_visibility(func); | ||
599 | let name = func.name()?.as_name(); | ||
600 | let generic_params = self.lower_generic_params(func); | ||
601 | |||
602 | let mut params = Vec::new(); | ||
603 | let mut has_self_param = false; | ||
604 | if let Some(param_list) = func.param_list() { | ||
605 | if let Some(self_param) = param_list.self_param() { | ||
606 | let self_type = if let Some(type_ref) = self_param.ascribed_type() { | ||
607 | TypeRef::from_ast(&self.body_ctx, type_ref) | ||
608 | } else { | ||
609 | let self_type = TypeRef::Path(name![Self].into()); | ||
610 | match self_param.kind() { | ||
611 | ast::SelfParamKind::Owned => self_type, | ||
612 | ast::SelfParamKind::Ref => { | ||
613 | TypeRef::Reference(Box::new(self_type), Mutability::Shared) | ||
614 | } | ||
615 | ast::SelfParamKind::MutRef => { | ||
616 | TypeRef::Reference(Box::new(self_type), Mutability::Mut) | ||
617 | } | ||
618 | } | ||
619 | }; | ||
620 | params.push(self_type); | ||
621 | has_self_param = true; | ||
622 | } | ||
623 | for param in param_list.params() { | ||
624 | let type_ref = TypeRef::from_ast_opt(&self.body_ctx, param.ascribed_type()); | ||
625 | params.push(type_ref); | ||
626 | } | ||
627 | } | ||
628 | let ret_type = match func.ret_type().and_then(|rt| rt.type_ref()) { | ||
629 | Some(type_ref) => TypeRef::from_ast(&self.body_ctx, type_ref), | ||
630 | _ => TypeRef::unit(), | ||
631 | }; | ||
632 | |||
633 | let ret_type = if func.async_token().is_some() { | ||
634 | let future_impl = desugar_future_path(ret_type); | ||
635 | let ty_bound = TypeBound::Path(future_impl); | ||
636 | TypeRef::ImplTrait(vec![ty_bound]) | ||
637 | } else { | ||
638 | ret_type | ||
639 | }; | ||
640 | |||
641 | let ast_id = self.source_ast_id_map.ast_id(func); | ||
642 | let res = Function { | ||
643 | name, | ||
644 | attrs, | ||
645 | visibility, | ||
646 | generic_params, | ||
647 | has_self_param, | ||
648 | params, | ||
649 | ret_type, | ||
650 | ast_id, | ||
651 | }; | ||
652 | Some(res) | ||
653 | } | ||
654 | |||
655 | fn lower_type_alias(&mut self, type_alias: &ast::TypeAliasDef) -> Option<TypeAlias> { | ||
656 | let name = type_alias.name()?.as_name(); | ||
657 | let type_ref = type_alias.type_ref().map(|it| self.lower_type_ref(&it)); | ||
658 | let visibility = self.lower_visibility(type_alias); | ||
659 | let generic_params = self.lower_generic_params(type_alias); | ||
660 | let ast_id = self.source_ast_id_map.ast_id(type_alias); | ||
661 | let res = TypeAlias { name, visibility, generic_params, type_ref, ast_id }; | ||
662 | Some(res) | ||
663 | } | ||
664 | |||
665 | fn lower_static(&mut self, static_: &ast::StaticDef) -> Option<Static> { | ||
666 | let name = static_.name()?.as_name(); | ||
667 | let type_ref = self.lower_type_ref_opt(static_.ascribed_type()); | ||
668 | let visibility = self.lower_visibility(static_); | ||
669 | let ast_id = self.source_ast_id_map.ast_id(static_); | ||
670 | let res = Static { name, visibility, type_ref, ast_id }; | ||
671 | Some(res) | ||
672 | } | ||
673 | |||
674 | fn lower_const(&mut self, konst: &ast::ConstDef) -> Const { | ||
675 | let name = konst.name().map(|it| it.as_name()); | ||
676 | let type_ref = self.lower_type_ref_opt(konst.ascribed_type()); | ||
677 | let visibility = self.lower_visibility(konst); | ||
678 | let ast_id = self.source_ast_id_map.ast_id(konst); | ||
679 | Const { name, visibility, type_ref, ast_id } | ||
680 | } | ||
681 | |||
682 | fn lower_module(&mut self, module: &ast::Module) -> Option<Mod> { | ||
683 | let name = module.name()?.as_name(); | ||
684 | let visibility = self.lower_visibility(module); | ||
685 | let kind = if module.semicolon_token().is_some() { | ||
686 | ModKind::Outline {} | ||
687 | } else { | ||
688 | ModKind::Inline { | ||
689 | items: module | ||
690 | .item_list() | ||
691 | .map(|list| { | ||
692 | list.items() | ||
693 | .flat_map(|item| self.lower_mod_item(&item)) | ||
694 | .flat_map(|items| items.0) | ||
695 | .collect() | ||
696 | }) | ||
697 | .unwrap_or_else(|| { | ||
698 | mark::hit!(name_res_works_for_broken_modules); | ||
699 | Vec::new() | ||
700 | }), | ||
701 | } | ||
702 | }; | ||
703 | let ast_id = self.source_ast_id_map.ast_id(module); | ||
704 | Some(Mod { name, visibility, kind, ast_id }) | ||
705 | } | ||
706 | |||
707 | fn lower_trait(&mut self, trait_def: &ast::TraitDef) -> Option<Trait> { | ||
708 | let name = trait_def.name()?.as_name(); | ||
709 | let visibility = self.lower_visibility(trait_def); | ||
710 | let generic_params = self.lower_generic_params(trait_def); | ||
711 | let auto = trait_def.auto_token().is_some(); | ||
712 | let items = trait_def.item_list().map(|list| { | ||
713 | // FIXME: Does not handle macros | ||
714 | list.assoc_items().flat_map(|item| self.lower_assoc_item(&item)).collect() | ||
715 | }); | ||
716 | let ast_id = self.source_ast_id_map.ast_id(trait_def); | ||
717 | Some(Trait { | ||
718 | name, | ||
719 | visibility, | ||
720 | generic_params, | ||
721 | auto, | ||
722 | items: items.unwrap_or_default(), | ||
723 | ast_id, | ||
724 | }) | ||
725 | } | ||
726 | |||
727 | fn lower_impl(&mut self, impl_def: &ast::ImplDef) -> Option<Impl> { | ||
728 | let generic_params = self.lower_generic_params(impl_def); | ||
729 | let target_trait = impl_def.target_trait().map(|tr| self.lower_type_ref(&tr)); | ||
730 | let target_type = self.lower_type_ref(&impl_def.target_type()?); | ||
731 | let is_negative = impl_def.excl_token().is_some(); | ||
732 | let items = impl_def | ||
733 | .item_list()? | ||
734 | .assoc_items() | ||
735 | .filter_map(|item| self.lower_assoc_item(&item)) | ||
736 | .collect(); | ||
737 | let ast_id = self.source_ast_id_map.ast_id(impl_def); | ||
738 | Some(Impl { generic_params, target_trait, target_type, is_negative, items, ast_id }) | ||
739 | } | ||
740 | |||
741 | fn lower_use(&mut self, use_item: &ast::UseItem) -> Vec<Import> { | ||
742 | // FIXME: cfg_attr | ||
743 | let is_prelude = use_item.has_atom_attr("prelude_import"); | ||
744 | let visibility = self.lower_visibility(use_item); | ||
745 | |||
746 | // Every use item can expand to many `Import`s. | ||
747 | let mut imports = Vec::new(); | ||
748 | ModPath::expand_use_item( | ||
749 | InFile::new(self.file, use_item.clone()), | ||
750 | &self.hygiene, | ||
751 | |path, _tree, is_glob, alias| { | ||
752 | imports.push(Import { | ||
753 | path, | ||
754 | alias, | ||
755 | visibility: visibility.clone(), | ||
756 | is_glob, | ||
757 | is_prelude, | ||
758 | is_extern_crate: false, | ||
759 | is_macro_use: false, | ||
760 | }); | ||
761 | }, | ||
762 | ); | ||
763 | |||
764 | imports | ||
765 | } | ||
766 | |||
767 | fn lower_extern_crate(&mut self, extern_crate: &ast::ExternCrateItem) -> Option<Import> { | ||
768 | let path = ModPath::from_name_ref(&extern_crate.name_ref()?); | ||
769 | let alias = extern_crate.alias().map(|a| { | ||
770 | a.name().map(|it| it.as_name()).map_or(ImportAlias::Underscore, ImportAlias::Alias) | ||
771 | }); | ||
772 | let visibility = self.lower_visibility(extern_crate); | ||
773 | // FIXME: cfg_attr | ||
774 | let is_macro_use = extern_crate.has_atom_attr("macro_use"); | ||
775 | |||
776 | Some(Import { | ||
777 | path, | ||
778 | alias, | ||
779 | visibility, | ||
780 | is_glob: false, | ||
781 | is_prelude: false, | ||
782 | is_extern_crate: true, | ||
783 | is_macro_use, | ||
784 | }) | ||
785 | } | ||
786 | |||
787 | fn lower_macro_call(&mut self, m: &ast::MacroCall) -> Option<MacroCall> { | ||
788 | let name = m.name().map(|it| it.as_name()); | ||
789 | let attrs = Attrs::new(m, &self.hygiene); | ||
790 | let path = ModPath::from_src(m.path()?, &self.hygiene)?; | ||
791 | |||
792 | let ast_id = self.source_ast_id_map.ast_id(m); | ||
793 | |||
794 | // FIXME: cfg_attr | ||
795 | let export_attr = attrs.by_key("macro_export"); | ||
796 | |||
797 | let is_export = export_attr.exists(); | ||
798 | let is_local_inner = if is_export { | ||
799 | export_attr.tt_values().map(|it| &it.token_trees).flatten().any(|it| match it { | ||
800 | tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) => { | ||
801 | ident.text.contains("local_inner_macros") | ||
802 | } | ||
803 | _ => false, | ||
804 | }) | ||
805 | } else { | ||
806 | false | ||
807 | }; | ||
808 | |||
809 | let is_builtin = attrs.by_key("rustc_builtin_macro").exists(); | ||
810 | Some(MacroCall { name, path, is_export, is_builtin, is_local_inner, ast_id }) | ||
811 | } | ||
812 | |||
813 | fn lower_extern_block(&mut self, block: &ast::ExternBlock) -> Vec<Either<Function, Static>> { | ||
814 | block.extern_item_list().map_or(Vec::new(), |list| { | ||
815 | list.extern_items() | ||
816 | .filter_map(|item| match item { | ||
817 | ast::ExternItem::FnDef(ast) => self.lower_function(&ast).map(Either::Left), | ||
818 | ast::ExternItem::StaticDef(ast) => self.lower_static(&ast).map(Either::Right), | ||
819 | }) | ||
820 | .collect() | ||
821 | }) | ||
822 | } | ||
823 | |||
824 | fn lower_generic_params( | ||
825 | &mut self, | ||
826 | _item: &impl ast::TypeParamsOwner, | ||
827 | ) -> generics::GenericParams { | ||
828 | // TODO | ||
829 | generics::GenericParams { types: Arena::new(), where_predicates: Vec::new() } | ||
830 | } | ||
831 | |||
832 | fn lower_attrs(&self, item: &impl ast::AttrsOwner) -> Attrs { | ||
833 | Attrs::new(item, &self.hygiene) | ||
834 | } | ||
835 | fn lower_visibility(&self, item: &impl ast::VisibilityOwner) -> RawVisibility { | ||
836 | RawVisibility::from_ast_with_hygiene(item.visibility(), &self.hygiene) | ||
837 | } | ||
838 | fn lower_type_ref(&self, type_ref: &ast::TypeRef) -> TypeRef { | ||
839 | TypeRef::from_ast(&self.body_ctx, type_ref.clone()) | ||
840 | } | ||
841 | fn lower_type_ref_opt(&self, type_ref: Option<ast::TypeRef>) -> TypeRef { | ||
842 | TypeRef::from_ast_opt(&self.body_ctx, type_ref) | ||
843 | } | ||
844 | |||
845 | fn next_field_idx(&self) -> Idx<Field> { | ||
846 | Idx::from_raw(RawId::from(self.tree.fields.len() as u32)) | ||
847 | } | ||
848 | fn next_variant_idx(&self) -> Idx<Variant> { | ||
849 | Idx::from_raw(RawId::from(self.tree.variants.len() as u32)) | ||
850 | } | ||
851 | } | ||
852 | |||
853 | fn desugar_future_path(orig: TypeRef) -> Path { | ||
854 | let path = path![core::future::Future]; | ||
855 | let mut generic_args: Vec<_> = std::iter::repeat(None).take(path.segments.len() - 1).collect(); | ||
856 | let mut last = GenericArgs::empty(); | ||
857 | let binding = | ||
858 | AssociatedTypeBinding { name: name![Output], type_ref: Some(orig), bounds: Vec::new() }; | ||
859 | last.bindings.push(binding); | ||
860 | generic_args.push(Some(Arc::new(last))); | ||
861 | |||
862 | Path::from_known_path(path, generic_args) | ||
863 | } | ||
diff --git a/crates/ra_hir_def/src/item_tree/lower.rs b/crates/ra_hir_def/src/item_tree/lower.rs new file mode 100644 index 000000000..d123a7310 --- /dev/null +++ b/crates/ra_hir_def/src/item_tree/lower.rs | |||
@@ -0,0 +1,501 @@ | |||
1 | use super::*; | ||
2 | use crate::attr::Attrs; | ||
3 | use hir_expand::{ast_id_map::AstIdMap, hygiene::Hygiene, HirFileId}; | ||
4 | use ra_syntax::ast::{self, ModuleItemOwner}; | ||
5 | use smallvec::SmallVec; | ||
6 | use std::sync::Arc; | ||
7 | |||
8 | struct ModItems(SmallVec<[ModItem; 1]>); | ||
9 | |||
10 | impl<T> From<T> for ModItems | ||
11 | where | ||
12 | T: Into<ModItem>, | ||
13 | { | ||
14 | fn from(t: T) -> Self { | ||
15 | ModItems(SmallVec::from_buf([t.into(); 1])) | ||
16 | } | ||
17 | } | ||
18 | |||
19 | pub(super) struct Ctx { | ||
20 | pub tree: ItemTree, | ||
21 | pub hygiene: Hygiene, | ||
22 | pub file: HirFileId, | ||
23 | pub source_ast_id_map: Arc<AstIdMap>, | ||
24 | pub body_ctx: crate::body::LowerCtx, | ||
25 | } | ||
26 | |||
27 | impl Ctx { | ||
28 | pub(super) fn lower(mut self, item_owner: &dyn ModuleItemOwner) -> ItemTree { | ||
29 | self.tree.top_level = item_owner | ||
30 | .items() | ||
31 | .flat_map(|item| self.lower_mod_item(&item)) | ||
32 | .flat_map(|items| items.0) | ||
33 | .collect(); | ||
34 | self.tree | ||
35 | } | ||
36 | |||
37 | fn lower_mod_item(&mut self, item: &ast::ModuleItem) -> Option<ModItems> { | ||
38 | let attrs = Attrs::new(item, &self.hygiene); | ||
39 | let items = match item { | ||
40 | ast::ModuleItem::StructDef(ast) => { | ||
41 | self.lower_struct(ast).map(|data| self.tree.structs.alloc(data).into()) | ||
42 | } | ||
43 | ast::ModuleItem::UnionDef(ast) => { | ||
44 | self.lower_union(ast).map(|data| self.tree.unions.alloc(data).into()) | ||
45 | } | ||
46 | ast::ModuleItem::EnumDef(ast) => { | ||
47 | self.lower_enum(ast).map(|data| self.tree.enums.alloc(data).into()) | ||
48 | } | ||
49 | ast::ModuleItem::FnDef(ast) => { | ||
50 | self.lower_function(ast).map(|data| self.tree.functions.alloc(data).into()) | ||
51 | } | ||
52 | ast::ModuleItem::TypeAliasDef(ast) => { | ||
53 | self.lower_type_alias(ast).map(|data| self.tree.type_aliases.alloc(data).into()) | ||
54 | } | ||
55 | ast::ModuleItem::StaticDef(ast) => { | ||
56 | self.lower_static(ast).map(|data| self.tree.statics.alloc(data).into()) | ||
57 | } | ||
58 | ast::ModuleItem::ConstDef(ast) => { | ||
59 | let data = self.lower_const(ast); | ||
60 | Some(self.tree.consts.alloc(data).into()) | ||
61 | } | ||
62 | ast::ModuleItem::Module(ast) => { | ||
63 | self.lower_module(ast).map(|data| self.tree.mods.alloc(data).into()) | ||
64 | } | ||
65 | ast::ModuleItem::TraitDef(ast) => { | ||
66 | self.lower_trait(ast).map(|data| self.tree.traits.alloc(data).into()) | ||
67 | } | ||
68 | ast::ModuleItem::ImplDef(ast) => { | ||
69 | self.lower_impl(ast).map(|data| self.tree.impls.alloc(data).into()) | ||
70 | } | ||
71 | ast::ModuleItem::UseItem(ast) => Some(ModItems( | ||
72 | self.lower_use(ast) | ||
73 | .into_iter() | ||
74 | .map(|data| self.tree.imports.alloc(data).into()) | ||
75 | .collect::<SmallVec<_>>(), | ||
76 | )), | ||
77 | ast::ModuleItem::ExternCrateItem(ast) => { | ||
78 | self.lower_extern_crate(ast).map(|data| self.tree.imports.alloc(data).into()) | ||
79 | } | ||
80 | ast::ModuleItem::MacroCall(ast) => { | ||
81 | self.lower_macro_call(ast).map(|data| self.tree.macro_calls.alloc(data).into()) | ||
82 | } | ||
83 | ast::ModuleItem::ExternBlock(ast) => Some(ModItems( | ||
84 | self.lower_extern_block(ast) | ||
85 | .into_iter() | ||
86 | .map(|item| match item { | ||
87 | Either::Left(func) => self.tree.functions.alloc(func).into(), | ||
88 | Either::Right(statik) => self.tree.statics.alloc(statik).into(), | ||
89 | }) | ||
90 | .collect::<SmallVec<_>>(), | ||
91 | )), | ||
92 | }; | ||
93 | |||
94 | if !attrs.is_empty() { | ||
95 | for item in items.iter().flat_map(|items| &items.0) { | ||
96 | self.tree.attrs.insert(*item, attrs.clone()); | ||
97 | } | ||
98 | } | ||
99 | |||
100 | items | ||
101 | } | ||
102 | |||
103 | fn lower_assoc_item(&mut self, item: &ast::AssocItem) -> Option<AssocItem> { | ||
104 | match item { | ||
105 | ast::AssocItem::FnDef(ast) => { | ||
106 | self.lower_function(ast).map(|data| self.tree.functions.alloc(data).into()) | ||
107 | } | ||
108 | ast::AssocItem::TypeAliasDef(ast) => { | ||
109 | self.lower_type_alias(ast).map(|data| self.tree.type_aliases.alloc(data).into()) | ||
110 | } | ||
111 | ast::AssocItem::ConstDef(ast) => { | ||
112 | let data = self.lower_const(ast); | ||
113 | Some(self.tree.consts.alloc(data).into()) | ||
114 | } | ||
115 | } | ||
116 | } | ||
117 | |||
118 | fn lower_struct(&mut self, strukt: &ast::StructDef) -> Option<Struct> { | ||
119 | let attrs = self.lower_attrs(strukt); | ||
120 | let visibility = self.lower_visibility(strukt); | ||
121 | let name = strukt.name()?.as_name(); | ||
122 | let generic_params = self.lower_generic_params(strukt); | ||
123 | let fields = self.lower_fields(&strukt.kind()); | ||
124 | let ast_id = self.source_ast_id_map.ast_id(strukt); | ||
125 | let kind = match strukt.kind() { | ||
126 | ast::StructKind::Record(_) => StructDefKind::Record, | ||
127 | ast::StructKind::Tuple(_) => StructDefKind::Tuple, | ||
128 | ast::StructKind::Unit => StructDefKind::Unit, | ||
129 | }; | ||
130 | let res = Struct { name, attrs, visibility, generic_params, fields, ast_id, kind }; | ||
131 | Some(res) | ||
132 | } | ||
133 | |||
134 | fn lower_fields(&mut self, strukt_kind: &ast::StructKind) -> Fields { | ||
135 | match strukt_kind { | ||
136 | ast::StructKind::Record(it) => { | ||
137 | let range = self.lower_record_fields(it); | ||
138 | Fields::Record(range) | ||
139 | } | ||
140 | ast::StructKind::Tuple(it) => { | ||
141 | let range = self.lower_tuple_fields(it); | ||
142 | Fields::Tuple(range) | ||
143 | } | ||
144 | ast::StructKind::Unit => Fields::Unit, | ||
145 | } | ||
146 | } | ||
147 | |||
148 | fn lower_record_fields(&mut self, fields: &ast::RecordFieldDefList) -> Range<Idx<Field>> { | ||
149 | let start = self.next_field_idx(); | ||
150 | for field in fields.fields() { | ||
151 | if let Some(data) = self.lower_record_field(&field) { | ||
152 | self.tree.fields.alloc(data); | ||
153 | } | ||
154 | } | ||
155 | let end = self.next_field_idx(); | ||
156 | start..end | ||
157 | } | ||
158 | |||
159 | fn lower_record_field(&self, field: &ast::RecordFieldDef) -> Option<Field> { | ||
160 | let name = field.name()?.as_name(); | ||
161 | let visibility = self.lower_visibility(field); | ||
162 | let type_ref = self.lower_type_ref(&field.ascribed_type()?); | ||
163 | let res = Field { name, type_ref, visibility }; | ||
164 | Some(res) | ||
165 | } | ||
166 | |||
167 | fn lower_tuple_fields(&mut self, fields: &ast::TupleFieldDefList) -> Range<Idx<Field>> { | ||
168 | let start = self.next_field_idx(); | ||
169 | for (i, field) in fields.fields().enumerate() { | ||
170 | if let Some(data) = self.lower_tuple_field(i, &field) { | ||
171 | self.tree.fields.alloc(data); | ||
172 | } | ||
173 | } | ||
174 | let end = self.next_field_idx(); | ||
175 | start..end | ||
176 | } | ||
177 | |||
178 | fn lower_tuple_field(&self, idx: usize, field: &ast::TupleFieldDef) -> Option<Field> { | ||
179 | let name = Name::new_tuple_field(idx); | ||
180 | let visibility = self.lower_visibility(field); | ||
181 | let type_ref = self.lower_type_ref(&field.type_ref()?); | ||
182 | let res = Field { name, type_ref, visibility }; | ||
183 | Some(res) | ||
184 | } | ||
185 | |||
186 | fn lower_union(&mut self, union: &ast::UnionDef) -> Option<Union> { | ||
187 | let attrs = self.lower_attrs(union); | ||
188 | let visibility = self.lower_visibility(union); | ||
189 | let name = union.name()?.as_name(); | ||
190 | let generic_params = self.lower_generic_params(union); | ||
191 | let fields = match union.record_field_def_list() { | ||
192 | Some(record_field_def_list) => { | ||
193 | self.lower_fields(&StructKind::Record(record_field_def_list)) | ||
194 | } | ||
195 | None => Fields::Record(self.next_field_idx()..self.next_field_idx()), | ||
196 | }; | ||
197 | let ast_id = self.source_ast_id_map.ast_id(union); | ||
198 | let res = Union { name, attrs, visibility, generic_params, fields, ast_id }; | ||
199 | Some(res) | ||
200 | } | ||
201 | |||
202 | fn lower_enum(&mut self, enum_: &ast::EnumDef) -> Option<Enum> { | ||
203 | let attrs = self.lower_attrs(enum_); | ||
204 | let visibility = self.lower_visibility(enum_); | ||
205 | let name = enum_.name()?.as_name(); | ||
206 | let generic_params = self.lower_generic_params(enum_); | ||
207 | let variants = match &enum_.variant_list() { | ||
208 | Some(variant_list) => self.lower_variants(variant_list), | ||
209 | None => self.next_variant_idx()..self.next_variant_idx(), | ||
210 | }; | ||
211 | let ast_id = self.source_ast_id_map.ast_id(enum_); | ||
212 | let res = Enum { name, attrs, visibility, generic_params, variants, ast_id }; | ||
213 | Some(res) | ||
214 | } | ||
215 | |||
216 | fn lower_variants(&mut self, variants: &ast::EnumVariantList) -> Range<Idx<Variant>> { | ||
217 | let start = self.next_variant_idx(); | ||
218 | for variant in variants.variants() { | ||
219 | if let Some(data) = self.lower_variant(&variant) { | ||
220 | self.tree.variants.alloc(data); | ||
221 | } | ||
222 | } | ||
223 | let end = self.next_variant_idx(); | ||
224 | start..end | ||
225 | } | ||
226 | |||
227 | fn lower_variant(&mut self, variant: &ast::EnumVariant) -> Option<Variant> { | ||
228 | let name = variant.name()?.as_name(); | ||
229 | let fields = self.lower_fields(&variant.kind()); | ||
230 | let res = Variant { name, fields }; | ||
231 | Some(res) | ||
232 | } | ||
233 | |||
234 | fn lower_function(&mut self, func: &ast::FnDef) -> Option<Function> { | ||
235 | let attrs = self.lower_attrs(func); | ||
236 | let visibility = self.lower_visibility(func); | ||
237 | let name = func.name()?.as_name(); | ||
238 | let generic_params = self.lower_generic_params(func); | ||
239 | |||
240 | let mut params = Vec::new(); | ||
241 | let mut has_self_param = false; | ||
242 | if let Some(param_list) = func.param_list() { | ||
243 | if let Some(self_param) = param_list.self_param() { | ||
244 | let self_type = if let Some(type_ref) = self_param.ascribed_type() { | ||
245 | TypeRef::from_ast(&self.body_ctx, type_ref) | ||
246 | } else { | ||
247 | let self_type = TypeRef::Path(name![Self].into()); | ||
248 | match self_param.kind() { | ||
249 | ast::SelfParamKind::Owned => self_type, | ||
250 | ast::SelfParamKind::Ref => { | ||
251 | TypeRef::Reference(Box::new(self_type), Mutability::Shared) | ||
252 | } | ||
253 | ast::SelfParamKind::MutRef => { | ||
254 | TypeRef::Reference(Box::new(self_type), Mutability::Mut) | ||
255 | } | ||
256 | } | ||
257 | }; | ||
258 | params.push(self_type); | ||
259 | has_self_param = true; | ||
260 | } | ||
261 | for param in param_list.params() { | ||
262 | let type_ref = TypeRef::from_ast_opt(&self.body_ctx, param.ascribed_type()); | ||
263 | params.push(type_ref); | ||
264 | } | ||
265 | } | ||
266 | let ret_type = match func.ret_type().and_then(|rt| rt.type_ref()) { | ||
267 | Some(type_ref) => TypeRef::from_ast(&self.body_ctx, type_ref), | ||
268 | _ => TypeRef::unit(), | ||
269 | }; | ||
270 | |||
271 | let ret_type = if func.async_token().is_some() { | ||
272 | let future_impl = desugar_future_path(ret_type); | ||
273 | let ty_bound = TypeBound::Path(future_impl); | ||
274 | TypeRef::ImplTrait(vec![ty_bound]) | ||
275 | } else { | ||
276 | ret_type | ||
277 | }; | ||
278 | |||
279 | let ast_id = self.source_ast_id_map.ast_id(func); | ||
280 | let res = Function { | ||
281 | name, | ||
282 | attrs, | ||
283 | visibility, | ||
284 | generic_params, | ||
285 | has_self_param, | ||
286 | params, | ||
287 | ret_type, | ||
288 | ast_id, | ||
289 | }; | ||
290 | Some(res) | ||
291 | } | ||
292 | |||
293 | fn lower_type_alias(&mut self, type_alias: &ast::TypeAliasDef) -> Option<TypeAlias> { | ||
294 | let name = type_alias.name()?.as_name(); | ||
295 | let type_ref = type_alias.type_ref().map(|it| self.lower_type_ref(&it)); | ||
296 | let visibility = self.lower_visibility(type_alias); | ||
297 | let generic_params = self.lower_generic_params(type_alias); | ||
298 | let ast_id = self.source_ast_id_map.ast_id(type_alias); | ||
299 | let res = TypeAlias { name, visibility, generic_params, type_ref, ast_id }; | ||
300 | Some(res) | ||
301 | } | ||
302 | |||
303 | fn lower_static(&mut self, static_: &ast::StaticDef) -> Option<Static> { | ||
304 | let name = static_.name()?.as_name(); | ||
305 | let type_ref = self.lower_type_ref_opt(static_.ascribed_type()); | ||
306 | let visibility = self.lower_visibility(static_); | ||
307 | let ast_id = self.source_ast_id_map.ast_id(static_); | ||
308 | let res = Static { name, visibility, type_ref, ast_id }; | ||
309 | Some(res) | ||
310 | } | ||
311 | |||
312 | fn lower_const(&mut self, konst: &ast::ConstDef) -> Const { | ||
313 | let name = konst.name().map(|it| it.as_name()); | ||
314 | let type_ref = self.lower_type_ref_opt(konst.ascribed_type()); | ||
315 | let visibility = self.lower_visibility(konst); | ||
316 | let ast_id = self.source_ast_id_map.ast_id(konst); | ||
317 | Const { name, visibility, type_ref, ast_id } | ||
318 | } | ||
319 | |||
320 | fn lower_module(&mut self, module: &ast::Module) -> Option<Mod> { | ||
321 | let name = module.name()?.as_name(); | ||
322 | let visibility = self.lower_visibility(module); | ||
323 | let kind = if module.semicolon_token().is_some() { | ||
324 | ModKind::Outline {} | ||
325 | } else { | ||
326 | ModKind::Inline { | ||
327 | items: module | ||
328 | .item_list() | ||
329 | .map(|list| { | ||
330 | list.items() | ||
331 | .flat_map(|item| self.lower_mod_item(&item)) | ||
332 | .flat_map(|items| items.0) | ||
333 | .collect() | ||
334 | }) | ||
335 | .unwrap_or_else(|| { | ||
336 | mark::hit!(name_res_works_for_broken_modules); | ||
337 | Vec::new() | ||
338 | }), | ||
339 | } | ||
340 | }; | ||
341 | let ast_id = self.source_ast_id_map.ast_id(module); | ||
342 | Some(Mod { name, visibility, kind, ast_id }) | ||
343 | } | ||
344 | |||
345 | fn lower_trait(&mut self, trait_def: &ast::TraitDef) -> Option<Trait> { | ||
346 | let name = trait_def.name()?.as_name(); | ||
347 | let visibility = self.lower_visibility(trait_def); | ||
348 | let generic_params = self.lower_generic_params(trait_def); | ||
349 | let auto = trait_def.auto_token().is_some(); | ||
350 | let items = trait_def.item_list().map(|list| { | ||
351 | // FIXME: Does not handle macros | ||
352 | list.assoc_items().flat_map(|item| self.lower_assoc_item(&item)).collect() | ||
353 | }); | ||
354 | let ast_id = self.source_ast_id_map.ast_id(trait_def); | ||
355 | Some(Trait { | ||
356 | name, | ||
357 | visibility, | ||
358 | generic_params, | ||
359 | auto, | ||
360 | items: items.unwrap_or_default(), | ||
361 | ast_id, | ||
362 | }) | ||
363 | } | ||
364 | |||
365 | fn lower_impl(&mut self, impl_def: &ast::ImplDef) -> Option<Impl> { | ||
366 | let generic_params = self.lower_generic_params(impl_def); | ||
367 | let target_trait = impl_def.target_trait().map(|tr| self.lower_type_ref(&tr)); | ||
368 | let target_type = self.lower_type_ref(&impl_def.target_type()?); | ||
369 | let is_negative = impl_def.excl_token().is_some(); | ||
370 | let items = impl_def | ||
371 | .item_list()? | ||
372 | .assoc_items() | ||
373 | .filter_map(|item| self.lower_assoc_item(&item)) | ||
374 | .collect(); | ||
375 | let ast_id = self.source_ast_id_map.ast_id(impl_def); | ||
376 | Some(Impl { generic_params, target_trait, target_type, is_negative, items, ast_id }) | ||
377 | } | ||
378 | |||
379 | fn lower_use(&mut self, use_item: &ast::UseItem) -> Vec<Import> { | ||
380 | // FIXME: cfg_attr | ||
381 | let is_prelude = use_item.has_atom_attr("prelude_import"); | ||
382 | let visibility = self.lower_visibility(use_item); | ||
383 | |||
384 | // Every use item can expand to many `Import`s. | ||
385 | let mut imports = Vec::new(); | ||
386 | ModPath::expand_use_item( | ||
387 | InFile::new(self.file, use_item.clone()), | ||
388 | &self.hygiene, | ||
389 | |path, _tree, is_glob, alias| { | ||
390 | imports.push(Import { | ||
391 | path, | ||
392 | alias, | ||
393 | visibility: visibility.clone(), | ||
394 | is_glob, | ||
395 | is_prelude, | ||
396 | is_extern_crate: false, | ||
397 | is_macro_use: false, | ||
398 | }); | ||
399 | }, | ||
400 | ); | ||
401 | |||
402 | imports | ||
403 | } | ||
404 | |||
405 | fn lower_extern_crate(&mut self, extern_crate: &ast::ExternCrateItem) -> Option<Import> { | ||
406 | let path = ModPath::from_name_ref(&extern_crate.name_ref()?); | ||
407 | let alias = extern_crate.alias().map(|a| { | ||
408 | a.name().map(|it| it.as_name()).map_or(ImportAlias::Underscore, ImportAlias::Alias) | ||
409 | }); | ||
410 | let visibility = self.lower_visibility(extern_crate); | ||
411 | // FIXME: cfg_attr | ||
412 | let is_macro_use = extern_crate.has_atom_attr("macro_use"); | ||
413 | |||
414 | Some(Import { | ||
415 | path, | ||
416 | alias, | ||
417 | visibility, | ||
418 | is_glob: false, | ||
419 | is_prelude: false, | ||
420 | is_extern_crate: true, | ||
421 | is_macro_use, | ||
422 | }) | ||
423 | } | ||
424 | |||
425 | fn lower_macro_call(&mut self, m: &ast::MacroCall) -> Option<MacroCall> { | ||
426 | let name = m.name().map(|it| it.as_name()); | ||
427 | let attrs = Attrs::new(m, &self.hygiene); | ||
428 | let path = ModPath::from_src(m.path()?, &self.hygiene)?; | ||
429 | |||
430 | let ast_id = self.source_ast_id_map.ast_id(m); | ||
431 | |||
432 | // FIXME: cfg_attr | ||
433 | let export_attr = attrs.by_key("macro_export"); | ||
434 | |||
435 | let is_export = export_attr.exists(); | ||
436 | let is_local_inner = if is_export { | ||
437 | export_attr.tt_values().map(|it| &it.token_trees).flatten().any(|it| match it { | ||
438 | tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) => { | ||
439 | ident.text.contains("local_inner_macros") | ||
440 | } | ||
441 | _ => false, | ||
442 | }) | ||
443 | } else { | ||
444 | false | ||
445 | }; | ||
446 | |||
447 | let is_builtin = attrs.by_key("rustc_builtin_macro").exists(); | ||
448 | Some(MacroCall { name, path, is_export, is_builtin, is_local_inner, ast_id }) | ||
449 | } | ||
450 | |||
451 | fn lower_extern_block(&mut self, block: &ast::ExternBlock) -> Vec<Either<Function, Static>> { | ||
452 | block.extern_item_list().map_or(Vec::new(), |list| { | ||
453 | list.extern_items() | ||
454 | .filter_map(|item| match item { | ||
455 | ast::ExternItem::FnDef(ast) => self.lower_function(&ast).map(Either::Left), | ||
456 | ast::ExternItem::StaticDef(ast) => self.lower_static(&ast).map(Either::Right), | ||
457 | }) | ||
458 | .collect() | ||
459 | }) | ||
460 | } | ||
461 | |||
462 | fn lower_generic_params( | ||
463 | &mut self, | ||
464 | _item: &impl ast::TypeParamsOwner, | ||
465 | ) -> generics::GenericParams { | ||
466 | // TODO | ||
467 | generics::GenericParams { types: Arena::new(), where_predicates: Vec::new() } | ||
468 | } | ||
469 | |||
470 | fn lower_attrs(&self, item: &impl ast::AttrsOwner) -> Attrs { | ||
471 | Attrs::new(item, &self.hygiene) | ||
472 | } | ||
473 | fn lower_visibility(&self, item: &impl ast::VisibilityOwner) -> RawVisibility { | ||
474 | RawVisibility::from_ast_with_hygiene(item.visibility(), &self.hygiene) | ||
475 | } | ||
476 | fn lower_type_ref(&self, type_ref: &ast::TypeRef) -> TypeRef { | ||
477 | TypeRef::from_ast(&self.body_ctx, type_ref.clone()) | ||
478 | } | ||
479 | fn lower_type_ref_opt(&self, type_ref: Option<ast::TypeRef>) -> TypeRef { | ||
480 | TypeRef::from_ast_opt(&self.body_ctx, type_ref) | ||
481 | } | ||
482 | |||
483 | fn next_field_idx(&self) -> Idx<Field> { | ||
484 | Idx::from_raw(RawId::from(self.tree.fields.len() as u32)) | ||
485 | } | ||
486 | fn next_variant_idx(&self) -> Idx<Variant> { | ||
487 | Idx::from_raw(RawId::from(self.tree.variants.len() as u32)) | ||
488 | } | ||
489 | } | ||
490 | |||
491 | fn desugar_future_path(orig: TypeRef) -> Path { | ||
492 | let path = path![core::future::Future]; | ||
493 | let mut generic_args: Vec<_> = std::iter::repeat(None).take(path.segments.len() - 1).collect(); | ||
494 | let mut last = GenericArgs::empty(); | ||
495 | let binding = | ||
496 | AssociatedTypeBinding { name: name![Output], type_ref: Some(orig), bounds: Vec::new() }; | ||
497 | last.bindings.push(binding); | ||
498 | generic_args.push(Some(Arc::new(last))); | ||
499 | |||
500 | Path::from_known_path(path, generic_args) | ||
501 | } | ||