mirror of
				https://github.com/rust-lang/rust-analyzer.git
				synced 2025-10-31 12:04:43 +00:00 
			
		
		
		
	Avoid referring to the item tree except in the def map
Item tree IDs are very unstable (adding an item of a kind invalidates all following items of the same kind). Instead use ast ids, which, since the previous commit, are pretty stable.
This commit is contained in:
		
							parent
							
								
									4bcf03e28b
								
							
						
					
					
						commit
						ed0b4506dd
					
				
					 37 changed files with 981 additions and 955 deletions
				
			
		|  | @ -14,6 +14,7 @@ use intern::{Symbol, sym}; | |||
| use la_arena::{ArenaMap, Idx, RawIdx}; | ||||
| use mbe::DelimiterKind; | ||||
| use rustc_abi::ReprOptions; | ||||
| use span::AstIdNode; | ||||
| use syntax::{ | ||||
|     AstPtr, | ||||
|     ast::{self, HasAttrs}, | ||||
|  | @ -22,10 +23,10 @@ use triomphe::Arc; | |||
| use tt::iter::{TtElement, TtIter}; | ||||
| 
 | ||||
| use crate::{ | ||||
|     AdtId, AttrDefId, GenericParamId, HasModule, ItemTreeLoc, LocalFieldId, Lookup, MacroId, | ||||
|     AdtId, AstIdLoc, AttrDefId, GenericParamId, HasModule, LocalFieldId, Lookup, MacroId, | ||||
|     VariantId, | ||||
|     db::DefDatabase, | ||||
|     item_tree::{AttrOwner, FieldParent, ItemTreeNode}, | ||||
|     item_tree::AttrOwner, | ||||
|     lang_item::LangItem, | ||||
|     nameres::{ModuleOrigin, ModuleSource}, | ||||
|     src::{HasChildSource, HasSource}, | ||||
|  | @ -42,6 +43,15 @@ pub struct AttrsWithOwner { | |||
| } | ||||
| 
 | ||||
| impl Attrs { | ||||
|     pub fn new( | ||||
|         db: &dyn DefDatabase, | ||||
|         owner: &dyn ast::HasAttrs, | ||||
|         span_map: SpanMapRef<'_>, | ||||
|         cfg_options: &CfgOptions, | ||||
|     ) -> Self { | ||||
|         Attrs(RawAttrs::new_expanded(db, owner, span_map, cfg_options)) | ||||
|     } | ||||
| 
 | ||||
|     pub fn get(&self, id: AttrId) -> Option<&Attr> { | ||||
|         (**self).iter().find(|attr| attr.id == id) | ||||
|     } | ||||
|  | @ -94,44 +104,64 @@ impl Attrs { | |||
|         v: VariantId, | ||||
|     ) -> Arc<ArenaMap<LocalFieldId, Attrs>> { | ||||
|         let _p = tracing::info_span!("fields_attrs_query").entered(); | ||||
|         // FIXME: There should be some proper form of mapping between item tree field ids and hir field ids
 | ||||
|         let mut res = ArenaMap::default(); | ||||
|         let item_tree; | ||||
|         let (parent, fields, krate) = match v { | ||||
|         let (fields, file_id, krate) = match v { | ||||
|             VariantId::EnumVariantId(it) => { | ||||
|                 let loc = it.lookup(db); | ||||
|                 let krate = loc.parent.lookup(db).container.krate; | ||||
|                 item_tree = loc.id.item_tree(db); | ||||
|                 let variant = &item_tree[loc.id.value]; | ||||
|                 (FieldParent::EnumVariant(loc.id.value), &variant.fields, krate) | ||||
|                 let source = loc.source(db); | ||||
|                 (source.value.field_list(), source.file_id, krate) | ||||
|             } | ||||
|             VariantId::StructId(it) => { | ||||
|                 let loc = it.lookup(db); | ||||
|                 let krate = loc.container.krate; | ||||
|                 item_tree = loc.id.item_tree(db); | ||||
|                 let struct_ = &item_tree[loc.id.value]; | ||||
|                 (FieldParent::Struct(loc.id.value), &struct_.fields, krate) | ||||
|                 let source = loc.source(db); | ||||
|                 (source.value.field_list(), source.file_id, krate) | ||||
|             } | ||||
|             VariantId::UnionId(it) => { | ||||
|                 let loc = it.lookup(db); | ||||
|                 let krate = loc.container.krate; | ||||
|                 item_tree = loc.id.item_tree(db); | ||||
|                 let union_ = &item_tree[loc.id.value]; | ||||
|                 (FieldParent::Union(loc.id.value), &union_.fields, krate) | ||||
|                 let source = loc.source(db); | ||||
|                 ( | ||||
|                     source.value.record_field_list().map(ast::FieldList::RecordFieldList), | ||||
|                     source.file_id, | ||||
|                     krate, | ||||
|                 ) | ||||
|             } | ||||
|         }; | ||||
|         let Some(fields) = fields else { | ||||
|             return Arc::new(res); | ||||
|         }; | ||||
| 
 | ||||
|         let cfg_options = krate.cfg_options(db); | ||||
|         let span_map = db.span_map(file_id); | ||||
| 
 | ||||
|         match fields { | ||||
|             ast::FieldList::RecordFieldList(fields) => { | ||||
|                 let mut idx = 0; | ||||
|         for (id, _field) in fields.iter().enumerate() { | ||||
|             let attrs = item_tree.attrs(db, krate, AttrOwner::make_field_indexed(parent, id)); | ||||
|             if attrs.is_cfg_enabled(cfg_options) { | ||||
|                 for field in fields.fields() { | ||||
|                     let attrs = | ||||
|                         Attrs(RawAttrs::new_expanded(db, &field, span_map.as_ref(), cfg_options)); | ||||
|                     if attrs.is_cfg_enabled(cfg_options).is_ok() { | ||||
|                         res.insert(Idx::from_raw(RawIdx::from(idx)), attrs); | ||||
|                         idx += 1; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|             ast::FieldList::TupleFieldList(fields) => { | ||||
|                 let mut idx = 0; | ||||
|                 for field in fields.fields() { | ||||
|                     let attrs = | ||||
|                         Attrs(RawAttrs::new_expanded(db, &field, span_map.as_ref(), cfg_options)); | ||||
|                     if attrs.is_cfg_enabled(cfg_options).is_ok() { | ||||
|                         res.insert(Idx::from_raw(RawIdx::from(idx)), attrs); | ||||
|                         idx += 1; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         res.shrink_to_fit(); | ||||
|         Arc::new(res) | ||||
|     } | ||||
| } | ||||
|  | @ -167,11 +197,10 @@ impl Attrs { | |||
|     } | ||||
| 
 | ||||
|     #[inline] | ||||
|     pub(crate) fn is_cfg_enabled(&self, cfg_options: &CfgOptions) -> bool { | ||||
|         match self.cfg() { | ||||
|             None => true, | ||||
|             Some(cfg) => cfg_options.check(&cfg) != Some(false), | ||||
|         } | ||||
|     pub(crate) fn is_cfg_enabled(&self, cfg_options: &CfgOptions) -> Result<(), CfgExpr> { | ||||
|         self.cfgs().try_for_each(|cfg| { | ||||
|             if cfg_options.check(&cfg) != Some(false) { Ok(()) } else { Err(cfg) } | ||||
|         }) | ||||
|     } | ||||
| 
 | ||||
|     #[inline] | ||||
|  | @ -488,12 +517,12 @@ impl AttrsWithOwner { | |||
|     pub(crate) fn attrs_query(db: &dyn DefDatabase, def: AttrDefId) -> Attrs { | ||||
|         let _p = tracing::info_span!("attrs_query").entered(); | ||||
|         // FIXME: this should use `Trace` to avoid duplication in `source_map` below
 | ||||
|         let raw_attrs = match def { | ||||
|         match def { | ||||
|             AttrDefId::ModuleId(module) => { | ||||
|                 let def_map = module.def_map(db); | ||||
|                 let mod_data = &def_map[module.local_id]; | ||||
| 
 | ||||
|                 match mod_data.origin { | ||||
|                 let raw_attrs = match mod_data.origin { | ||||
|                     ModuleOrigin::File { definition, declaration_tree_id, .. } => { | ||||
|                         let decl_attrs = declaration_tree_id | ||||
|                             .item_tree(db) | ||||
|  | @ -515,34 +544,33 @@ impl AttrsWithOwner { | |||
|                         let tree = db.block_item_tree(id); | ||||
|                         tree.raw_attrs(AttrOwner::TopLevel).clone() | ||||
|                     } | ||||
|                 }; | ||||
|                 Attrs::expand_cfg_attr(db, module.krate, raw_attrs) | ||||
|             } | ||||
|             } | ||||
|             AttrDefId::FieldId(it) => { | ||||
|                 return db.fields_attrs(it.parent)[it.local_id].clone(); | ||||
|             } | ||||
|             AttrDefId::EnumVariantId(it) => attrs_from_item_tree_loc(db, it), | ||||
|             AttrDefId::FieldId(it) => db.fields_attrs(it.parent)[it.local_id].clone(), | ||||
|             AttrDefId::EnumVariantId(it) => attrs_from_ast_id_loc(db, it), | ||||
|             AttrDefId::AdtId(it) => match it { | ||||
|                 AdtId::StructId(it) => attrs_from_item_tree_loc(db, it), | ||||
|                 AdtId::EnumId(it) => attrs_from_item_tree_loc(db, it), | ||||
|                 AdtId::UnionId(it) => attrs_from_item_tree_loc(db, it), | ||||
|                 AdtId::StructId(it) => attrs_from_ast_id_loc(db, it), | ||||
|                 AdtId::EnumId(it) => attrs_from_ast_id_loc(db, it), | ||||
|                 AdtId::UnionId(it) => attrs_from_ast_id_loc(db, it), | ||||
|             }, | ||||
|             AttrDefId::TraitId(it) => attrs_from_item_tree_loc(db, it), | ||||
|             AttrDefId::TraitAliasId(it) => attrs_from_item_tree_loc(db, it), | ||||
|             AttrDefId::TraitId(it) => attrs_from_ast_id_loc(db, it), | ||||
|             AttrDefId::TraitAliasId(it) => attrs_from_ast_id_loc(db, it), | ||||
|             AttrDefId::MacroId(it) => match it { | ||||
|                 MacroId::Macro2Id(it) => attrs_from_item_tree_loc(db, it), | ||||
|                 MacroId::MacroRulesId(it) => attrs_from_item_tree_loc(db, it), | ||||
|                 MacroId::ProcMacroId(it) => attrs_from_item_tree_loc(db, it), | ||||
|                 MacroId::Macro2Id(it) => attrs_from_ast_id_loc(db, it), | ||||
|                 MacroId::MacroRulesId(it) => attrs_from_ast_id_loc(db, it), | ||||
|                 MacroId::ProcMacroId(it) => attrs_from_ast_id_loc(db, it), | ||||
|             }, | ||||
|             AttrDefId::ImplId(it) => attrs_from_item_tree_loc(db, it), | ||||
|             AttrDefId::ConstId(it) => attrs_from_item_tree_loc(db, it), | ||||
|             AttrDefId::StaticId(it) => attrs_from_item_tree_loc(db, it), | ||||
|             AttrDefId::FunctionId(it) => attrs_from_item_tree_loc(db, it), | ||||
|             AttrDefId::TypeAliasId(it) => attrs_from_item_tree_loc(db, it), | ||||
|             AttrDefId::ImplId(it) => attrs_from_ast_id_loc(db, it), | ||||
|             AttrDefId::ConstId(it) => attrs_from_ast_id_loc(db, it), | ||||
|             AttrDefId::StaticId(it) => attrs_from_ast_id_loc(db, it), | ||||
|             AttrDefId::FunctionId(it) => attrs_from_ast_id_loc(db, it), | ||||
|             AttrDefId::TypeAliasId(it) => attrs_from_ast_id_loc(db, it), | ||||
|             AttrDefId::GenericParamId(it) => match it { | ||||
|                 GenericParamId::ConstParamId(it) => { | ||||
|                     let src = it.parent().child_source(db); | ||||
|                     // FIXME: We should be never getting `None` here.
 | ||||
|                     return Attrs(match src.value.get(it.local_id()) { | ||||
|                     Attrs(match src.value.get(it.local_id()) { | ||||
|                         Some(val) => RawAttrs::new_expanded( | ||||
|                             db, | ||||
|                             val, | ||||
|  | @ -550,12 +578,12 @@ impl AttrsWithOwner { | |||
|                             def.krate(db).cfg_options(db), | ||||
|                         ), | ||||
|                         None => RawAttrs::EMPTY, | ||||
|                     }); | ||||
|                     }) | ||||
|                 } | ||||
|                 GenericParamId::TypeParamId(it) => { | ||||
|                     let src = it.parent().child_source(db); | ||||
|                     // FIXME: We should be never getting `None` here.
 | ||||
|                     return Attrs(match src.value.get(it.local_id()) { | ||||
|                     Attrs(match src.value.get(it.local_id()) { | ||||
|                         Some(val) => RawAttrs::new_expanded( | ||||
|                             db, | ||||
|                             val, | ||||
|  | @ -563,12 +591,12 @@ impl AttrsWithOwner { | |||
|                             def.krate(db).cfg_options(db), | ||||
|                         ), | ||||
|                         None => RawAttrs::EMPTY, | ||||
|                     }); | ||||
|                     }) | ||||
|                 } | ||||
|                 GenericParamId::LifetimeParamId(it) => { | ||||
|                     let src = it.parent.child_source(db); | ||||
|                     // FIXME: We should be never getting `None` here.
 | ||||
|                     return Attrs(match src.value.get(it.local_id) { | ||||
|                     Attrs(match src.value.get(it.local_id) { | ||||
|                         Some(val) => RawAttrs::new_expanded( | ||||
|                             db, | ||||
|                             val, | ||||
|  | @ -576,16 +604,13 @@ impl AttrsWithOwner { | |||
|                             def.krate(db).cfg_options(db), | ||||
|                         ), | ||||
|                         None => RawAttrs::EMPTY, | ||||
|                     }); | ||||
|                     }) | ||||
|                 } | ||||
|             }, | ||||
|             AttrDefId::ExternBlockId(it) => attrs_from_item_tree_loc(db, it), | ||||
|             AttrDefId::ExternCrateId(it) => attrs_from_item_tree_loc(db, it), | ||||
|             AttrDefId::UseId(it) => attrs_from_item_tree_loc(db, it), | ||||
|         }; | ||||
| 
 | ||||
|         let attrs = raw_attrs.expand_cfg_attr(db, def.krate(db)); | ||||
|         Attrs(attrs) | ||||
|             AttrDefId::ExternBlockId(it) => attrs_from_ast_id_loc(db, it), | ||||
|             AttrDefId::ExternCrateId(it) => attrs_from_ast_id_loc(db, it), | ||||
|             AttrDefId::UseId(it) => attrs_from_ast_id_loc(db, it), | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn source_map(&self, db: &dyn DefDatabase) -> AttrSourceMap { | ||||
|  | @ -787,14 +812,15 @@ fn any_has_attrs<'db>( | |||
|     id.lookup(db).source(db).map(ast::AnyHasAttrs::new) | ||||
| } | ||||
| 
 | ||||
| fn attrs_from_item_tree_loc<'db, N: ItemTreeNode>( | ||||
| fn attrs_from_ast_id_loc<'db, N: AstIdNode + HasAttrs>( | ||||
|     db: &(dyn DefDatabase + 'db), | ||||
|     lookup: impl Lookup<Database = dyn DefDatabase, Data = impl ItemTreeLoc<Id = N>>, | ||||
| ) -> RawAttrs { | ||||
|     let id = lookup.lookup(db).item_tree_id(); | ||||
|     let tree = id.item_tree(db); | ||||
|     let attr_owner = N::attr_owner(id.value); | ||||
|     tree.raw_attrs(attr_owner).clone() | ||||
|     lookup: impl Lookup<Database = dyn DefDatabase, Data = impl AstIdLoc<Ast = N> + HasModule>, | ||||
| ) -> Attrs { | ||||
|     let loc = lookup.lookup(db); | ||||
|     let source = loc.source(db); | ||||
|     let span_map = db.span_map(source.file_id); | ||||
|     let cfg_options = loc.krate(db).cfg_options(db); | ||||
|     Attrs(RawAttrs::new_expanded(db, &source.value, span_map.as_ref(), cfg_options)) | ||||
| } | ||||
| 
 | ||||
| pub(crate) fn fields_attrs_source_map( | ||||
|  |  | |||
|  | @ -1,8 +1,11 @@ | |||
| //! Defines database & queries for name resolution.
 | ||||
| use base_db::{Crate, RootQueryDb, SourceDatabase}; | ||||
| use either::Either; | ||||
| use hir_expand::{EditionedFileId, HirFileId, MacroCallId, MacroDefId, db::ExpandDatabase}; | ||||
| use intern::sym; | ||||
| use hir_expand::{ | ||||
|     EditionedFileId, HirFileId, InFile, Lookup, MacroCallId, MacroDefId, MacroDefKind, | ||||
|     db::ExpandDatabase, | ||||
| }; | ||||
| use intern::{Symbol, sym}; | ||||
| use la_arena::ArenaMap; | ||||
| use syntax::{AstPtr, ast}; | ||||
| use thin_vec::ThinVec; | ||||
|  | @ -11,8 +14,8 @@ use triomphe::Arc; | |||
| use crate::{ | ||||
|     AttrDefId, BlockId, BlockLoc, ConstId, ConstLoc, DefWithBodyId, EnumId, EnumLoc, EnumVariantId, | ||||
|     EnumVariantLoc, ExternBlockId, ExternBlockLoc, ExternCrateId, ExternCrateLoc, FunctionId, | ||||
|     FunctionLoc, GenericDefId, ImplId, ImplLoc, LocalFieldId, Macro2Id, Macro2Loc, MacroId, | ||||
|     MacroRulesId, MacroRulesLoc, MacroRulesLocFlags, ProcMacroId, ProcMacroLoc, StaticId, | ||||
|     FunctionLoc, GenericDefId, ImplId, ImplLoc, LocalFieldId, Macro2Id, Macro2Loc, MacroExpander, | ||||
|     MacroId, MacroRulesId, MacroRulesLoc, MacroRulesLocFlags, ProcMacroId, ProcMacroLoc, StaticId, | ||||
|     StaticLoc, StructId, StructLoc, TraitAliasId, TraitAliasLoc, TraitId, TraitLoc, TypeAliasId, | ||||
|     TypeAliasLoc, UnionId, UnionLoc, UseId, UseLoc, VariantId, | ||||
|     attr::{Attrs, AttrsWithOwner}, | ||||
|  | @ -123,6 +126,8 @@ pub trait DefDatabase: InternDatabase + ExpandDatabase + SourceDatabase { | |||
|         id: VariantId, | ||||
|     ) -> (Arc<VariantFields>, Arc<ExpressionStoreSourceMap>); | ||||
| 
 | ||||
|     // FIXME: Should we make this transparent? The only unstable thing in `enum_variants_with_diagnostics()`
 | ||||
|     // is ast ids, and ast ids are pretty stable now.
 | ||||
|     #[salsa::tracked] | ||||
|     fn enum_variants(&self, id: EnumId) -> Arc<EnumVariants> { | ||||
|         self.enum_variants_with_diagnostics(id).0 | ||||
|  | @ -263,6 +268,9 @@ pub trait DefDatabase: InternDatabase + ExpandDatabase + SourceDatabase { | |||
|         e: TypeAliasId, | ||||
|     ) -> (Arc<TypeAliasSignature>, Arc<ExpressionStoreSourceMap>); | ||||
| 
 | ||||
|     #[salsa::invoke(crate::signatures::extern_block_abi_query)] | ||||
|     fn extern_block_abi(&self, extern_block: ExternBlockId) -> Option<Symbol>; | ||||
| 
 | ||||
|     // endregion:data
 | ||||
| 
 | ||||
|     #[salsa::invoke(Body::body_with_source_map_query)] | ||||
|  | @ -399,10 +407,6 @@ fn crate_supports_no_std(db: &dyn DefDatabase, crate_id: Crate) -> bool { | |||
| } | ||||
| 
 | ||||
| fn macro_def(db: &dyn DefDatabase, id: MacroId) -> MacroDefId { | ||||
|     use hir_expand::InFile; | ||||
| 
 | ||||
|     use crate::{Lookup, MacroDefKind, MacroExpander}; | ||||
| 
 | ||||
|     let kind = |expander, file_id, m| { | ||||
|         let in_file = InFile::new(file_id, m); | ||||
|         match expander { | ||||
|  | @ -418,11 +422,9 @@ fn macro_def(db: &dyn DefDatabase, id: MacroId) -> MacroDefId { | |||
|         MacroId::Macro2Id(it) => { | ||||
|             let loc: Macro2Loc = it.lookup(db); | ||||
| 
 | ||||
|             let item_tree = loc.id.item_tree(db); | ||||
|             let makro = &item_tree[loc.id.value]; | ||||
|             MacroDefId { | ||||
|                 krate: loc.container.krate, | ||||
|                 kind: kind(loc.expander, loc.id.file_id(), makro.ast_id.upcast()), | ||||
|                 kind: kind(loc.expander, loc.id.file_id, loc.id.value.upcast()), | ||||
|                 local_inner: false, | ||||
|                 allow_internal_unsafe: loc.allow_internal_unsafe, | ||||
|                 edition: loc.edition, | ||||
|  | @ -431,11 +433,9 @@ fn macro_def(db: &dyn DefDatabase, id: MacroId) -> MacroDefId { | |||
|         MacroId::MacroRulesId(it) => { | ||||
|             let loc: MacroRulesLoc = it.lookup(db); | ||||
| 
 | ||||
|             let item_tree = loc.id.item_tree(db); | ||||
|             let makro = &item_tree[loc.id.value]; | ||||
|             MacroDefId { | ||||
|                 krate: loc.container.krate, | ||||
|                 kind: kind(loc.expander, loc.id.file_id(), makro.ast_id.upcast()), | ||||
|                 kind: kind(loc.expander, loc.id.file_id, loc.id.value.upcast()), | ||||
|                 local_inner: loc.flags.contains(MacroRulesLocFlags::LOCAL_INNER), | ||||
|                 allow_internal_unsafe: loc | ||||
|                     .flags | ||||
|  | @ -446,15 +446,9 @@ fn macro_def(db: &dyn DefDatabase, id: MacroId) -> MacroDefId { | |||
|         MacroId::ProcMacroId(it) => { | ||||
|             let loc = it.lookup(db); | ||||
| 
 | ||||
|             let item_tree = loc.id.item_tree(db); | ||||
|             let makro = &item_tree[loc.id.value]; | ||||
|             MacroDefId { | ||||
|                 krate: loc.container.krate, | ||||
|                 kind: MacroDefKind::ProcMacro( | ||||
|                     InFile::new(loc.id.file_id(), makro.ast_id), | ||||
|                     loc.expander, | ||||
|                     loc.kind, | ||||
|                 ), | ||||
|                 kind: MacroDefKind::ProcMacro(loc.id, loc.expander, loc.kind), | ||||
|                 local_inner: false, | ||||
|                 allow_internal_unsafe: false, | ||||
|                 edition: loc.edition, | ||||
|  |  | |||
|  | @ -6,6 +6,7 @@ use base_db::Crate; | |||
| use cfg::CfgOptions; | ||||
| use drop_bomb::DropBomb; | ||||
| use hir_expand::AstId; | ||||
| use hir_expand::span_map::SpanMapRef; | ||||
| use hir_expand::{ | ||||
|     ExpandError, ExpandErrorKind, ExpandResult, HirFileId, InFile, Lookup, MacroCallId, | ||||
|     eager::EagerCallBackFn, mod_path::ModPath, span_map::SpanMap, | ||||
|  | @ -223,9 +224,15 @@ impl Expander { | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     #[inline] | ||||
|     pub(super) fn ast_id_map(&self) -> &AstIdMap { | ||||
|         &self.ast_id_map | ||||
|     } | ||||
| 
 | ||||
|     #[inline] | ||||
|     pub(super) fn span_map(&self) -> SpanMapRef<'_> { | ||||
|         self.span_map.as_ref() | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug)] | ||||
|  |  | |||
|  | @ -10,9 +10,10 @@ use std::mem; | |||
| use cfg::CfgOptions; | ||||
| use either::Either; | ||||
| use hir_expand::{ | ||||
|     HirFileId, InFile, Lookup, MacroDefId, | ||||
|     HirFileId, InFile, MacroDefId, | ||||
|     mod_path::tool_path, | ||||
|     name::{AsName, Name}, | ||||
|     span_map::SpanMapRef, | ||||
| }; | ||||
| use intern::{Symbol, sym}; | ||||
| use rustc_hash::FxHashMap; | ||||
|  | @ -30,8 +31,8 @@ use triomphe::Arc; | |||
| use tt::TextRange; | ||||
| 
 | ||||
| use crate::{ | ||||
|     AdtId, BlockId, BlockLoc, DefWithBodyId, FunctionId, GenericDefId, ImplId, ItemTreeLoc, | ||||
|     MacroId, ModuleDefId, ModuleId, TraitAliasId, TraitId, TypeAliasId, UnresolvedMacro, | ||||
|     AdtId, BlockId, BlockLoc, DefWithBodyId, FunctionId, GenericDefId, ImplId, MacroId, | ||||
|     ModuleDefId, ModuleId, TraitAliasId, TraitId, TypeAliasId, UnresolvedMacro, | ||||
|     builtin_type::BuiltinUint, | ||||
|     db::DefDatabase, | ||||
|     expr_store::{ | ||||
|  | @ -564,6 +565,11 @@ impl ExprCollector<'_> { | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     #[inline] | ||||
|     pub(crate) fn span_map(&self) -> SpanMapRef<'_> { | ||||
|         self.expander.span_map() | ||||
|     } | ||||
| 
 | ||||
|     pub fn lower_lifetime_ref(&mut self, lifetime: ast::Lifetime) -> LifetimeRefId { | ||||
|         // FIXME: Keyword check?
 | ||||
|         let lifetime_ref = match &*lifetime.text() { | ||||
|  | @ -2244,11 +2250,8 @@ impl ExprCollector<'_> { | |||
|                     match resolved.take_values() { | ||||
|                         Some(ModuleDefId::ConstId(_)) => (None, Pat::Path(name.into())), | ||||
|                         Some(ModuleDefId::EnumVariantId(variant)) | ||||
|                             if { | ||||
|                                 let loc = variant.lookup(self.db); | ||||
|                                 let tree = loc.item_tree_id().item_tree(self.db); | ||||
|                                 tree[loc.id.value].shape != FieldsShape::Record | ||||
|                             } => | ||||
|                         // FIXME: This can cause a cycle if the user is writing invalid code
 | ||||
|                             if self.db.variant_fields(variant.into()).shape != FieldsShape::Record => | ||||
|                         { | ||||
|                             (None, Pat::Path(name.into())) | ||||
|                         } | ||||
|  |  | |||
|  | @ -9,9 +9,10 @@ use std::{ | |||
| use hir_expand::{Lookup, mod_path::PathKind}; | ||||
| use itertools::Itertools; | ||||
| use span::Edition; | ||||
| use syntax::ast::HasName; | ||||
| 
 | ||||
| use crate::{ | ||||
|     AdtId, DefWithBodyId, GenericDefId, ItemTreeLoc, TypeParamId, VariantId, | ||||
|     AdtId, DefWithBodyId, GenericDefId, TypeParamId, VariantId, | ||||
|     expr_store::path::{GenericArg, GenericArgs}, | ||||
|     hir::{ | ||||
|         Array, BindingAnnotation, CaptureBy, ClosureKind, Literal, Movability, Statement, | ||||
|  | @ -19,6 +20,7 @@ use crate::{ | |||
|     }, | ||||
|     lang_item::LangItemTarget, | ||||
|     signatures::{FnFlags, FunctionSignature, StructSignature}, | ||||
|     src::HasSource, | ||||
|     type_ref::{ConstRef, LifetimeRef, Mutability, TraitBoundModifier, TypeBound, UseArgRef}, | ||||
| }; | ||||
| use crate::{LifetimeParamId, signatures::StructFlags}; | ||||
|  | @ -48,6 +50,17 @@ pub enum LineFormat { | |||
|     Indentation, | ||||
| } | ||||
| 
 | ||||
| fn item_name<Id, Loc>(db: &dyn DefDatabase, id: Id, default: &str) -> String | ||||
| where | ||||
|     Id: Lookup<Database = dyn DefDatabase, Data = Loc>, | ||||
|     Loc: HasSource, | ||||
|     Loc::Value: ast::HasName, | ||||
| { | ||||
|     let loc = id.lookup(db); | ||||
|     let source = loc.source(db); | ||||
|     source.value.name().map_or_else(|| default.to_owned(), |name| name.to_string()) | ||||
| } | ||||
| 
 | ||||
| pub fn print_body_hir( | ||||
|     db: &dyn DefDatabase, | ||||
|     body: &Body, | ||||
|  | @ -55,31 +68,14 @@ pub fn print_body_hir( | |||
|     edition: Edition, | ||||
| ) -> String { | ||||
|     let header = match owner { | ||||
|         DefWithBodyId::FunctionId(it) => { | ||||
|             it.lookup(db).id.resolved(db, |it| format!("fn {}", it.name.display(db, edition))) | ||||
|         } | ||||
|         DefWithBodyId::StaticId(it) => it | ||||
|             .lookup(db) | ||||
|             .id | ||||
|             .resolved(db, |it| format!("static {} = ", it.name.display(db, edition))), | ||||
|         DefWithBodyId::ConstId(it) => it.lookup(db).id.resolved(db, |it| { | ||||
|             format!( | ||||
|                 "const {} = ", | ||||
|                 match &it.name { | ||||
|                     Some(name) => name.display(db, edition).to_string(), | ||||
|                     None => "_".to_owned(), | ||||
|                 } | ||||
|             ) | ||||
|         }), | ||||
|         DefWithBodyId::VariantId(it) => { | ||||
|             let loc = it.lookup(db); | ||||
|             let enum_loc = loc.parent.lookup(db); | ||||
|             format!( | ||||
|         DefWithBodyId::FunctionId(it) => format!("fn {}", item_name(db, it, "<missing>")), | ||||
|         DefWithBodyId::StaticId(it) => format!("static {} = ", item_name(db, it, "<missing>")), | ||||
|         DefWithBodyId::ConstId(it) => format!("const {} = ", item_name(db, it, "_")), | ||||
|         DefWithBodyId::VariantId(it) => format!( | ||||
|             "enum {}::{}", | ||||
|                 enum_loc.id.item_tree(db)[enum_loc.id.value].name.display(db, edition), | ||||
|                 loc.id.item_tree(db)[loc.id.value].name.display(db, edition), | ||||
|             ) | ||||
|         } | ||||
|             item_name(db, it.lookup(db).parent, "<missing>"), | ||||
|             item_name(db, it, "<missing>") | ||||
|         ), | ||||
|     }; | ||||
| 
 | ||||
|     let mut p = Printer { | ||||
|  | @ -116,22 +112,13 @@ pub fn print_body_hir( | |||
| 
 | ||||
| pub fn print_variant_body_hir(db: &dyn DefDatabase, owner: VariantId, edition: Edition) -> String { | ||||
|     let header = match owner { | ||||
|         VariantId::StructId(it) => { | ||||
|             it.lookup(db).id.resolved(db, |it| format!("struct {}", it.name.display(db, edition))) | ||||
|         } | ||||
|         VariantId::EnumVariantId(enum_variant_id) => { | ||||
|             let loc = enum_variant_id.lookup(db); | ||||
|             let enum_loc = loc.parent.lookup(db); | ||||
|             format!( | ||||
|         VariantId::StructId(it) => format!("struct {}", item_name(db, it, "<missing>")), | ||||
|         VariantId::EnumVariantId(it) => format!( | ||||
|             "enum {}::{}", | ||||
|                 enum_loc.id.item_tree(db)[enum_loc.id.value].name.display(db, edition), | ||||
|                 loc.id.item_tree(db)[loc.id.value].name.display(db, edition), | ||||
|             ) | ||||
|         } | ||||
|         VariantId::UnionId(union_id) => union_id | ||||
|             .lookup(db) | ||||
|             .id | ||||
|             .resolved(db, |it| format!("union {}", it.name.display(db, edition))), | ||||
|             item_name(db, it.lookup(db).parent, "<missing>"), | ||||
|             item_name(db, it, "<missing>") | ||||
|         ), | ||||
|         VariantId::UnionId(it) => format!("union {}", item_name(db, it, "<missing>")), | ||||
|     }; | ||||
| 
 | ||||
|     let fields = db.variant_fields(owner); | ||||
|  | @ -1089,10 +1076,7 @@ impl Printer<'_> { | |||
|             w!(self, "builtin#lang("); | ||||
|             macro_rules! write_name { | ||||
|                 ($it:ident) => {{ | ||||
|                     let loc = $it.lookup(self.db); | ||||
|                     let tree = loc.item_tree_id().item_tree(self.db); | ||||
|                     let name = &tree[loc.id.value].name; | ||||
|                     w!(self, "{}", name.display(self.db, self.edition)); | ||||
|                     w!(self, "{}", item_name(self.db, $it, "<missing>")); | ||||
|                 }}; | ||||
|             } | ||||
|             match *it { | ||||
|  |  | |||
|  | @ -46,7 +46,7 @@ use std::{ | |||
| use ast::{AstNode, StructKind}; | ||||
| use base_db::Crate; | ||||
| use hir_expand::{ | ||||
|     ExpandTo, HirFileId, InFile, | ||||
|     ExpandTo, HirFileId, | ||||
|     attrs::RawAttrs, | ||||
|     mod_path::{ModPath, PathKind}, | ||||
|     name::Name, | ||||
|  | @ -62,6 +62,8 @@ use triomphe::Arc; | |||
| 
 | ||||
| use crate::{BlockId, Lookup, attr::Attrs, db::DefDatabase}; | ||||
| 
 | ||||
| pub(crate) use crate::item_tree::lower::{lower_use_tree, visibility_from_ast}; | ||||
| 
 | ||||
| #[derive(Copy, Clone, Eq, PartialEq)] | ||||
| pub struct RawVisibilityId(u32); | ||||
| 
 | ||||
|  | @ -446,6 +448,7 @@ impl TreeId { | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     #[inline] | ||||
|     pub fn file_id(self) -> HirFileId { | ||||
|         self.file | ||||
|     } | ||||
|  | @ -878,43 +881,6 @@ pub struct Macro2 { | |||
|     pub ast_id: FileAstId<ast::MacroDef>, | ||||
| } | ||||
| 
 | ||||
| impl Use { | ||||
|     /// Maps a `UseTree` contained in this import back to its AST node.
 | ||||
|     pub fn use_tree_to_ast( | ||||
|         &self, | ||||
|         db: &dyn DefDatabase, | ||||
|         file_id: HirFileId, | ||||
|         index: Idx<ast::UseTree>, | ||||
|     ) -> ast::UseTree { | ||||
|         // Re-lower the AST item and get the source map.
 | ||||
|         // Note: The AST unwraps are fine, since if they fail we should have never obtained `index`.
 | ||||
|         let ast = InFile::new(file_id, self.ast_id).to_node(db); | ||||
|         let ast_use_tree = ast.use_tree().expect("missing `use_tree`"); | ||||
|         let (_, source_map) = lower::lower_use_tree(db, ast_use_tree, &mut |range| { | ||||
|             db.span_map(file_id).span_for_range(range).ctx | ||||
|         }) | ||||
|         .expect("failed to lower use tree"); | ||||
|         source_map[index].clone() | ||||
|     } | ||||
| 
 | ||||
|     /// Maps a `UseTree` contained in this import back to its AST node.
 | ||||
|     pub fn use_tree_source_map( | ||||
|         &self, | ||||
|         db: &dyn DefDatabase, | ||||
|         file_id: HirFileId, | ||||
|     ) -> Arena<ast::UseTree> { | ||||
|         // Re-lower the AST item and get the source map.
 | ||||
|         // Note: The AST unwraps are fine, since if they fail we should have never obtained `index`.
 | ||||
|         let ast = InFile::new(file_id, self.ast_id).to_node(db); | ||||
|         let ast_use_tree = ast.use_tree().expect("missing `use_tree`"); | ||||
|         lower::lower_use_tree(db, ast_use_tree, &mut |range| { | ||||
|             db.span_map(file_id).span_for_range(range).ctx | ||||
|         }) | ||||
|         .expect("failed to lower use tree") | ||||
|         .1 | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[derive(Clone, Copy, Debug, Eq, PartialEq)] | ||||
| pub enum ImportKind { | ||||
|     /// The `ModPath` is imported normally.
 | ||||
|  |  | |||
|  | @ -626,7 +626,7 @@ fn private_vis() -> RawVisibility { | |||
|     ) | ||||
| } | ||||
| 
 | ||||
| fn visibility_from_ast( | ||||
| pub(crate) fn visibility_from_ast( | ||||
|     db: &dyn DefDatabase, | ||||
|     node: Option<ast::Visibility>, | ||||
|     span_for_range: &mut dyn FnMut(::tt::TextRange) -> SyntaxContext, | ||||
|  |  | |||
|  | @ -258,7 +258,7 @@ impl Printer<'_> { | |||
|                 let Enum { name, visibility, variants, ast_id } = &self.tree[it]; | ||||
|                 self.print_ast_id(ast_id.erase()); | ||||
|                 self.print_visibility(*visibility); | ||||
|                 w!(self, "enum {}", name.display(self.db, self.edition)); | ||||
|                 w!(self, "enum {} {{", name.display(self.db, self.edition)); | ||||
|                 let edition = self.edition; | ||||
|                 self.indented(|this| { | ||||
|                     for variant in FileItemTreeId::range_iter(variants.clone()) { | ||||
|  |  | |||
|  | @ -147,7 +147,7 @@ enum E { | |||
|             } | ||||
| 
 | ||||
|             // AstId: Enum[7FF8, 0]
 | ||||
|             pub(self) enum E | ||||
|             pub(self) enum E { | ||||
|                 // AstId: Variant[C717, 0]
 | ||||
|                 #[doc = " comment on Unit"] | ||||
|                 Unit, | ||||
|  |  | |||
|  | @ -125,7 +125,7 @@ pub fn crate_lang_items(db: &dyn DefDatabase, krate: Crate) -> Option<Box<LangIt | |||
|                 } | ||||
|                 ModuleDefId::AdtId(AdtId::EnumId(e)) => { | ||||
|                     lang_items.collect_lang_item(db, e, LangItemTarget::EnumId); | ||||
|                     db.enum_variants(e).variants.iter().for_each(|&(id, _)| { | ||||
|                     db.enum_variants(e).variants.iter().for_each(|&(id, _, _)| { | ||||
|                         lang_items.collect_lang_item(db, id, LangItemTarget::EnumVariant); | ||||
|                     }); | ||||
|                 } | ||||
|  |  | |||
|  | @ -74,12 +74,11 @@ use hir_expand::{ | |||
|     name::Name, | ||||
|     proc_macro::{CustomProcMacroExpander, ProcMacroKind}, | ||||
| }; | ||||
| use item_tree::ExternBlock; | ||||
| use la_arena::Idx; | ||||
| use nameres::DefMap; | ||||
| use span::{AstIdNode, Edition, FileAstId, SyntaxContext}; | ||||
| use stdx::impl_from; | ||||
| use syntax::ast; | ||||
| use syntax::{AstNode, ast}; | ||||
| 
 | ||||
| pub use hir_expand::{Intern, Lookup, tt}; | ||||
| 
 | ||||
|  | @ -88,10 +87,6 @@ use crate::{ | |||
|     builtin_type::BuiltinType, | ||||
|     db::DefDatabase, | ||||
|     hir::generics::{LocalLifetimeParamId, LocalTypeOrConstParamId}, | ||||
|     item_tree::{ | ||||
|         Const, Enum, ExternCrate, Function, Impl, ItemTreeId, ItemTreeNode, Macro2, MacroRules, | ||||
|         Static, Struct, Trait, TraitAlias, TypeAlias, Union, Use, Variant, | ||||
|     }, | ||||
|     nameres::{LocalDefMap, block_def_map, crate_def_map, crate_local_def_map}, | ||||
|     signatures::VariantFields, | ||||
| }; | ||||
|  | @ -113,70 +108,110 @@ pub struct ImportPathConfig { | |||
| } | ||||
| 
 | ||||
| #[derive(Debug)] | ||||
| pub struct ItemLoc<N: ItemTreeNode> { | ||||
| pub struct ItemLoc<N: AstIdNode> { | ||||
|     pub container: ModuleId, | ||||
|     pub id: ItemTreeId<N>, | ||||
|     pub id: AstId<N>, | ||||
| } | ||||
| 
 | ||||
| impl<N: ItemTreeNode> Clone for ItemLoc<N> { | ||||
| impl<N: AstIdNode> Clone for ItemLoc<N> { | ||||
|     fn clone(&self) -> Self { | ||||
|         *self | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl<N: ItemTreeNode> Copy for ItemLoc<N> {} | ||||
| impl<N: AstIdNode> Copy for ItemLoc<N> {} | ||||
| 
 | ||||
| impl<N: ItemTreeNode> PartialEq for ItemLoc<N> { | ||||
| impl<N: AstIdNode> PartialEq for ItemLoc<N> { | ||||
|     fn eq(&self, other: &Self) -> bool { | ||||
|         self.container == other.container && self.id == other.id | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl<N: ItemTreeNode> Eq for ItemLoc<N> {} | ||||
| impl<N: AstIdNode> Eq for ItemLoc<N> {} | ||||
| 
 | ||||
| impl<N: ItemTreeNode> Hash for ItemLoc<N> { | ||||
| impl<N: AstIdNode> Hash for ItemLoc<N> { | ||||
|     fn hash<H: Hasher>(&self, state: &mut H) { | ||||
|         self.container.hash(state); | ||||
|         self.id.hash(state); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl<N: AstIdNode> HasModule for ItemLoc<N> { | ||||
|     #[inline] | ||||
|     fn module(&self, _db: &dyn DefDatabase) -> ModuleId { | ||||
|         self.container | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug)] | ||||
| pub struct AssocItemLoc<N: ItemTreeNode> { | ||||
| pub struct AssocItemLoc<N: AstIdNode> { | ||||
|     pub container: ItemContainerId, | ||||
|     pub id: ItemTreeId<N>, | ||||
|     pub id: AstId<N>, | ||||
| } | ||||
| 
 | ||||
| impl<N: ItemTreeNode> Clone for AssocItemLoc<N> { | ||||
| impl<N: AstIdNode> Clone for AssocItemLoc<N> { | ||||
|     fn clone(&self) -> Self { | ||||
|         *self | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl<N: ItemTreeNode> Copy for AssocItemLoc<N> {} | ||||
| impl<N: AstIdNode> Copy for AssocItemLoc<N> {} | ||||
| 
 | ||||
| impl<N: ItemTreeNode> PartialEq for AssocItemLoc<N> { | ||||
| impl<N: AstIdNode> PartialEq for AssocItemLoc<N> { | ||||
|     fn eq(&self, other: &Self) -> bool { | ||||
|         self.container == other.container && self.id == other.id | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl<N: ItemTreeNode> Eq for AssocItemLoc<N> {} | ||||
| impl<N: AstIdNode> Eq for AssocItemLoc<N> {} | ||||
| 
 | ||||
| impl<N: ItemTreeNode> Hash for AssocItemLoc<N> { | ||||
| impl<N: AstIdNode> Hash for AssocItemLoc<N> { | ||||
|     fn hash<H: Hasher>(&self, state: &mut H) { | ||||
|         self.container.hash(state); | ||||
|         self.id.hash(state); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| pub trait ItemTreeLoc { | ||||
| impl<N: AstIdNode> HasModule for AssocItemLoc<N> { | ||||
|     #[inline] | ||||
|     fn module(&self, db: &dyn DefDatabase) -> ModuleId { | ||||
|         self.container.module(db) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| pub trait AstIdLoc { | ||||
|     type Container; | ||||
|     type Id; | ||||
|     fn item_tree_id(&self) -> ItemTreeId<Self::Id>; | ||||
|     type Ast: AstNode; | ||||
|     fn ast_id(&self) -> AstId<Self::Ast>; | ||||
|     fn container(&self) -> Self::Container; | ||||
| } | ||||
| 
 | ||||
| impl<N: AstIdNode> AstIdLoc for ItemLoc<N> { | ||||
|     type Container = ModuleId; | ||||
|     type Ast = N; | ||||
|     #[inline] | ||||
|     fn ast_id(&self) -> AstId<Self::Ast> { | ||||
|         self.id | ||||
|     } | ||||
|     #[inline] | ||||
|     fn container(&self) -> Self::Container { | ||||
|         self.container | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl<N: AstIdNode> AstIdLoc for AssocItemLoc<N> { | ||||
|     type Container = ItemContainerId; | ||||
|     type Ast = N; | ||||
|     #[inline] | ||||
|     fn ast_id(&self) -> AstId<Self::Ast> { | ||||
|         self.id | ||||
|     } | ||||
|     #[inline] | ||||
|     fn container(&self) -> Self::Container { | ||||
|         self.container | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| macro_rules! impl_intern { | ||||
|     ($id:ident, $loc:ident, $intern:ident, $lookup:ident) => { | ||||
|         impl_intern_key!($id, $loc); | ||||
|  | @ -186,74 +221,68 @@ macro_rules! impl_intern { | |||
| 
 | ||||
| macro_rules! impl_loc { | ||||
|     ($loc:ident, $id:ident: $id_ty:ident, $container:ident: $container_type:ident) => { | ||||
|         impl ItemTreeLoc for $loc { | ||||
|         impl AstIdLoc for $loc { | ||||
|             type Container = $container_type; | ||||
|             type Id = $id_ty; | ||||
|             fn item_tree_id(&self) -> ItemTreeId<Self::Id> { | ||||
|             type Ast = ast::$id_ty; | ||||
|             fn ast_id(&self) -> AstId<Self::Ast> { | ||||
|                 self.$id | ||||
|             } | ||||
|             fn container(&self) -> Self::Container { | ||||
|                 self.$container | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         impl HasModule for $loc { | ||||
|             #[inline] | ||||
|             fn module(&self, db: &dyn DefDatabase) -> ModuleId { | ||||
|                 self.$container.module(db) | ||||
|             } | ||||
|         } | ||||
|     }; | ||||
| } | ||||
| 
 | ||||
| type FunctionLoc = AssocItemLoc<Function>; | ||||
| type FunctionLoc = AssocItemLoc<ast::Fn>; | ||||
| impl_intern!(FunctionId, FunctionLoc, intern_function, lookup_intern_function); | ||||
| impl_loc!(FunctionLoc, id: Function, container: ItemContainerId); | ||||
| 
 | ||||
| type StructLoc = ItemLoc<Struct>; | ||||
| type StructLoc = ItemLoc<ast::Struct>; | ||||
| impl_intern!(StructId, StructLoc, intern_struct, lookup_intern_struct); | ||||
| impl_loc!(StructLoc, id: Struct, container: ModuleId); | ||||
| 
 | ||||
| pub type UnionLoc = ItemLoc<Union>; | ||||
| pub type UnionLoc = ItemLoc<ast::Union>; | ||||
| impl_intern!(UnionId, UnionLoc, intern_union, lookup_intern_union); | ||||
| impl_loc!(UnionLoc, id: Union, container: ModuleId); | ||||
| 
 | ||||
| pub type EnumLoc = ItemLoc<Enum>; | ||||
| pub type EnumLoc = ItemLoc<ast::Enum>; | ||||
| impl_intern!(EnumId, EnumLoc, intern_enum, lookup_intern_enum); | ||||
| impl_loc!(EnumLoc, id: Enum, container: ModuleId); | ||||
| 
 | ||||
| type ConstLoc = AssocItemLoc<Const>; | ||||
| type ConstLoc = AssocItemLoc<ast::Const>; | ||||
| impl_intern!(ConstId, ConstLoc, intern_const, lookup_intern_const); | ||||
| impl_loc!(ConstLoc, id: Const, container: ItemContainerId); | ||||
| 
 | ||||
| pub type StaticLoc = AssocItemLoc<Static>; | ||||
| pub type StaticLoc = AssocItemLoc<ast::Static>; | ||||
| impl_intern!(StaticId, StaticLoc, intern_static, lookup_intern_static); | ||||
| impl_loc!(StaticLoc, id: Static, container: ItemContainerId); | ||||
| 
 | ||||
| pub type TraitLoc = ItemLoc<Trait>; | ||||
| pub type TraitLoc = ItemLoc<ast::Trait>; | ||||
| impl_intern!(TraitId, TraitLoc, intern_trait, lookup_intern_trait); | ||||
| impl_loc!(TraitLoc, id: Trait, container: ModuleId); | ||||
| 
 | ||||
| pub type TraitAliasLoc = ItemLoc<TraitAlias>; | ||||
| pub type TraitAliasLoc = ItemLoc<ast::TraitAlias>; | ||||
| impl_intern!(TraitAliasId, TraitAliasLoc, intern_trait_alias, lookup_intern_trait_alias); | ||||
| impl_loc!(TraitAliasLoc, id: TraitAlias, container: ModuleId); | ||||
| 
 | ||||
| type TypeAliasLoc = AssocItemLoc<TypeAlias>; | ||||
| type TypeAliasLoc = AssocItemLoc<ast::TypeAlias>; | ||||
| impl_intern!(TypeAliasId, TypeAliasLoc, intern_type_alias, lookup_intern_type_alias); | ||||
| impl_loc!(TypeAliasLoc, id: TypeAlias, container: ItemContainerId); | ||||
| 
 | ||||
| type ImplLoc = ItemLoc<Impl>; | ||||
| type ImplLoc = ItemLoc<ast::Impl>; | ||||
| impl_intern!(ImplId, ImplLoc, intern_impl, lookup_intern_impl); | ||||
| impl_loc!(ImplLoc, id: Impl, container: ModuleId); | ||||
| 
 | ||||
| type UseLoc = ItemLoc<Use>; | ||||
| type UseLoc = ItemLoc<ast::Use>; | ||||
| impl_intern!(UseId, UseLoc, intern_use, lookup_intern_use); | ||||
| impl_loc!(UseLoc, id: Use, container: ModuleId); | ||||
| 
 | ||||
| type ExternCrateLoc = ItemLoc<ExternCrate>; | ||||
| type ExternCrateLoc = ItemLoc<ast::ExternCrate>; | ||||
| impl_intern!(ExternCrateId, ExternCrateLoc, intern_extern_crate, lookup_intern_extern_crate); | ||||
| impl_loc!(ExternCrateLoc, id: ExternCrate, container: ModuleId); | ||||
| 
 | ||||
| type ExternBlockLoc = ItemLoc<ExternBlock>; | ||||
| type ExternBlockLoc = ItemLoc<ast::ExternBlock>; | ||||
| impl_intern!(ExternBlockId, ExternBlockLoc, intern_extern_block, lookup_intern_extern_block); | ||||
| impl_loc!(ExternBlockLoc, id: ExternBlock, container: ModuleId); | ||||
| 
 | ||||
| #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||||
| pub struct EnumVariantLoc { | ||||
|     pub id: ItemTreeId<Variant>, | ||||
|     pub id: AstId<ast::Variant>, | ||||
|     pub parent: EnumId, | ||||
|     pub index: u32, | ||||
| } | ||||
|  | @ -262,18 +291,18 @@ impl_loc!(EnumVariantLoc, id: Variant, parent: EnumId); | |||
| #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||||
| pub struct Macro2Loc { | ||||
|     pub container: ModuleId, | ||||
|     pub id: ItemTreeId<Macro2>, | ||||
|     pub id: AstId<ast::MacroDef>, | ||||
|     pub expander: MacroExpander, | ||||
|     pub allow_internal_unsafe: bool, | ||||
|     pub edition: Edition, | ||||
| } | ||||
| impl_intern!(Macro2Id, Macro2Loc, intern_macro2, lookup_intern_macro2); | ||||
| impl_loc!(Macro2Loc, id: Macro2, container: ModuleId); | ||||
| impl_loc!(Macro2Loc, id: MacroDef, container: ModuleId); | ||||
| 
 | ||||
| #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||||
| pub struct MacroRulesLoc { | ||||
|     pub container: ModuleId, | ||||
|     pub id: ItemTreeId<MacroRules>, | ||||
|     pub id: AstId<ast::MacroRules>, | ||||
|     pub expander: MacroExpander, | ||||
|     pub flags: MacroRulesLocFlags, | ||||
|     pub edition: Edition, | ||||
|  | @ -301,13 +330,13 @@ pub enum MacroExpander { | |||
| #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||||
| pub struct ProcMacroLoc { | ||||
|     pub container: CrateRootModuleId, | ||||
|     pub id: ItemTreeId<Function>, | ||||
|     pub id: AstId<ast::Fn>, | ||||
|     pub expander: CustomProcMacroExpander, | ||||
|     pub kind: ProcMacroKind, | ||||
|     pub edition: Edition, | ||||
| } | ||||
| impl_intern!(ProcMacroId, ProcMacroLoc, intern_proc_macro, lookup_intern_proc_macro); | ||||
| impl_loc!(ProcMacroLoc, id: Function, container: CrateRootModuleId); | ||||
| impl_loc!(ProcMacroLoc, id: Fn, container: CrateRootModuleId); | ||||
| 
 | ||||
| #[derive(Debug, Hash, PartialEq, Eq, Clone)] | ||||
| pub struct BlockLoc { | ||||
|  | @ -338,6 +367,18 @@ impl CrateRootModuleId { | |||
|     } | ||||
| } | ||||
| 
 | ||||
| impl HasModule for CrateRootModuleId { | ||||
|     #[inline] | ||||
|     fn module(&self, _db: &dyn DefDatabase) -> ModuleId { | ||||
|         ModuleId { krate: self.krate, block: None, local_id: DefMap::ROOT } | ||||
|     } | ||||
| 
 | ||||
|     #[inline] | ||||
|     fn krate(&self, _db: &dyn DefDatabase) -> Crate { | ||||
|         self.krate | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl PartialEq<ModuleId> for CrateRootModuleId { | ||||
|     fn eq(&self, other: &ModuleId) -> bool { | ||||
|         other.block.is_none() && other.local_id == DefMap::ROOT && self.krate == other.krate | ||||
|  | @ -466,6 +507,13 @@ impl ModuleId { | |||
|     } | ||||
| } | ||||
| 
 | ||||
| impl HasModule for ModuleId { | ||||
|     #[inline] | ||||
|     fn module(&self, _db: &dyn DefDatabase) -> ModuleId { | ||||
|         *self | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| /// An ID of a module, **local** to a `DefMap`.
 | ||||
| pub type LocalModuleId = Idx<nameres::ModuleData>; | ||||
| 
 | ||||
|  | @ -642,15 +690,10 @@ impl GeneralConstId { | |||
|     pub fn name(self, db: &dyn DefDatabase) -> String { | ||||
|         match self { | ||||
|             GeneralConstId::StaticId(it) => { | ||||
|                 let loc = it.lookup(db); | ||||
|                 let tree = loc.item_tree_id().item_tree(db); | ||||
|                 let name = tree[loc.id.value].name.display(db, Edition::CURRENT); | ||||
|                 name.to_string() | ||||
|                 db.static_signature(it).name.display(db, Edition::CURRENT).to_string() | ||||
|             } | ||||
|             GeneralConstId::ConstId(const_id) => { | ||||
|                 let loc = const_id.lookup(db); | ||||
|                 let tree = loc.item_tree_id().item_tree(db); | ||||
|                 tree[loc.id.value].name.as_ref().map_or_else( | ||||
|                 db.const_signature(const_id).name.as_ref().map_or_else( | ||||
|                     || "_".to_owned(), | ||||
|                     |name| name.display(db, Edition::CURRENT).to_string(), | ||||
|                 ) | ||||
|  | @ -768,8 +811,8 @@ impl GenericDefId { | |||
|             GenericDefId::TraitId(it) => file_id_and_params_of_item_loc(db, it), | ||||
|             GenericDefId::TraitAliasId(it) => file_id_and_params_of_item_loc(db, it), | ||||
|             GenericDefId::ImplId(it) => file_id_and_params_of_item_loc(db, it), | ||||
|             GenericDefId::ConstId(it) => (it.lookup(db).id.file_id(), None), | ||||
|             GenericDefId::StaticId(it) => (it.lookup(db).id.file_id(), None), | ||||
|             GenericDefId::ConstId(it) => (it.lookup(db).id.file_id, None), | ||||
|             GenericDefId::StaticId(it) => (it.lookup(db).id.file_id, None), | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|  | @ -935,9 +978,9 @@ impl VariantId { | |||
| 
 | ||||
|     pub fn file_id(self, db: &dyn DefDatabase) -> HirFileId { | ||||
|         match self { | ||||
|             VariantId::EnumVariantId(it) => it.lookup(db).id.file_id(), | ||||
|             VariantId::StructId(it) => it.lookup(db).id.file_id(), | ||||
|             VariantId::UnionId(it) => it.lookup(db).id.file_id(), | ||||
|             VariantId::EnumVariantId(it) => it.lookup(db).id.file_id, | ||||
|             VariantId::StructId(it) => it.lookup(db).id.file_id, | ||||
|             VariantId::UnionId(it) => it.lookup(db).id.file_id, | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|  | @ -977,7 +1020,7 @@ pub trait HasModule { | |||
| 
 | ||||
| impl<N, ItemId> HasModule for ItemId | ||||
| where | ||||
|     N: ItemTreeNode, | ||||
|     N: AstIdNode, | ||||
|     ItemId: Lookup<Database = dyn DefDatabase, Data = ItemLoc<N>> + Copy, | ||||
| { | ||||
|     #[inline] | ||||
|  | @ -1003,7 +1046,7 @@ where | |||
| #[inline] | ||||
| fn module_for_assoc_item_loc<'db>( | ||||
|     db: &(dyn 'db + DefDatabase), | ||||
|     id: impl Lookup<Database = dyn DefDatabase, Data = AssocItemLoc<impl ItemTreeNode>>, | ||||
|     id: impl Lookup<Database = dyn DefDatabase, Data = AssocItemLoc<impl AstIdNode>>, | ||||
| ) -> ModuleId { | ||||
|     id.lookup(db).container.module(db) | ||||
| } | ||||
|  |  | |||
|  | @ -171,12 +171,10 @@ pub struct DefMap { | |||
|     /// ExternCrateId being None implies it being imported from the general prelude import.
 | ||||
|     macro_use_prelude: FxHashMap<Name, (MacroId, Option<ExternCrateId>)>, | ||||
| 
 | ||||
|     // FIXME: AstId's are fairly unstable
 | ||||
|     /// Tracks which custom derives are in scope for an item, to allow resolution of derive helper
 | ||||
|     /// attributes.
 | ||||
|     // FIXME: Figure out a better way for the IDE layer to resolve these?
 | ||||
|     derive_helpers_in_scope: FxHashMap<AstId<ast::Item>, Vec<(Name, MacroId, MacroCallId)>>, | ||||
|     // FIXME: AstId's are fairly unstable
 | ||||
|     /// A mapping from [`hir_expand::MacroDefId`] to [`crate::MacroId`].
 | ||||
|     pub macro_def_to_macro_id: FxHashMap<ErasedAstId, MacroId>, | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,14 +1,28 @@ | |||
| //! Expansion of associated items
 | ||||
| 
 | ||||
| use hir_expand::{AstId, InFile, Intern, Lookup, MacroCallKind, MacroDefKind, name::Name}; | ||||
| use syntax::ast; | ||||
| use std::mem; | ||||
| 
 | ||||
| use cfg::CfgOptions; | ||||
| use hir_expand::{ | ||||
|     AstId, ExpandTo, HirFileId, InFile, Intern, Lookup, MacroCallKind, MacroDefKind, | ||||
|     mod_path::ModPath, | ||||
|     name::{AsName, Name}, | ||||
|     span_map::SpanMap, | ||||
| }; | ||||
| use intern::Interned; | ||||
| use span::AstIdMap; | ||||
| use syntax::{ | ||||
|     AstNode, | ||||
|     ast::{self, HasModuleItem, HasName}, | ||||
| }; | ||||
| use thin_vec::ThinVec; | ||||
| use triomphe::Arc; | ||||
| 
 | ||||
| use crate::{ | ||||
|     AssocItemId, AstIdWithPath, ConstLoc, FunctionId, FunctionLoc, ImplId, ItemContainerId, | ||||
|     ItemLoc, MacroCallId, ModuleId, TraitId, TypeAliasId, TypeAliasLoc, | ||||
|     attr::Attrs, | ||||
|     db::DefDatabase, | ||||
|     item_tree::{AssocItem, ItemTree, ItemTreeId, MacroCall, ModItem, TreeId}, | ||||
|     macro_call_as_call_id, | ||||
|     nameres::{ | ||||
|         DefMap, LocalDefMap, MacroSubNs, | ||||
|  | @ -20,9 +34,8 @@ use crate::{ | |||
| #[derive(Debug, Clone, PartialEq, Eq)] | ||||
| pub struct TraitItems { | ||||
|     pub items: Box<[(Name, AssocItemId)]>, | ||||
|     // box it as the vec is usually empty anyways
 | ||||
|     // FIXME: AstIds are rather unstable...
 | ||||
|     pub macro_calls: Option<Box<Vec<(AstId<ast::Item>, MacroCallId)>>>, | ||||
|     // `ThinVec` as the vec is usually empty anyways
 | ||||
|     pub macro_calls: ThinVec<(AstId<ast::Item>, MacroCallId)>, | ||||
| } | ||||
| 
 | ||||
| impl TraitItems { | ||||
|  | @ -35,12 +48,12 @@ impl TraitItems { | |||
|         db: &dyn DefDatabase, | ||||
|         tr: TraitId, | ||||
|     ) -> (Arc<TraitItems>, DefDiagnostics) { | ||||
|         let ItemLoc { container: module_id, id: tree_id } = tr.lookup(db); | ||||
|         let ItemLoc { container: module_id, id: ast_id } = tr.lookup(db); | ||||
| 
 | ||||
|         let collector = AssocItemCollector::new(db, module_id, ItemContainerId::TraitId(tr)); | ||||
|         let item_tree = tree_id.item_tree(db); | ||||
|         let (items, macro_calls, diagnostics) = | ||||
|             collector.collect(&item_tree, tree_id.tree_id(), &item_tree[tree_id.value].items); | ||||
|         let collector = | ||||
|             AssocItemCollector::new(db, module_id, ItemContainerId::TraitId(tr), ast_id.file_id); | ||||
|         let source = ast_id.with_value(collector.ast_id_map.get(ast_id.value)).to_node(db); | ||||
|         let (items, macro_calls, diagnostics) = collector.collect(source.assoc_item_list()); | ||||
| 
 | ||||
|         (Arc::new(TraitItems { macro_calls, items }), DefDiagnostics::new(diagnostics)) | ||||
|     } | ||||
|  | @ -76,16 +89,15 @@ impl TraitItems { | |||
|     } | ||||
| 
 | ||||
|     pub fn macro_calls(&self) -> impl Iterator<Item = (AstId<ast::Item>, MacroCallId)> + '_ { | ||||
|         self.macro_calls.iter().flat_map(|it| it.iter()).copied() | ||||
|         self.macro_calls.iter().copied() | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug, PartialEq, Eq)] | ||||
| pub struct ImplItems { | ||||
|     pub items: Box<[(Name, AssocItemId)]>, | ||||
|     // box it as the vec is usually empty anyways
 | ||||
|     // FIXME: AstIds are rather unstable...
 | ||||
|     pub macro_calls: Option<Box<Vec<(AstId<ast::Item>, MacroCallId)>>>, | ||||
|     // `ThinVec` as the vec is usually empty anyways
 | ||||
|     pub macro_calls: ThinVec<(AstId<ast::Item>, MacroCallId)>, | ||||
| } | ||||
| 
 | ||||
| impl ImplItems { | ||||
|  | @ -99,18 +111,18 @@ impl ImplItems { | |||
|         id: ImplId, | ||||
|     ) -> (Arc<ImplItems>, DefDiagnostics) { | ||||
|         let _p = tracing::info_span!("impl_items_with_diagnostics_query").entered(); | ||||
|         let ItemLoc { container: module_id, id: tree_id } = id.lookup(db); | ||||
|         let ItemLoc { container: module_id, id: ast_id } = id.lookup(db); | ||||
| 
 | ||||
|         let collector = AssocItemCollector::new(db, module_id, ItemContainerId::ImplId(id)); | ||||
|         let item_tree = tree_id.item_tree(db); | ||||
|         let (items, macro_calls, diagnostics) = | ||||
|             collector.collect(&item_tree, tree_id.tree_id(), &item_tree[tree_id.value].items); | ||||
|         let collector = | ||||
|             AssocItemCollector::new(db, module_id, ItemContainerId::ImplId(id), ast_id.file_id); | ||||
|         let source = ast_id.with_value(collector.ast_id_map.get(ast_id.value)).to_node(db); | ||||
|         let (items, macro_calls, diagnostics) = collector.collect(source.assoc_item_list()); | ||||
| 
 | ||||
|         (Arc::new(ImplItems { items, macro_calls }), DefDiagnostics::new(diagnostics)) | ||||
|     } | ||||
| 
 | ||||
|     pub fn macro_calls(&self) -> impl Iterator<Item = (AstId<ast::Item>, MacroCallId)> + '_ { | ||||
|         self.macro_calls.iter().flat_map(|it| it.iter()).copied() | ||||
|         self.macro_calls.iter().copied() | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | @ -119,67 +131,73 @@ struct AssocItemCollector<'a> { | |||
|     module_id: ModuleId, | ||||
|     def_map: &'a DefMap, | ||||
|     local_def_map: &'a LocalDefMap, | ||||
|     ast_id_map: Arc<AstIdMap>, | ||||
|     span_map: SpanMap, | ||||
|     cfg_options: &'a CfgOptions, | ||||
|     file_id: HirFileId, | ||||
|     diagnostics: Vec<DefDiagnostic>, | ||||
|     container: ItemContainerId, | ||||
| 
 | ||||
|     depth: usize, | ||||
|     items: Vec<(Name, AssocItemId)>, | ||||
|     macro_calls: Vec<(AstId<ast::Item>, MacroCallId)>, | ||||
|     macro_calls: ThinVec<(AstId<ast::Item>, MacroCallId)>, | ||||
| } | ||||
| 
 | ||||
| impl<'a> AssocItemCollector<'a> { | ||||
|     fn new(db: &'a dyn DefDatabase, module_id: ModuleId, container: ItemContainerId) -> Self { | ||||
|     fn new( | ||||
|         db: &'a dyn DefDatabase, | ||||
|         module_id: ModuleId, | ||||
|         container: ItemContainerId, | ||||
|         file_id: HirFileId, | ||||
|     ) -> Self { | ||||
|         let (def_map, local_def_map) = module_id.local_def_map(db); | ||||
|         Self { | ||||
|             db, | ||||
|             module_id, | ||||
|             def_map, | ||||
|             local_def_map, | ||||
|             ast_id_map: db.ast_id_map(file_id), | ||||
|             span_map: db.span_map(file_id), | ||||
|             cfg_options: module_id.krate.cfg_options(db), | ||||
|             file_id, | ||||
|             container, | ||||
|             items: Vec::new(), | ||||
| 
 | ||||
|             depth: 0, | ||||
|             macro_calls: Vec::new(), | ||||
|             macro_calls: ThinVec::new(), | ||||
|             diagnostics: Vec::new(), | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     fn collect( | ||||
|         mut self, | ||||
|         item_tree: &ItemTree, | ||||
|         tree_id: TreeId, | ||||
|         assoc_items: &[AssocItem], | ||||
|     ) -> ( | ||||
|         Box<[(Name, AssocItemId)]>, | ||||
|         Option<Box<Vec<(AstId<ast::Item>, MacroCallId)>>>, | ||||
|         Vec<DefDiagnostic>, | ||||
|     ) { | ||||
|         self.items.reserve(assoc_items.len()); | ||||
|         for &item in assoc_items { | ||||
|             self.collect_item(item_tree, tree_id, item); | ||||
|         item_list: Option<ast::AssocItemList>, | ||||
|     ) -> (Box<[(Name, AssocItemId)]>, ThinVec<(AstId<ast::Item>, MacroCallId)>, Vec<DefDiagnostic>) | ||||
|     { | ||||
|         if let Some(item_list) = item_list { | ||||
|             for item in item_list.assoc_items() { | ||||
|                 self.collect_item(item); | ||||
|             } | ||||
|         ( | ||||
|             self.items.into_boxed_slice(), | ||||
|             if self.macro_calls.is_empty() { None } else { Some(Box::new(self.macro_calls)) }, | ||||
|             self.diagnostics, | ||||
|         ) | ||||
|         } | ||||
|         self.macro_calls.shrink_to_fit(); | ||||
|         (self.items.into_boxed_slice(), self.macro_calls, self.diagnostics) | ||||
|     } | ||||
| 
 | ||||
|     fn collect_item(&mut self, item_tree: &ItemTree, tree_id: TreeId, item: AssocItem) { | ||||
|         let attrs = item_tree.attrs(self.db, self.module_id.krate, ModItem::from(item).into()); | ||||
|         if !attrs.is_cfg_enabled(self.module_id.krate.cfg_options(self.db)) { | ||||
|     fn collect_item(&mut self, item: ast::AssocItem) { | ||||
|         let ast_id = self.ast_id_map.ast_id(&item); | ||||
|         let attrs = Attrs::new(self.db, &item, self.span_map.as_ref(), self.cfg_options); | ||||
|         if let Err(cfg) = attrs.is_cfg_enabled(self.cfg_options) { | ||||
|             self.diagnostics.push(DefDiagnostic::unconfigured_code( | ||||
|                 self.module_id.local_id, | ||||
|                 tree_id, | ||||
|                 ModItem::from(item).into(), | ||||
|                 attrs.cfg().unwrap(), | ||||
|                 self.module_id.krate.cfg_options(self.db).clone(), | ||||
|                 InFile::new(self.file_id, ast_id.erase()), | ||||
|                 cfg, | ||||
|                 self.cfg_options.clone(), | ||||
|             )); | ||||
|             return; | ||||
|         } | ||||
|         let ast_id = InFile::new(self.file_id, ast_id.upcast()); | ||||
| 
 | ||||
|         'attrs: for attr in &*attrs { | ||||
|             let ast_id = AstId::new(tree_id.file_id(), item.ast_id(item_tree).upcast()); | ||||
|             let ast_id_with_path = AstIdWithPath { path: attr.path.clone(), ast_id }; | ||||
| 
 | ||||
|             match self.def_map.resolve_attr_macro( | ||||
|  | @ -223,34 +241,51 @@ impl<'a> AssocItemCollector<'a> { | |||
|             } | ||||
|         } | ||||
| 
 | ||||
|         self.record_item(item_tree, tree_id, item); | ||||
|         self.record_item(item); | ||||
|     } | ||||
| 
 | ||||
|     fn record_item(&mut self, item_tree: &ItemTree, tree_id: TreeId, item: AssocItem) { | ||||
|     fn record_item(&mut self, item: ast::AssocItem) { | ||||
|         match item { | ||||
|             AssocItem::Function(id) => { | ||||
|                 let item = &item_tree[id]; | ||||
|             ast::AssocItem::Fn(function) => { | ||||
|                 let Some(name) = function.name() else { return }; | ||||
|                 let ast_id = self.ast_id_map.ast_id(&function); | ||||
|                 let def = FunctionLoc { | ||||
|                     container: self.container, | ||||
|                     id: InFile::new(self.file_id, ast_id), | ||||
|                 } | ||||
|                 .intern(self.db); | ||||
|                 self.items.push((name.as_name(), def.into())); | ||||
|             } | ||||
|             ast::AssocItem::TypeAlias(type_alias) => { | ||||
|                 let Some(name) = type_alias.name() else { return }; | ||||
|                 let ast_id = self.ast_id_map.ast_id(&type_alias); | ||||
|                 let def = TypeAliasLoc { | ||||
|                     container: self.container, | ||||
|                     id: InFile::new(self.file_id, ast_id), | ||||
|                 } | ||||
|                 .intern(self.db); | ||||
|                 self.items.push((name.as_name(), def.into())); | ||||
|             } | ||||
|             ast::AssocItem::Const(konst) => { | ||||
|                 let Some(name) = konst.name() else { return }; | ||||
|                 let ast_id = self.ast_id_map.ast_id(&konst); | ||||
|                 let def = | ||||
|                     FunctionLoc { container: self.container, id: ItemTreeId::new(tree_id, id) } | ||||
|                     ConstLoc { container: self.container, id: InFile::new(self.file_id, ast_id) } | ||||
|                         .intern(self.db); | ||||
|                 self.items.push((item.name.clone(), def.into())); | ||||
|                 self.items.push((name.as_name(), def.into())); | ||||
|             } | ||||
|             AssocItem::TypeAlias(id) => { | ||||
|                 let item = &item_tree[id]; | ||||
|                 let def = | ||||
|                     TypeAliasLoc { container: self.container, id: ItemTreeId::new(tree_id, id) } | ||||
|                         .intern(self.db); | ||||
|                 self.items.push((item.name.clone(), def.into())); | ||||
|             } | ||||
|             AssocItem::Const(id) => { | ||||
|                 let item = &item_tree[id]; | ||||
|                 let Some(name) = item.name.clone() else { return }; | ||||
|                 let def = ConstLoc { container: self.container, id: ItemTreeId::new(tree_id, id) } | ||||
|                     .intern(self.db); | ||||
|                 self.items.push((name, def.into())); | ||||
|             } | ||||
|             AssocItem::MacroCall(call) => { | ||||
|                 let MacroCall { ast_id, expand_to, ctxt, ref path } = item_tree[call]; | ||||
|             ast::AssocItem::MacroCall(call) => { | ||||
|                 let ast_id = self.ast_id_map.ast_id(&call); | ||||
|                 let ast_id = InFile::new(self.file_id, ast_id); | ||||
|                 let Some(path) = call.path() else { return }; | ||||
|                 let range = path.syntax().text_range(); | ||||
|                 let Some(path) = ModPath::from_src(self.db, path, &mut |range| { | ||||
|                     self.span_map.span_for_range(range).ctx | ||||
|                 }) else { | ||||
|                     return; | ||||
|                 }; | ||||
|                 let path = Interned::new(path); | ||||
|                 let ctxt = self.span_map.span_for_range(range).ctx; | ||||
| 
 | ||||
|                 let resolver = |path: &_| { | ||||
|                     self.def_map | ||||
|  | @ -268,10 +303,10 @@ impl<'a> AssocItemCollector<'a> { | |||
|                 }; | ||||
|                 match macro_call_as_call_id( | ||||
|                     self.db, | ||||
|                     InFile::new(tree_id.file_id(), ast_id), | ||||
|                     path, | ||||
|                     ast_id, | ||||
|                     &path, | ||||
|                     ctxt, | ||||
|                     expand_to, | ||||
|                     ExpandTo::Items, | ||||
|                     self.module_id.krate(), | ||||
|                     resolver, | ||||
|                     &mut |ptr, call_id| { | ||||
|  | @ -281,8 +316,7 @@ impl<'a> AssocItemCollector<'a> { | |||
|                     // FIXME: Expansion error?
 | ||||
|                     Ok(call_id) => match call_id.value { | ||||
|                         Some(call_id) => { | ||||
|                             self.macro_calls | ||||
|                                 .push((InFile::new(tree_id.file_id(), ast_id.upcast()), call_id)); | ||||
|                             self.macro_calls.push((ast_id.upcast(), call_id)); | ||||
|                             self.collect_macro_items(call_id); | ||||
|                         } | ||||
|                         None => (), | ||||
|  | @ -291,11 +325,11 @@ impl<'a> AssocItemCollector<'a> { | |||
|                         self.diagnostics.push(DefDiagnostic::unresolved_macro_call( | ||||
|                             self.module_id.local_id, | ||||
|                             MacroCallKind::FnLike { | ||||
|                                 ast_id: InFile::new(tree_id.file_id(), ast_id), | ||||
|                                 expand_to, | ||||
|                                 ast_id, | ||||
|                                 expand_to: ExpandTo::Items, | ||||
|                                 eager: None, | ||||
|                             }, | ||||
|                             Clone::clone(path), | ||||
|                             (*path).clone(), | ||||
|                         )); | ||||
|                     } | ||||
|                 } | ||||
|  | @ -308,13 +342,29 @@ impl<'a> AssocItemCollector<'a> { | |||
|             tracing::warn!("macro expansion is too deep"); | ||||
|             return; | ||||
|         } | ||||
|         let tree_id = TreeId::new(macro_call_id.into(), None); | ||||
|         let item_tree = self.db.file_item_tree(macro_call_id.into()); | ||||
| 
 | ||||
|         let (syntax, span_map) = self.db.parse_macro_expansion(macro_call_id).value; | ||||
|         let old_file_id = mem::replace(&mut self.file_id, macro_call_id.into()); | ||||
|         let old_ast_id_map = mem::replace(&mut self.ast_id_map, self.db.ast_id_map(self.file_id)); | ||||
|         let old_span_map = mem::replace(&mut self.span_map, SpanMap::ExpansionSpanMap(span_map)); | ||||
|         self.depth += 1; | ||||
|         for item in item_tree.top_level_items().iter().filter_map(ModItem::as_assoc_item) { | ||||
|             self.collect_item(&item_tree, tree_id, item); | ||||
| 
 | ||||
|         let items = ast::MacroItems::cast(syntax.syntax_node()).expect("not `MacroItems`"); | ||||
|         for item in items.items() { | ||||
|             let item = match item { | ||||
|                 ast::Item::Fn(it) => ast::AssocItem::from(it), | ||||
|                 ast::Item::Const(it) => it.into(), | ||||
|                 ast::Item::TypeAlias(it) => it.into(), | ||||
|                 ast::Item::MacroCall(it) => it.into(), | ||||
|                 // FIXME: Should error on disallowed item kinds.
 | ||||
|                 _ => continue, | ||||
|             }; | ||||
|             self.collect_item(item); | ||||
|         } | ||||
| 
 | ||||
|         self.depth -= 1; | ||||
|         self.file_id = old_file_id; | ||||
|         self.ast_id_map = old_ast_id_map; | ||||
|         self.span_map = old_span_map; | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -9,8 +9,8 @@ use base_db::{BuiltDependency, Crate, CrateOrigin, LangCrateOrigin}; | |||
| use cfg::{CfgAtom, CfgExpr, CfgOptions}; | ||||
| use either::Either; | ||||
| use hir_expand::{ | ||||
|     EditionedFileId, ExpandTo, HirFileId, InFile, MacroCallId, MacroCallKind, MacroDefId, | ||||
|     MacroDefKind, | ||||
|     EditionedFileId, ErasedAstId, ExpandTo, HirFileId, InFile, MacroCallId, MacroCallKind, | ||||
|     MacroDefId, MacroDefKind, | ||||
|     attrs::{Attr, AttrId}, | ||||
|     builtin::{find_builtin_attr, find_builtin_derive, find_builtin_macro}, | ||||
|     mod_path::{ModPath, PathKind}, | ||||
|  | @ -35,9 +35,8 @@ use crate::{ | |||
|     db::DefDatabase, | ||||
|     item_scope::{GlobId, ImportId, ImportOrExternCrate, PerNsGlobImports}, | ||||
|     item_tree::{ | ||||
|         self, AttrOwner, FieldsShape, FileItemTreeId, ImportAlias, ImportKind, ItemTree, | ||||
|         ItemTreeId, ItemTreeNode, Macro2, MacroCall, MacroRules, Mod, ModItem, ModKind, TreeId, | ||||
|         UseTreeKind, | ||||
|         self, FieldsShape, FileItemTreeId, ImportAlias, ImportKind, ItemTree, ItemTreeId, | ||||
|         ItemTreeNode, Macro2, MacroCall, MacroRules, Mod, ModItem, ModKind, TreeId, UseTreeKind, | ||||
|     }, | ||||
|     macro_call_as_call_id, | ||||
|     nameres::{ | ||||
|  | @ -141,6 +140,7 @@ struct ImportSource { | |||
|     id: UseId, | ||||
|     is_prelude: bool, | ||||
|     kind: ImportKind, | ||||
|     item_tree_id: ItemTreeId<item_tree::Use>, | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug, Eq, PartialEq)] | ||||
|  | @ -166,7 +166,7 @@ impl Import { | |||
|                 path, | ||||
|                 alias, | ||||
|                 visibility: visibility.clone(), | ||||
|                 source: ImportSource { use_tree: idx, id, is_prelude, kind }, | ||||
|                 source: ImportSource { use_tree: idx, id, is_prelude, kind, item_tree_id }, | ||||
|             }); | ||||
|         }); | ||||
|     } | ||||
|  | @ -576,13 +576,7 @@ impl DefCollector<'_> { | |||
|     /// use a dummy expander that always errors. This comes with the drawback of macros potentially
 | ||||
|     /// going out of sync with what the build system sees (since we resolve using VFS state, but
 | ||||
|     /// Cargo builds only on-disk files). We could and probably should add diagnostics for that.
 | ||||
|     fn export_proc_macro( | ||||
|         &mut self, | ||||
|         def: ProcMacroDef, | ||||
|         id: ItemTreeId<item_tree::Function>, | ||||
|         ast_id: AstId<ast::Fn>, | ||||
|         fn_id: FunctionId, | ||||
|     ) { | ||||
|     fn export_proc_macro(&mut self, def: ProcMacroDef, ast_id: AstId<ast::Fn>, fn_id: FunctionId) { | ||||
|         let kind = def.kind.to_basedb_kind(); | ||||
|         let (expander, kind) = match self.proc_macros.iter().find(|(n, _, _)| n == &def.name) { | ||||
|             Some(_) | ||||
|  | @ -598,7 +592,7 @@ impl DefCollector<'_> { | |||
| 
 | ||||
|         let proc_macro_id = ProcMacroLoc { | ||||
|             container: self.def_map.crate_root(), | ||||
|             id, | ||||
|             id: ast_id, | ||||
|             expander, | ||||
|             kind, | ||||
|             edition: self.def_map.data.edition, | ||||
|  | @ -866,6 +860,7 @@ impl DefCollector<'_> { | |||
|                 kind: kind @ (ImportKind::Plain | ImportKind::TypeOnly), | ||||
|                 id, | ||||
|                 use_tree, | ||||
|                 item_tree_id, | ||||
|                 .. | ||||
|             } => { | ||||
|                 let name = match &import.alias { | ||||
|  | @ -887,9 +882,33 @@ impl DefCollector<'_> { | |||
|                 let imp = ImportOrExternCrate::Import(ImportId { use_: id, idx: use_tree }); | ||||
|                 tracing::debug!("resolved import {:?} ({:?}) to {:?}", name, import, def); | ||||
| 
 | ||||
|                 // `extern crate crate_name` things can be re-exported as `pub use crate_name`.
 | ||||
|                 // But they cannot be re-exported as `pub use self::crate_name`, `pub use crate::crate_name`
 | ||||
|                 // or `pub use ::crate_name`.
 | ||||
|                 //
 | ||||
|                 // This has been historically allowed, but may be not allowed in future
 | ||||
|                 // https://github.com/rust-lang/rust/issues/127909
 | ||||
|                 if let Some(def) = def.types.as_mut() { | ||||
|                     let is_extern_crate_reimport_without_prefix = || { | ||||
|                         let Some(ImportOrExternCrate::ExternCrate(_)) = def.import else { | ||||
|                             return false; | ||||
|                         }; | ||||
|                         let item_tree = item_tree_id.item_tree(self.db); | ||||
|                         let use_kind = item_tree[item_tree_id.value].use_tree.kind(); | ||||
|                         let UseTreeKind::Single { path, .. } = use_kind else { | ||||
|                             return false; | ||||
|                         }; | ||||
|                         matches!(path.kind, PathKind::Plain | PathKind::SELF) | ||||
|                             && path.segments().len() < 2 | ||||
|                     }; | ||||
|                     if is_extern_crate_reimport_without_prefix() { | ||||
|                         def.vis = vis; | ||||
|                     } | ||||
|                 } | ||||
| 
 | ||||
|                 self.update(module_id, &[(name.cloned(), def)], vis, Some(imp)); | ||||
|             } | ||||
|             ImportSource { kind: ImportKind::Glob, id, is_prelude, use_tree } => { | ||||
|             ImportSource { kind: ImportKind::Glob, id, is_prelude, use_tree, .. } => { | ||||
|                 tracing::debug!("glob import: {:?}", import); | ||||
|                 let glob = GlobId { use_: id, idx: use_tree }; | ||||
|                 match def.take_types() { | ||||
|  | @ -978,7 +997,7 @@ impl DefCollector<'_> { | |||
|                             .enum_variants(e) | ||||
|                             .variants | ||||
|                             .iter() | ||||
|                             .map(|&(variant, ref name)| { | ||||
|                             .map(|&(variant, ref name, _)| { | ||||
|                                 let res = PerNs::both(variant.into(), variant.into(), vis, None); | ||||
|                                 (Some(name.clone()), res) | ||||
|                             }) | ||||
|  | @ -1150,34 +1169,9 @@ impl DefCollector<'_> { | |||
|         vis: Visibility, | ||||
|         def_import_type: Option<ImportOrExternCrate>, | ||||
|     ) -> bool { | ||||
|         // `extern crate crate_name` things can be re-exported as `pub use crate_name`.
 | ||||
|         // But they cannot be re-exported as `pub use self::crate_name`, `pub use crate::crate_name`
 | ||||
|         // or `pub use ::crate_name`.
 | ||||
|         //
 | ||||
|         // This has been historically allowed, but may be not allowed in future
 | ||||
|         // https://github.com/rust-lang/rust/issues/127909
 | ||||
|         if let Some(def) = defs.types.as_mut() { | ||||
|             let is_extern_crate_reimport_without_prefix = || { | ||||
|                 let Some(ImportOrExternCrate::ExternCrate(_)) = def.import else { | ||||
|                     return false; | ||||
|                 }; | ||||
|                 let Some(ImportOrExternCrate::Import(id)) = def_import_type else { | ||||
|                     return false; | ||||
|                 }; | ||||
|                 let use_id = id.use_.lookup(self.db).id; | ||||
|                 let item_tree = use_id.item_tree(self.db); | ||||
|                 let use_kind = item_tree[use_id.value].use_tree.kind(); | ||||
|                 let UseTreeKind::Single { path, .. } = use_kind else { | ||||
|                     return false; | ||||
|                 }; | ||||
|                 path.segments().len() < 2 | ||||
|             }; | ||||
|             if is_extern_crate_reimport_without_prefix() { | ||||
|                 def.vis = vis; | ||||
|             } else { | ||||
|             def.vis = def.vis.min(vis, &self.def_map).unwrap_or(vis); | ||||
|         } | ||||
|         } | ||||
|         if let Some(def) = defs.values.as_mut() { | ||||
|             def.vis = def.vis.min(vis, &self.def_map).unwrap_or(vis); | ||||
|         } | ||||
|  | @ -1648,7 +1642,8 @@ impl DefCollector<'_> { | |||
|                 import: | ||||
|                     Import { | ||||
|                         ref path, | ||||
|                         source: ImportSource { use_tree, id, is_prelude: _, kind: _ }, | ||||
|                         source: | ||||
|                             ImportSource { use_tree, id, is_prelude: _, kind: _, item_tree_id: _ }, | ||||
|                         .. | ||||
|                     }, | ||||
|                 .. | ||||
|  | @ -1730,7 +1725,26 @@ impl ModCollector<'_, '_> { | |||
|             let attrs = self.item_tree.attrs(db, krate, item.into()); | ||||
|             if let Some(cfg) = attrs.cfg() { | ||||
|                 if !self.is_cfg_enabled(&cfg) { | ||||
|                     self.emit_unconfigured_diagnostic(self.tree_id, item.into(), &cfg); | ||||
|                     let ast_id = match item { | ||||
|                         ModItem::Use(it) => self.item_tree[it].ast_id.erase(), | ||||
|                         ModItem::ExternCrate(it) => self.item_tree[it].ast_id.erase(), | ||||
|                         ModItem::ExternBlock(it) => self.item_tree[it].ast_id.erase(), | ||||
|                         ModItem::Function(it) => self.item_tree[it].ast_id.erase(), | ||||
|                         ModItem::Struct(it) => self.item_tree[it].ast_id.erase(), | ||||
|                         ModItem::Union(it) => self.item_tree[it].ast_id.erase(), | ||||
|                         ModItem::Enum(it) => self.item_tree[it].ast_id.erase(), | ||||
|                         ModItem::Const(it) => self.item_tree[it].ast_id.erase(), | ||||
|                         ModItem::Static(it) => self.item_tree[it].ast_id.erase(), | ||||
|                         ModItem::Trait(it) => self.item_tree[it].ast_id.erase(), | ||||
|                         ModItem::TraitAlias(it) => self.item_tree[it].ast_id.erase(), | ||||
|                         ModItem::Impl(it) => self.item_tree[it].ast_id.erase(), | ||||
|                         ModItem::TypeAlias(it) => self.item_tree[it].ast_id.erase(), | ||||
|                         ModItem::Mod(it) => self.item_tree[it].ast_id.erase(), | ||||
|                         ModItem::MacroCall(it) => self.item_tree[it].ast_id.erase(), | ||||
|                         ModItem::MacroRules(it) => self.item_tree[it].ast_id.erase(), | ||||
|                         ModItem::Macro2(it) => self.item_tree[it].ast_id.erase(), | ||||
|                     }; | ||||
|                     self.emit_unconfigured_diagnostic(InFile::new(self.file_id(), ast_id), &cfg); | ||||
|                     return; | ||||
|                 } | ||||
|             } | ||||
|  | @ -1751,7 +1765,7 @@ impl ModCollector<'_, '_> { | |||
|                 ModItem::Use(item_tree_id) => { | ||||
|                     let id = UseLoc { | ||||
|                         container: module, | ||||
|                         id: ItemTreeId::new(self.tree_id, item_tree_id), | ||||
|                         id: InFile::new(self.file_id(), self.item_tree[item_tree_id].ast_id), | ||||
|                     } | ||||
|                     .intern(db); | ||||
|                     let is_prelude = attrs.by_key(sym::prelude_import).exists(); | ||||
|  | @ -1770,16 +1784,16 @@ impl ModCollector<'_, '_> { | |||
|                     ) | ||||
|                 } | ||||
|                 ModItem::ExternCrate(item_tree_id) => { | ||||
|                     let item_tree::ExternCrate { name, visibility, alias, ast_id } = | ||||
|                         &self.item_tree[item_tree_id]; | ||||
| 
 | ||||
|                     let id = ExternCrateLoc { | ||||
|                         container: module, | ||||
|                         id: ItemTreeId::new(self.tree_id, item_tree_id), | ||||
|                         id: InFile::new(self.tree_id.file_id(), *ast_id), | ||||
|                     } | ||||
|                     .intern(db); | ||||
|                     def_map.modules[self.module_id].scope.define_extern_crate_decl(id); | ||||
| 
 | ||||
|                     let item_tree::ExternCrate { name, visibility, alias, ast_id } = | ||||
|                         &self.item_tree[item_tree_id]; | ||||
| 
 | ||||
|                     let is_self = *name == sym::self_; | ||||
|                     let resolved = if is_self { | ||||
|                         cov_mark::hit!(extern_crate_self_as); | ||||
|  | @ -1846,7 +1860,7 @@ impl ModCollector<'_, '_> { | |||
|                 ModItem::ExternBlock(block) => { | ||||
|                     let extern_block_id = ExternBlockLoc { | ||||
|                         container: module, | ||||
|                         id: ItemTreeId::new(self.tree_id, block), | ||||
|                         id: InFile::new(self.file_id(), self.item_tree[block].ast_id), | ||||
|                     } | ||||
|                     .intern(db); | ||||
|                     self.def_collector.def_map.modules[self.module_id] | ||||
|  | @ -1861,15 +1875,20 @@ impl ModCollector<'_, '_> { | |||
|                 ModItem::MacroRules(id) => self.collect_macro_rules(id, module), | ||||
|                 ModItem::Macro2(id) => self.collect_macro_def(id, module), | ||||
|                 ModItem::Impl(imp) => { | ||||
|                     let impl_id = | ||||
|                         ImplLoc { container: module, id: ItemTreeId::new(self.tree_id, imp) } | ||||
|                     let impl_id = ImplLoc { | ||||
|                         container: module, | ||||
|                         id: InFile::new(self.file_id(), self.item_tree[imp].ast_id), | ||||
|                     } | ||||
|                     .intern(db); | ||||
|                     self.def_collector.def_map.modules[self.module_id].scope.define_impl(impl_id) | ||||
|                 } | ||||
|                 ModItem::Function(id) => { | ||||
|                     let it = &self.item_tree[id]; | ||||
|                     let fn_id = | ||||
|                         FunctionLoc { container, id: ItemTreeId::new(self.tree_id, id) }.intern(db); | ||||
|                     let fn_id = FunctionLoc { | ||||
|                         container, | ||||
|                         id: InFile::new(self.tree_id.file_id(), it.ast_id), | ||||
|                     } | ||||
|                     .intern(db); | ||||
| 
 | ||||
|                     let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]); | ||||
| 
 | ||||
|  | @ -1880,7 +1899,6 @@ impl ModCollector<'_, '_> { | |||
|                         if let Some(proc_macro) = attrs.parse_proc_macro_decl(&it.name) { | ||||
|                             self.def_collector.export_proc_macro( | ||||
|                                 proc_macro, | ||||
|                                 ItemTreeId::new(self.tree_id, id), | ||||
|                                 InFile::new(self.file_id(), self.item_tree[id].ast_id()), | ||||
|                                 fn_id, | ||||
|                             ); | ||||
|  | @ -1895,7 +1913,7 @@ impl ModCollector<'_, '_> { | |||
|                     let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]); | ||||
|                     update_def( | ||||
|                         self.def_collector, | ||||
|                         StructLoc { container: module, id: ItemTreeId::new(self.tree_id, id) } | ||||
|                         StructLoc { container: module, id: InFile::new(self.file_id(), it.ast_id) } | ||||
|                             .intern(db) | ||||
|                             .into(), | ||||
|                         &it.name, | ||||
|  | @ -1909,7 +1927,7 @@ impl ModCollector<'_, '_> { | |||
|                     let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]); | ||||
|                     update_def( | ||||
|                         self.def_collector, | ||||
|                         UnionLoc { container: module, id: ItemTreeId::new(self.tree_id, id) } | ||||
|                         UnionLoc { container: module, id: InFile::new(self.file_id(), it.ast_id) } | ||||
|                             .intern(db) | ||||
|                             .into(), | ||||
|                         &it.name, | ||||
|  | @ -1919,8 +1937,10 @@ impl ModCollector<'_, '_> { | |||
|                 } | ||||
|                 ModItem::Enum(id) => { | ||||
|                     let it = &self.item_tree[id]; | ||||
|                     let enum_ = | ||||
|                         EnumLoc { container: module, id: ItemTreeId::new(self.tree_id, id) } | ||||
|                     let enum_ = EnumLoc { | ||||
|                         container: module, | ||||
|                         id: InFile::new(self.tree_id.file_id(), it.ast_id), | ||||
|                     } | ||||
|                     .intern(db); | ||||
| 
 | ||||
|                     let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]); | ||||
|  | @ -1929,7 +1949,8 @@ impl ModCollector<'_, '_> { | |||
|                 ModItem::Const(id) => { | ||||
|                     let it = &self.item_tree[id]; | ||||
|                     let const_id = | ||||
|                         ConstLoc { container, id: ItemTreeId::new(self.tree_id, id) }.intern(db); | ||||
|                         ConstLoc { container, id: InFile::new(self.tree_id.file_id(), it.ast_id) } | ||||
|                             .intern(db); | ||||
| 
 | ||||
|                     match &it.name { | ||||
|                         Some(name) => { | ||||
|  | @ -1951,7 +1972,7 @@ impl ModCollector<'_, '_> { | |||
|                     let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]); | ||||
|                     update_def( | ||||
|                         self.def_collector, | ||||
|                         StaticLoc { container, id: ItemTreeId::new(self.tree_id, id) } | ||||
|                         StaticLoc { container, id: InFile::new(self.file_id(), it.ast_id) } | ||||
|                             .intern(db) | ||||
|                             .into(), | ||||
|                         &it.name, | ||||
|  | @ -1965,7 +1986,7 @@ impl ModCollector<'_, '_> { | |||
|                     let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]); | ||||
|                     update_def( | ||||
|                         self.def_collector, | ||||
|                         TraitLoc { container: module, id: ItemTreeId::new(self.tree_id, id) } | ||||
|                         TraitLoc { container: module, id: InFile::new(self.file_id(), it.ast_id) } | ||||
|                             .intern(db) | ||||
|                             .into(), | ||||
|                         &it.name, | ||||
|  | @ -1979,7 +2000,10 @@ impl ModCollector<'_, '_> { | |||
|                     let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]); | ||||
|                     update_def( | ||||
|                         self.def_collector, | ||||
|                         TraitAliasLoc { container: module, id: ItemTreeId::new(self.tree_id, id) } | ||||
|                         TraitAliasLoc { | ||||
|                             container: module, | ||||
|                             id: InFile::new(self.file_id(), it.ast_id), | ||||
|                         } | ||||
|                         .intern(db) | ||||
|                         .into(), | ||||
|                         &it.name, | ||||
|  | @ -1993,7 +2017,7 @@ impl ModCollector<'_, '_> { | |||
|                     let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]); | ||||
|                     update_def( | ||||
|                         self.def_collector, | ||||
|                         TypeAliasLoc { container, id: ItemTreeId::new(self.tree_id, id) } | ||||
|                         TypeAliasLoc { container, id: InFile::new(self.file_id(), it.ast_id) } | ||||
|                             .intern(db) | ||||
|                             .into(), | ||||
|                         &it.name, | ||||
|  | @ -2110,8 +2134,10 @@ impl ModCollector<'_, '_> { | |||
|                         match is_enabled { | ||||
|                             Err(cfg) => { | ||||
|                                 self.emit_unconfigured_diagnostic( | ||||
|                                     self.tree_id, | ||||
|                                     AttrOwner::ModItem(module_id.into()), | ||||
|                                     InFile::new( | ||||
|                                         self.file_id(), | ||||
|                                         self.item_tree[module_id].ast_id.erase(), | ||||
|                                     ), | ||||
|                                     &cfg, | ||||
|                                 ); | ||||
|                             } | ||||
|  | @ -2352,7 +2378,7 @@ impl ModCollector<'_, '_> { | |||
| 
 | ||||
|         let macro_id = MacroRulesLoc { | ||||
|             container: module, | ||||
|             id: ItemTreeId::new(self.tree_id, id), | ||||
|             id: InFile::new(self.file_id(), mac.ast_id), | ||||
|             flags, | ||||
|             expander, | ||||
|             edition: self.def_collector.def_map.data.edition, | ||||
|  | @ -2420,7 +2446,7 @@ impl ModCollector<'_, '_> { | |||
| 
 | ||||
|         let macro_id = Macro2Loc { | ||||
|             container: module, | ||||
|             id: ItemTreeId::new(self.tree_id, id), | ||||
|             id: InFile::new(self.file_id(), mac.ast_id), | ||||
|             expander, | ||||
|             allow_internal_unsafe, | ||||
|             edition: self.def_collector.def_map.data.edition, | ||||
|  | @ -2565,16 +2591,16 @@ impl ModCollector<'_, '_> { | |||
|         self.def_collector.cfg_options.check(cfg) != Some(false) | ||||
|     } | ||||
| 
 | ||||
|     fn emit_unconfigured_diagnostic(&mut self, tree_id: TreeId, item: AttrOwner, cfg: &CfgExpr) { | ||||
|     fn emit_unconfigured_diagnostic(&mut self, ast_id: ErasedAstId, cfg: &CfgExpr) { | ||||
|         self.def_collector.def_map.diagnostics.push(DefDiagnostic::unconfigured_code( | ||||
|             self.module_id, | ||||
|             tree_id, | ||||
|             item, | ||||
|             ast_id, | ||||
|             cfg.clone(), | ||||
|             self.def_collector.cfg_options.clone(), | ||||
|         )); | ||||
|     } | ||||
| 
 | ||||
|     #[inline] | ||||
|     fn file_id(&self) -> HirFileId { | ||||
|         self.tree_id.file_id() | ||||
|     } | ||||
|  |  | |||
|  | @ -3,22 +3,18 @@ | |||
| use std::ops::Not; | ||||
| 
 | ||||
| use cfg::{CfgExpr, CfgOptions}; | ||||
| use hir_expand::{ExpandErrorKind, MacroCallKind, attrs::AttrId, mod_path::ModPath}; | ||||
| use hir_expand::{ErasedAstId, ExpandErrorKind, MacroCallKind, attrs::AttrId, mod_path::ModPath}; | ||||
| use la_arena::Idx; | ||||
| use syntax::ast; | ||||
| 
 | ||||
| use crate::{ | ||||
|     AstId, | ||||
|     item_tree::{self, AttrOwner, ItemTreeId, TreeId}, | ||||
|     nameres::LocalModuleId, | ||||
| }; | ||||
| use crate::{AstId, nameres::LocalModuleId}; | ||||
| 
 | ||||
| #[derive(Debug, PartialEq, Eq)] | ||||
| pub enum DefDiagnosticKind { | ||||
|     UnresolvedModule { ast: AstId<ast::Module>, candidates: Box<[String]> }, | ||||
|     UnresolvedExternCrate { ast: AstId<ast::ExternCrate> }, | ||||
|     UnresolvedImport { id: ItemTreeId<item_tree::Use>, index: Idx<ast::UseTree> }, | ||||
|     UnconfiguredCode { tree: TreeId, item: AttrOwner, cfg: CfgExpr, opts: CfgOptions }, | ||||
|     UnresolvedImport { id: AstId<ast::Use>, index: Idx<ast::UseTree> }, | ||||
|     UnconfiguredCode { ast_id: ErasedAstId, cfg: CfgExpr, opts: CfgOptions }, | ||||
|     UnresolvedMacroCall { ast: MacroCallKind, path: ModPath }, | ||||
|     UnimplementedBuiltinMacro { ast: AstId<ast::Macro> }, | ||||
|     InvalidDeriveTarget { ast: AstId<ast::Item>, id: usize }, | ||||
|  | @ -28,7 +24,7 @@ pub enum DefDiagnosticKind { | |||
| } | ||||
| 
 | ||||
| #[derive(Clone, Debug, PartialEq, Eq)] | ||||
| pub struct DefDiagnostics(Option<triomphe::Arc<Box<[DefDiagnostic]>>>); | ||||
| pub struct DefDiagnostics(Option<triomphe::ThinArc<(), DefDiagnostic>>); | ||||
| 
 | ||||
| impl DefDiagnostics { | ||||
|     pub fn new(diagnostics: Vec<DefDiagnostic>) -> Self { | ||||
|  | @ -36,12 +32,12 @@ impl DefDiagnostics { | |||
|             diagnostics | ||||
|                 .is_empty() | ||||
|                 .not() | ||||
|                 .then(|| triomphe::Arc::new(diagnostics.into_boxed_slice())), | ||||
|                 .then(|| triomphe::ThinArc::from_header_and_iter((), diagnostics.into_iter())), | ||||
|         ) | ||||
|     } | ||||
| 
 | ||||
|     pub fn iter(&self) -> impl Iterator<Item = &DefDiagnostic> { | ||||
|         self.0.as_ref().into_iter().flat_map(|it| &***it) | ||||
|         self.0.as_ref().into_iter().flat_map(|it| &it.slice) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | @ -75,7 +71,7 @@ impl DefDiagnostic { | |||
| 
 | ||||
|     pub(super) fn unresolved_import( | ||||
|         container: LocalModuleId, | ||||
|         id: ItemTreeId<item_tree::Use>, | ||||
|         id: AstId<ast::Use>, | ||||
|         index: Idx<ast::UseTree>, | ||||
|     ) -> Self { | ||||
|         Self { in_module: container, kind: DefDiagnosticKind::UnresolvedImport { id, index } } | ||||
|  | @ -92,14 +88,13 @@ impl DefDiagnostic { | |||
| 
 | ||||
|     pub fn unconfigured_code( | ||||
|         container: LocalModuleId, | ||||
|         tree: TreeId, | ||||
|         item: AttrOwner, | ||||
|         ast_id: ErasedAstId, | ||||
|         cfg: CfgExpr, | ||||
|         opts: CfgOptions, | ||||
|     ) -> Self { | ||||
|         Self { | ||||
|             in_module: container, | ||||
|             kind: DefDiagnosticKind::UnconfiguredCode { tree, item, cfg, opts }, | ||||
|             kind: DefDiagnosticKind::UnconfiguredCode { ast_id, cfg, opts }, | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|  |  | |||
|  | @ -12,7 +12,6 @@ | |||
| 
 | ||||
| use either::Either; | ||||
| use hir_expand::{ | ||||
|     Lookup, | ||||
|     mod_path::{ModPath, PathKind}, | ||||
|     name::Name, | ||||
| }; | ||||
|  | @ -529,11 +528,12 @@ impl DefMap { | |||
|                     // enum variant
 | ||||
|                     cov_mark::hit!(can_import_enum_variant); | ||||
| 
 | ||||
|                     let res = | ||||
|                         db.enum_variants(e).variants.iter().find(|(_, name)| name == segment).map( | ||||
|                             |&(variant, _)| { | ||||
|                                 let item_tree_id = variant.lookup(db).id; | ||||
|                                 match item_tree_id.item_tree(db)[item_tree_id.value].shape { | ||||
|                     let res = db | ||||
|                         .enum_variants(e) | ||||
|                         .variants | ||||
|                         .iter() | ||||
|                         .find(|(_, name, _)| name == segment) | ||||
|                         .map(|&(variant, _, shape)| match shape { | ||||
|                             FieldsShape::Record => { | ||||
|                                 PerNs::types(variant.into(), Visibility::Public, None) | ||||
|                             } | ||||
|  | @ -543,9 +543,7 @@ impl DefMap { | |||
|                                 Visibility::Public, | ||||
|                                 None, | ||||
|                             ), | ||||
|                                 } | ||||
|                             }, | ||||
|                         ); | ||||
|                         }); | ||||
|                     // FIXME: Need to filter visibility here and below? Not sure.
 | ||||
|                     return match res { | ||||
|                         Some(res) => { | ||||
|  |  | |||
|  | @ -5,21 +5,22 @@ use base_db::Crate; | |||
| use hir_expand::{ | ||||
|     MacroDefId, | ||||
|     mod_path::{ModPath, PathKind}, | ||||
|     name::Name, | ||||
|     name::{AsName, Name}, | ||||
| }; | ||||
| use intern::{Symbol, sym}; | ||||
| use itertools::Itertools as _; | ||||
| use rustc_hash::FxHashSet; | ||||
| use smallvec::{SmallVec, smallvec}; | ||||
| use span::SyntaxContext; | ||||
| use syntax::ast::HasName; | ||||
| use triomphe::Arc; | ||||
| 
 | ||||
| use crate::{ | ||||
|     AdtId, ConstId, ConstParamId, CrateRootModuleId, DefWithBodyId, EnumId, EnumVariantId, | ||||
|     ExternBlockId, ExternCrateId, FunctionId, FxIndexMap, GenericDefId, GenericParamId, HasModule, | ||||
|     ImplId, ItemContainerId, ItemTreeLoc, LifetimeParamId, LocalModuleId, Lookup, Macro2Id, | ||||
|     MacroId, MacroRulesId, ModuleDefId, ModuleId, ProcMacroId, StaticId, StructId, TraitAliasId, | ||||
|     TraitId, TypeAliasId, TypeOrConstParamId, TypeParamId, UseId, VariantId, | ||||
|     AdtId, AstIdLoc, ConstId, ConstParamId, CrateRootModuleId, DefWithBodyId, EnumId, | ||||
|     EnumVariantId, ExternBlockId, ExternCrateId, FunctionId, FxIndexMap, GenericDefId, | ||||
|     GenericParamId, HasModule, ImplId, ItemContainerId, LifetimeParamId, LocalModuleId, Lookup, | ||||
|     Macro2Id, MacroId, MacroRulesId, ModuleDefId, ModuleId, ProcMacroId, StaticId, StructId, | ||||
|     TraitAliasId, TraitId, TypeAliasId, TypeOrConstParamId, TypeParamId, UseId, VariantId, | ||||
|     builtin_type::BuiltinType, | ||||
|     db::DefDatabase, | ||||
|     expr_store::{ | ||||
|  | @ -32,10 +33,10 @@ use crate::{ | |||
|         generics::{GenericParams, TypeOrConstParamData}, | ||||
|     }, | ||||
|     item_scope::{BUILTIN_SCOPE, BuiltinShadowMode, ImportOrExternCrate, ImportOrGlob, ItemScope}, | ||||
|     item_tree::ImportAlias, | ||||
|     lang_item::LangItemTarget, | ||||
|     nameres::{DefMap, LocalDefMap, MacroSubNs, ResolvePathResultPrefixInfo, block_def_map}, | ||||
|     per_ns::PerNs, | ||||
|     src::HasSource, | ||||
|     type_ref::LifetimeRef, | ||||
|     visibility::{RawVisibility, Visibility}, | ||||
| }; | ||||
|  | @ -627,14 +628,14 @@ impl<'db> Resolver<'db> { | |||
|             .extern_crate_decls() | ||||
|             .filter_map(|id| { | ||||
|                 let loc = id.lookup(db); | ||||
|                 let tree = loc.item_tree_id().item_tree(db); | ||||
|                 match &tree[loc.id.value].alias { | ||||
|                     Some(alias) => match alias { | ||||
|                         ImportAlias::Underscore => None, | ||||
|                         ImportAlias::Alias(name) => Some(name.clone()), | ||||
|                     }, | ||||
|                     None => Some(tree[loc.id.value].name.clone()), | ||||
|                 } | ||||
|                 let extern_crate = loc.source(db); | ||||
|                 // If there is a rename (`as x`), extract the renamed name, or remove the `extern crate`
 | ||||
|                 // if it is an underscore.
 | ||||
|                 extern_crate | ||||
|                     .value | ||||
|                     .rename() | ||||
|                     .map(|a| a.name().map(|it| it.as_name())) | ||||
|                     .unwrap_or_else(|| extern_crate.value.name_ref().map(|it| it.as_name())) | ||||
|             }) | ||||
|     } | ||||
| 
 | ||||
|  | @ -1471,10 +1472,7 @@ impl HasResolver for MacroRulesId { | |||
| 
 | ||||
| fn lookup_resolver( | ||||
|     db: &dyn DefDatabase, | ||||
|     lookup: impl Lookup< | ||||
|         Database = dyn DefDatabase, | ||||
|         Data = impl ItemTreeLoc<Container = impl HasResolver>, | ||||
|     >, | ||||
|     lookup: impl Lookup<Database = dyn DefDatabase, Data = impl AstIdLoc<Container = impl HasResolver>>, | ||||
| ) -> Resolver<'_> { | ||||
|     lookup.lookup(db).container().resolver(db) | ||||
| } | ||||
|  |  | |||
|  | @ -4,21 +4,25 @@ use std::ops::Not as _; | |||
| 
 | ||||
| use bitflags::bitflags; | ||||
| use cfg::{CfgExpr, CfgOptions}; | ||||
| use either::Either; | ||||
| use hir_expand::{InFile, Intern, Lookup, name::Name}; | ||||
| use hir_expand::{ | ||||
|     InFile, Intern, Lookup, | ||||
|     name::{AsName, Name}, | ||||
| }; | ||||
| use intern::{Symbol, sym}; | ||||
| use la_arena::{Arena, Idx}; | ||||
| use rustc_abi::{IntegerType, ReprOptions}; | ||||
| use syntax::{ | ||||
|     AstNode, SyntaxNodePtr, | ||||
|     ast::{self, HasGenericParams, IsString}, | ||||
|     NodeOrToken, SyntaxNodePtr, T, | ||||
|     ast::{self, HasGenericParams, HasName, HasVisibility, IsString}, | ||||
| }; | ||||
| use thin_vec::ThinVec; | ||||
| use triomphe::Arc; | ||||
| 
 | ||||
| use crate::{ | ||||
|     ConstId, EnumId, EnumVariantId, EnumVariantLoc, FunctionId, HasModule, ImplId, ItemContainerId, | ||||
|     ModuleId, StaticId, StructId, TraitAliasId, TraitId, TypeAliasId, UnionId, VariantId, | ||||
|     ConstId, EnumId, EnumVariantId, EnumVariantLoc, ExternBlockId, FunctionId, HasModule, ImplId, | ||||
|     ItemContainerId, ModuleId, StaticId, StructId, TraitAliasId, TraitId, TypeAliasId, UnionId, | ||||
|     VariantId, | ||||
|     attr::Attrs, | ||||
|     db::DefDatabase, | ||||
|     expr_store::{ | ||||
|         ExpressionStore, ExpressionStoreSourceMap, | ||||
|  | @ -28,15 +32,17 @@ use crate::{ | |||
|         }, | ||||
|     }, | ||||
|     hir::{ExprId, PatId, generics::GenericParams}, | ||||
|     item_tree::{ | ||||
|         AttrOwner, Field, FieldParent, FieldsShape, FileItemTreeId, ItemTree, ItemTreeId, ModItem, | ||||
|         RawVisibility, RawVisibilityId, | ||||
|     }, | ||||
|     item_tree::{FieldsShape, RawVisibility, visibility_from_ast}, | ||||
|     lang_item::LangItem, | ||||
|     src::HasSource, | ||||
|     type_ref::{TraitRef, TypeBound, TypeRefId}, | ||||
| }; | ||||
| 
 | ||||
| #[inline] | ||||
| fn as_name_opt(name: Option<ast::Name>) -> Name { | ||||
|     name.map_or_else(Name::missing, |it| it.as_name()) | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug, PartialEq, Eq)] | ||||
| pub struct StructSignature { | ||||
|     pub name: Name, | ||||
|  | @ -70,8 +76,8 @@ bitflags! { | |||
| impl StructSignature { | ||||
|     pub fn query(db: &dyn DefDatabase, id: StructId) -> (Arc<Self>, Arc<ExpressionStoreSourceMap>) { | ||||
|         let loc = id.lookup(db); | ||||
|         let item_tree = loc.id.item_tree(db); | ||||
|         let attrs = item_tree.attrs(db, loc.container.krate, ModItem::from(loc.id.value).into()); | ||||
|         let InFile { file_id, value: source } = loc.source(db); | ||||
|         let attrs = db.attrs(id.into()); | ||||
| 
 | ||||
|         let mut flags = StructFlags::empty(); | ||||
|         if attrs.by_key(sym::rustc_has_incoherent_inherent_impls).exists() { | ||||
|  | @ -91,23 +97,23 @@ impl StructSignature { | |||
|             } | ||||
|         } | ||||
|         let repr = attrs.repr(); | ||||
|         let shape = adt_shape(source.kind()); | ||||
| 
 | ||||
|         let hir_expand::files::InFileWrapper { file_id, value } = loc.source(db); | ||||
|         let (store, generic_params, source_map) = lower_generic_params( | ||||
|             db, | ||||
|             loc.container, | ||||
|             id.into(), | ||||
|             file_id, | ||||
|             value.generic_param_list(), | ||||
|             value.where_clause(), | ||||
|             source.generic_param_list(), | ||||
|             source.where_clause(), | ||||
|         ); | ||||
|         ( | ||||
|             Arc::new(StructSignature { | ||||
|                 generic_params, | ||||
|                 store, | ||||
|                 flags, | ||||
|                 shape: item_tree[loc.id.value].shape, | ||||
|                 name: item_tree[loc.id.value].name.clone(), | ||||
|                 shape, | ||||
|                 name: as_name_opt(source.name()), | ||||
|                 repr, | ||||
|             }), | ||||
|             Arc::new(source_map), | ||||
|  | @ -115,6 +121,15 @@ impl StructSignature { | |||
|     } | ||||
| } | ||||
| 
 | ||||
| #[inline] | ||||
| fn adt_shape(adt_kind: ast::StructKind) -> FieldsShape { | ||||
|     match adt_kind { | ||||
|         ast::StructKind::Record(_) => FieldsShape::Record, | ||||
|         ast::StructKind::Tuple(_) => FieldsShape::Tuple, | ||||
|         ast::StructKind::Unit => FieldsShape::Unit, | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug, PartialEq, Eq)] | ||||
| pub struct UnionSignature { | ||||
|     pub name: Name, | ||||
|  | @ -127,9 +142,7 @@ pub struct UnionSignature { | |||
| impl UnionSignature { | ||||
|     pub fn query(db: &dyn DefDatabase, id: UnionId) -> (Arc<Self>, Arc<ExpressionStoreSourceMap>) { | ||||
|         let loc = id.lookup(db); | ||||
|         let krate = loc.container.krate; | ||||
|         let item_tree = loc.id.item_tree(db); | ||||
|         let attrs = item_tree.attrs(db, krate, ModItem::from(loc.id.value).into()); | ||||
|         let attrs = db.attrs(id.into()); | ||||
|         let mut flags = StructFlags::empty(); | ||||
|         if attrs.by_key(sym::rustc_has_incoherent_inherent_impls).exists() { | ||||
|             flags |= StructFlags::RUSTC_HAS_INCOHERENT_INHERENT_IMPLS; | ||||
|  | @ -140,14 +153,14 @@ impl UnionSignature { | |||
| 
 | ||||
|         let repr = attrs.repr(); | ||||
| 
 | ||||
|         let hir_expand::files::InFileWrapper { file_id, value } = loc.source(db); | ||||
|         let InFile { file_id, value: source } = loc.source(db); | ||||
|         let (store, generic_params, source_map) = lower_generic_params( | ||||
|             db, | ||||
|             loc.container, | ||||
|             id.into(), | ||||
|             file_id, | ||||
|             value.generic_param_list(), | ||||
|             value.where_clause(), | ||||
|             source.generic_param_list(), | ||||
|             source.where_clause(), | ||||
|         ); | ||||
|         ( | ||||
|             Arc::new(UnionSignature { | ||||
|  | @ -155,7 +168,7 @@ impl UnionSignature { | |||
|                 store, | ||||
|                 flags, | ||||
|                 repr, | ||||
|                 name: item_tree[loc.id.value].name.clone(), | ||||
|                 name: as_name_opt(source.name()), | ||||
|             }), | ||||
|             Arc::new(source_map), | ||||
|         ) | ||||
|  | @ -181,8 +194,7 @@ pub struct EnumSignature { | |||
| impl EnumSignature { | ||||
|     pub fn query(db: &dyn DefDatabase, id: EnumId) -> (Arc<Self>, Arc<ExpressionStoreSourceMap>) { | ||||
|         let loc = id.lookup(db); | ||||
|         let item_tree = loc.id.item_tree(db); | ||||
|         let attrs = item_tree.attrs(db, loc.container.krate, ModItem::from(loc.id.value).into()); | ||||
|         let attrs = db.attrs(id.into()); | ||||
|         let mut flags = EnumFlags::empty(); | ||||
|         if attrs.by_key(sym::rustc_has_incoherent_inherent_impls).exists() { | ||||
|             flags |= EnumFlags::RUSTC_HAS_INCOHERENT_INHERENT_IMPLS; | ||||
|  | @ -190,14 +202,14 @@ impl EnumSignature { | |||
| 
 | ||||
|         let repr = attrs.repr(); | ||||
| 
 | ||||
|         let hir_expand::files::InFileWrapper { file_id, value } = loc.source(db); | ||||
|         let InFile { file_id, value: source } = loc.source(db); | ||||
|         let (store, generic_params, source_map) = lower_generic_params( | ||||
|             db, | ||||
|             loc.container, | ||||
|             id.into(), | ||||
|             file_id, | ||||
|             value.generic_param_list(), | ||||
|             value.where_clause(), | ||||
|             source.generic_param_list(), | ||||
|             source.where_clause(), | ||||
|         ); | ||||
| 
 | ||||
|         ( | ||||
|  | @ -206,7 +218,7 @@ impl EnumSignature { | |||
|                 store, | ||||
|                 flags, | ||||
|                 repr, | ||||
|                 name: item_tree[loc.id.value].name.clone(), | ||||
|                 name: as_name_opt(source.name()), | ||||
|             }), | ||||
|             Arc::new(source_map), | ||||
|         ) | ||||
|  | @ -239,10 +251,9 @@ pub struct ConstSignature { | |||
| impl ConstSignature { | ||||
|     pub fn query(db: &dyn DefDatabase, id: ConstId) -> (Arc<Self>, Arc<ExpressionStoreSourceMap>) { | ||||
|         let loc = id.lookup(db); | ||||
|         let item_tree = loc.id.item_tree(db); | ||||
| 
 | ||||
|         let module = loc.container.module(db); | ||||
|         let attrs = item_tree.attrs(db, module.krate, ModItem::from(loc.id.value).into()); | ||||
|         let attrs = db.attrs(id.into()); | ||||
|         let mut flags = ConstFlags::empty(); | ||||
|         if attrs.by_key(sym::rustc_allow_incoherent_impl).exists() { | ||||
|             flags |= ConstFlags::RUSTC_ALLOW_INCOHERENT_IMPL; | ||||
|  | @ -253,14 +264,14 @@ impl ConstSignature { | |||
|         } | ||||
| 
 | ||||
|         let (store, source_map, type_ref) = | ||||
|             crate::expr_store::lower::lower_type_ref(db, module, source.map(|it| it.ty())); | ||||
|             crate::expr_store::lower::lower_type_ref(db, module, source.as_ref().map(|it| it.ty())); | ||||
| 
 | ||||
|         ( | ||||
|             Arc::new(ConstSignature { | ||||
|                 store: Arc::new(store), | ||||
|                 type_ref, | ||||
|                 flags, | ||||
|                 name: item_tree[loc.id.value].name.clone(), | ||||
|                 name: source.value.name().map(|it| it.as_name()), | ||||
|             }), | ||||
|             Arc::new(source_map), | ||||
|         ) | ||||
|  | @ -295,10 +306,9 @@ pub struct StaticSignature { | |||
| impl StaticSignature { | ||||
|     pub fn query(db: &dyn DefDatabase, id: StaticId) -> (Arc<Self>, Arc<ExpressionStoreSourceMap>) { | ||||
|         let loc = id.lookup(db); | ||||
|         let item_tree = loc.id.item_tree(db); | ||||
| 
 | ||||
|         let module = loc.container.module(db); | ||||
|         let attrs = item_tree.attrs(db, module.krate, ModItem::from(loc.id.value).into()); | ||||
|         let attrs = db.attrs(id.into()); | ||||
|         let mut flags = StaticFlags::empty(); | ||||
|         if attrs.by_key(sym::rustc_allow_incoherent_impl).exists() { | ||||
|             flags |= StaticFlags::RUSTC_ALLOW_INCOHERENT_IMPL; | ||||
|  | @ -323,14 +333,14 @@ impl StaticSignature { | |||
|         } | ||||
| 
 | ||||
|         let (store, source_map, type_ref) = | ||||
|             crate::expr_store::lower::lower_type_ref(db, module, source.map(|it| it.ty())); | ||||
|             crate::expr_store::lower::lower_type_ref(db, module, source.as_ref().map(|it| it.ty())); | ||||
| 
 | ||||
|         ( | ||||
|             Arc::new(StaticSignature { | ||||
|                 store: Arc::new(store), | ||||
|                 type_ref, | ||||
|                 flags, | ||||
|                 name: item_tree[loc.id.value].name.clone(), | ||||
|                 name: as_name_opt(source.value.name()), | ||||
|             }), | ||||
|             Arc::new(source_map), | ||||
|         ) | ||||
|  | @ -407,10 +417,9 @@ pub struct TraitSignature { | |||
| impl TraitSignature { | ||||
|     pub fn query(db: &dyn DefDatabase, id: TraitId) -> (Arc<Self>, Arc<ExpressionStoreSourceMap>) { | ||||
|         let loc = id.lookup(db); | ||||
|         let item_tree = loc.id.item_tree(db); | ||||
| 
 | ||||
|         let mut flags = TraitFlags::empty(); | ||||
|         let attrs = item_tree.attrs(db, loc.container.krate, ModItem::from(loc.id.value).into()); | ||||
|         let attrs = db.attrs(id.into()); | ||||
|         let source = loc.source(db); | ||||
|         if source.value.auto_token().is_some() { | ||||
|             flags.insert(TraitFlags::AUTO); | ||||
|  | @ -446,15 +455,11 @@ impl TraitSignature { | |||
|             flags |= TraitFlags::SKIP_BOXED_SLICE_DURING_METHOD_DISPATCH; | ||||
|         } | ||||
| 
 | ||||
|         let name = as_name_opt(source.value.name()); | ||||
|         let (store, source_map, generic_params) = lower_trait(db, loc.container, source, id); | ||||
| 
 | ||||
|         ( | ||||
|             Arc::new(TraitSignature { | ||||
|                 store: Arc::new(store), | ||||
|                 generic_params, | ||||
|                 flags, | ||||
|                 name: item_tree[loc.id.value].name.clone(), | ||||
|             }), | ||||
|             Arc::new(TraitSignature { store: Arc::new(store), generic_params, flags, name }), | ||||
|             Arc::new(source_map), | ||||
|         ) | ||||
|     } | ||||
|  | @ -473,17 +478,13 @@ impl TraitAliasSignature { | |||
|         id: TraitAliasId, | ||||
|     ) -> (Arc<Self>, Arc<ExpressionStoreSourceMap>) { | ||||
|         let loc = id.lookup(db); | ||||
|         let item_tree = loc.id.item_tree(db); | ||||
| 
 | ||||
|         let source = loc.source(db); | ||||
|         let name = as_name_opt(source.value.name()); | ||||
|         let (store, source_map, generic_params) = lower_trait_alias(db, loc.container, source, id); | ||||
| 
 | ||||
|         ( | ||||
|             Arc::new(TraitAliasSignature { | ||||
|                 generic_params, | ||||
|                 store: Arc::new(store), | ||||
|                 name: item_tree[loc.id.value].name.clone(), | ||||
|             }), | ||||
|             Arc::new(TraitAliasSignature { generic_params, store: Arc::new(store), name }), | ||||
|             Arc::new(source_map), | ||||
|         ) | ||||
|     } | ||||
|  | @ -530,10 +531,9 @@ impl FunctionSignature { | |||
|     ) -> (Arc<Self>, Arc<ExpressionStoreSourceMap>) { | ||||
|         let loc = id.lookup(db); | ||||
|         let module = loc.container.module(db); | ||||
|         let item_tree = loc.id.item_tree(db); | ||||
| 
 | ||||
|         let mut flags = FnFlags::empty(); | ||||
|         let attrs = item_tree.attrs(db, module.krate, ModItem::from(loc.id.value).into()); | ||||
|         let attrs = db.attrs(id.into()); | ||||
|         if attrs.by_key(sym::rustc_allow_incoherent_impl).exists() { | ||||
|             flags.insert(FnFlags::RUSTC_ALLOW_INCOHERENT_IMPL); | ||||
|         } | ||||
|  | @ -568,6 +568,7 @@ impl FunctionSignature { | |||
|             flags.insert(FnFlags::HAS_BODY); | ||||
|         } | ||||
| 
 | ||||
|         let name = as_name_opt(source.value.name()); | ||||
|         let abi = source.value.abi().map(|abi| { | ||||
|             abi.abi_string().map_or_else(|| sym::C, |it| Symbol::intern(it.text_without_quotes())) | ||||
|         }); | ||||
|  | @ -588,7 +589,7 @@ impl FunctionSignature { | |||
|                 abi, | ||||
|                 flags, | ||||
|                 legacy_const_generics_indices, | ||||
|                 name: item_tree[loc.id.value].name.clone(), | ||||
|                 name, | ||||
|             }), | ||||
|             Arc::new(source_map), | ||||
|         ) | ||||
|  | @ -662,14 +663,9 @@ impl TypeAliasSignature { | |||
|         id: TypeAliasId, | ||||
|     ) -> (Arc<Self>, Arc<ExpressionStoreSourceMap>) { | ||||
|         let loc = id.lookup(db); | ||||
|         let item_tree = loc.id.item_tree(db); | ||||
| 
 | ||||
|         let mut flags = TypeAliasFlags::empty(); | ||||
|         let attrs = item_tree.attrs( | ||||
|             db, | ||||
|             loc.container.module(db).krate(), | ||||
|             ModItem::from(loc.id.value).into(), | ||||
|         ); | ||||
|         let attrs = db.attrs(id.into()); | ||||
|         if attrs.by_key(sym::rustc_has_incoherent_inherent_impls).exists() { | ||||
|             flags.insert(TypeAliasFlags::RUSTC_HAS_INCOHERENT_INHERENT_IMPL); | ||||
|         } | ||||
|  | @ -680,6 +676,7 @@ impl TypeAliasSignature { | |||
|             flags.insert(TypeAliasFlags::IS_EXTERN); | ||||
|         } | ||||
|         let source = loc.source(db); | ||||
|         let name = as_name_opt(source.value.name()); | ||||
|         let (store, source_map, generic_params, bounds, ty) = | ||||
|             lower_type_alias(db, loc.container.module(db), source, id); | ||||
| 
 | ||||
|  | @ -689,7 +686,7 @@ impl TypeAliasSignature { | |||
|                 generic_params, | ||||
|                 flags, | ||||
|                 bounds, | ||||
|                 name: item_tree[loc.id.value].name.clone(), | ||||
|                 name, | ||||
|                 ty, | ||||
|             }), | ||||
|             Arc::new(source_map), | ||||
|  | @ -743,104 +740,41 @@ impl VariantFields { | |||
|         let (shape, (fields, store, source_map)) = match id { | ||||
|             VariantId::EnumVariantId(id) => { | ||||
|                 let loc = id.lookup(db); | ||||
|                 let item_tree = loc.id.item_tree(db); | ||||
|                 let parent = loc.parent.lookup(db); | ||||
|                 let variant = &item_tree[loc.id.value]; | ||||
|                 ( | ||||
|                     variant.shape, | ||||
|                     lower_fields( | ||||
|                 let source = loc.source(db); | ||||
|                 let shape = adt_shape(source.value.kind()); | ||||
|                 let span_map = db.span_map(source.file_id); | ||||
|                 let override_visibility = visibility_from_ast( | ||||
|                     db, | ||||
|                     source.value.parent_enum().visibility(), | ||||
|                     &mut |range| span_map.span_for_range(range).ctx, | ||||
|                 ); | ||||
|                 let fields = lower_field_list( | ||||
|                     db, | ||||
|                     parent.container, | ||||
|                         &item_tree, | ||||
|                         FieldParent::EnumVariant(loc.id.value), | ||||
|                         loc.source(db).map(|src| { | ||||
|                             variant.fields.iter().zip( | ||||
|                                 src.field_list() | ||||
|                                     .map(|it| { | ||||
|                                         match it { | ||||
|                                             ast::FieldList::RecordFieldList(record_field_list) => { | ||||
|                                                 Either::Left(record_field_list.fields().map(|it| { | ||||
|                                                     (SyntaxNodePtr::new(it.syntax()), it.ty()) | ||||
|                                                 })) | ||||
|                                             } | ||||
|                                             ast::FieldList::TupleFieldList(field_list) => { | ||||
|                                                 Either::Right(field_list.fields().map(|it| { | ||||
|                                                     (SyntaxNodePtr::new(it.syntax()), it.ty()) | ||||
|                                                 })) | ||||
|                                             } | ||||
|                                         } | ||||
|                                         .into_iter() | ||||
|                                     }) | ||||
|                                     .into_iter() | ||||
|                                     .flatten(), | ||||
|                             ) | ||||
|                         }), | ||||
|                         Some(item_tree[parent.id.value].visibility), | ||||
|                     ), | ||||
|                 ) | ||||
|                     source.map(|src| src.field_list()), | ||||
|                     Some(override_visibility), | ||||
|                 ); | ||||
|                 (shape, fields) | ||||
|             } | ||||
|             VariantId::StructId(id) => { | ||||
|                 let loc = id.lookup(db); | ||||
|                 let item_tree = loc.id.item_tree(db); | ||||
|                 let strukt = &item_tree[loc.id.value]; | ||||
|                 ( | ||||
|                     strukt.shape, | ||||
|                     lower_fields( | ||||
|                         db, | ||||
|                         loc.container, | ||||
|                         &item_tree, | ||||
|                         FieldParent::Struct(loc.id.value), | ||||
|                         loc.source(db).map(|src| { | ||||
|                             strukt.fields.iter().zip( | ||||
|                                 src.field_list() | ||||
|                                     .map(|it| { | ||||
|                                         match it { | ||||
|                                             ast::FieldList::RecordFieldList(record_field_list) => { | ||||
|                                                 Either::Left(record_field_list.fields().map(|it| { | ||||
|                                                     (SyntaxNodePtr::new(it.syntax()), it.ty()) | ||||
|                                                 })) | ||||
|                                             } | ||||
|                                             ast::FieldList::TupleFieldList(field_list) => { | ||||
|                                                 Either::Right(field_list.fields().map(|it| { | ||||
|                                                     (SyntaxNodePtr::new(it.syntax()), it.ty()) | ||||
|                                                 })) | ||||
|                                             } | ||||
|                                         } | ||||
|                                         .into_iter() | ||||
|                                     }) | ||||
|                                     .into_iter() | ||||
|                                     .flatten(), | ||||
|                             ) | ||||
|                         }), | ||||
|                         None, | ||||
|                     ), | ||||
|                 ) | ||||
|                 let source = loc.source(db); | ||||
|                 let shape = adt_shape(source.value.kind()); | ||||
|                 let fields = | ||||
|                     lower_field_list(db, loc.container, source.map(|src| src.field_list()), None); | ||||
|                 (shape, fields) | ||||
|             } | ||||
|             VariantId::UnionId(id) => { | ||||
|                 let loc = id.lookup(db); | ||||
|                 let item_tree = loc.id.item_tree(db); | ||||
|                 let union = &item_tree[loc.id.value]; | ||||
|                 ( | ||||
|                     FieldsShape::Record, | ||||
|                     lower_fields( | ||||
|                 let source = loc.source(db); | ||||
|                 let fields = lower_field_list( | ||||
|                     db, | ||||
|                     loc.container, | ||||
|                         &item_tree, | ||||
|                         FieldParent::Union(loc.id.value), | ||||
|                         loc.source(db).map(|src| { | ||||
|                             union.fields.iter().zip( | ||||
|                                 src.record_field_list() | ||||
|                                     .map(|it| { | ||||
|                                         it.fields() | ||||
|                                             .map(|it| (SyntaxNodePtr::new(it.syntax()), it.ty())) | ||||
|                                     }) | ||||
|                                     .into_iter() | ||||
|                                     .flatten(), | ||||
|                             ) | ||||
|                         }), | ||||
|                     source.map(|src| src.record_field_list().map(ast::FieldList::RecordFieldList)), | ||||
|                     None, | ||||
|                     ), | ||||
|                 ) | ||||
|                 ); | ||||
|                 (FieldsShape::Record, fields) | ||||
|             } | ||||
|         }; | ||||
| 
 | ||||
|  | @ -860,39 +794,81 @@ impl VariantFields { | |||
|     } | ||||
| } | ||||
| 
 | ||||
| fn lower_fields<'a>( | ||||
| fn lower_field_list( | ||||
|     db: &dyn DefDatabase, | ||||
|     module: ModuleId, | ||||
|     item_tree: &ItemTree, | ||||
|     parent: FieldParent, | ||||
|     fields: InFile<impl Iterator<Item = (&'a Field, (SyntaxNodePtr, Option<ast::Type>))>>, | ||||
|     override_visibility: Option<RawVisibilityId>, | ||||
|     fields: InFile<Option<ast::FieldList>>, | ||||
|     override_visibility: Option<RawVisibility>, | ||||
| ) -> (Arena<FieldData>, ExpressionStore, ExpressionStoreSourceMap) { | ||||
|     let file_id = fields.file_id; | ||||
|     match fields.value { | ||||
|         Some(ast::FieldList::RecordFieldList(fields)) => lower_fields( | ||||
|             db, | ||||
|             module, | ||||
|             InFile::new(file_id, fields.fields().map(|field| (field.ty(), field))), | ||||
|             |_, field| as_name_opt(field.name()), | ||||
|             override_visibility, | ||||
|         ), | ||||
|         Some(ast::FieldList::TupleFieldList(fields)) => lower_fields( | ||||
|             db, | ||||
|             module, | ||||
|             InFile::new(file_id, fields.fields().map(|field| (field.ty(), field))), | ||||
|             |idx, _| Name::new_tuple_field(idx), | ||||
|             override_visibility, | ||||
|         ), | ||||
|         None => lower_fields( | ||||
|             db, | ||||
|             module, | ||||
|             InFile::new(file_id, std::iter::empty::<(Option<ast::Type>, ast::RecordField)>()), | ||||
|             |_, _| Name::missing(), | ||||
|             None, | ||||
|         ), | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| fn lower_fields<Field: ast::HasAttrs + ast::HasVisibility>( | ||||
|     db: &dyn DefDatabase, | ||||
|     module: ModuleId, | ||||
|     fields: InFile<impl Iterator<Item = (Option<ast::Type>, Field)>>, | ||||
|     mut field_name: impl FnMut(usize, &Field) -> Name, | ||||
|     override_visibility: Option<RawVisibility>, | ||||
| ) -> (Arena<FieldData>, ExpressionStore, ExpressionStoreSourceMap) { | ||||
|     let mut arena = Arena::new(); | ||||
|     let cfg_options = module.krate.cfg_options(db); | ||||
|     let mut col = ExprCollector::new(db, module, fields.file_id); | ||||
|     for (idx, (field, (ptr, ty))) in fields.value.enumerate() { | ||||
|         let attr_owner = AttrOwner::make_field_indexed(parent, idx); | ||||
|         let attrs = item_tree.attrs(db, module.krate, attr_owner); | ||||
|         if attrs.is_cfg_enabled(cfg_options) { | ||||
|             arena.alloc(FieldData { | ||||
|                 name: field.name.clone(), | ||||
|                 type_ref: col | ||||
|                     .lower_type_ref_opt(ty, &mut ExprCollector::impl_trait_error_allocator), | ||||
|                 visibility: item_tree[override_visibility.unwrap_or(field.visibility)].clone(), | ||||
|                 is_unsafe: field.is_unsafe, | ||||
|     let mut idx = 0; | ||||
|     for (ty, field) in fields.value { | ||||
|         match Attrs::is_cfg_enabled_for(db, &field, col.span_map(), cfg_options) { | ||||
|             Ok(()) => { | ||||
|                 let type_ref = | ||||
|                     col.lower_type_ref_opt(ty, &mut ExprCollector::impl_trait_error_allocator); | ||||
|                 let visibility = override_visibility.clone().unwrap_or_else(|| { | ||||
|                     visibility_from_ast(db, field.visibility(), &mut |range| { | ||||
|                         col.span_map().span_for_range(range).ctx | ||||
|                     }) | ||||
|                 }); | ||||
|         } else { | ||||
|                 let is_unsafe = field | ||||
|                     .syntax() | ||||
|                     .children_with_tokens() | ||||
|                     .filter_map(NodeOrToken::into_token) | ||||
|                     .any(|token| token.kind() == T![unsafe]); | ||||
|                 let name = field_name(idx, &field); | ||||
|                 arena.alloc(FieldData { name, type_ref, visibility, is_unsafe }); | ||||
|                 idx += 1; | ||||
|             } | ||||
|             Err(cfg) => { | ||||
|                 col.source_map.diagnostics.push( | ||||
|                     crate::expr_store::ExpressionStoreDiagnostics::InactiveCode { | ||||
|                     node: InFile::new(fields.file_id, ptr), | ||||
|                     cfg: attrs.cfg().unwrap(), | ||||
|                         node: InFile::new(fields.file_id, SyntaxNodePtr::new(field.syntax())), | ||||
|                         cfg, | ||||
|                         opts: cfg_options.clone(), | ||||
|                     }, | ||||
|                 ); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     let store = col.store.finish(); | ||||
|     arena.shrink_to_fit(); | ||||
|     (arena, store, col.source_map) | ||||
| } | ||||
| 
 | ||||
|  | @ -905,7 +881,7 @@ pub struct InactiveEnumVariantCode { | |||
| 
 | ||||
| #[derive(Debug, Clone, PartialEq, Eq)] | ||||
| pub struct EnumVariants { | ||||
|     pub variants: Box<[(EnumVariantId, Name)]>, | ||||
|     pub variants: Box<[(EnumVariantId, Name, FieldsShape)]>, | ||||
| } | ||||
| 
 | ||||
| impl EnumVariants { | ||||
|  | @ -914,31 +890,39 @@ impl EnumVariants { | |||
|         e: EnumId, | ||||
|     ) -> (Arc<EnumVariants>, Option<Arc<ThinVec<InactiveEnumVariantCode>>>) { | ||||
|         let loc = e.lookup(db); | ||||
|         let item_tree = loc.id.item_tree(db); | ||||
|         let source = loc.source(db); | ||||
|         let ast_id_map = db.ast_id_map(source.file_id); | ||||
|         let span_map = db.span_map(source.file_id); | ||||
| 
 | ||||
|         let mut diagnostics = ThinVec::new(); | ||||
|         let cfg_options = loc.container.krate.cfg_options(db); | ||||
|         let mut index = 0; | ||||
|         let variants = FileItemTreeId::range_iter(item_tree[loc.id.value].variants.clone()) | ||||
|         let Some(variants) = source.value.variant_list() else { | ||||
|             return (Arc::new(EnumVariants { variants: Box::default() }), None); | ||||
|         }; | ||||
|         let variants = variants | ||||
|             .variants() | ||||
|             .filter_map(|variant| { | ||||
|                 let attrs = item_tree.attrs(db, loc.container.krate, variant.into()); | ||||
|                 if attrs.is_cfg_enabled(cfg_options) { | ||||
|                     let enum_variant = EnumVariantLoc { | ||||
|                         id: ItemTreeId::new(loc.id.tree_id(), variant), | ||||
|                         parent: e, | ||||
|                         index, | ||||
|                     } | ||||
|                 let ast_id = ast_id_map.ast_id(&variant); | ||||
|                 match Attrs::is_cfg_enabled_for(db, &variant, span_map.as_ref(), cfg_options) { | ||||
|                     Ok(()) => { | ||||
|                         let enum_variant = | ||||
|                             EnumVariantLoc { id: source.with_value(ast_id), parent: e, index } | ||||
|                                 .intern(db); | ||||
|                         index += 1; | ||||
|                     Some((enum_variant, item_tree[variant].name.clone())) | ||||
|                 } else { | ||||
|                         let name = as_name_opt(variant.name()); | ||||
|                         let shape = adt_shape(variant.kind()); | ||||
|                         Some((enum_variant, name, shape)) | ||||
|                     } | ||||
|                     Err(cfg) => { | ||||
|                         diagnostics.push(InactiveEnumVariantCode { | ||||
|                         ast_id: item_tree[variant].ast_id, | ||||
|                         cfg: attrs.cfg().unwrap(), | ||||
|                             ast_id, | ||||
|                             cfg, | ||||
|                             opts: cfg_options.clone(), | ||||
|                         }); | ||||
|                         None | ||||
|                     } | ||||
|                 } | ||||
|             }) | ||||
|             .collect(); | ||||
| 
 | ||||
|  | @ -949,12 +933,18 @@ impl EnumVariants { | |||
|     } | ||||
| 
 | ||||
|     pub fn variant(&self, name: &Name) -> Option<EnumVariantId> { | ||||
|         self.variants.iter().find_map(|(v, n)| if n == name { Some(*v) } else { None }) | ||||
|         self.variants.iter().find_map(|(v, n, _)| if n == name { Some(*v) } else { None }) | ||||
|     } | ||||
| 
 | ||||
|     pub fn variant_name_by_id(&self, variant_id: EnumVariantId) -> Option<Name> { | ||||
|         self.variants | ||||
|             .iter() | ||||
|             .find_map(|(id, name, _)| if *id == variant_id { Some(name.clone()) } else { None }) | ||||
|     } | ||||
| 
 | ||||
|     // [Adopted from rustc](https://github.com/rust-lang/rust/blob/bd53aa3bf7a24a70d763182303bd75e5fc51a9af/compiler/rustc_middle/src/ty/adt.rs#L446-L448)
 | ||||
|     pub fn is_payload_free(&self, db: &dyn DefDatabase) -> bool { | ||||
|         self.variants.iter().all(|&(v, _)| { | ||||
|         self.variants.iter().all(|&(v, _, _)| { | ||||
|             // The condition check order is slightly modified from rustc
 | ||||
|             // to improve performance by early returning with relatively fast checks
 | ||||
|             let variant = &db.variant_fields(v.into()); | ||||
|  | @ -973,3 +963,17 @@ impl EnumVariants { | |||
|         }) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| pub(crate) fn extern_block_abi_query( | ||||
|     db: &dyn DefDatabase, | ||||
|     extern_block: ExternBlockId, | ||||
| ) -> Option<Symbol> { | ||||
|     let source = extern_block.lookup(db).source(db); | ||||
|     source.value.abi().map(|abi| { | ||||
|         match abi.abi_string() { | ||||
|             Some(tok) => Symbol::intern(tok.text_without_quotes()), | ||||
|             // `extern` default to be `extern "C"`.
 | ||||
|             _ => sym::C, | ||||
|         } | ||||
|     }) | ||||
| } | ||||
|  |  | |||
|  | @ -1,15 +1,13 @@ | |||
| //! Utilities for mapping between hir IDs and the surface syntax.
 | ||||
| 
 | ||||
| use either::Either; | ||||
| use hir_expand::InFile; | ||||
| use la_arena::ArenaMap; | ||||
| use hir_expand::{AstId, InFile}; | ||||
| use la_arena::{Arena, ArenaMap, Idx}; | ||||
| use syntax::{AstNode, AstPtr, ast}; | ||||
| 
 | ||||
| use crate::{ | ||||
|     GenericDefId, ItemTreeLoc, LocalFieldId, LocalLifetimeParamId, LocalTypeOrConstParamId, Lookup, | ||||
|     UseId, VariantId, | ||||
|     db::DefDatabase, | ||||
|     item_tree::{AttrOwner, FieldParent, ItemTreeNode}, | ||||
|     AstIdLoc, GenericDefId, LocalFieldId, LocalLifetimeParamId, LocalTypeOrConstParamId, Lookup, | ||||
|     UseId, VariantId, attr::Attrs, db::DefDatabase, | ||||
| }; | ||||
| 
 | ||||
| pub trait HasSource { | ||||
|  | @ -23,18 +21,13 @@ pub trait HasSource { | |||
| 
 | ||||
| impl<T> HasSource for T | ||||
| where | ||||
|     T: ItemTreeLoc, | ||||
|     T::Id: ItemTreeNode, | ||||
|     T: AstIdLoc, | ||||
| { | ||||
|     type Value = <T::Id as ItemTreeNode>::Source; | ||||
|     type Value = T::Ast; | ||||
|     fn ast_ptr(&self, db: &dyn DefDatabase) -> InFile<AstPtr<Self::Value>> { | ||||
|         let id = self.item_tree_id(); | ||||
|         let file_id = id.file_id(); | ||||
|         let tree = id.item_tree(db); | ||||
|         let ast_id_map = db.ast_id_map(file_id); | ||||
|         let node = &tree[id.value]; | ||||
| 
 | ||||
|         InFile::new(file_id, ast_id_map.get(node.ast_id())) | ||||
|         let id = self.ast_id(); | ||||
|         let ast_id_map = db.ast_id_map(id.file_id); | ||||
|         InFile::new(id.file_id, ast_id_map.get(id.value)) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | @ -43,18 +36,37 @@ pub trait HasChildSource<ChildId> { | |||
|     fn child_source(&self, db: &dyn DefDatabase) -> InFile<ArenaMap<ChildId, Self::Value>>; | ||||
| } | ||||
| 
 | ||||
| /// Maps a `UseTree` contained in this import back to its AST node.
 | ||||
| pub fn use_tree_to_ast( | ||||
|     db: &dyn DefDatabase, | ||||
|     use_ast_id: AstId<ast::Use>, | ||||
|     index: Idx<ast::UseTree>, | ||||
| ) -> ast::UseTree { | ||||
|     use_tree_source_map(db, use_ast_id)[index].clone() | ||||
| } | ||||
| 
 | ||||
| /// Maps a `UseTree` contained in this import back to its AST node.
 | ||||
| fn use_tree_source_map(db: &dyn DefDatabase, use_ast_id: AstId<ast::Use>) -> Arena<ast::UseTree> { | ||||
|     // Re-lower the AST item and get the source map.
 | ||||
|     // Note: The AST unwraps are fine, since if they fail we should have never obtained `index`.
 | ||||
|     let ast = use_ast_id.to_node(db); | ||||
|     let ast_use_tree = ast.use_tree().expect("missing `use_tree`"); | ||||
|     let mut span_map = None; | ||||
|     crate::item_tree::lower_use_tree(db, ast_use_tree, &mut |range| { | ||||
|         span_map.get_or_insert_with(|| db.span_map(use_ast_id.file_id)).span_for_range(range).ctx | ||||
|     }) | ||||
|     .expect("failed to lower use tree") | ||||
|     .1 | ||||
| } | ||||
| 
 | ||||
| impl HasChildSource<la_arena::Idx<ast::UseTree>> for UseId { | ||||
|     type Value = ast::UseTree; | ||||
|     fn child_source( | ||||
|         &self, | ||||
|         db: &dyn DefDatabase, | ||||
|     ) -> InFile<ArenaMap<la_arena::Idx<ast::UseTree>, Self::Value>> { | ||||
|         let loc = &self.lookup(db); | ||||
|         let use_ = &loc.id.item_tree(db)[loc.id.value]; | ||||
|         InFile::new( | ||||
|             loc.id.file_id(), | ||||
|             use_.use_tree_source_map(db, loc.id.file_id()).into_iter().collect(), | ||||
|         ) | ||||
|         let loc = self.lookup(db); | ||||
|         InFile::new(loc.id.file_id, use_tree_source_map(db, loc.id).into_iter().collect()) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | @ -124,49 +136,30 @@ impl HasChildSource<LocalFieldId> for VariantId { | |||
|     type Value = Either<ast::TupleField, ast::RecordField>; | ||||
| 
 | ||||
|     fn child_source(&self, db: &dyn DefDatabase) -> InFile<ArenaMap<LocalFieldId, Self::Value>> { | ||||
|         let item_tree; | ||||
|         let (src, parent, container) = match *self { | ||||
|         let (src, container) = match *self { | ||||
|             VariantId::EnumVariantId(it) => { | ||||
|                 let lookup = it.lookup(db); | ||||
|                 item_tree = lookup.id.item_tree(db); | ||||
|                 ( | ||||
|                     lookup.source(db).map(|it| it.kind()), | ||||
|                     FieldParent::EnumVariant(lookup.id.value), | ||||
|                     lookup.parent.lookup(db).container, | ||||
|                 ) | ||||
|                 (lookup.source(db).map(|it| it.kind()), lookup.parent.lookup(db).container) | ||||
|             } | ||||
|             VariantId::StructId(it) => { | ||||
|                 let lookup = it.lookup(db); | ||||
|                 item_tree = lookup.id.item_tree(db); | ||||
|                 ( | ||||
|                     lookup.source(db).map(|it| it.kind()), | ||||
|                     FieldParent::Struct(lookup.id.value), | ||||
|                     lookup.container, | ||||
|                 ) | ||||
|                 (lookup.source(db).map(|it| it.kind()), lookup.container) | ||||
|             } | ||||
|             VariantId::UnionId(it) => { | ||||
|                 let lookup = it.lookup(db); | ||||
|                 item_tree = lookup.id.item_tree(db); | ||||
|                 ( | ||||
|                     lookup.source(db).map(|it| it.kind()), | ||||
|                     FieldParent::Union(lookup.id.value), | ||||
|                     lookup.container, | ||||
|                 ) | ||||
|                 (lookup.source(db).map(|it| it.kind()), lookup.container) | ||||
|             } | ||||
|         }; | ||||
| 
 | ||||
|         let span_map = db.span_map(src.file_id); | ||||
|         let mut map = ArenaMap::new(); | ||||
|         match &src.value { | ||||
|             ast::StructKind::Tuple(fl) => { | ||||
|                 let cfg_options = container.krate.cfg_options(db); | ||||
|                 let mut idx = 0; | ||||
|                 for (i, fd) in fl.fields().enumerate() { | ||||
|                     let attrs = item_tree.attrs( | ||||
|                         db, | ||||
|                         container.krate, | ||||
|                         AttrOwner::make_field_indexed(parent, i), | ||||
|                     ); | ||||
|                     if !attrs.is_cfg_enabled(cfg_options) { | ||||
|                 for fd in fl.fields() { | ||||
|                     let enabled = | ||||
|                         Attrs::is_cfg_enabled_for(db, &fd, span_map.as_ref(), cfg_options).is_ok(); | ||||
|                     if !enabled { | ||||
|                         continue; | ||||
|                     } | ||||
|                     map.insert( | ||||
|  | @ -179,13 +172,10 @@ impl HasChildSource<LocalFieldId> for VariantId { | |||
|             ast::StructKind::Record(fl) => { | ||||
|                 let cfg_options = container.krate.cfg_options(db); | ||||
|                 let mut idx = 0; | ||||
|                 for (i, fd) in fl.fields().enumerate() { | ||||
|                     let attrs = item_tree.attrs( | ||||
|                         db, | ||||
|                         container.krate, | ||||
|                         AttrOwner::make_field_indexed(parent, i), | ||||
|                     ); | ||||
|                     if !attrs.is_cfg_enabled(cfg_options) { | ||||
|                 for fd in fl.fields() { | ||||
|                     let enabled = | ||||
|                         Attrs::is_cfg_enabled_for(db, &fd, span_map.as_ref(), cfg_options).is_ok(); | ||||
|                     if !enabled { | ||||
|                         continue; | ||||
|                     } | ||||
|                     map.insert( | ||||
|  | @ -195,7 +185,7 @@ impl HasChildSource<LocalFieldId> for VariantId { | |||
|                     idx += 1; | ||||
|                 } | ||||
|             } | ||||
|             _ => (), | ||||
|             ast::StructKind::Unit => (), | ||||
|         } | ||||
|         InFile::new(src.file_id, map) | ||||
|     } | ||||
|  |  | |||
|  | @ -2,16 +2,18 @@ | |||
| 
 | ||||
| use std::iter; | ||||
| 
 | ||||
| use hir_expand::Lookup; | ||||
| use hir_expand::{InFile, Lookup}; | ||||
| use la_arena::ArenaMap; | ||||
| use syntax::ast::{self, HasVisibility}; | ||||
| use triomphe::Arc; | ||||
| 
 | ||||
| use crate::{ | ||||
|     ConstId, FunctionId, HasModule, ItemContainerId, ItemLoc, ItemTreeLoc, LocalFieldId, | ||||
|     LocalModuleId, ModuleId, TraitId, TypeAliasId, VariantId, | ||||
|     ConstId, FunctionId, HasModule, ItemContainerId, LocalFieldId, LocalModuleId, ModuleId, | ||||
|     TraitId, TypeAliasId, VariantId, | ||||
|     db::DefDatabase, | ||||
|     nameres::DefMap, | ||||
|     resolver::{HasResolver, Resolver}, | ||||
|     src::HasSource, | ||||
| }; | ||||
| 
 | ||||
| pub use crate::item_tree::{RawVisibility, VisibilityExplicitness}; | ||||
|  | @ -217,49 +219,69 @@ pub(crate) fn field_visibilities_query( | |||
|     for (field_id, field_data) in fields.iter() { | ||||
|         res.insert(field_id, Visibility::resolve(db, &resolver, &field_data.visibility)); | ||||
|     } | ||||
|     res.shrink_to_fit(); | ||||
|     Arc::new(res) | ||||
| } | ||||
| 
 | ||||
| pub fn visibility_from_ast( | ||||
|     db: &dyn DefDatabase, | ||||
|     resolver: &Resolver<'_>, | ||||
|     ast_vis: InFile<Option<ast::Visibility>>, | ||||
| ) -> Visibility { | ||||
|     let mut span_map = None; | ||||
|     let raw_vis = crate::item_tree::visibility_from_ast(db, ast_vis.value, &mut |range| { | ||||
|         span_map.get_or_insert_with(|| db.span_map(ast_vis.file_id)).span_for_range(range).ctx | ||||
|     }); | ||||
|     Visibility::resolve(db, resolver, &raw_vis) | ||||
| } | ||||
| 
 | ||||
| fn trait_item_visibility( | ||||
|     db: &dyn DefDatabase, | ||||
|     resolver: &Resolver<'_>, | ||||
|     container: ItemContainerId, | ||||
| ) -> Option<Visibility> { | ||||
|     match container { | ||||
|         ItemContainerId::TraitId(trait_) => Some(trait_visibility(db, resolver, trait_)), | ||||
|         _ => None, | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| /// Resolve visibility of a function.
 | ||||
| pub(crate) fn function_visibility_query(db: &dyn DefDatabase, def: FunctionId) -> Visibility { | ||||
|     let resolver = def.resolver(db); | ||||
|     let loc = def.lookup(db); | ||||
|     let tree = loc.item_tree_id().item_tree(db); | ||||
|     if let ItemContainerId::TraitId(trait_id) = loc.container { | ||||
|         trait_vis(db, &resolver, trait_id) | ||||
|     } else { | ||||
|         Visibility::resolve(db, &resolver, &tree[tree[loc.id.value].visibility]) | ||||
|     } | ||||
|     let resolver = def.resolver(db); | ||||
|     trait_item_visibility(db, &resolver, loc.container).unwrap_or_else(|| { | ||||
|         let source = loc.source(db); | ||||
|         visibility_from_ast(db, &resolver, source.map(|src| src.visibility())) | ||||
|     }) | ||||
| } | ||||
| 
 | ||||
| /// Resolve visibility of a const.
 | ||||
| pub(crate) fn const_visibility_query(db: &dyn DefDatabase, def: ConstId) -> Visibility { | ||||
|     let resolver = def.resolver(db); | ||||
|     let loc = def.lookup(db); | ||||
|     let tree = loc.item_tree_id().item_tree(db); | ||||
|     if let ItemContainerId::TraitId(trait_id) = loc.container { | ||||
|         trait_vis(db, &resolver, trait_id) | ||||
|     } else { | ||||
|         Visibility::resolve(db, &resolver, &tree[tree[loc.id.value].visibility]) | ||||
|     } | ||||
|     let resolver = def.resolver(db); | ||||
|     trait_item_visibility(db, &resolver, loc.container).unwrap_or_else(|| { | ||||
|         let source = loc.source(db); | ||||
|         visibility_from_ast(db, &resolver, source.map(|src| src.visibility())) | ||||
|     }) | ||||
| } | ||||
| 
 | ||||
| /// Resolve visibility of a type alias.
 | ||||
| pub(crate) fn type_alias_visibility_query(db: &dyn DefDatabase, def: TypeAliasId) -> Visibility { | ||||
|     let resolver = def.resolver(db); | ||||
|     let loc = def.lookup(db); | ||||
|     let tree = loc.item_tree_id().item_tree(db); | ||||
|     if let ItemContainerId::TraitId(trait_id) = loc.container { | ||||
|         trait_vis(db, &resolver, trait_id) | ||||
|     } else { | ||||
|         Visibility::resolve(db, &resolver, &tree[tree[loc.id.value].visibility]) | ||||
|     } | ||||
|     let resolver = def.resolver(db); | ||||
|     trait_item_visibility(db, &resolver, loc.container).unwrap_or_else(|| { | ||||
|         let source = loc.source(db); | ||||
|         visibility_from_ast(db, &resolver, source.map(|src| src.visibility())) | ||||
|     }) | ||||
| } | ||||
| 
 | ||||
| #[inline] | ||||
| fn trait_vis(db: &dyn DefDatabase, resolver: &Resolver<'_>, trait_id: TraitId) -> Visibility { | ||||
|     let ItemLoc { id: tree_id, .. } = trait_id.lookup(db); | ||||
|     let item_tree = tree_id.item_tree(db); | ||||
|     let tr_def = &item_tree[tree_id.value]; | ||||
|     Visibility::resolve(db, resolver, &item_tree[tr_def.visibility]) | ||||
| pub(crate) fn trait_visibility( | ||||
|     db: &dyn DefDatabase, | ||||
|     resolver: &Resolver<'_>, | ||||
|     def: TraitId, | ||||
| ) -> Visibility { | ||||
|     let loc = def.lookup(db); | ||||
|     let source = loc.source(db); | ||||
|     visibility_from_ast(db, resolver, source.map(|src| src.visibility())) | ||||
| } | ||||
|  |  | |||
|  | @ -2,7 +2,7 @@ | |||
| use std::borrow::Borrow; | ||||
| 
 | ||||
| use either::Either; | ||||
| use span::{ErasedFileAstId, FileAstId, FileId, SyntaxContext}; | ||||
| use span::{AstIdNode, ErasedFileAstId, FileAstId, FileId, SyntaxContext}; | ||||
| use syntax::{AstNode, AstPtr, SyntaxNode, SyntaxNodePtr, SyntaxToken, TextRange, TextSize}; | ||||
| 
 | ||||
| use crate::{ | ||||
|  | @ -122,6 +122,13 @@ impl<N: AstNode> AstId<N> { | |||
|     pub fn erase(&self) -> ErasedAstId { | ||||
|         crate::InFile::new(self.file_id, self.value.erase()) | ||||
|     } | ||||
|     #[inline] | ||||
|     pub fn upcast<M: AstIdNode>(self) -> AstId<M> | ||||
|     where | ||||
|         N: Into<M>, | ||||
|     { | ||||
|         self.map(|it| it.upcast()) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| pub type ErasedAstId = crate::InFile<ErasedFileAstId>; | ||||
|  |  | |||
|  | @ -817,7 +817,7 @@ pub(crate) fn adt_datum_query( | |||
|                 .enum_variants(id) | ||||
|                 .variants | ||||
|                 .iter() | ||||
|                 .map(|&(variant_id, _)| variant_id_to_fields(variant_id.into())) | ||||
|                 .map(|&(variant_id, _, _)| variant_id_to_fields(variant_id.into())) | ||||
|                 .collect(); | ||||
|             (rust_ir::AdtKind::Enum, variants) | ||||
|         } | ||||
|  |  | |||
|  | @ -397,7 +397,7 @@ impl<'a> DeclValidator<'a> { | |||
|     fn validate_enum_variants(&mut self, enum_id: EnumId) { | ||||
|         let data = self.db.enum_variants(enum_id); | ||||
| 
 | ||||
|         for (variant_id, _) in data.variants.iter() { | ||||
|         for (variant_id, _, _) in data.variants.iter() { | ||||
|             self.validate_enum_variant_fields(*variant_id); | ||||
|         } | ||||
| 
 | ||||
|  | @ -405,7 +405,7 @@ impl<'a> DeclValidator<'a> { | |||
|         let mut enum_variants_replacements = data | ||||
|             .variants | ||||
|             .iter() | ||||
|             .filter_map(|(_, name)| { | ||||
|             .filter_map(|(_, name, _)| { | ||||
|                 to_camel_case(&name.display_no_db(edition).to_smolstr()).map(|new_name| { | ||||
|                     Replacement { | ||||
|                         current_name: name.clone(), | ||||
|  |  | |||
|  | @ -465,7 +465,7 @@ impl PatCx for MatchCheckCtx<'_> { | |||
|                     ConstructorSet::NoConstructors | ||||
|                 } else { | ||||
|                     let mut variants = IndexVec::with_capacity(enum_data.variants.len()); | ||||
|                     for &(variant, _) in enum_data.variants.iter() { | ||||
|                     for &(variant, _, _) in enum_data.variants.iter() { | ||||
|                         let is_uninhabited = is_enum_variant_uninhabited_from( | ||||
|                             cx.db, | ||||
|                             variant, | ||||
|  |  | |||
|  | @ -71,7 +71,7 @@ pub(crate) fn has_drop_glue(db: &dyn HirDatabase, ty: Ty, env: Arc<TraitEnvironm | |||
|                     .enum_variants(id) | ||||
|                     .variants | ||||
|                     .iter() | ||||
|                     .map(|&(variant, _)| { | ||||
|                     .map(|&(variant, _, _)| { | ||||
|                         db.field_types(variant.into()) | ||||
|                             .iter() | ||||
|                             .map(|(_, field_ty)| { | ||||
|  |  | |||
|  | @ -115,7 +115,7 @@ impl UninhabitedFrom<'_> { | |||
|             AdtId::EnumId(e) => { | ||||
|                 let enum_data = self.db.enum_variants(e); | ||||
| 
 | ||||
|                 for &(variant, _) in enum_data.variants.iter() { | ||||
|                 for &(variant, _, _) in enum_data.variants.iter() { | ||||
|                     let variant_inhabitedness = self.visit_variant(variant.into(), subst); | ||||
|                     match variant_inhabitedness { | ||||
|                         Break(VisiblyUninhabited) => (), | ||||
|  |  | |||
|  | @ -60,7 +60,7 @@ pub fn layout_of_adt_query( | |||
|             let r = variants | ||||
|                 .variants | ||||
|                 .iter() | ||||
|                 .map(|&(v, _)| handle_variant(v.into(), &db.variant_fields(v.into()))) | ||||
|                 .map(|&(v, _, _)| handle_variant(v.into(), &db.variant_fields(v.into()))) | ||||
|                 .collect::<Result<SmallVec<_>, _>>()?; | ||||
|             (r, db.enum_signature(e).repr.unwrap_or_default(), false) | ||||
|         } | ||||
|  |  | |||
|  | @ -2771,12 +2771,15 @@ impl Evaluator<'_> { | |||
|             Err(e) => { | ||||
|                 let db = self.db; | ||||
|                 let loc = variant.lookup(db); | ||||
|                 let enum_loc = loc.parent.lookup(db); | ||||
|                 let edition = self.crate_id.data(self.db).edition; | ||||
|                 let name = format!( | ||||
|                     "{}::{}", | ||||
|                     enum_loc.id.item_tree(db)[enum_loc.id.value].name.display(db, edition), | ||||
|                     loc.id.item_tree(db)[loc.id.value].name.display(db, edition), | ||||
|                     self.db.enum_signature(loc.parent).name.display(db, edition), | ||||
|                     self.db | ||||
|                         .enum_variants(loc.parent) | ||||
|                         .variant_name_by_id(variant) | ||||
|                         .unwrap() | ||||
|                         .display(db, edition), | ||||
|                 ); | ||||
|                 Err(MirEvalError::ConstEvalError(name, Box::new(e))) | ||||
|             } | ||||
|  |  | |||
|  | @ -65,9 +65,7 @@ impl Evaluator<'_> { | |||
|                 Some(abi) => *abi == sym::rust_dash_intrinsic, | ||||
|                 None => match def.lookup(self.db).container { | ||||
|                     hir_def::ItemContainerId::ExternBlockId(block) => { | ||||
|                         let id = block.lookup(self.db).id; | ||||
|                         id.item_tree(self.db)[id.value].abi.as_ref() | ||||
|                             == Some(&sym::rust_dash_intrinsic) | ||||
|                         self.db.extern_block_abi(block) == Some(sym::rust_dash_intrinsic) | ||||
|                     } | ||||
|                     _ => false, | ||||
|                 }, | ||||
|  | @ -87,8 +85,7 @@ impl Evaluator<'_> { | |||
|         } | ||||
|         let is_extern_c = match def.lookup(self.db).container { | ||||
|             hir_def::ItemContainerId::ExternBlockId(block) => { | ||||
|                 let id = block.lookup(self.db).id; | ||||
|                 id.item_tree(self.db)[id.value].abi.as_ref() == Some(&sym::C) | ||||
|                 self.db.extern_block_abi(block) == Some(sym::C) | ||||
|             } | ||||
|             _ => false, | ||||
|         }; | ||||
|  |  | |||
|  | @ -1922,11 +1922,14 @@ impl<'ctx> MirLowerCtx<'ctx> { | |||
|                 let edition = self.edition(); | ||||
|                 let db = self.db; | ||||
|                 let loc = variant.lookup(db); | ||||
|                 let enum_loc = loc.parent.lookup(db); | ||||
|                 let name = format!( | ||||
|                     "{}::{}", | ||||
|                     enum_loc.id.item_tree(db)[enum_loc.id.value].name.display(db, edition), | ||||
|                     loc.id.item_tree(db)[loc.id.value].name.display(db, edition), | ||||
|                     self.db.enum_signature(loc.parent).name.display(db, edition), | ||||
|                     self.db | ||||
|                         .enum_variants(loc.parent) | ||||
|                         .variant_name_by_id(variant) | ||||
|                         .unwrap() | ||||
|                         .display(db, edition), | ||||
|                 ); | ||||
|                 Err(MirLowerError::ConstEvalError(name.into(), Box::new(e))) | ||||
|             } | ||||
|  |  | |||
|  | @ -63,16 +63,15 @@ impl MirBody { | |||
|             } | ||||
|             hir_def::DefWithBodyId::VariantId(id) => { | ||||
|                 let loc = id.lookup(db); | ||||
|                 let enum_loc = loc.parent.lookup(db); | ||||
|                 let edition = this.display_target.edition; | ||||
|                 w!( | ||||
|                     this, | ||||
|                     "enum {}::{} = ", | ||||
|                     enum_loc.id.item_tree(db)[enum_loc.id.value] | ||||
|                         .name | ||||
|                         .display(db, this.display_target.edition), | ||||
|                     loc.id.item_tree(db)[loc.id.value] | ||||
|                         .name | ||||
|                         .display(db, this.display_target.edition), | ||||
|                     db.enum_signature(loc.parent).name.display(db, edition), | ||||
|                     db.enum_variants(loc.parent) | ||||
|                         .variant_name_by_id(id) | ||||
|                         .unwrap() | ||||
|                         .display(db, edition), | ||||
|                 ) | ||||
|             } | ||||
|         }); | ||||
|  |  | |||
|  | @ -479,7 +479,7 @@ pub(crate) fn visit_module( | |||
|                     visit_body(db, &body, cb); | ||||
|                 } | ||||
|                 ModuleDefId::AdtId(hir_def::AdtId::EnumId(it)) => { | ||||
|                     db.enum_variants(it).variants.iter().for_each(|&(it, _)| { | ||||
|                     db.enum_variants(it).variants.iter().for_each(|&(it, _, _)| { | ||||
|                         let body = db.body(it.into()); | ||||
|                         cb(it.into()); | ||||
|                         visit_body(db, &body, cb); | ||||
|  |  | |||
|  | @ -353,6 +353,7 @@ impl SomeStruct { | |||
|             "impl_self_ty_with_diagnostics_shim".to_owned(), | ||||
|             "struct_signature_shim".to_owned(), | ||||
|             "struct_signature_with_source_map_shim".to_owned(), | ||||
|             "attrs_shim".to_owned(), | ||||
|             "type_for_adt_tracked".to_owned(), | ||||
|         ]; | ||||
| 
 | ||||
|  | @ -442,6 +443,6 @@ fn main() { | |||
|                 let _inference_result = db.infer(def); | ||||
|             } | ||||
|         }); | ||||
|         assert!(format!("{events:?}").contains("trait_solve_shim")) | ||||
|         assert!(!format!("{events:?}").contains("trait_solve_shim")) | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -293,9 +293,7 @@ pub fn is_fn_unsafe_to_call( | |||
|     let loc = func.lookup(db); | ||||
|     match loc.container { | ||||
|         hir_def::ItemContainerId::ExternBlockId(block) => { | ||||
|             let id = block.lookup(db).id; | ||||
|             let is_intrinsic_block = | ||||
|                 id.item_tree(db)[id.value].abi.as_ref() == Some(&sym::rust_dash_intrinsic); | ||||
|             let is_intrinsic_block = db.extern_block_abi(block) == Some(sym::rust_dash_intrinsic); | ||||
|             if is_intrinsic_block { | ||||
|                 // legacy intrinsics
 | ||||
|                 // extern "rust-intrinsic" intrinsics are unsafe unless they have the rustc_safe_intrinsic attribute
 | ||||
|  |  | |||
|  | @ -213,7 +213,7 @@ impl Context<'_> { | |||
|                     AdtId::StructId(s) => add_constraints_from_variant(VariantId::StructId(s)), | ||||
|                     AdtId::UnionId(u) => add_constraints_from_variant(VariantId::UnionId(u)), | ||||
|                     AdtId::EnumId(e) => { | ||||
|                         db.enum_variants(e).variants.iter().for_each(|&(variant, _)| { | ||||
|                         db.enum_variants(e).variants.iter().for_each(|&(variant, _, _)| { | ||||
|                             add_constraints_from_variant(VariantId::EnumVariantId(variant)) | ||||
|                         }); | ||||
|                     } | ||||
|  |  | |||
|  | @ -52,12 +52,14 @@ use hir_def::{ | |||
|         BindingAnnotation, BindingId, Expr, ExprId, ExprOrPatId, LabelId, Pat, | ||||
|         generics::{LifetimeParamData, TypeOrConstParamData, TypeParamProvenance}, | ||||
|     }, | ||||
|     item_tree::{AttrOwner, FieldParent, ImportAlias, ItemTreeFieldId, ItemTreeNode}, | ||||
|     item_tree::ImportAlias, | ||||
|     layout::{self, ReprOptions, TargetDataLayout}, | ||||
|     nameres::{self, diagnostics::DefDiagnostic}, | ||||
|     per_ns::PerNs, | ||||
|     resolver::{HasResolver, Resolver}, | ||||
|     signatures::{ImplFlags, StaticFlags, TraitFlags, VariantFields}, | ||||
|     src::HasSource as _, | ||||
|     visibility::visibility_from_ast, | ||||
| }; | ||||
| use hir_expand::{ | ||||
|     AstId, MacroCallKind, RenderedExpandError, ValueResult, attrs::collect_attrs, | ||||
|  | @ -81,11 +83,11 @@ use itertools::Itertools; | |||
| use nameres::diagnostics::DefDiagnosticKind; | ||||
| use rustc_hash::FxHashSet; | ||||
| use smallvec::SmallVec; | ||||
| use span::{Edition, FileId}; | ||||
| use span::{AstIdNode, Edition, FileId}; | ||||
| use stdx::{format_to, impl_from, never}; | ||||
| use syntax::{ | ||||
|     AstNode, AstPtr, SmolStr, SyntaxNode, SyntaxNodePtr, T, TextRange, ToSmolStr, | ||||
|     ast::{self, HasAttrs as _, HasName}, | ||||
|     ast::{self, HasAttrs as _, HasName, HasVisibility as _}, | ||||
|     format_smolstr, | ||||
| }; | ||||
| use triomphe::{Arc, ThinArc}; | ||||
|  | @ -687,7 +689,7 @@ impl Module { | |||
|                             let source_map = db.enum_signature_with_source_map(e.id).1; | ||||
|                             expr_store_diagnostics(db, acc, &source_map); | ||||
|                             let (variants, diagnostics) = db.enum_variants_with_diagnostics(e.id); | ||||
|                             let file = e.id.lookup(db).id.file_id(); | ||||
|                             let file = e.id.lookup(db).id.file_id; | ||||
|                             let ast_id_map = db.ast_id_map(file); | ||||
|                             if let Some(diagnostics) = &diagnostics { | ||||
|                                 for diag in diagnostics.iter() { | ||||
|  | @ -704,7 +706,7 @@ impl Module { | |||
|                                     ); | ||||
|                                 } | ||||
|                             } | ||||
|                             for &(v, _) in &variants.variants { | ||||
|                             for &(v, _, _) in &variants.variants { | ||||
|                                 let source_map = db.variant_fields_with_source_map(v.into()).1; | ||||
|                                 push_ty_diagnostics( | ||||
|                                     db, | ||||
|  | @ -742,12 +744,10 @@ impl Module { | |||
|             GenericDef::Impl(impl_def).diagnostics(db, acc); | ||||
| 
 | ||||
|             let loc = impl_def.id.lookup(db); | ||||
|             let tree = loc.id.item_tree(db); | ||||
|             let source_map = db.impl_signature_with_source_map(impl_def.id).1; | ||||
|             expr_store_diagnostics(db, acc, &source_map); | ||||
| 
 | ||||
|             let node = &tree[loc.id.value]; | ||||
|             let file_id = loc.id.file_id(); | ||||
|             let file_id = loc.id.file_id; | ||||
|             if file_id.macro_file().is_some_and(|it| it.kind(db) == MacroKind::DeriveBuiltIn) { | ||||
|                 // these expansion come from us, diagnosing them is a waste of resources
 | ||||
|                 // FIXME: Once we diagnose the inputs to builtin derives, we should at least extract those diagnostics somehow
 | ||||
|  | @ -765,11 +765,11 @@ impl Module { | |||
|             } | ||||
| 
 | ||||
|             if inherent_impls.invalid_impls().contains(&impl_def.id) { | ||||
|                 acc.push(IncoherentImpl { impl_: ast_id_map.get(node.ast_id()), file_id }.into()) | ||||
|                 acc.push(IncoherentImpl { impl_: ast_id_map.get(loc.id.value), file_id }.into()) | ||||
|             } | ||||
| 
 | ||||
|             if !impl_def.check_orphan_rules(db) { | ||||
|                 acc.push(TraitImplOrphan { impl_: ast_id_map.get(node.ast_id()), file_id }.into()) | ||||
|                 acc.push(TraitImplOrphan { impl_: ast_id_map.get(loc.id.value), file_id }.into()) | ||||
|             } | ||||
| 
 | ||||
|             let trait_ = impl_def.trait_(db); | ||||
|  | @ -808,11 +808,11 @@ impl Module { | |||
|                 // unsafe negative impl
 | ||||
|                 (true, _, true, _) | | ||||
|                 // unsafe impl for safe trait
 | ||||
|                 (true, false, _, false) => acc.push(TraitImplIncorrectSafety { impl_: ast_id_map.get(node.ast_id()), file_id, should_be_safe: true }.into()), | ||||
|                 (true, false, _, false) => acc.push(TraitImplIncorrectSafety { impl_: ast_id_map.get(loc.id.value), file_id, should_be_safe: true }.into()), | ||||
|                 // safe impl for unsafe trait
 | ||||
|                 (false, true, false, _) | | ||||
|                 // safe impl of dangling drop
 | ||||
|                 (false, false, _, true) => acc.push(TraitImplIncorrectSafety { impl_: ast_id_map.get(node.ast_id()), file_id, should_be_safe: false }.into()), | ||||
|                 (false, false, _, true) => acc.push(TraitImplIncorrectSafety { impl_: ast_id_map.get(loc.id.value), file_id, should_be_safe: false }.into()), | ||||
|                 _ => (), | ||||
|             }; | ||||
| 
 | ||||
|  | @ -839,7 +839,7 @@ impl Module { | |||
|                         TraitImplRedundantAssocItems { | ||||
|                             trait_, | ||||
|                             file_id, | ||||
|                             impl_: ast_id_map.get(node.ast_id()), | ||||
|                             impl_: ast_id_map.get(loc.id.value), | ||||
|                             assoc_item: (name, assoc_item), | ||||
|                         } | ||||
|                         .into(), | ||||
|  | @ -889,7 +889,7 @@ impl Module { | |||
|                 if !missing.is_empty() { | ||||
|                     acc.push( | ||||
|                         TraitImplMissingAssocItems { | ||||
|                             impl_: ast_id_map.get(node.ast_id()), | ||||
|                             impl_: ast_id_map.get(loc.id.value), | ||||
|                             file_id, | ||||
|                             missing, | ||||
|                         } | ||||
|  | @ -1076,73 +1076,25 @@ fn emit_def_diagnostic_( | |||
|             ) | ||||
|         } | ||||
|         DefDiagnosticKind::UnresolvedImport { id, index } => { | ||||
|             let file_id = id.file_id(); | ||||
|             let item_tree = id.item_tree(db); | ||||
|             let import = &item_tree[id.value]; | ||||
|             let file_id = id.file_id; | ||||
| 
 | ||||
|             let use_tree = import.use_tree_to_ast(db, file_id, *index); | ||||
|             let use_tree = hir_def::src::use_tree_to_ast(db, *id, *index); | ||||
|             acc.push( | ||||
|                 UnresolvedImport { decl: InFile::new(file_id, AstPtr::new(&use_tree)) }.into(), | ||||
|             ); | ||||
|         } | ||||
| 
 | ||||
|         DefDiagnosticKind::UnconfiguredCode { tree, item, cfg, opts } => { | ||||
|             let item_tree = tree.item_tree(db); | ||||
|             let ast_id_map = db.ast_id_map(tree.file_id()); | ||||
|             // FIXME: This parses... We could probably store relative ranges for the children things
 | ||||
|             // here in the item tree?
 | ||||
|             (|| { | ||||
|                 let process_field_list = | ||||
|                     |field_list: Option<_>, idx: ItemTreeFieldId| match field_list? { | ||||
|                         ast::FieldList::RecordFieldList(it) => Some(SyntaxNodePtr::new( | ||||
|                             it.fields().nth(idx.into_raw().into_u32() as usize)?.syntax(), | ||||
|                         )), | ||||
|                         ast::FieldList::TupleFieldList(it) => Some(SyntaxNodePtr::new( | ||||
|                             it.fields().nth(idx.into_raw().into_u32() as usize)?.syntax(), | ||||
|                         )), | ||||
|                     }; | ||||
|                 let ptr = match *item { | ||||
|                     AttrOwner::ModItem(it) => { | ||||
|                         ast_id_map.get(it.ast_id(&item_tree)).syntax_node_ptr() | ||||
|                     } | ||||
|                     AttrOwner::TopLevel => ast_id_map.root(), | ||||
|                     AttrOwner::Variant(it) => { | ||||
|                         ast_id_map.get(item_tree[it].ast_id).syntax_node_ptr() | ||||
|                     } | ||||
|                     AttrOwner::Field(FieldParent::EnumVariant(parent), idx) => process_field_list( | ||||
|                         ast_id_map | ||||
|                             .get(item_tree[parent].ast_id) | ||||
|                             .to_node(&db.parse_or_expand(tree.file_id())) | ||||
|                             .field_list(), | ||||
|                         idx, | ||||
|                     )?, | ||||
|                     AttrOwner::Field(FieldParent::Struct(parent), idx) => process_field_list( | ||||
|                         ast_id_map | ||||
|                             .get(item_tree[parent.index()].ast_id) | ||||
|                             .to_node(&db.parse_or_expand(tree.file_id())) | ||||
|                             .field_list(), | ||||
|                         idx, | ||||
|                     )?, | ||||
|                     AttrOwner::Field(FieldParent::Union(parent), idx) => SyntaxNodePtr::new( | ||||
|                         ast_id_map | ||||
|                             .get(item_tree[parent.index()].ast_id) | ||||
|                             .to_node(&db.parse_or_expand(tree.file_id())) | ||||
|                             .record_field_list()? | ||||
|                             .fields() | ||||
|                             .nth(idx.into_raw().into_u32() as usize)? | ||||
|                             .syntax(), | ||||
|                     ), | ||||
|                 }; | ||||
|         DefDiagnosticKind::UnconfiguredCode { ast_id, cfg, opts } => { | ||||
|             let ast_id_map = db.ast_id_map(ast_id.file_id); | ||||
|             let ptr = ast_id_map.get_erased(ast_id.value); | ||||
|             acc.push( | ||||
|                 InactiveCode { | ||||
|                         node: InFile::new(tree.file_id(), ptr), | ||||
|                     node: InFile::new(ast_id.file_id, ptr), | ||||
|                     cfg: cfg.clone(), | ||||
|                     opts: opts.clone(), | ||||
|                 } | ||||
|                 .into(), | ||||
|             ); | ||||
|                 Some(()) | ||||
|             })(); | ||||
|         } | ||||
|         DefDiagnosticKind::UnresolvedMacroCall { ast, path } => { | ||||
|             let (node, precise_location) = precise_macro_call_location(ast, db); | ||||
|  | @ -1478,12 +1430,8 @@ impl Struct { | |||
| impl HasVisibility for Struct { | ||||
|     fn visibility(&self, db: &dyn HirDatabase) -> Visibility { | ||||
|         let loc = self.id.lookup(db); | ||||
|         let item_tree = loc.id.item_tree(db); | ||||
|         Visibility::resolve( | ||||
|             db, | ||||
|             &self.id.resolver(db), | ||||
|             &item_tree[item_tree[loc.id.value].visibility], | ||||
|         ) | ||||
|         let source = loc.source(db); | ||||
|         visibility_from_ast(db, &self.id.resolver(db), source.map(|src| src.visibility())) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | @ -1536,12 +1484,8 @@ impl Union { | |||
| impl HasVisibility for Union { | ||||
|     fn visibility(&self, db: &dyn HirDatabase) -> Visibility { | ||||
|         let loc = self.id.lookup(db); | ||||
|         let item_tree = loc.id.item_tree(db); | ||||
|         Visibility::resolve( | ||||
|             db, | ||||
|             &self.id.resolver(db), | ||||
|             &item_tree[item_tree[loc.id.value].visibility], | ||||
|         ) | ||||
|         let source = loc.source(db); | ||||
|         visibility_from_ast(db, &self.id.resolver(db), source.map(|src| src.visibility())) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | @ -1560,7 +1504,7 @@ impl Enum { | |||
|     } | ||||
| 
 | ||||
|     pub fn variants(self, db: &dyn HirDatabase) -> Vec<Variant> { | ||||
|         db.enum_variants(self.id).variants.iter().map(|&(id, _)| Variant { id }).collect() | ||||
|         db.enum_variants(self.id).variants.iter().map(|&(id, _, _)| Variant { id }).collect() | ||||
|     } | ||||
| 
 | ||||
|     pub fn num_variants(self, db: &dyn HirDatabase) -> usize { | ||||
|  | @ -1629,12 +1573,8 @@ impl Enum { | |||
| impl HasVisibility for Enum { | ||||
|     fn visibility(&self, db: &dyn HirDatabase) -> Visibility { | ||||
|         let loc = self.id.lookup(db); | ||||
|         let item_tree = loc.id.item_tree(db); | ||||
|         Visibility::resolve( | ||||
|             db, | ||||
|             &self.id.resolver(db), | ||||
|             &item_tree[item_tree[loc.id.value].visibility], | ||||
|         ) | ||||
|         let source = loc.source(db); | ||||
|         visibility_from_ast(db, &self.id.resolver(db), source.map(|src| src.visibility())) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | @ -2708,10 +2648,9 @@ impl ExternCrateDecl { | |||
| 
 | ||||
|     pub fn resolved_crate(self, db: &dyn HirDatabase) -> Option<Crate> { | ||||
|         let loc = self.id.lookup(db); | ||||
|         let item_tree = loc.id.item_tree(db); | ||||
|         let krate = loc.container.krate(); | ||||
|         let name = &item_tree[loc.id.value].name; | ||||
|         if *name == sym::self_ { | ||||
|         let name = self.name(db); | ||||
|         if name == sym::self_ { | ||||
|             Some(krate.into()) | ||||
|         } else { | ||||
|             krate.data(db).dependencies.iter().find_map(|dep| { | ||||
|  | @ -2722,25 +2661,29 @@ impl ExternCrateDecl { | |||
| 
 | ||||
|     pub fn name(self, db: &dyn HirDatabase) -> Name { | ||||
|         let loc = self.id.lookup(db); | ||||
|         let item_tree = loc.id.item_tree(db); | ||||
|         item_tree[loc.id.value].name.clone() | ||||
|         let source = loc.source(db); | ||||
|         as_name_opt(source.value.name_ref()) | ||||
|     } | ||||
| 
 | ||||
|     pub fn alias(self, db: &dyn HirDatabase) -> Option<ImportAlias> { | ||||
|         let loc = self.id.lookup(db); | ||||
|         let item_tree = loc.id.item_tree(db); | ||||
|         item_tree[loc.id.value].alias.clone() | ||||
|         let source = loc.source(db); | ||||
|         let rename = source.value.rename()?; | ||||
|         if let Some(name) = rename.name() { | ||||
|             Some(ImportAlias::Alias(name.as_name())) | ||||
|         } else if rename.underscore_token().is_some() { | ||||
|             Some(ImportAlias::Underscore) | ||||
|         } else { | ||||
|             None | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /// Returns the name under which this crate is made accessible, taking `_` into account.
 | ||||
|     pub fn alias_or_name(self, db: &dyn HirDatabase) -> Option<Name> { | ||||
|         let loc = self.id.lookup(db); | ||||
|         let item_tree = loc.id.item_tree(db); | ||||
| 
 | ||||
|         match &item_tree[loc.id.value].alias { | ||||
|         match self.alias(db) { | ||||
|             Some(ImportAlias::Underscore) => None, | ||||
|             Some(ImportAlias::Alias(alias)) => Some(alias.clone()), | ||||
|             None => Some(item_tree[loc.id.value].name.clone()), | ||||
|             Some(ImportAlias::Alias(alias)) => Some(alias), | ||||
|             None => Some(self.name(db)), | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -2748,12 +2691,8 @@ impl ExternCrateDecl { | |||
| impl HasVisibility for ExternCrateDecl { | ||||
|     fn visibility(&self, db: &dyn HirDatabase) -> Visibility { | ||||
|         let loc = self.id.lookup(db); | ||||
|         let item_tree = loc.id.item_tree(db); | ||||
|         Visibility::resolve( | ||||
|             db, | ||||
|             &self.id.resolver(db), | ||||
|             &item_tree[item_tree[loc.id.value].visibility], | ||||
|         ) | ||||
|         let source = loc.source(db); | ||||
|         visibility_from_ast(db, &self.id.resolver(db), source.map(|src| src.visibility())) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | @ -2873,12 +2812,8 @@ impl Static { | |||
| impl HasVisibility for Static { | ||||
|     fn visibility(&self, db: &dyn HirDatabase) -> Visibility { | ||||
|         let loc = self.id.lookup(db); | ||||
|         let item_tree = loc.id.item_tree(db); | ||||
|         Visibility::resolve( | ||||
|             db, | ||||
|             &self.id.resolver(db), | ||||
|             &item_tree[item_tree[loc.id.value].visibility], | ||||
|         ) | ||||
|         let source = loc.source(db); | ||||
|         visibility_from_ast(db, &self.id.resolver(db), source.map(|src| src.visibility())) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | @ -2967,11 +2902,7 @@ impl Trait { | |||
|     } | ||||
| 
 | ||||
|     fn all_macro_calls(&self, db: &dyn HirDatabase) -> Box<[(AstId<ast::Item>, MacroCallId)]> { | ||||
|         db.trait_items(self.id) | ||||
|             .macro_calls | ||||
|             .as_ref() | ||||
|             .map(|it| it.as_ref().clone().into_boxed_slice()) | ||||
|             .unwrap_or_default() | ||||
|         db.trait_items(self.id).macro_calls.to_vec().into_boxed_slice() | ||||
|     } | ||||
| 
 | ||||
|     /// `#[rust_analyzer::completions(...)]` mode.
 | ||||
|  | @ -2983,12 +2914,8 @@ impl Trait { | |||
| impl HasVisibility for Trait { | ||||
|     fn visibility(&self, db: &dyn HirDatabase) -> Visibility { | ||||
|         let loc = self.id.lookup(db); | ||||
|         let item_tree = loc.id.item_tree(db); | ||||
|         Visibility::resolve( | ||||
|             db, | ||||
|             &self.id.resolver(db), | ||||
|             &item_tree[item_tree[loc.id.value].visibility], | ||||
|         ) | ||||
|         let source = loc.source(db); | ||||
|         visibility_from_ast(db, &self.id.resolver(db), source.map(|src| src.visibility())) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | @ -3010,12 +2937,8 @@ impl TraitAlias { | |||
| impl HasVisibility for TraitAlias { | ||||
|     fn visibility(&self, db: &dyn HirDatabase) -> Visibility { | ||||
|         let loc = self.id.lookup(db); | ||||
|         let item_tree = loc.id.item_tree(db); | ||||
|         Visibility::resolve( | ||||
|             db, | ||||
|             &self.id.resolver(db), | ||||
|             &item_tree[item_tree[loc.id.value].visibility], | ||||
|         ) | ||||
|         let source = loc.source(db); | ||||
|         visibility_from_ast(db, &self.id.resolver(db), source.map(|src| src.visibility())) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | @ -3163,25 +3086,23 @@ impl Macro { | |||
|         match self.id { | ||||
|             MacroId::Macro2Id(id) => { | ||||
|                 let loc = id.lookup(db); | ||||
|                 let item_tree = loc.id.item_tree(db); | ||||
|                 item_tree[loc.id.value].name.clone() | ||||
|                 let source = loc.source(db); | ||||
|                 as_name_opt(source.value.name()) | ||||
|             } | ||||
|             MacroId::MacroRulesId(id) => { | ||||
|                 let loc = id.lookup(db); | ||||
|                 let item_tree = loc.id.item_tree(db); | ||||
|                 item_tree[loc.id.value].name.clone() | ||||
|                 let source = loc.source(db); | ||||
|                 as_name_opt(source.value.name()) | ||||
|             } | ||||
|             MacroId::ProcMacroId(id) => { | ||||
|                 let loc = id.lookup(db); | ||||
|                 let item_tree = loc.id.item_tree(db); | ||||
|                 let source = loc.source(db); | ||||
|                 match loc.kind { | ||||
|                     ProcMacroKind::CustomDerive => db | ||||
|                         .attrs(id.into()) | ||||
|                         .parse_proc_macro_derive() | ||||
|                         .map_or_else(|| item_tree[loc.id.value].name.clone(), |(it, _)| it), | ||||
|                     ProcMacroKind::Bang | ProcMacroKind::Attr => { | ||||
|                         item_tree[loc.id.value].name.clone() | ||||
|                     } | ||||
|                         .map_or_else(|| as_name_opt(source.value.name()), |(it, _)| it), | ||||
|                     ProcMacroKind::Bang | ProcMacroKind::Attr => as_name_opt(source.value.name()), | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | @ -3278,12 +3199,8 @@ impl HasVisibility for Macro { | |||
|         match self.id { | ||||
|             MacroId::Macro2Id(id) => { | ||||
|                 let loc = id.lookup(db); | ||||
|                 let item_tree = loc.id.item_tree(db); | ||||
|                 Visibility::resolve( | ||||
|                     db, | ||||
|                     &id.resolver(db), | ||||
|                     &item_tree[item_tree[loc.id.value].visibility], | ||||
|                 ) | ||||
|                 let source = loc.source(db); | ||||
|                 visibility_from_ast(db, &id.resolver(db), source.map(|src| src.visibility())) | ||||
|             } | ||||
|             MacroId::MacroRulesId(_) => Visibility::Public, | ||||
|             MacroId::ProcMacroId(_) => Visibility::Public, | ||||
|  | @ -3437,7 +3354,7 @@ fn as_assoc_item<'db, ID, DEF, LOC>( | |||
| where | ||||
|     ID: Lookup<Database = dyn DefDatabase, Data = AssocItemLoc<LOC>>, | ||||
|     DEF: From<ID>, | ||||
|     LOC: ItemTreeNode, | ||||
|     LOC: AstIdNode, | ||||
| { | ||||
|     match id.lookup(db).container { | ||||
|         ItemContainerId::TraitId(_) | ItemContainerId::ImplId(_) => Some(ctor(DEF::from(id))), | ||||
|  | @ -3453,7 +3370,7 @@ fn as_extern_assoc_item<'db, ID, DEF, LOC>( | |||
| where | ||||
|     ID: Lookup<Database = dyn DefDatabase, Data = AssocItemLoc<LOC>>, | ||||
|     DEF: From<ID>, | ||||
|     LOC: ItemTreeNode, | ||||
|     LOC: AstIdNode, | ||||
| { | ||||
|     match id.lookup(db).container { | ||||
|         ItemContainerId::ExternBlockId(_) => Some(ctor(DEF::from(id))), | ||||
|  | @ -4545,11 +4462,7 @@ impl Impl { | |||
|     } | ||||
| 
 | ||||
|     fn all_macro_calls(&self, db: &dyn HirDatabase) -> Box<[(AstId<ast::Item>, MacroCallId)]> { | ||||
|         db.impl_items(self.id) | ||||
|             .macro_calls | ||||
|             .as_ref() | ||||
|             .map(|it| it.as_ref().clone().into_boxed_slice()) | ||||
|             .unwrap_or_default() | ||||
|         db.impl_items(self.id).macro_calls.to_vec().into_boxed_slice() | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | @ -6510,3 +6423,7 @@ pub fn resolve_absolute_path<'a, I: Iterator<Item = Symbol> + Clone + 'a>( | |||
|         }) | ||||
|         .flatten() | ||||
| } | ||||
| 
 | ||||
| fn as_name_opt(name: Option<impl AsName>) -> Name { | ||||
|     name.map_or_else(Name::missing, |name| name.as_name()) | ||||
| } | ||||
|  |  | |||
|  | @ -6,10 +6,11 @@ | |||
| 
 | ||||
| use either::Either; | ||||
| use hir_expand::{HirFileId, attrs::collect_attrs}; | ||||
| use span::AstIdNode; | ||||
| use syntax::{AstPtr, ast}; | ||||
| 
 | ||||
| use hir_def::{ | ||||
|     AdtId, AssocItemId, DefWithBodyId, EnumId, FieldId, GenericDefId, ImplId, ItemTreeLoc, | ||||
|     AdtId, AssocItemId, AstIdLoc, DefWithBodyId, EnumId, FieldId, GenericDefId, ImplId, | ||||
|     LifetimeParamId, Lookup, MacroId, ModuleDefId, ModuleId, TraitId, TypeOrConstParamId, | ||||
|     VariantId, | ||||
|     db::DefDatabase, | ||||
|  | @ -19,7 +20,6 @@ use hir_def::{ | |||
|     }, | ||||
|     hir::generics::GenericParams, | ||||
|     item_scope::ItemScope, | ||||
|     item_tree::ItemTreeNode, | ||||
|     nameres::DefMap, | ||||
|     src::{HasChildSource, HasSource}, | ||||
| }; | ||||
|  | @ -113,7 +113,7 @@ impl ChildBySource for ItemScope { | |||
|             ids.iter().for_each(|&id| { | ||||
|                 if let MacroId::MacroRulesId(id) = id { | ||||
|                     let loc = id.lookup(db); | ||||
|                     if loc.id.file_id() == file_id { | ||||
|                     if loc.id.file_id == file_id { | ||||
|                         res[keys::MACRO_RULES].insert(loc.ast_ptr(db).value, id); | ||||
|                     } | ||||
|                 } | ||||
|  | @ -199,16 +199,14 @@ impl ChildBySource for VariantId { | |||
| impl ChildBySource for EnumId { | ||||
|     fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap, file_id: HirFileId) { | ||||
|         let loc = &self.lookup(db); | ||||
|         if file_id != loc.id.file_id() { | ||||
|         if file_id != loc.id.file_id { | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         let tree = loc.id.item_tree(db); | ||||
|         let ast_id_map = db.ast_id_map(loc.id.file_id()); | ||||
|         let ast_id_map = db.ast_id_map(loc.id.file_id); | ||||
| 
 | ||||
|         db.enum_variants(*self).variants.iter().for_each(|&(variant, _)| { | ||||
|             res[keys::ENUM_VARIANT] | ||||
|                 .insert(ast_id_map.get(tree[variant.lookup(db).id.value].ast_id), variant); | ||||
|         db.enum_variants(*self).variants.iter().for_each(|&(variant, _, _)| { | ||||
|             res[keys::ENUM_VARIANT].insert(ast_id_map.get(variant.lookup(db).id.value), variant); | ||||
|         }); | ||||
|         let (_, source_map) = db.enum_signature_with_source_map(*self); | ||||
|         source_map | ||||
|  | @ -287,15 +285,14 @@ fn insert_item_loc<ID, N, Data>( | |||
|     res: &mut DynMap, | ||||
|     file_id: HirFileId, | ||||
|     id: ID, | ||||
|     key: Key<N::Source, ID>, | ||||
|     key: Key<N, ID>, | ||||
| ) where | ||||
|     ID: Lookup<Database = dyn DefDatabase, Data = Data> + 'static, | ||||
|     Data: ItemTreeLoc<Id = N>, | ||||
|     N: ItemTreeNode, | ||||
|     N::Source: 'static, | ||||
|     Data: AstIdLoc<Ast = N>, | ||||
|     N: AstIdNode + 'static, | ||||
| { | ||||
|     let loc = id.lookup(db); | ||||
|     if loc.item_tree_id().file_id() == file_id { | ||||
|     if loc.ast_id().file_id == file_id { | ||||
|         res[key].insert(loc.ast_ptr(db).value, id) | ||||
|     } | ||||
| } | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Chayim Refael Friedman
						Chayim Refael Friedman