mirror of
				https://github.com/rust-lang/rust-analyzer.git
				synced 2025-10-31 03:54:42 +00:00 
			
		
		
		
	Merge pull request #19837 from ChayimFriedman2/stable-astid
Provide better incrementality when items are changed
This commit is contained in:
		
						commit
						c15fc9a344
					
				
					 57 changed files with 2246 additions and 1935 deletions
				
			
		|  | @ -18,6 +18,7 @@ extend-ignore-re = [ | ||||||
|     "INOUT", |     "INOUT", | ||||||
|     "optin", |     "optin", | ||||||
|     "=Pn", |     "=Pn", | ||||||
|  |     "\\[[0-9A-F]{4},",  # AstId hex hashes | ||||||
|     # ignore `// spellchecker:off` until `// spellchecker:on` |     # ignore `// spellchecker:off` until `// spellchecker:on` | ||||||
|     "(?s)(#|//)\\s*spellchecker:off.*?\\n\\s*(#|//)\\s*spellchecker:on", |     "(?s)(#|//)\\s*spellchecker:off.*?\\n\\s*(#|//)\\s*spellchecker:on", | ||||||
| ] | ] | ||||||
|  |  | ||||||
|  | @ -14,6 +14,7 @@ use intern::{Symbol, sym}; | ||||||
| use la_arena::{ArenaMap, Idx, RawIdx}; | use la_arena::{ArenaMap, Idx, RawIdx}; | ||||||
| use mbe::DelimiterKind; | use mbe::DelimiterKind; | ||||||
| use rustc_abi::ReprOptions; | use rustc_abi::ReprOptions; | ||||||
|  | use span::AstIdNode; | ||||||
| use syntax::{ | use syntax::{ | ||||||
|     AstPtr, |     AstPtr, | ||||||
|     ast::{self, HasAttrs}, |     ast::{self, HasAttrs}, | ||||||
|  | @ -22,10 +23,10 @@ use triomphe::Arc; | ||||||
| use tt::iter::{TtElement, TtIter}; | use tt::iter::{TtElement, TtIter}; | ||||||
| 
 | 
 | ||||||
| use crate::{ | use crate::{ | ||||||
|     AdtId, AttrDefId, GenericParamId, HasModule, ItemTreeLoc, LocalFieldId, Lookup, MacroId, |     AdtId, AstIdLoc, AttrDefId, GenericParamId, HasModule, LocalFieldId, Lookup, MacroId, | ||||||
|     VariantId, |     VariantId, | ||||||
|     db::DefDatabase, |     db::DefDatabase, | ||||||
|     item_tree::{AttrOwner, FieldParent, ItemTreeNode}, |     item_tree::AttrOwner, | ||||||
|     lang_item::LangItem, |     lang_item::LangItem, | ||||||
|     nameres::{ModuleOrigin, ModuleSource}, |     nameres::{ModuleOrigin, ModuleSource}, | ||||||
|     src::{HasChildSource, HasSource}, |     src::{HasChildSource, HasSource}, | ||||||
|  | @ -42,6 +43,15 @@ pub struct AttrsWithOwner { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl Attrs { | 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> { |     pub fn get(&self, id: AttrId) -> Option<&Attr> { | ||||||
|         (**self).iter().find(|attr| attr.id == id) |         (**self).iter().find(|attr| attr.id == id) | ||||||
|     } |     } | ||||||
|  | @ -94,44 +104,64 @@ impl Attrs { | ||||||
|         v: VariantId, |         v: VariantId, | ||||||
|     ) -> Arc<ArenaMap<LocalFieldId, Attrs>> { |     ) -> Arc<ArenaMap<LocalFieldId, Attrs>> { | ||||||
|         let _p = tracing::info_span!("fields_attrs_query").entered(); |         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 mut res = ArenaMap::default(); | ||||||
|         let item_tree; |         let (fields, file_id, krate) = match v { | ||||||
|         let (parent, fields, krate) = match v { |  | ||||||
|             VariantId::EnumVariantId(it) => { |             VariantId::EnumVariantId(it) => { | ||||||
|                 let loc = it.lookup(db); |                 let loc = it.lookup(db); | ||||||
|                 let krate = loc.parent.lookup(db).container.krate; |                 let krate = loc.parent.lookup(db).container.krate; | ||||||
|                 item_tree = loc.id.item_tree(db); |                 let source = loc.source(db); | ||||||
|                 let variant = &item_tree[loc.id.value]; |                 (source.value.field_list(), source.file_id, krate) | ||||||
|                 (FieldParent::EnumVariant(loc.id.value), &variant.fields, krate) |  | ||||||
|             } |             } | ||||||
|             VariantId::StructId(it) => { |             VariantId::StructId(it) => { | ||||||
|                 let loc = it.lookup(db); |                 let loc = it.lookup(db); | ||||||
|                 let krate = loc.container.krate; |                 let krate = loc.container.krate; | ||||||
|                 item_tree = loc.id.item_tree(db); |                 let source = loc.source(db); | ||||||
|                 let struct_ = &item_tree[loc.id.value]; |                 (source.value.field_list(), source.file_id, krate) | ||||||
|                 (FieldParent::Struct(loc.id.value), &struct_.fields, krate) |  | ||||||
|             } |             } | ||||||
|             VariantId::UnionId(it) => { |             VariantId::UnionId(it) => { | ||||||
|                 let loc = it.lookup(db); |                 let loc = it.lookup(db); | ||||||
|                 let krate = loc.container.krate; |                 let krate = loc.container.krate; | ||||||
|                 item_tree = loc.id.item_tree(db); |                 let source = loc.source(db); | ||||||
|                 let union_ = &item_tree[loc.id.value]; |                 ( | ||||||
|                 (FieldParent::Union(loc.id.value), &union_.fields, krate) |                     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 cfg_options = krate.cfg_options(db); | ||||||
|  |         let span_map = db.span_map(file_id); | ||||||
| 
 | 
 | ||||||
|         let mut idx = 0; |         match fields { | ||||||
|         for (id, _field) in fields.iter().enumerate() { |             ast::FieldList::RecordFieldList(fields) => { | ||||||
|             let attrs = item_tree.attrs(db, krate, AttrOwner::make_field_indexed(parent, id)); |                 let mut idx = 0; | ||||||
|             if attrs.is_cfg_enabled(cfg_options) { |                 for field in fields.fields() { | ||||||
|                 res.insert(Idx::from_raw(RawIdx::from(idx)), attrs); |                     let attrs = | ||||||
|                 idx += 1; |                         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) |         Arc::new(res) | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | @ -167,11 +197,10 @@ impl Attrs { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     #[inline] |     #[inline] | ||||||
|     pub(crate) fn is_cfg_enabled(&self, cfg_options: &CfgOptions) -> bool { |     pub(crate) fn is_cfg_enabled(&self, cfg_options: &CfgOptions) -> Result<(), CfgExpr> { | ||||||
|         match self.cfg() { |         self.cfgs().try_for_each(|cfg| { | ||||||
|             None => true, |             if cfg_options.check(&cfg) != Some(false) { Ok(()) } else { Err(cfg) } | ||||||
|             Some(cfg) => cfg_options.check(&cfg) != Some(false), |         }) | ||||||
|         } |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     #[inline] |     #[inline] | ||||||
|  | @ -488,12 +517,12 @@ impl AttrsWithOwner { | ||||||
|     pub(crate) fn attrs_query(db: &dyn DefDatabase, def: AttrDefId) -> Attrs { |     pub(crate) fn attrs_query(db: &dyn DefDatabase, def: AttrDefId) -> Attrs { | ||||||
|         let _p = tracing::info_span!("attrs_query").entered(); |         let _p = tracing::info_span!("attrs_query").entered(); | ||||||
|         // FIXME: this should use `Trace` to avoid duplication in `source_map` below
 |         // FIXME: this should use `Trace` to avoid duplication in `source_map` below
 | ||||||
|         let raw_attrs = match def { |         match def { | ||||||
|             AttrDefId::ModuleId(module) => { |             AttrDefId::ModuleId(module) => { | ||||||
|                 let def_map = module.def_map(db); |                 let def_map = module.def_map(db); | ||||||
|                 let mod_data = &def_map[module.local_id]; |                 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, .. } => { |                     ModuleOrigin::File { definition, declaration_tree_id, .. } => { | ||||||
|                         let decl_attrs = declaration_tree_id |                         let decl_attrs = declaration_tree_id | ||||||
|                             .item_tree(db) |                             .item_tree(db) | ||||||
|  | @ -515,34 +544,33 @@ impl AttrsWithOwner { | ||||||
|                         let tree = db.block_item_tree(id); |                         let tree = db.block_item_tree(id); | ||||||
|                         tree.raw_attrs(AttrOwner::TopLevel).clone() |                         tree.raw_attrs(AttrOwner::TopLevel).clone() | ||||||
|                     } |                     } | ||||||
|                 } |                 }; | ||||||
|  |                 Attrs::expand_cfg_attr(db, module.krate, raw_attrs) | ||||||
|             } |             } | ||||||
|             AttrDefId::FieldId(it) => { |             AttrDefId::FieldId(it) => db.fields_attrs(it.parent)[it.local_id].clone(), | ||||||
|                 return db.fields_attrs(it.parent)[it.local_id].clone(); |             AttrDefId::EnumVariantId(it) => attrs_from_ast_id_loc(db, it), | ||||||
|             } |  | ||||||
|             AttrDefId::EnumVariantId(it) => attrs_from_item_tree_loc(db, it), |  | ||||||
|             AttrDefId::AdtId(it) => match it { |             AttrDefId::AdtId(it) => match it { | ||||||
|                 AdtId::StructId(it) => attrs_from_item_tree_loc(db, it), |                 AdtId::StructId(it) => attrs_from_ast_id_loc(db, it), | ||||||
|                 AdtId::EnumId(it) => attrs_from_item_tree_loc(db, it), |                 AdtId::EnumId(it) => attrs_from_ast_id_loc(db, it), | ||||||
|                 AdtId::UnionId(it) => attrs_from_item_tree_loc(db, it), |                 AdtId::UnionId(it) => attrs_from_ast_id_loc(db, it), | ||||||
|             }, |             }, | ||||||
|             AttrDefId::TraitId(it) => attrs_from_item_tree_loc(db, it), |             AttrDefId::TraitId(it) => attrs_from_ast_id_loc(db, it), | ||||||
|             AttrDefId::TraitAliasId(it) => attrs_from_item_tree_loc(db, it), |             AttrDefId::TraitAliasId(it) => attrs_from_ast_id_loc(db, it), | ||||||
|             AttrDefId::MacroId(it) => match it { |             AttrDefId::MacroId(it) => match it { | ||||||
|                 MacroId::Macro2Id(it) => attrs_from_item_tree_loc(db, it), |                 MacroId::Macro2Id(it) => attrs_from_ast_id_loc(db, it), | ||||||
|                 MacroId::MacroRulesId(it) => attrs_from_item_tree_loc(db, it), |                 MacroId::MacroRulesId(it) => attrs_from_ast_id_loc(db, it), | ||||||
|                 MacroId::ProcMacroId(it) => attrs_from_item_tree_loc(db, it), |                 MacroId::ProcMacroId(it) => attrs_from_ast_id_loc(db, it), | ||||||
|             }, |             }, | ||||||
|             AttrDefId::ImplId(it) => attrs_from_item_tree_loc(db, it), |             AttrDefId::ImplId(it) => attrs_from_ast_id_loc(db, it), | ||||||
|             AttrDefId::ConstId(it) => attrs_from_item_tree_loc(db, it), |             AttrDefId::ConstId(it) => attrs_from_ast_id_loc(db, it), | ||||||
|             AttrDefId::StaticId(it) => attrs_from_item_tree_loc(db, it), |             AttrDefId::StaticId(it) => attrs_from_ast_id_loc(db, it), | ||||||
|             AttrDefId::FunctionId(it) => attrs_from_item_tree_loc(db, it), |             AttrDefId::FunctionId(it) => attrs_from_ast_id_loc(db, it), | ||||||
|             AttrDefId::TypeAliasId(it) => attrs_from_item_tree_loc(db, it), |             AttrDefId::TypeAliasId(it) => attrs_from_ast_id_loc(db, it), | ||||||
|             AttrDefId::GenericParamId(it) => match it { |             AttrDefId::GenericParamId(it) => match it { | ||||||
|                 GenericParamId::ConstParamId(it) => { |                 GenericParamId::ConstParamId(it) => { | ||||||
|                     let src = it.parent().child_source(db); |                     let src = it.parent().child_source(db); | ||||||
|                     // FIXME: We should be never getting `None` here.
 |                     // 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( |                         Some(val) => RawAttrs::new_expanded( | ||||||
|                             db, |                             db, | ||||||
|                             val, |                             val, | ||||||
|  | @ -550,12 +578,12 @@ impl AttrsWithOwner { | ||||||
|                             def.krate(db).cfg_options(db), |                             def.krate(db).cfg_options(db), | ||||||
|                         ), |                         ), | ||||||
|                         None => RawAttrs::EMPTY, |                         None => RawAttrs::EMPTY, | ||||||
|                     }); |                     }) | ||||||
|                 } |                 } | ||||||
|                 GenericParamId::TypeParamId(it) => { |                 GenericParamId::TypeParamId(it) => { | ||||||
|                     let src = it.parent().child_source(db); |                     let src = it.parent().child_source(db); | ||||||
|                     // FIXME: We should be never getting `None` here.
 |                     // 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( |                         Some(val) => RawAttrs::new_expanded( | ||||||
|                             db, |                             db, | ||||||
|                             val, |                             val, | ||||||
|  | @ -563,12 +591,12 @@ impl AttrsWithOwner { | ||||||
|                             def.krate(db).cfg_options(db), |                             def.krate(db).cfg_options(db), | ||||||
|                         ), |                         ), | ||||||
|                         None => RawAttrs::EMPTY, |                         None => RawAttrs::EMPTY, | ||||||
|                     }); |                     }) | ||||||
|                 } |                 } | ||||||
|                 GenericParamId::LifetimeParamId(it) => { |                 GenericParamId::LifetimeParamId(it) => { | ||||||
|                     let src = it.parent.child_source(db); |                     let src = it.parent.child_source(db); | ||||||
|                     // FIXME: We should be never getting `None` here.
 |                     // 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( |                         Some(val) => RawAttrs::new_expanded( | ||||||
|                             db, |                             db, | ||||||
|                             val, |                             val, | ||||||
|  | @ -576,16 +604,13 @@ impl AttrsWithOwner { | ||||||
|                             def.krate(db).cfg_options(db), |                             def.krate(db).cfg_options(db), | ||||||
|                         ), |                         ), | ||||||
|                         None => RawAttrs::EMPTY, |                         None => RawAttrs::EMPTY, | ||||||
|                     }); |                     }) | ||||||
|                 } |                 } | ||||||
|             }, |             }, | ||||||
|             AttrDefId::ExternBlockId(it) => attrs_from_item_tree_loc(db, it), |             AttrDefId::ExternBlockId(it) => attrs_from_ast_id_loc(db, it), | ||||||
|             AttrDefId::ExternCrateId(it) => attrs_from_item_tree_loc(db, it), |             AttrDefId::ExternCrateId(it) => attrs_from_ast_id_loc(db, it), | ||||||
|             AttrDefId::UseId(it) => attrs_from_item_tree_loc(db, it), |             AttrDefId::UseId(it) => attrs_from_ast_id_loc(db, it), | ||||||
|         }; |         } | ||||||
| 
 |  | ||||||
|         let attrs = raw_attrs.expand_cfg_attr(db, def.krate(db)); |  | ||||||
|         Attrs(attrs) |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn source_map(&self, db: &dyn DefDatabase) -> AttrSourceMap { |     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) |     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), |     db: &(dyn DefDatabase + 'db), | ||||||
|     lookup: impl Lookup<Database = dyn DefDatabase, Data = impl ItemTreeLoc<Id = N>>, |     lookup: impl Lookup<Database = dyn DefDatabase, Data = impl AstIdLoc<Ast = N> + HasModule>, | ||||||
| ) -> RawAttrs { | ) -> Attrs { | ||||||
|     let id = lookup.lookup(db).item_tree_id(); |     let loc = lookup.lookup(db); | ||||||
|     let tree = id.item_tree(db); |     let source = loc.source(db); | ||||||
|     let attr_owner = N::attr_owner(id.value); |     let span_map = db.span_map(source.file_id); | ||||||
|     tree.raw_attrs(attr_owner).clone() |     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( | pub(crate) fn fields_attrs_source_map( | ||||||
|  |  | ||||||
|  | @ -1,8 +1,11 @@ | ||||||
| //! Defines database & queries for name resolution.
 | //! Defines database & queries for name resolution.
 | ||||||
| use base_db::{Crate, RootQueryDb, SourceDatabase}; | use base_db::{Crate, RootQueryDb, SourceDatabase}; | ||||||
| use either::Either; | use either::Either; | ||||||
| use hir_expand::{EditionedFileId, HirFileId, MacroCallId, MacroDefId, db::ExpandDatabase}; | use hir_expand::{ | ||||||
| use intern::sym; |     EditionedFileId, HirFileId, InFile, Lookup, MacroCallId, MacroDefId, MacroDefKind, | ||||||
|  |     db::ExpandDatabase, | ||||||
|  | }; | ||||||
|  | use intern::{Symbol, sym}; | ||||||
| use la_arena::ArenaMap; | use la_arena::ArenaMap; | ||||||
| use syntax::{AstPtr, ast}; | use syntax::{AstPtr, ast}; | ||||||
| use thin_vec::ThinVec; | use thin_vec::ThinVec; | ||||||
|  | @ -11,8 +14,8 @@ use triomphe::Arc; | ||||||
| use crate::{ | use crate::{ | ||||||
|     AttrDefId, BlockId, BlockLoc, ConstId, ConstLoc, DefWithBodyId, EnumId, EnumLoc, EnumVariantId, |     AttrDefId, BlockId, BlockLoc, ConstId, ConstLoc, DefWithBodyId, EnumId, EnumLoc, EnumVariantId, | ||||||
|     EnumVariantLoc, ExternBlockId, ExternBlockLoc, ExternCrateId, ExternCrateLoc, FunctionId, |     EnumVariantLoc, ExternBlockId, ExternBlockLoc, ExternCrateId, ExternCrateLoc, FunctionId, | ||||||
|     FunctionLoc, GenericDefId, ImplId, ImplLoc, LocalFieldId, Macro2Id, Macro2Loc, MacroId, |     FunctionLoc, GenericDefId, ImplId, ImplLoc, LocalFieldId, Macro2Id, Macro2Loc, MacroExpander, | ||||||
|     MacroRulesId, MacroRulesLoc, MacroRulesLocFlags, ProcMacroId, ProcMacroLoc, StaticId, |     MacroId, MacroRulesId, MacroRulesLoc, MacroRulesLocFlags, ProcMacroId, ProcMacroLoc, StaticId, | ||||||
|     StaticLoc, StructId, StructLoc, TraitAliasId, TraitAliasLoc, TraitId, TraitLoc, TypeAliasId, |     StaticLoc, StructId, StructLoc, TraitAliasId, TraitAliasLoc, TraitId, TraitLoc, TypeAliasId, | ||||||
|     TypeAliasLoc, UnionId, UnionLoc, UseId, UseLoc, VariantId, |     TypeAliasLoc, UnionId, UnionLoc, UseId, UseLoc, VariantId, | ||||||
|     attr::{Attrs, AttrsWithOwner}, |     attr::{Attrs, AttrsWithOwner}, | ||||||
|  | @ -123,6 +126,8 @@ pub trait DefDatabase: InternDatabase + ExpandDatabase + SourceDatabase { | ||||||
|         id: VariantId, |         id: VariantId, | ||||||
|     ) -> (Arc<VariantFields>, Arc<ExpressionStoreSourceMap>); |     ) -> (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] |     #[salsa::tracked] | ||||||
|     fn enum_variants(&self, id: EnumId) -> Arc<EnumVariants> { |     fn enum_variants(&self, id: EnumId) -> Arc<EnumVariants> { | ||||||
|         self.enum_variants_with_diagnostics(id).0 |         self.enum_variants_with_diagnostics(id).0 | ||||||
|  | @ -263,6 +268,9 @@ pub trait DefDatabase: InternDatabase + ExpandDatabase + SourceDatabase { | ||||||
|         e: TypeAliasId, |         e: TypeAliasId, | ||||||
|     ) -> (Arc<TypeAliasSignature>, Arc<ExpressionStoreSourceMap>); |     ) -> (Arc<TypeAliasSignature>, Arc<ExpressionStoreSourceMap>); | ||||||
| 
 | 
 | ||||||
|  |     #[salsa::invoke(crate::signatures::extern_block_abi_query)] | ||||||
|  |     fn extern_block_abi(&self, extern_block: ExternBlockId) -> Option<Symbol>; | ||||||
|  | 
 | ||||||
|     // endregion:data
 |     // endregion:data
 | ||||||
| 
 | 
 | ||||||
|     #[salsa::invoke(Body::body_with_source_map_query)] |     #[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 { | 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 kind = |expander, file_id, m| { | ||||||
|         let in_file = InFile::new(file_id, m); |         let in_file = InFile::new(file_id, m); | ||||||
|         match expander { |         match expander { | ||||||
|  | @ -418,11 +422,9 @@ fn macro_def(db: &dyn DefDatabase, id: MacroId) -> MacroDefId { | ||||||
|         MacroId::Macro2Id(it) => { |         MacroId::Macro2Id(it) => { | ||||||
|             let loc: Macro2Loc = it.lookup(db); |             let loc: Macro2Loc = it.lookup(db); | ||||||
| 
 | 
 | ||||||
|             let item_tree = loc.id.item_tree(db); |  | ||||||
|             let makro = &item_tree[loc.id.value]; |  | ||||||
|             MacroDefId { |             MacroDefId { | ||||||
|                 krate: loc.container.krate, |                 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, |                 local_inner: false, | ||||||
|                 allow_internal_unsafe: loc.allow_internal_unsafe, |                 allow_internal_unsafe: loc.allow_internal_unsafe, | ||||||
|                 edition: loc.edition, |                 edition: loc.edition, | ||||||
|  | @ -431,11 +433,9 @@ fn macro_def(db: &dyn DefDatabase, id: MacroId) -> MacroDefId { | ||||||
|         MacroId::MacroRulesId(it) => { |         MacroId::MacroRulesId(it) => { | ||||||
|             let loc: MacroRulesLoc = it.lookup(db); |             let loc: MacroRulesLoc = it.lookup(db); | ||||||
| 
 | 
 | ||||||
|             let item_tree = loc.id.item_tree(db); |  | ||||||
|             let makro = &item_tree[loc.id.value]; |  | ||||||
|             MacroDefId { |             MacroDefId { | ||||||
|                 krate: loc.container.krate, |                 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), |                 local_inner: loc.flags.contains(MacroRulesLocFlags::LOCAL_INNER), | ||||||
|                 allow_internal_unsafe: loc |                 allow_internal_unsafe: loc | ||||||
|                     .flags |                     .flags | ||||||
|  | @ -446,15 +446,9 @@ fn macro_def(db: &dyn DefDatabase, id: MacroId) -> MacroDefId { | ||||||
|         MacroId::ProcMacroId(it) => { |         MacroId::ProcMacroId(it) => { | ||||||
|             let loc = it.lookup(db); |             let loc = it.lookup(db); | ||||||
| 
 | 
 | ||||||
|             let item_tree = loc.id.item_tree(db); |  | ||||||
|             let makro = &item_tree[loc.id.value]; |  | ||||||
|             MacroDefId { |             MacroDefId { | ||||||
|                 krate: loc.container.krate, |                 krate: loc.container.krate, | ||||||
|                 kind: MacroDefKind::ProcMacro( |                 kind: MacroDefKind::ProcMacro(loc.id, loc.expander, loc.kind), | ||||||
|                     InFile::new(loc.id.file_id(), makro.ast_id), |  | ||||||
|                     loc.expander, |  | ||||||
|                     loc.kind, |  | ||||||
|                 ), |  | ||||||
|                 local_inner: false, |                 local_inner: false, | ||||||
|                 allow_internal_unsafe: false, |                 allow_internal_unsafe: false, | ||||||
|                 edition: loc.edition, |                 edition: loc.edition, | ||||||
|  |  | ||||||
|  | @ -6,6 +6,7 @@ use base_db::Crate; | ||||||
| use cfg::CfgOptions; | use cfg::CfgOptions; | ||||||
| use drop_bomb::DropBomb; | use drop_bomb::DropBomb; | ||||||
| use hir_expand::AstId; | use hir_expand::AstId; | ||||||
|  | use hir_expand::span_map::SpanMapRef; | ||||||
| use hir_expand::{ | use hir_expand::{ | ||||||
|     ExpandError, ExpandErrorKind, ExpandResult, HirFileId, InFile, Lookup, MacroCallId, |     ExpandError, ExpandErrorKind, ExpandResult, HirFileId, InFile, Lookup, MacroCallId, | ||||||
|     eager::EagerCallBackFn, mod_path::ModPath, span_map::SpanMap, |     eager::EagerCallBackFn, mod_path::ModPath, span_map::SpanMap, | ||||||
|  | @ -223,9 +224,15 @@ impl Expander { | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     #[inline] | ||||||
|     pub(super) fn ast_id_map(&self) -> &AstIdMap { |     pub(super) fn ast_id_map(&self) -> &AstIdMap { | ||||||
|         &self.ast_id_map |         &self.ast_id_map | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     #[inline] | ||||||
|  |     pub(super) fn span_map(&self) -> SpanMapRef<'_> { | ||||||
|  |         self.span_map.as_ref() | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[derive(Debug)] | #[derive(Debug)] | ||||||
|  |  | ||||||
|  | @ -10,9 +10,10 @@ use std::mem; | ||||||
| use cfg::CfgOptions; | use cfg::CfgOptions; | ||||||
| use either::Either; | use either::Either; | ||||||
| use hir_expand::{ | use hir_expand::{ | ||||||
|     HirFileId, InFile, Lookup, MacroDefId, |     HirFileId, InFile, MacroDefId, | ||||||
|     mod_path::tool_path, |     mod_path::tool_path, | ||||||
|     name::{AsName, Name}, |     name::{AsName, Name}, | ||||||
|  |     span_map::SpanMapRef, | ||||||
| }; | }; | ||||||
| use intern::{Symbol, sym}; | use intern::{Symbol, sym}; | ||||||
| use rustc_hash::FxHashMap; | use rustc_hash::FxHashMap; | ||||||
|  | @ -30,8 +31,8 @@ use triomphe::Arc; | ||||||
| use tt::TextRange; | use tt::TextRange; | ||||||
| 
 | 
 | ||||||
| use crate::{ | use crate::{ | ||||||
|     AdtId, BlockId, BlockLoc, DefWithBodyId, FunctionId, GenericDefId, ImplId, ItemTreeLoc, |     AdtId, BlockId, BlockLoc, DefWithBodyId, FunctionId, GenericDefId, ImplId, MacroId, | ||||||
|     MacroId, ModuleDefId, ModuleId, TraitAliasId, TraitId, TypeAliasId, UnresolvedMacro, |     ModuleDefId, ModuleId, TraitAliasId, TraitId, TypeAliasId, UnresolvedMacro, | ||||||
|     builtin_type::BuiltinUint, |     builtin_type::BuiltinUint, | ||||||
|     db::DefDatabase, |     db::DefDatabase, | ||||||
|     expr_store::{ |     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 { |     pub fn lower_lifetime_ref(&mut self, lifetime: ast::Lifetime) -> LifetimeRefId { | ||||||
|         // FIXME: Keyword check?
 |         // FIXME: Keyword check?
 | ||||||
|         let lifetime_ref = match &*lifetime.text() { |         let lifetime_ref = match &*lifetime.text() { | ||||||
|  | @ -2141,26 +2147,10 @@ impl ExprCollector<'_> { | ||||||
|         block: ast::BlockExpr, |         block: ast::BlockExpr, | ||||||
|         mk_block: impl FnOnce(Option<BlockId>, Box<[Statement]>, Option<ExprId>) -> Expr, |         mk_block: impl FnOnce(Option<BlockId>, Box<[Statement]>, Option<ExprId>) -> Expr, | ||||||
|     ) -> ExprId { |     ) -> ExprId { | ||||||
|         let block_has_items = { |         let block_id = self.expander.ast_id_map().ast_id_for_block(&block).map(|file_local_id| { | ||||||
|             let statement_has_item = block.statements().any(|stmt| match stmt { |  | ||||||
|                 ast::Stmt::Item(_) => true, |  | ||||||
|                 // Macro calls can be both items and expressions. The syntax library always treats
 |  | ||||||
|                 // them as expressions here, so we undo that.
 |  | ||||||
|                 ast::Stmt::ExprStmt(es) => matches!(es.expr(), Some(ast::Expr::MacroExpr(_))), |  | ||||||
|                 _ => false, |  | ||||||
|             }); |  | ||||||
|             statement_has_item |  | ||||||
|                 || matches!(block.tail_expr(), Some(ast::Expr::MacroExpr(_))) |  | ||||||
|                 || (block.may_carry_attributes() && block.attrs().next().is_some()) |  | ||||||
|         }; |  | ||||||
| 
 |  | ||||||
|         let block_id = if block_has_items { |  | ||||||
|             let file_local_id = self.expander.ast_id_map().ast_id(&block); |  | ||||||
|             let ast_id = self.expander.in_file(file_local_id); |             let ast_id = self.expander.in_file(file_local_id); | ||||||
|             Some(self.db.intern_block(BlockLoc { ast_id, module: self.module })) |             self.db.intern_block(BlockLoc { ast_id, module: self.module }) | ||||||
|         } else { |         }); | ||||||
|             None |  | ||||||
|         }; |  | ||||||
| 
 | 
 | ||||||
|         let (module, def_map) = |         let (module, def_map) = | ||||||
|             match block_id.map(|block_id| (block_def_map(self.db, block_id), block_id)) { |             match block_id.map(|block_id| (block_def_map(self.db, block_id), block_id)) { | ||||||
|  | @ -2260,11 +2250,8 @@ impl ExprCollector<'_> { | ||||||
|                     match resolved.take_values() { |                     match resolved.take_values() { | ||||||
|                         Some(ModuleDefId::ConstId(_)) => (None, Pat::Path(name.into())), |                         Some(ModuleDefId::ConstId(_)) => (None, Pat::Path(name.into())), | ||||||
|                         Some(ModuleDefId::EnumVariantId(variant)) |                         Some(ModuleDefId::EnumVariantId(variant)) | ||||||
|                             if { |                         // FIXME: This can cause a cycle if the user is writing invalid code
 | ||||||
|                                 let loc = variant.lookup(self.db); |                             if self.db.variant_fields(variant.into()).shape != FieldsShape::Record => | ||||||
|                                 let tree = loc.item_tree_id().item_tree(self.db); |  | ||||||
|                                 tree[loc.id.value].shape != FieldsShape::Record |  | ||||||
|                             } => |  | ||||||
|                         { |                         { | ||||||
|                             (None, Pat::Path(name.into())) |                             (None, Pat::Path(name.into())) | ||||||
|                         } |                         } | ||||||
|  |  | ||||||
|  | @ -9,9 +9,10 @@ use std::{ | ||||||
| use hir_expand::{Lookup, mod_path::PathKind}; | use hir_expand::{Lookup, mod_path::PathKind}; | ||||||
| use itertools::Itertools; | use itertools::Itertools; | ||||||
| use span::Edition; | use span::Edition; | ||||||
|  | use syntax::ast::HasName; | ||||||
| 
 | 
 | ||||||
| use crate::{ | use crate::{ | ||||||
|     AdtId, DefWithBodyId, GenericDefId, ItemTreeLoc, TypeParamId, VariantId, |     AdtId, DefWithBodyId, GenericDefId, TypeParamId, VariantId, | ||||||
|     expr_store::path::{GenericArg, GenericArgs}, |     expr_store::path::{GenericArg, GenericArgs}, | ||||||
|     hir::{ |     hir::{ | ||||||
|         Array, BindingAnnotation, CaptureBy, ClosureKind, Literal, Movability, Statement, |         Array, BindingAnnotation, CaptureBy, ClosureKind, Literal, Movability, Statement, | ||||||
|  | @ -19,6 +20,7 @@ use crate::{ | ||||||
|     }, |     }, | ||||||
|     lang_item::LangItemTarget, |     lang_item::LangItemTarget, | ||||||
|     signatures::{FnFlags, FunctionSignature, StructSignature}, |     signatures::{FnFlags, FunctionSignature, StructSignature}, | ||||||
|  |     src::HasSource, | ||||||
|     type_ref::{ConstRef, LifetimeRef, Mutability, TraitBoundModifier, TypeBound, UseArgRef}, |     type_ref::{ConstRef, LifetimeRef, Mutability, TraitBoundModifier, TypeBound, UseArgRef}, | ||||||
| }; | }; | ||||||
| use crate::{LifetimeParamId, signatures::StructFlags}; | use crate::{LifetimeParamId, signatures::StructFlags}; | ||||||
|  | @ -48,6 +50,17 @@ pub enum LineFormat { | ||||||
|     Indentation, |     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( | pub fn print_body_hir( | ||||||
|     db: &dyn DefDatabase, |     db: &dyn DefDatabase, | ||||||
|     body: &Body, |     body: &Body, | ||||||
|  | @ -55,31 +68,14 @@ pub fn print_body_hir( | ||||||
|     edition: Edition, |     edition: Edition, | ||||||
| ) -> String { | ) -> String { | ||||||
|     let header = match owner { |     let header = match owner { | ||||||
|         DefWithBodyId::FunctionId(it) => { |         DefWithBodyId::FunctionId(it) => format!("fn {}", item_name(db, it, "<missing>")), | ||||||
|             it.lookup(db).id.resolved(db, |it| format!("fn {}", it.name.display(db, edition))) |         DefWithBodyId::StaticId(it) => format!("static {} = ", item_name(db, it, "<missing>")), | ||||||
|         } |         DefWithBodyId::ConstId(it) => format!("const {} = ", item_name(db, it, "_")), | ||||||
|         DefWithBodyId::StaticId(it) => it |         DefWithBodyId::VariantId(it) => format!( | ||||||
|             .lookup(db) |             "enum {}::{}", | ||||||
|             .id |             item_name(db, it.lookup(db).parent, "<missing>"), | ||||||
|             .resolved(db, |it| format!("static {} = ", it.name.display(db, edition))), |             item_name(db, it, "<missing>") | ||||||
|         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!( |  | ||||||
|                 "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), |  | ||||||
|             ) |  | ||||||
|         } |  | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     let mut p = Printer { |     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 { | pub fn print_variant_body_hir(db: &dyn DefDatabase, owner: VariantId, edition: Edition) -> String { | ||||||
|     let header = match owner { |     let header = match owner { | ||||||
|         VariantId::StructId(it) => { |         VariantId::StructId(it) => format!("struct {}", item_name(db, it, "<missing>")), | ||||||
|             it.lookup(db).id.resolved(db, |it| format!("struct {}", it.name.display(db, edition))) |         VariantId::EnumVariantId(it) => format!( | ||||||
|         } |             "enum {}::{}", | ||||||
|         VariantId::EnumVariantId(enum_variant_id) => { |             item_name(db, it.lookup(db).parent, "<missing>"), | ||||||
|             let loc = enum_variant_id.lookup(db); |             item_name(db, it, "<missing>") | ||||||
|             let enum_loc = loc.parent.lookup(db); |         ), | ||||||
|             format!( |         VariantId::UnionId(it) => format!("union {}", item_name(db, it, "<missing>")), | ||||||
|                 "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))), |  | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     let fields = db.variant_fields(owner); |     let fields = db.variant_fields(owner); | ||||||
|  | @ -1089,10 +1076,7 @@ impl Printer<'_> { | ||||||
|             w!(self, "builtin#lang("); |             w!(self, "builtin#lang("); | ||||||
|             macro_rules! write_name { |             macro_rules! write_name { | ||||||
|                 ($it:ident) => {{ |                 ($it:ident) => {{ | ||||||
|                     let loc = $it.lookup(self.db); |                     w!(self, "{}", item_name(self.db, $it, "<missing>")); | ||||||
|                     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)); |  | ||||||
|                 }}; |                 }}; | ||||||
|             } |             } | ||||||
|             match *it { |             match *it { | ||||||
|  |  | ||||||
|  | @ -29,7 +29,6 @@ | ||||||
| //!
 | //!
 | ||||||
| //! In general, any item in the `ItemTree` stores its `AstId`, which allows mapping it back to its
 | //! In general, any item in the `ItemTree` stores its `AstId`, which allows mapping it back to its
 | ||||||
| //! surface syntax.
 | //! surface syntax.
 | ||||||
| #![allow(unexpected_cfgs)] |  | ||||||
| 
 | 
 | ||||||
| mod lower; | mod lower; | ||||||
| mod pretty; | mod pretty; | ||||||
|  | @ -46,12 +45,12 @@ use std::{ | ||||||
| use ast::{AstNode, StructKind}; | use ast::{AstNode, StructKind}; | ||||||
| use base_db::Crate; | use base_db::Crate; | ||||||
| use hir_expand::{ | use hir_expand::{ | ||||||
|     ExpandTo, HirFileId, InFile, |     ExpandTo, HirFileId, | ||||||
|     attrs::RawAttrs, |     attrs::RawAttrs, | ||||||
|     mod_path::{ModPath, PathKind}, |     mod_path::{ModPath, PathKind}, | ||||||
|     name::Name, |     name::Name, | ||||||
| }; | }; | ||||||
| use intern::{Interned, Symbol}; | use intern::Interned; | ||||||
| use la_arena::{Arena, Idx, RawIdx}; | use la_arena::{Arena, Idx, RawIdx}; | ||||||
| use rustc_hash::FxHashMap; | use rustc_hash::FxHashMap; | ||||||
| use smallvec::SmallVec; | use smallvec::SmallVec; | ||||||
|  | @ -62,6 +61,8 @@ use triomphe::Arc; | ||||||
| 
 | 
 | ||||||
| use crate::{BlockId, Lookup, attr::Attrs, db::DefDatabase}; | 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)] | #[derive(Copy, Clone, Eq, PartialEq)] | ||||||
| pub struct RawVisibilityId(u32); | pub struct RawVisibilityId(u32); | ||||||
| 
 | 
 | ||||||
|  | @ -235,7 +236,6 @@ impl ItemTree { | ||||||
|                 structs, |                 structs, | ||||||
|                 unions, |                 unions, | ||||||
|                 enums, |                 enums, | ||||||
|                 variants, |  | ||||||
|                 consts, |                 consts, | ||||||
|                 statics, |                 statics, | ||||||
|                 traits, |                 traits, | ||||||
|  | @ -256,7 +256,6 @@ impl ItemTree { | ||||||
|             structs.shrink_to_fit(); |             structs.shrink_to_fit(); | ||||||
|             unions.shrink_to_fit(); |             unions.shrink_to_fit(); | ||||||
|             enums.shrink_to_fit(); |             enums.shrink_to_fit(); | ||||||
|             variants.shrink_to_fit(); |  | ||||||
|             consts.shrink_to_fit(); |             consts.shrink_to_fit(); | ||||||
|             statics.shrink_to_fit(); |             statics.shrink_to_fit(); | ||||||
|             traits.shrink_to_fit(); |             traits.shrink_to_fit(); | ||||||
|  | @ -308,7 +307,6 @@ struct ItemTreeData { | ||||||
|     structs: Arena<Struct>, |     structs: Arena<Struct>, | ||||||
|     unions: Arena<Union>, |     unions: Arena<Union>, | ||||||
|     enums: Arena<Enum>, |     enums: Arena<Enum>, | ||||||
|     variants: Arena<Variant>, |  | ||||||
|     consts: Arena<Const>, |     consts: Arena<Const>, | ||||||
|     statics: Arena<Static>, |     statics: Arena<Static>, | ||||||
|     traits: Arena<Trait>, |     traits: Arena<Trait>, | ||||||
|  | @ -338,41 +336,15 @@ pub enum AttrOwner { | ||||||
|     ModItem(ModItem), |     ModItem(ModItem), | ||||||
|     /// Inner attributes of the source file.
 |     /// Inner attributes of the source file.
 | ||||||
|     TopLevel, |     TopLevel, | ||||||
| 
 |  | ||||||
|     Variant(FileItemTreeId<Variant>), |  | ||||||
|     // while not relevant to early name resolution, fields can contain visibility
 |  | ||||||
|     Field(FieldParent, ItemTreeFieldId), |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl AttrOwner { | impl From<ModItem> for AttrOwner { | ||||||
|     pub fn make_field_indexed(parent: FieldParent, idx: usize) -> Self { |     #[inline] | ||||||
|         AttrOwner::Field(parent, ItemTreeFieldId::from_raw(RawIdx::from_u32(idx as u32))) |     fn from(value: ModItem) -> Self { | ||||||
|  |         AttrOwner::ModItem(value) | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] |  | ||||||
| pub enum FieldParent { |  | ||||||
|     Struct(FileItemTreeId<Struct>), |  | ||||||
|     Union(FileItemTreeId<Union>), |  | ||||||
|     EnumVariant(FileItemTreeId<Variant>), |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| pub type ItemTreeFieldId = Idx<Field>; |  | ||||||
| 
 |  | ||||||
| macro_rules! from_attrs { |  | ||||||
|     ( $( $var:ident($t:ty) ),+ $(,)? ) => { |  | ||||||
|         $( |  | ||||||
|             impl From<$t> for AttrOwner { |  | ||||||
|                 fn from(t: $t) -> AttrOwner { |  | ||||||
|                     AttrOwner::$var(t) |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         )+ |  | ||||||
|     }; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| from_attrs!(ModItem(ModItem), Variant(FileItemTreeId<Variant>)); |  | ||||||
| 
 |  | ||||||
| /// Trait implemented by all nodes in the item tree.
 | /// Trait implemented by all nodes in the item tree.
 | ||||||
| pub trait ItemTreeNode: Clone { | pub trait ItemTreeNode: Clone { | ||||||
|     type Source: AstIdNode; |     type Source: AstIdNode; | ||||||
|  | @ -381,7 +353,6 @@ pub trait ItemTreeNode: Clone { | ||||||
| 
 | 
 | ||||||
|     /// Looks up an instance of `Self` in an item tree.
 |     /// Looks up an instance of `Self` in an item tree.
 | ||||||
|     fn lookup(tree: &ItemTree, index: Idx<Self>) -> &Self; |     fn lookup(tree: &ItemTree, index: Idx<Self>) -> &Self; | ||||||
|     fn attr_owner(id: FileItemTreeId<Self>) -> AttrOwner; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub struct FileItemTreeId<N>(Idx<N>); | pub struct FileItemTreeId<N>(Idx<N>); | ||||||
|  | @ -446,6 +417,7 @@ impl TreeId { | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     #[inline] | ||||||
|     pub fn file_id(self) -> HirFileId { |     pub fn file_id(self) -> HirFileId { | ||||||
|         self.file |         self.file | ||||||
|     } |     } | ||||||
|  | @ -544,10 +516,6 @@ macro_rules! mod_items { | ||||||
|                 fn lookup(tree: &ItemTree, index: Idx<Self>) -> &Self { |                 fn lookup(tree: &ItemTree, index: Idx<Self>) -> &Self { | ||||||
|                     &tree.data().$fld[index] |                     &tree.data().$fld[index] | ||||||
|                 } |                 } | ||||||
| 
 |  | ||||||
|                 fn attr_owner(id: FileItemTreeId<Self>) -> AttrOwner { |  | ||||||
|                     AttrOwner::ModItem(ModItem::$typ(id)) |  | ||||||
|                 } |  | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             impl Index<Idx<$typ>> for ItemTree { |             impl Index<Idx<$typ>> for ItemTree { | ||||||
|  | @ -621,22 +589,6 @@ impl<N: ItemTreeNode> Index<FileItemTreeId<N>> for ItemTree { | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl ItemTreeNode for Variant { |  | ||||||
|     type Source = ast::Variant; |  | ||||||
| 
 |  | ||||||
|     fn ast_id(&self) -> FileAstId<Self::Source> { |  | ||||||
|         self.ast_id |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     fn lookup(tree: &ItemTree, index: Idx<Self>) -> &Self { |  | ||||||
|         &tree.data().variants[index] |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     fn attr_owner(id: FileItemTreeId<Self>) -> AttrOwner { |  | ||||||
|         AttrOwner::Variant(id) |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| #[derive(Debug, Clone, Eq, PartialEq)] | #[derive(Debug, Clone, Eq, PartialEq)] | ||||||
| pub struct Use { | pub struct Use { | ||||||
|     pub visibility: RawVisibilityId, |     pub visibility: RawVisibilityId, | ||||||
|  | @ -709,7 +661,6 @@ pub struct ExternCrate { | ||||||
| 
 | 
 | ||||||
| #[derive(Debug, Clone, Eq, PartialEq)] | #[derive(Debug, Clone, Eq, PartialEq)] | ||||||
| pub struct ExternBlock { | pub struct ExternBlock { | ||||||
|     pub abi: Option<Symbol>, |  | ||||||
|     pub ast_id: FileAstId<ast::ExternBlock>, |     pub ast_id: FileAstId<ast::ExternBlock>, | ||||||
|     pub children: Box<[ModItem]>, |     pub children: Box<[ModItem]>, | ||||||
| } | } | ||||||
|  | @ -725,7 +676,6 @@ pub struct Function { | ||||||
| pub struct Struct { | pub struct Struct { | ||||||
|     pub name: Name, |     pub name: Name, | ||||||
|     pub visibility: RawVisibilityId, |     pub visibility: RawVisibilityId, | ||||||
|     pub fields: Box<[Field]>, |  | ||||||
|     pub shape: FieldsShape, |     pub shape: FieldsShape, | ||||||
|     pub ast_id: FileAstId<ast::Struct>, |     pub ast_id: FileAstId<ast::Struct>, | ||||||
| } | } | ||||||
|  | @ -734,7 +684,6 @@ pub struct Struct { | ||||||
| pub struct Union { | pub struct Union { | ||||||
|     pub name: Name, |     pub name: Name, | ||||||
|     pub visibility: RawVisibilityId, |     pub visibility: RawVisibilityId, | ||||||
|     pub fields: Box<[Field]>, |  | ||||||
|     pub ast_id: FileAstId<ast::Union>, |     pub ast_id: FileAstId<ast::Union>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -742,18 +691,9 @@ pub struct Union { | ||||||
| pub struct Enum { | pub struct Enum { | ||||||
|     pub name: Name, |     pub name: Name, | ||||||
|     pub visibility: RawVisibilityId, |     pub visibility: RawVisibilityId, | ||||||
|     pub variants: Range<FileItemTreeId<Variant>>, |  | ||||||
|     pub ast_id: FileAstId<ast::Enum>, |     pub ast_id: FileAstId<ast::Enum>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[derive(Debug, Clone, PartialEq, Eq)] |  | ||||||
| pub struct Variant { |  | ||||||
|     pub name: Name, |  | ||||||
|     pub fields: Box<[Field]>, |  | ||||||
|     pub shape: FieldsShape, |  | ||||||
|     pub ast_id: FileAstId<ast::Variant>, |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| #[derive(Debug, Copy, Clone, PartialEq, Eq)] | #[derive(Debug, Copy, Clone, PartialEq, Eq)] | ||||||
| pub enum FieldsShape { | pub enum FieldsShape { | ||||||
|     Record, |     Record, | ||||||
|  | @ -785,16 +725,6 @@ impl VisibilityExplicitness { | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // FIXME: Remove this from item tree?
 |  | ||||||
| /// A single field of an enum variant or struct
 |  | ||||||
| #[derive(Debug, Clone, PartialEq, Eq)] |  | ||||||
| pub struct Field { |  | ||||||
|     pub name: Name, |  | ||||||
|     pub visibility: RawVisibilityId, |  | ||||||
|     // FIXME: Not an item tree property
 |  | ||||||
|     pub is_unsafe: bool, |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| #[derive(Debug, Clone, Eq, PartialEq)] | #[derive(Debug, Clone, Eq, PartialEq)] | ||||||
| pub struct Const { | pub struct Const { | ||||||
|     /// `None` for `const _: () = ();`
 |     /// `None` for `const _: () = ();`
 | ||||||
|  | @ -814,7 +744,6 @@ pub struct Static { | ||||||
| pub struct Trait { | pub struct Trait { | ||||||
|     pub name: Name, |     pub name: Name, | ||||||
|     pub visibility: RawVisibilityId, |     pub visibility: RawVisibilityId, | ||||||
|     pub items: Box<[AssocItem]>, |  | ||||||
|     pub ast_id: FileAstId<ast::Trait>, |     pub ast_id: FileAstId<ast::Trait>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -827,7 +756,6 @@ pub struct TraitAlias { | ||||||
| 
 | 
 | ||||||
| #[derive(Debug, Clone, Eq, PartialEq)] | #[derive(Debug, Clone, Eq, PartialEq)] | ||||||
| pub struct Impl { | pub struct Impl { | ||||||
|     pub items: Box<[AssocItem]>, |  | ||||||
|     pub ast_id: FileAstId<ast::Impl>, |     pub ast_id: FileAstId<ast::Impl>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -878,43 +806,6 @@ pub struct Macro2 { | ||||||
|     pub ast_id: FileAstId<ast::MacroDef>, |     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)] | #[derive(Clone, Copy, Debug, Eq, PartialEq)] | ||||||
| pub enum ImportKind { | pub enum ImportKind { | ||||||
|     /// The `ModPath` is imported normally.
 |     /// The `ModPath` is imported normally.
 | ||||||
|  | @ -1005,76 +896,3 @@ impl UseTree { | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 |  | ||||||
| macro_rules! impl_froms { |  | ||||||
|     ($e:ident { $($v:ident ($t:ty)),* $(,)? }) => { |  | ||||||
|         $( |  | ||||||
|             impl From<$t> for $e { |  | ||||||
|                 fn from(it: $t) -> $e { |  | ||||||
|                     $e::$v(it) |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         )* |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| impl ModItem { |  | ||||||
|     pub fn as_assoc_item(&self) -> Option<AssocItem> { |  | ||||||
|         match self { |  | ||||||
|             ModItem::Use(_) |  | ||||||
|             | ModItem::ExternCrate(_) |  | ||||||
|             | ModItem::ExternBlock(_) |  | ||||||
|             | ModItem::Struct(_) |  | ||||||
|             | ModItem::Union(_) |  | ||||||
|             | ModItem::Enum(_) |  | ||||||
|             | ModItem::Static(_) |  | ||||||
|             | ModItem::Trait(_) |  | ||||||
|             | ModItem::TraitAlias(_) |  | ||||||
|             | ModItem::Impl(_) |  | ||||||
|             | ModItem::Mod(_) |  | ||||||
|             | ModItem::MacroRules(_) |  | ||||||
|             | ModItem::Macro2(_) => None, |  | ||||||
|             &ModItem::MacroCall(call) => Some(AssocItem::MacroCall(call)), |  | ||||||
|             &ModItem::Const(konst) => Some(AssocItem::Const(konst)), |  | ||||||
|             &ModItem::TypeAlias(alias) => Some(AssocItem::TypeAlias(alias)), |  | ||||||
|             &ModItem::Function(func) => Some(AssocItem::Function(func)), |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| #[derive(Debug, Copy, Clone, Eq, PartialEq)] |  | ||||||
| pub enum AssocItem { |  | ||||||
|     Function(FileItemTreeId<Function>), |  | ||||||
|     TypeAlias(FileItemTreeId<TypeAlias>), |  | ||||||
|     Const(FileItemTreeId<Const>), |  | ||||||
|     MacroCall(FileItemTreeId<MacroCall>), |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| impl_froms!(AssocItem { |  | ||||||
|     Function(FileItemTreeId<Function>), |  | ||||||
|     TypeAlias(FileItemTreeId<TypeAlias>), |  | ||||||
|     Const(FileItemTreeId<Const>), |  | ||||||
|     MacroCall(FileItemTreeId<MacroCall>), |  | ||||||
| }); |  | ||||||
| 
 |  | ||||||
| impl From<AssocItem> for ModItem { |  | ||||||
|     fn from(item: AssocItem) -> Self { |  | ||||||
|         match item { |  | ||||||
|             AssocItem::Function(it) => it.into(), |  | ||||||
|             AssocItem::TypeAlias(it) => it.into(), |  | ||||||
|             AssocItem::Const(it) => it.into(), |  | ||||||
|             AssocItem::MacroCall(it) => it.into(), |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| impl AssocItem { |  | ||||||
|     pub fn ast_id(self, tree: &ItemTree) -> FileAstId<ast::AssocItem> { |  | ||||||
|         match self { |  | ||||||
|             AssocItem::Function(id) => tree[id].ast_id.upcast(), |  | ||||||
|             AssocItem::TypeAlias(id) => tree[id].ast_id.upcast(), |  | ||||||
|             AssocItem::Const(id) => tree[id].ast_id.upcast(), |  | ||||||
|             AssocItem::MacroCall(id) => tree[id].ast_id.upcast(), |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  | @ -8,23 +8,22 @@ use hir_expand::{ | ||||||
|     name::AsName, |     name::AsName, | ||||||
|     span_map::{SpanMap, SpanMapRef}, |     span_map::{SpanMap, SpanMapRef}, | ||||||
| }; | }; | ||||||
| use intern::{Symbol, sym}; |  | ||||||
| use la_arena::Arena; | use la_arena::Arena; | ||||||
| use span::{AstIdMap, SyntaxContext}; | use span::{AstIdMap, SyntaxContext}; | ||||||
| use syntax::{ | use syntax::{ | ||||||
|     AstNode, |     AstNode, | ||||||
|     ast::{self, HasModuleItem, HasName, IsString}, |     ast::{self, HasModuleItem, HasName}, | ||||||
| }; | }; | ||||||
| use triomphe::Arc; | use triomphe::Arc; | ||||||
| 
 | 
 | ||||||
| use crate::{ | use crate::{ | ||||||
|     db::DefDatabase, |     db::DefDatabase, | ||||||
|     item_tree::{ |     item_tree::{ | ||||||
|         AssocItem, AttrOwner, Const, Enum, ExternBlock, ExternCrate, Field, FieldParent, |         AttrOwner, Const, Enum, ExternBlock, ExternCrate, FieldsShape, FileItemTreeId, Function, | ||||||
|         FieldsShape, FileItemTreeId, Function, Idx, Impl, ImportAlias, Interned, ItemTree, |         Idx, Impl, ImportAlias, Interned, ItemTree, ItemTreeData, Macro2, MacroCall, MacroRules, | ||||||
|         ItemTreeData, Macro2, MacroCall, MacroRules, Mod, ModItem, ModKind, ModPath, Name, Range, |         Mod, ModItem, ModKind, ModPath, RawAttrs, RawVisibility, RawVisibilityId, Static, Struct, | ||||||
|         RawAttrs, RawIdx, RawVisibility, RawVisibilityId, Static, Struct, StructKind, Trait, |         StructKind, Trait, TraitAlias, TypeAlias, Union, Use, UseTree, UseTreeKind, | ||||||
|         TraitAlias, TypeAlias, Union, Use, UseTree, UseTreeKind, Variant, VisibilityExplicitness, |         VisibilityExplicitness, | ||||||
|     }, |     }, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | @ -163,118 +162,23 @@ impl<'a> Ctx<'a> { | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fn lower_assoc_item(&mut self, item_node: &ast::AssocItem) -> Option<AssocItem> { |  | ||||||
|         let item: AssocItem = match item_node { |  | ||||||
|             ast::AssocItem::Fn(ast) => self.lower_function(ast).map(Into::into), |  | ||||||
|             ast::AssocItem::TypeAlias(ast) => self.lower_type_alias(ast).map(Into::into), |  | ||||||
|             ast::AssocItem::Const(ast) => Some(self.lower_const(ast).into()), |  | ||||||
|             ast::AssocItem::MacroCall(ast) => self.lower_macro_call(ast).map(Into::into), |  | ||||||
|         }?; |  | ||||||
|         let attrs = RawAttrs::new(self.db, item_node, self.span_map()); |  | ||||||
|         self.add_attrs( |  | ||||||
|             match item { |  | ||||||
|                 AssocItem::Function(it) => AttrOwner::ModItem(ModItem::Function(it)), |  | ||||||
|                 AssocItem::TypeAlias(it) => AttrOwner::ModItem(ModItem::TypeAlias(it)), |  | ||||||
|                 AssocItem::Const(it) => AttrOwner::ModItem(ModItem::Const(it)), |  | ||||||
|                 AssocItem::MacroCall(it) => AttrOwner::ModItem(ModItem::MacroCall(it)), |  | ||||||
|             }, |  | ||||||
|             attrs, |  | ||||||
|         ); |  | ||||||
|         Some(item) |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     fn lower_struct(&mut self, strukt: &ast::Struct) -> Option<FileItemTreeId<Struct>> { |     fn lower_struct(&mut self, strukt: &ast::Struct) -> Option<FileItemTreeId<Struct>> { | ||||||
|         let visibility = self.lower_visibility(strukt); |         let visibility = self.lower_visibility(strukt); | ||||||
|         let name = strukt.name()?.as_name(); |         let name = strukt.name()?.as_name(); | ||||||
|         let ast_id = self.source_ast_id_map.ast_id(strukt); |         let ast_id = self.source_ast_id_map.ast_id(strukt); | ||||||
|         let (fields, kind, attrs) = self.lower_fields(&strukt.kind()); |         let shape = adt_shape(strukt.kind()); | ||||||
|         let res = Struct { name, visibility, fields, shape: kind, ast_id }; |         let res = Struct { name, visibility, shape, ast_id }; | ||||||
|         let id = id(self.data().structs.alloc(res)); |         let id = id(self.data().structs.alloc(res)); | ||||||
| 
 | 
 | ||||||
|         for (idx, attr) in attrs { |  | ||||||
|             self.add_attrs( |  | ||||||
|                 AttrOwner::Field( |  | ||||||
|                     FieldParent::Struct(id), |  | ||||||
|                     Idx::from_raw(RawIdx::from_u32(idx as u32)), |  | ||||||
|                 ), |  | ||||||
|                 attr, |  | ||||||
|             ); |  | ||||||
|         } |  | ||||||
|         Some(id) |         Some(id) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fn lower_fields( |  | ||||||
|         &mut self, |  | ||||||
|         strukt_kind: &ast::StructKind, |  | ||||||
|     ) -> (Box<[Field]>, FieldsShape, Vec<(usize, RawAttrs)>) { |  | ||||||
|         match strukt_kind { |  | ||||||
|             ast::StructKind::Record(it) => { |  | ||||||
|                 let mut fields = vec![]; |  | ||||||
|                 let mut attrs = vec![]; |  | ||||||
| 
 |  | ||||||
|                 for (i, field) in it.fields().enumerate() { |  | ||||||
|                     let data = self.lower_record_field(&field); |  | ||||||
|                     fields.push(data); |  | ||||||
|                     let attr = RawAttrs::new(self.db, &field, self.span_map()); |  | ||||||
|                     if !attr.is_empty() { |  | ||||||
|                         attrs.push((i, attr)) |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|                 (fields.into(), FieldsShape::Record, attrs) |  | ||||||
|             } |  | ||||||
|             ast::StructKind::Tuple(it) => { |  | ||||||
|                 let mut fields = vec![]; |  | ||||||
|                 let mut attrs = vec![]; |  | ||||||
| 
 |  | ||||||
|                 for (i, field) in it.fields().enumerate() { |  | ||||||
|                     let data = self.lower_tuple_field(i, &field); |  | ||||||
|                     fields.push(data); |  | ||||||
|                     let attr = RawAttrs::new(self.db, &field, self.span_map()); |  | ||||||
|                     if !attr.is_empty() { |  | ||||||
|                         attrs.push((i, attr)) |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|                 (fields.into(), FieldsShape::Tuple, attrs) |  | ||||||
|             } |  | ||||||
|             ast::StructKind::Unit => (Box::default(), FieldsShape::Unit, Vec::default()), |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     fn lower_record_field(&mut self, field: &ast::RecordField) -> Field { |  | ||||||
|         let name = match field.name() { |  | ||||||
|             Some(name) => name.as_name(), |  | ||||||
|             None => Name::missing(), |  | ||||||
|         }; |  | ||||||
|         let visibility = self.lower_visibility(field); |  | ||||||
| 
 |  | ||||||
|         Field { name, visibility, is_unsafe: field.unsafe_token().is_some() } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     fn lower_tuple_field(&mut self, idx: usize, field: &ast::TupleField) -> Field { |  | ||||||
|         let name = Name::new_tuple_field(idx); |  | ||||||
|         let visibility = self.lower_visibility(field); |  | ||||||
|         Field { name, visibility, is_unsafe: false } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     fn lower_union(&mut self, union: &ast::Union) -> Option<FileItemTreeId<Union>> { |     fn lower_union(&mut self, union: &ast::Union) -> Option<FileItemTreeId<Union>> { | ||||||
|         let visibility = self.lower_visibility(union); |         let visibility = self.lower_visibility(union); | ||||||
|         let name = union.name()?.as_name(); |         let name = union.name()?.as_name(); | ||||||
|         let ast_id = self.source_ast_id_map.ast_id(union); |         let ast_id = self.source_ast_id_map.ast_id(union); | ||||||
|         let (fields, _, attrs) = match union.record_field_list() { |         let res = Union { name, visibility, ast_id }; | ||||||
|             Some(record_field_list) => self.lower_fields(&StructKind::Record(record_field_list)), |  | ||||||
|             None => (Box::default(), FieldsShape::Record, Vec::default()), |  | ||||||
|         }; |  | ||||||
|         let res = Union { name, visibility, fields, ast_id }; |  | ||||||
|         let id = id(self.data().unions.alloc(res)); |         let id = id(self.data().unions.alloc(res)); | ||||||
|         for (idx, attr) in attrs { |  | ||||||
|             self.add_attrs( |  | ||||||
|                 AttrOwner::Field( |  | ||||||
|                     FieldParent::Union(id), |  | ||||||
|                     Idx::from_raw(RawIdx::from_u32(idx as u32)), |  | ||||||
|                 ), |  | ||||||
|                 attr, |  | ||||||
|             ); |  | ||||||
|         } |  | ||||||
|         Some(id) |         Some(id) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -282,48 +186,11 @@ impl<'a> Ctx<'a> { | ||||||
|         let visibility = self.lower_visibility(enum_); |         let visibility = self.lower_visibility(enum_); | ||||||
|         let name = enum_.name()?.as_name(); |         let name = enum_.name()?.as_name(); | ||||||
|         let ast_id = self.source_ast_id_map.ast_id(enum_); |         let ast_id = self.source_ast_id_map.ast_id(enum_); | ||||||
|         let variants = match &enum_.variant_list() { |         let res = Enum { name, visibility, ast_id }; | ||||||
|             Some(variant_list) => self.lower_variants(variant_list), |  | ||||||
|             None => { |  | ||||||
|                 FileItemTreeId(self.next_variant_idx())..FileItemTreeId(self.next_variant_idx()) |  | ||||||
|             } |  | ||||||
|         }; |  | ||||||
|         let res = Enum { name, visibility, variants, ast_id }; |  | ||||||
|         let id = id(self.data().enums.alloc(res)); |         let id = id(self.data().enums.alloc(res)); | ||||||
|         Some(id) |         Some(id) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fn lower_variants(&mut self, variants: &ast::VariantList) -> Range<FileItemTreeId<Variant>> { |  | ||||||
|         let start = self.next_variant_idx(); |  | ||||||
|         for variant in variants.variants() { |  | ||||||
|             let idx = self.lower_variant(&variant); |  | ||||||
|             self.add_attrs(id(idx).into(), RawAttrs::new(self.db, &variant, self.span_map())); |  | ||||||
|         } |  | ||||||
|         let end = self.next_variant_idx(); |  | ||||||
|         FileItemTreeId(start)..FileItemTreeId(end) |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     fn lower_variant(&mut self, variant: &ast::Variant) -> Idx<Variant> { |  | ||||||
|         let name = match variant.name() { |  | ||||||
|             Some(name) => name.as_name(), |  | ||||||
|             None => Name::missing(), |  | ||||||
|         }; |  | ||||||
|         let (fields, kind, attrs) = self.lower_fields(&variant.kind()); |  | ||||||
|         let ast_id = self.source_ast_id_map.ast_id(variant); |  | ||||||
|         let res = Variant { name, fields, shape: kind, ast_id }; |  | ||||||
|         let id = self.data().variants.alloc(res); |  | ||||||
|         for (idx, attr) in attrs { |  | ||||||
|             self.add_attrs( |  | ||||||
|                 AttrOwner::Field( |  | ||||||
|                     FieldParent::EnumVariant(FileItemTreeId(id)), |  | ||||||
|                     Idx::from_raw(RawIdx::from_u32(idx as u32)), |  | ||||||
|                 ), |  | ||||||
|                 attr, |  | ||||||
|             ); |  | ||||||
|         } |  | ||||||
|         id |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     fn lower_function(&mut self, func: &ast::Fn) -> Option<FileItemTreeId<Function>> { |     fn lower_function(&mut self, func: &ast::Fn) -> Option<FileItemTreeId<Function>> { | ||||||
|         let visibility = self.lower_visibility(func); |         let visibility = self.lower_visibility(func); | ||||||
|         let name = func.name()?.as_name(); |         let name = func.name()?.as_name(); | ||||||
|  | @ -390,14 +257,7 @@ impl<'a> Ctx<'a> { | ||||||
|         let visibility = self.lower_visibility(trait_def); |         let visibility = self.lower_visibility(trait_def); | ||||||
|         let ast_id = self.source_ast_id_map.ast_id(trait_def); |         let ast_id = self.source_ast_id_map.ast_id(trait_def); | ||||||
| 
 | 
 | ||||||
|         let items = trait_def |         let def = Trait { name, visibility, ast_id }; | ||||||
|             .assoc_item_list() |  | ||||||
|             .into_iter() |  | ||||||
|             .flat_map(|list| list.assoc_items()) |  | ||||||
|             .filter_map(|item_node| self.lower_assoc_item(&item_node)) |  | ||||||
|             .collect(); |  | ||||||
| 
 |  | ||||||
|         let def = Trait { name, visibility, items, ast_id }; |  | ||||||
|         let id = id(self.data().traits.alloc(def)); |         let id = id(self.data().traits.alloc(def)); | ||||||
|         Some(id) |         Some(id) | ||||||
|     } |     } | ||||||
|  | @ -417,16 +277,9 @@ impl<'a> Ctx<'a> { | ||||||
| 
 | 
 | ||||||
|     fn lower_impl(&mut self, impl_def: &ast::Impl) -> FileItemTreeId<Impl> { |     fn lower_impl(&mut self, impl_def: &ast::Impl) -> FileItemTreeId<Impl> { | ||||||
|         let ast_id = self.source_ast_id_map.ast_id(impl_def); |         let ast_id = self.source_ast_id_map.ast_id(impl_def); | ||||||
|         // We cannot use `assoc_items()` here as that does not include macro calls.
 |  | ||||||
|         let items = impl_def |  | ||||||
|             .assoc_item_list() |  | ||||||
|             .into_iter() |  | ||||||
|             .flat_map(|it| it.assoc_items()) |  | ||||||
|             .filter_map(|item| self.lower_assoc_item(&item)) |  | ||||||
|             .collect(); |  | ||||||
|         // Note that trait impls don't get implicit `Self` unlike traits, because here they are a
 |         // Note that trait impls don't get implicit `Self` unlike traits, because here they are a
 | ||||||
|         // type alias rather than a type parameter, so this is handled by the resolver.
 |         // type alias rather than a type parameter, so this is handled by the resolver.
 | ||||||
|         let res = Impl { items, ast_id }; |         let res = Impl { ast_id }; | ||||||
|         id(self.data().impls.alloc(res)) |         id(self.data().impls.alloc(res)) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -489,7 +342,6 @@ impl<'a> Ctx<'a> { | ||||||
| 
 | 
 | ||||||
|     fn lower_extern_block(&mut self, block: &ast::ExternBlock) -> FileItemTreeId<ExternBlock> { |     fn lower_extern_block(&mut self, block: &ast::ExternBlock) -> FileItemTreeId<ExternBlock> { | ||||||
|         let ast_id = self.source_ast_id_map.ast_id(block); |         let ast_id = self.source_ast_id_map.ast_id(block); | ||||||
|         let abi = block.abi().map(lower_abi); |  | ||||||
|         let children: Box<[_]> = block.extern_item_list().map_or(Box::new([]), |list| { |         let children: Box<[_]> = block.extern_item_list().map_or(Box::new([]), |list| { | ||||||
|             list.extern_items() |             list.extern_items() | ||||||
|                 .filter_map(|item| { |                 .filter_map(|item| { | ||||||
|  | @ -510,7 +362,7 @@ impl<'a> Ctx<'a> { | ||||||
|                 .collect() |                 .collect() | ||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
|         let res = ExternBlock { abi, ast_id, children }; |         let res = ExternBlock { ast_id, children }; | ||||||
|         id(self.data().extern_blocks.alloc(res)) |         id(self.data().extern_blocks.alloc(res)) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -520,20 +372,6 @@ impl<'a> Ctx<'a> { | ||||||
|         }); |         }); | ||||||
|         self.data().vis.alloc(vis) |         self.data().vis.alloc(vis) | ||||||
|     } |     } | ||||||
| 
 |  | ||||||
|     fn next_variant_idx(&self) -> Idx<Variant> { |  | ||||||
|         Idx::from_raw(RawIdx::from( |  | ||||||
|             self.tree.data.as_ref().map_or(0, |data| data.variants.len() as u32), |  | ||||||
|         )) |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| fn lower_abi(abi: ast::Abi) -> Symbol { |  | ||||||
|     match abi.abi_string() { |  | ||||||
|         Some(tok) => Symbol::intern(tok.text_without_quotes()), |  | ||||||
|         // `extern` default to be `extern "C"`.
 |  | ||||||
|         _ => sym::C, |  | ||||||
|     } |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| struct UseTreeLowering<'a> { | struct UseTreeLowering<'a> { | ||||||
|  | @ -626,7 +464,7 @@ fn private_vis() -> RawVisibility { | ||||||
|     ) |     ) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fn visibility_from_ast( | pub(crate) fn visibility_from_ast( | ||||||
|     db: &dyn DefDatabase, |     db: &dyn DefDatabase, | ||||||
|     node: Option<ast::Visibility>, |     node: Option<ast::Visibility>, | ||||||
|     span_for_range: &mut dyn FnMut(::tt::TextRange) -> SyntaxContext, |     span_for_range: &mut dyn FnMut(::tt::TextRange) -> SyntaxContext, | ||||||
|  | @ -647,3 +485,11 @@ fn visibility_from_ast( | ||||||
|     }; |     }; | ||||||
|     RawVisibility::Module(Interned::new(path), VisibilityExplicitness::Explicit) |     RawVisibility::Module(Interned::new(path), VisibilityExplicitness::Explicit) | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | fn adt_shape(kind: StructKind) -> FieldsShape { | ||||||
|  |     match kind { | ||||||
|  |         StructKind::Record(_) => FieldsShape::Record, | ||||||
|  |         StructKind::Tuple(_) => FieldsShape::Tuple, | ||||||
|  |         StructKind::Unit => FieldsShape::Unit, | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -2,15 +2,13 @@ | ||||||
| 
 | 
 | ||||||
| use std::fmt::{self, Write}; | use std::fmt::{self, Write}; | ||||||
| 
 | 
 | ||||||
| use la_arena::{Idx, RawIdx}; |  | ||||||
| use span::{Edition, ErasedFileAstId}; | use span::{Edition, ErasedFileAstId}; | ||||||
| 
 | 
 | ||||||
| use crate::{ | use crate::{ | ||||||
|     item_tree::{ |     item_tree::{ | ||||||
|         AttrOwner, Const, DefDatabase, Enum, ExternBlock, ExternCrate, Field, FieldParent, |         AttrOwner, Const, DefDatabase, Enum, ExternBlock, ExternCrate, FieldsShape, Function, Impl, | ||||||
|         FieldsShape, FileItemTreeId, Function, Impl, ItemTree, Macro2, MacroCall, MacroRules, Mod, |         ItemTree, Macro2, MacroCall, MacroRules, Mod, ModItem, ModKind, RawAttrs, RawVisibilityId, | ||||||
|         ModItem, ModKind, RawAttrs, RawVisibilityId, Static, Struct, Trait, TraitAlias, TypeAlias, |         Static, Struct, Trait, TraitAlias, TypeAlias, Union, Use, UseTree, UseTreeKind, | ||||||
|         Union, Use, UseTree, UseTreeKind, Variant, |  | ||||||
|     }, |     }, | ||||||
|     visibility::RawVisibility, |     visibility::RawVisibility, | ||||||
| }; | }; | ||||||
|  | @ -118,44 +116,14 @@ impl Printer<'_> { | ||||||
|         }; |         }; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fn print_fields(&mut self, parent: FieldParent, kind: FieldsShape, fields: &[Field]) { |     fn print_fields(&mut self, kind: FieldsShape) { | ||||||
|         let edition = self.edition; |  | ||||||
|         match kind { |         match kind { | ||||||
|             FieldsShape::Record => { |             FieldsShape::Record => { | ||||||
|                 self.whitespace(); |                 self.whitespace(); | ||||||
|                 w!(self, "{{"); |                 w!(self, "{{ ... }}"); | ||||||
|                 self.indented(|this| { |  | ||||||
|                     for (idx, Field { name, visibility, is_unsafe }) in fields.iter().enumerate() { |  | ||||||
|                         this.print_attrs_of( |  | ||||||
|                             AttrOwner::Field(parent, Idx::from_raw(RawIdx::from(idx as u32))), |  | ||||||
|                             "\n", |  | ||||||
|                         ); |  | ||||||
|                         this.print_visibility(*visibility); |  | ||||||
|                         if *is_unsafe { |  | ||||||
|                             w!(this, "unsafe "); |  | ||||||
|                         } |  | ||||||
| 
 |  | ||||||
|                         wln!(this, "{},", name.display(self.db, edition)); |  | ||||||
|                     } |  | ||||||
|                 }); |  | ||||||
|                 w!(self, "}}"); |  | ||||||
|             } |             } | ||||||
|             FieldsShape::Tuple => { |             FieldsShape::Tuple => { | ||||||
|                 w!(self, "("); |                 w!(self, "(...)"); | ||||||
|                 self.indented(|this| { |  | ||||||
|                     for (idx, Field { name, visibility, is_unsafe }) in fields.iter().enumerate() { |  | ||||||
|                         this.print_attrs_of( |  | ||||||
|                             AttrOwner::Field(parent, Idx::from_raw(RawIdx::from(idx as u32))), |  | ||||||
|                             "\n", |  | ||||||
|                         ); |  | ||||||
|                         this.print_visibility(*visibility); |  | ||||||
|                         if *is_unsafe { |  | ||||||
|                             w!(this, "unsafe "); |  | ||||||
|                         } |  | ||||||
|                         wln!(this, "{},", name.display(self.db, edition)); |  | ||||||
|                     } |  | ||||||
|                 }); |  | ||||||
|                 w!(self, ")"); |  | ||||||
|             } |             } | ||||||
|             FieldsShape::Unit => {} |             FieldsShape::Unit => {} | ||||||
|         } |         } | ||||||
|  | @ -214,13 +182,9 @@ impl Printer<'_> { | ||||||
|                 wln!(self, ";"); |                 wln!(self, ";"); | ||||||
|             } |             } | ||||||
|             ModItem::ExternBlock(it) => { |             ModItem::ExternBlock(it) => { | ||||||
|                 let ExternBlock { abi, ast_id, children } = &self.tree[it]; |                 let ExternBlock { ast_id, children } = &self.tree[it]; | ||||||
|                 self.print_ast_id(ast_id.erase()); |                 self.print_ast_id(ast_id.erase()); | ||||||
|                 w!(self, "extern "); |                 w!(self, "extern {{"); | ||||||
|                 if let Some(abi) = abi { |  | ||||||
|                     w!(self, "\"{}\" ", abi); |  | ||||||
|                 } |  | ||||||
|                 w!(self, "{{"); |  | ||||||
|                 self.indented(|this| { |                 self.indented(|this| { | ||||||
|                     for child in &**children { |                     for child in &**children { | ||||||
|                         this.print_mod_item(*child); |                         this.print_mod_item(*child); | ||||||
|  | @ -235,11 +199,11 @@ impl Printer<'_> { | ||||||
|                 wln!(self, "fn {};", name.display(self.db, self.edition)); |                 wln!(self, "fn {};", name.display(self.db, self.edition)); | ||||||
|             } |             } | ||||||
|             ModItem::Struct(it) => { |             ModItem::Struct(it) => { | ||||||
|                 let Struct { visibility, name, fields, shape: kind, ast_id } = &self.tree[it]; |                 let Struct { visibility, name, shape: kind, ast_id } = &self.tree[it]; | ||||||
|                 self.print_ast_id(ast_id.erase()); |                 self.print_ast_id(ast_id.erase()); | ||||||
|                 self.print_visibility(*visibility); |                 self.print_visibility(*visibility); | ||||||
|                 w!(self, "struct {}", name.display(self.db, self.edition)); |                 w!(self, "struct {}", name.display(self.db, self.edition)); | ||||||
|                 self.print_fields(FieldParent::Struct(it), *kind, fields); |                 self.print_fields(*kind); | ||||||
|                 if matches!(kind, FieldsShape::Record) { |                 if matches!(kind, FieldsShape::Record) { | ||||||
|                     wln!(self); |                     wln!(self); | ||||||
|                 } else { |                 } else { | ||||||
|  | @ -247,30 +211,18 @@ impl Printer<'_> { | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             ModItem::Union(it) => { |             ModItem::Union(it) => { | ||||||
|                 let Union { name, visibility, fields, ast_id } = &self.tree[it]; |                 let Union { name, visibility, ast_id } = &self.tree[it]; | ||||||
|                 self.print_ast_id(ast_id.erase()); |                 self.print_ast_id(ast_id.erase()); | ||||||
|                 self.print_visibility(*visibility); |                 self.print_visibility(*visibility); | ||||||
|                 w!(self, "union {}", name.display(self.db, self.edition)); |                 w!(self, "union {}", name.display(self.db, self.edition)); | ||||||
|                 self.print_fields(FieldParent::Union(it), FieldsShape::Record, fields); |                 self.print_fields(FieldsShape::Record); | ||||||
|                 wln!(self); |                 wln!(self); | ||||||
|             } |             } | ||||||
|             ModItem::Enum(it) => { |             ModItem::Enum(it) => { | ||||||
|                 let Enum { name, visibility, variants, ast_id } = &self.tree[it]; |                 let Enum { name, visibility, ast_id } = &self.tree[it]; | ||||||
|                 self.print_ast_id(ast_id.erase()); |                 self.print_ast_id(ast_id.erase()); | ||||||
|                 self.print_visibility(*visibility); |                 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()) { |  | ||||||
|                         let Variant { name, fields, shape: kind, ast_id } = &this.tree[variant]; |  | ||||||
|                         this.print_ast_id(ast_id.erase()); |  | ||||||
|                         this.print_attrs_of(variant, "\n"); |  | ||||||
|                         w!(this, "{}", name.display(self.db, edition)); |  | ||||||
|                         this.print_fields(FieldParent::EnumVariant(variant), *kind, fields); |  | ||||||
|                         wln!(this, ","); |  | ||||||
|                     } |  | ||||||
|                 }); |  | ||||||
|                 wln!(self, "}}"); |  | ||||||
|             } |             } | ||||||
|             ModItem::Const(it) => { |             ModItem::Const(it) => { | ||||||
|                 let Const { name, visibility, ast_id } = &self.tree[it]; |                 let Const { name, visibility, ast_id } = &self.tree[it]; | ||||||
|  | @ -293,16 +245,10 @@ impl Printer<'_> { | ||||||
|                 wln!(self); |                 wln!(self); | ||||||
|             } |             } | ||||||
|             ModItem::Trait(it) => { |             ModItem::Trait(it) => { | ||||||
|                 let Trait { name, visibility, items, ast_id } = &self.tree[it]; |                 let Trait { name, visibility, ast_id } = &self.tree[it]; | ||||||
|                 self.print_ast_id(ast_id.erase()); |                 self.print_ast_id(ast_id.erase()); | ||||||
|                 self.print_visibility(*visibility); |                 self.print_visibility(*visibility); | ||||||
|                 w!(self, "trait {} {{", name.display(self.db, self.edition)); |                 w!(self, "trait {} {{ ... }}", name.display(self.db, self.edition)); | ||||||
|                 self.indented(|this| { |  | ||||||
|                     for item in &**items { |  | ||||||
|                         this.print_mod_item((*item).into()); |  | ||||||
|                     } |  | ||||||
|                 }); |  | ||||||
|                 wln!(self, "}}"); |  | ||||||
|             } |             } | ||||||
|             ModItem::TraitAlias(it) => { |             ModItem::TraitAlias(it) => { | ||||||
|                 let TraitAlias { name, visibility, ast_id } = &self.tree[it]; |                 let TraitAlias { name, visibility, ast_id } = &self.tree[it]; | ||||||
|  | @ -311,15 +257,9 @@ impl Printer<'_> { | ||||||
|                 wln!(self, "trait {} = ..;", name.display(self.db, self.edition)); |                 wln!(self, "trait {} = ..;", name.display(self.db, self.edition)); | ||||||
|             } |             } | ||||||
|             ModItem::Impl(it) => { |             ModItem::Impl(it) => { | ||||||
|                 let Impl { items, ast_id } = &self.tree[it]; |                 let Impl { ast_id } = &self.tree[it]; | ||||||
|                 self.print_ast_id(ast_id.erase()); |                 self.print_ast_id(ast_id.erase()); | ||||||
|                 w!(self, "impl {{"); |                 w!(self, "impl {{ ... }}"); | ||||||
|                 self.indented(|this| { |  | ||||||
|                     for item in &**items { |  | ||||||
|                         this.print_mod_item((*item).into()); |  | ||||||
|                     } |  | ||||||
|                 }); |  | ||||||
|                 wln!(self, "}}"); |  | ||||||
|             } |             } | ||||||
|             ModItem::TypeAlias(it) => { |             ModItem::TypeAlias(it) => { | ||||||
|                 let TypeAlias { name, visibility, ast_id } = &self.tree[it]; |                 let TypeAlias { name, visibility, ast_id } = &self.tree[it]; | ||||||
|  | @ -353,8 +293,8 @@ impl Printer<'_> { | ||||||
|                 let MacroCall { path, ast_id, expand_to, ctxt } = &self.tree[it]; |                 let MacroCall { path, ast_id, expand_to, ctxt } = &self.tree[it]; | ||||||
|                 let _ = writeln!( |                 let _ = writeln!( | ||||||
|                     self, |                     self, | ||||||
|                     "// AstId: {:?}, SyntaxContextId: {}, ExpandTo: {:?}", |                     "// AstId: {:#?}, SyntaxContextId: {}, ExpandTo: {:?}", | ||||||
|                     ast_id.erase().into_raw(), |                     ast_id.erase(), | ||||||
|                     ctxt, |                     ctxt, | ||||||
|                     expand_to |                     expand_to | ||||||
|                 ); |                 ); | ||||||
|  | @ -377,7 +317,7 @@ impl Printer<'_> { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fn print_ast_id(&mut self, ast_id: ErasedFileAstId) { |     fn print_ast_id(&mut self, ast_id: ErasedFileAstId) { | ||||||
|         wln!(self, "// AstId: {:?}", ast_id.into_raw()); |         wln!(self, "// AstId: {ast_id:#?}"); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -35,23 +35,23 @@ use a::{c, d::{e}}; | ||||||
|             #![no_std] |             #![no_std] | ||||||
|             #![doc = " another file comment"] |             #![doc = " another file comment"] | ||||||
| 
 | 
 | ||||||
|             // AstId: 1
 |             // AstId: ExternCrate[5A82, 0]
 | ||||||
|             pub(self) extern crate self as renamed; |             pub(self) extern crate self as renamed; | ||||||
| 
 | 
 | ||||||
|             // AstId: 2
 |             // AstId: ExternCrate[7E1C, 0]
 | ||||||
|             pub(super) extern crate bli; |             pub(super) extern crate bli; | ||||||
| 
 | 
 | ||||||
|             // AstId: 3
 |             // AstId: Use[0000, 0]
 | ||||||
|             pub use crate::path::{nested, items as renamed, Trait as _}; |             pub use crate::path::{nested, items as renamed, Trait as _}; | ||||||
| 
 | 
 | ||||||
|             // AstId: 4
 |             // AstId: Use[0000, 1]
 | ||||||
|             pub(self) use globs::*; |             pub(self) use globs::*; | ||||||
| 
 | 
 | ||||||
|             #[doc = " docs on import"] |             #[doc = " docs on import"] | ||||||
|             // AstId: 5
 |             // AstId: Use[0000, 2]
 | ||||||
|             pub(self) use crate::{A, B}; |             pub(self) use crate::{A, B}; | ||||||
| 
 | 
 | ||||||
|             // AstId: 6
 |             // AstId: Use[0000, 3]
 | ||||||
|             pub(self) use a::{c, d::{e}}; |             pub(self) use a::{c, d::{e}}; | ||||||
|         "##]],
 |         "##]],
 | ||||||
|     ); |     ); | ||||||
|  | @ -73,23 +73,23 @@ extern "C" { | ||||||
|     fn ex_fn(); |     fn ex_fn(); | ||||||
| } | } | ||||||
|         "#,
 |         "#,
 | ||||||
|         expect![[r##" |         expect![[r#" | ||||||
|             #[on_extern_block] |             #[on_extern_block] | ||||||
|             // AstId: 1
 |             // AstId: ExternBlock[0000, 0]
 | ||||||
|             extern "C" { |             extern { | ||||||
|                 #[on_extern_type] |                 #[on_extern_type] | ||||||
|                 // AstId: 2
 |                 // AstId: TypeAlias[9FDF, 0]
 | ||||||
|                 pub(self) type ExType; |                 pub(self) type ExType; | ||||||
| 
 | 
 | ||||||
|                 #[on_extern_static] |                 #[on_extern_static] | ||||||
|                 // AstId: 3
 |                 // AstId: Static[43C1, 0]
 | ||||||
|                 pub(self) static EX_STATIC = _; |                 pub(self) static EX_STATIC = _; | ||||||
| 
 | 
 | ||||||
|                 #[on_extern_fn] |                 #[on_extern_fn] | ||||||
|                 // AstId: 4
 |                 // AstId: Fn[452D, 0]
 | ||||||
|                 pub(self) fn ex_fn; |                 pub(self) fn ex_fn; | ||||||
|             } |             } | ||||||
|         "##]],
 |         "#]],
 | ||||||
|     ); |     ); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -124,44 +124,21 @@ enum E { | ||||||
| } | } | ||||||
|         "#,
 |         "#,
 | ||||||
|         expect![[r#" |         expect![[r#" | ||||||
|             // AstId: 1
 |             // AstId: Struct[DFF3, 0]
 | ||||||
|             pub(self) struct Unit; |             pub(self) struct Unit; | ||||||
| 
 | 
 | ||||||
|             #[derive(Debug)] |             #[derive(Debug)] | ||||||
|             // AstId: 2
 |             // AstId: Struct[C7A1, 0]
 | ||||||
|             pub(self) struct Struct { |             pub(self) struct Struct { ... } | ||||||
|                 #[doc = " fld docs"] |  | ||||||
|                 pub(self) fld, |  | ||||||
|             } |  | ||||||
| 
 | 
 | ||||||
|             // AstId: 3
 |             // AstId: Struct[DAC2, 0]
 | ||||||
|             pub(self) struct Tuple( |             pub(self) struct Tuple(...); | ||||||
|                 #[attr] |  | ||||||
|                 pub(self) 0, |  | ||||||
|             ); |  | ||||||
| 
 | 
 | ||||||
|             // AstId: 4
 |             // AstId: Union[2DBB, 0]
 | ||||||
|             pub(self) union Ize { |             pub(self) union Ize { ... } | ||||||
|                 pub(self) a, |  | ||||||
|                 pub(self) b, |  | ||||||
|             } |  | ||||||
| 
 | 
 | ||||||
|             // AstId: 5
 |             // AstId: Enum[7FF8, 0]
 | ||||||
|             pub(self) enum E |             pub(self) enum E { ... } | ||||||
|                 // AstId: 6
 |  | ||||||
|                 #[doc = " comment on Unit"] |  | ||||||
|                 Unit, |  | ||||||
|                 // AstId: 7
 |  | ||||||
|                 #[doc = " comment on Tuple"] |  | ||||||
|                 Tuple( |  | ||||||
|                     pub(self) 0, |  | ||||||
|                 ), |  | ||||||
|                 // AstId: 8
 |  | ||||||
|                 Struct { |  | ||||||
|                     #[doc = " comment on a: u8"] |  | ||||||
|                     pub(self) a, |  | ||||||
|                 }, |  | ||||||
|             } |  | ||||||
|         "#]],
 |         "#]],
 | ||||||
|     ); |     ); | ||||||
| } | } | ||||||
|  | @ -185,25 +162,19 @@ trait Tr: SuperTrait + 'lifetime { | ||||||
| } | } | ||||||
|         "#,
 |         "#,
 | ||||||
|         expect![[r#" |         expect![[r#" | ||||||
|             // AstId: 1
 |             // AstId: Static[B393, 0]
 | ||||||
|             pub static ST = _; |             pub static ST = _; | ||||||
| 
 | 
 | ||||||
|             // AstId: 2
 |             // AstId: Const[B309, 0]
 | ||||||
|             pub(self) const _ = _; |             pub(self) const _ = _; | ||||||
| 
 | 
 | ||||||
|             #[attr] |             #[attr] | ||||||
|             #[inner_attr_in_fn] |             #[inner_attr_in_fn] | ||||||
|             // AstId: 3
 |             // AstId: Fn[75E3, 0]
 | ||||||
|             pub(self) fn f; |             pub(self) fn f; | ||||||
| 
 | 
 | ||||||
|             // AstId: 4
 |             // AstId: Trait[2998, 0]
 | ||||||
|             pub(self) trait Tr { |             pub(self) trait Tr { ... } | ||||||
|                 // AstId: 6
 |  | ||||||
|                 pub(self) type Assoc; |  | ||||||
| 
 |  | ||||||
|                 // AstId: 7
 |  | ||||||
|                 pub(self) fn method; |  | ||||||
|             } |  | ||||||
|         "#]],
 |         "#]],
 | ||||||
|     ); |     ); | ||||||
| } | } | ||||||
|  | @ -226,16 +197,16 @@ mod outline; | ||||||
|         expect![[r##" |         expect![[r##" | ||||||
|             #[doc = " outer"] |             #[doc = " outer"] | ||||||
|             #[doc = " inner"] |             #[doc = " inner"] | ||||||
|             // AstId: 1
 |             // AstId: Module[CF93, 0]
 | ||||||
|             pub(self) mod inline { |             pub(self) mod inline { | ||||||
|                 // AstId: 3
 |                 // AstId: Use[0000, 0]
 | ||||||
|                 pub(self) use super::*; |                 pub(self) use super::*; | ||||||
| 
 | 
 | ||||||
|                 // AstId: 4
 |                 // AstId: Fn[1B26, 0]
 | ||||||
|                 pub(self) fn fn_in_module; |                 pub(self) fn fn_in_module; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             // AstId: 2
 |             // AstId: Module[8994, 0]
 | ||||||
|             pub(self) mod outline; |             pub(self) mod outline; | ||||||
|         "##]],
 |         "##]],
 | ||||||
|     ); |     ); | ||||||
|  | @ -254,13 +225,13 @@ pub macro m2() {} | ||||||
| m!(); | m!(); | ||||||
|         "#,
 |         "#,
 | ||||||
|         expect![[r#" |         expect![[r#" | ||||||
|             // AstId: 1
 |             // AstId: MacroRules[88CE, 0]
 | ||||||
|             macro_rules! m { ... } |             macro_rules! m { ... } | ||||||
| 
 | 
 | ||||||
|             // AstId: 2
 |             // AstId: MacroDef[DC34, 0]
 | ||||||
|             pub macro m2 { ... } |             pub macro m2 { ... } | ||||||
| 
 | 
 | ||||||
|             // AstId: 3, SyntaxContextId: ROOT2024, ExpandTo: Items
 |             // AstId: MacroCall[612F, 0], SyntaxContextId: ROOT2024, ExpandTo: Items
 | ||||||
|             m!(...); |             m!(...); | ||||||
|         "#]],
 |         "#]],
 | ||||||
|     ); |     ); | ||||||
|  | @ -273,7 +244,7 @@ fn pub_self() { | ||||||
| pub(self) struct S; | pub(self) struct S; | ||||||
|         "#,
 |         "#,
 | ||||||
|         expect![[r#" |         expect![[r#" | ||||||
|             // AstId: 1
 |             // AstId: Struct[42E2, 0]
 | ||||||
|             pub(self) struct S; |             pub(self) struct S; | ||||||
|         "#]],
 |         "#]],
 | ||||||
|     ) |     ) | ||||||
|  |  | ||||||
|  | @ -125,7 +125,7 @@ pub fn crate_lang_items(db: &dyn DefDatabase, krate: Crate) -> Option<Box<LangIt | ||||||
|                 } |                 } | ||||||
|                 ModuleDefId::AdtId(AdtId::EnumId(e)) => { |                 ModuleDefId::AdtId(AdtId::EnumId(e)) => { | ||||||
|                     lang_items.collect_lang_item(db, e, LangItemTarget::EnumId); |                     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); |                         lang_items.collect_lang_item(db, id, LangItemTarget::EnumVariant); | ||||||
|                     }); |                     }); | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|  | @ -74,12 +74,11 @@ use hir_expand::{ | ||||||
|     name::Name, |     name::Name, | ||||||
|     proc_macro::{CustomProcMacroExpander, ProcMacroKind}, |     proc_macro::{CustomProcMacroExpander, ProcMacroKind}, | ||||||
| }; | }; | ||||||
| use item_tree::ExternBlock; |  | ||||||
| use la_arena::Idx; | use la_arena::Idx; | ||||||
| use nameres::DefMap; | use nameres::DefMap; | ||||||
| use span::{AstIdNode, Edition, FileAstId, SyntaxContext}; | use span::{AstIdNode, Edition, FileAstId, SyntaxContext}; | ||||||
| use stdx::impl_from; | use stdx::impl_from; | ||||||
| use syntax::ast; | use syntax::{AstNode, ast}; | ||||||
| 
 | 
 | ||||||
| pub use hir_expand::{Intern, Lookup, tt}; | pub use hir_expand::{Intern, Lookup, tt}; | ||||||
| 
 | 
 | ||||||
|  | @ -88,10 +87,6 @@ use crate::{ | ||||||
|     builtin_type::BuiltinType, |     builtin_type::BuiltinType, | ||||||
|     db::DefDatabase, |     db::DefDatabase, | ||||||
|     hir::generics::{LocalLifetimeParamId, LocalTypeOrConstParamId}, |     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}, |     nameres::{LocalDefMap, block_def_map, crate_def_map, crate_local_def_map}, | ||||||
|     signatures::VariantFields, |     signatures::VariantFields, | ||||||
| }; | }; | ||||||
|  | @ -113,70 +108,110 @@ pub struct ImportPathConfig { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[derive(Debug)] | #[derive(Debug)] | ||||||
| pub struct ItemLoc<N: ItemTreeNode> { | pub struct ItemLoc<N: AstIdNode> { | ||||||
|     pub container: ModuleId, |     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 { |     fn clone(&self) -> 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 { |     fn eq(&self, other: &Self) -> bool { | ||||||
|         self.container == other.container && self.id == other.id |         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) { |     fn hash<H: Hasher>(&self, state: &mut H) { | ||||||
|         self.container.hash(state); |         self.container.hash(state); | ||||||
|         self.id.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)] | #[derive(Debug)] | ||||||
| pub struct AssocItemLoc<N: ItemTreeNode> { | pub struct AssocItemLoc<N: AstIdNode> { | ||||||
|     pub container: ItemContainerId, |     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 { |     fn clone(&self) -> 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 { |     fn eq(&self, other: &Self) -> bool { | ||||||
|         self.container == other.container && self.id == other.id |         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) { |     fn hash<H: Hasher>(&self, state: &mut H) { | ||||||
|         self.container.hash(state); |         self.container.hash(state); | ||||||
|         self.id.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 Container; | ||||||
|     type Id; |     type Ast: AstNode; | ||||||
|     fn item_tree_id(&self) -> ItemTreeId<Self::Id>; |     fn ast_id(&self) -> AstId<Self::Ast>; | ||||||
|     fn container(&self) -> Self::Container; |     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 { | macro_rules! impl_intern { | ||||||
|     ($id:ident, $loc:ident, $intern:ident, $lookup:ident) => { |     ($id:ident, $loc:ident, $intern:ident, $lookup:ident) => { | ||||||
|         impl_intern_key!($id, $loc); |         impl_intern_key!($id, $loc); | ||||||
|  | @ -186,74 +221,68 @@ macro_rules! impl_intern { | ||||||
| 
 | 
 | ||||||
| macro_rules! impl_loc { | macro_rules! impl_loc { | ||||||
|     ($loc:ident, $id:ident: $id_ty:ident, $container:ident: $container_type:ident) => { |     ($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 Container = $container_type; | ||||||
|             type Id = $id_ty; |             type Ast = ast::$id_ty; | ||||||
|             fn item_tree_id(&self) -> ItemTreeId<Self::Id> { |             fn ast_id(&self) -> AstId<Self::Ast> { | ||||||
|                 self.$id |                 self.$id | ||||||
|             } |             } | ||||||
|             fn container(&self) -> Self::Container { |             fn container(&self) -> Self::Container { | ||||||
|                 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_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_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_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_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_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_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_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_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_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_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_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_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_intern!(ExternBlockId, ExternBlockLoc, intern_extern_block, lookup_intern_extern_block); | ||||||
| impl_loc!(ExternBlockLoc, id: ExternBlock, container: ModuleId); |  | ||||||
| 
 | 
 | ||||||
| #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||||||
| pub struct EnumVariantLoc { | pub struct EnumVariantLoc { | ||||||
|     pub id: ItemTreeId<Variant>, |     pub id: AstId<ast::Variant>, | ||||||
|     pub parent: EnumId, |     pub parent: EnumId, | ||||||
|     pub index: u32, |     pub index: u32, | ||||||
| } | } | ||||||
|  | @ -262,18 +291,18 @@ impl_loc!(EnumVariantLoc, id: Variant, parent: EnumId); | ||||||
| #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||||||
| pub struct Macro2Loc { | pub struct Macro2Loc { | ||||||
|     pub container: ModuleId, |     pub container: ModuleId, | ||||||
|     pub id: ItemTreeId<Macro2>, |     pub id: AstId<ast::MacroDef>, | ||||||
|     pub expander: MacroExpander, |     pub expander: MacroExpander, | ||||||
|     pub allow_internal_unsafe: bool, |     pub allow_internal_unsafe: bool, | ||||||
|     pub edition: Edition, |     pub edition: Edition, | ||||||
| } | } | ||||||
| impl_intern!(Macro2Id, Macro2Loc, intern_macro2, lookup_intern_macro2); | 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)] | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||||||
| pub struct MacroRulesLoc { | pub struct MacroRulesLoc { | ||||||
|     pub container: ModuleId, |     pub container: ModuleId, | ||||||
|     pub id: ItemTreeId<MacroRules>, |     pub id: AstId<ast::MacroRules>, | ||||||
|     pub expander: MacroExpander, |     pub expander: MacroExpander, | ||||||
|     pub flags: MacroRulesLocFlags, |     pub flags: MacroRulesLocFlags, | ||||||
|     pub edition: Edition, |     pub edition: Edition, | ||||||
|  | @ -301,13 +330,13 @@ pub enum MacroExpander { | ||||||
| #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||||||
| pub struct ProcMacroLoc { | pub struct ProcMacroLoc { | ||||||
|     pub container: CrateRootModuleId, |     pub container: CrateRootModuleId, | ||||||
|     pub id: ItemTreeId<Function>, |     pub id: AstId<ast::Fn>, | ||||||
|     pub expander: CustomProcMacroExpander, |     pub expander: CustomProcMacroExpander, | ||||||
|     pub kind: ProcMacroKind, |     pub kind: ProcMacroKind, | ||||||
|     pub edition: Edition, |     pub edition: Edition, | ||||||
| } | } | ||||||
| impl_intern!(ProcMacroId, ProcMacroLoc, intern_proc_macro, lookup_intern_proc_macro); | 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)] | #[derive(Debug, Hash, PartialEq, Eq, Clone)] | ||||||
| pub struct BlockLoc { | 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 { | impl PartialEq<ModuleId> for CrateRootModuleId { | ||||||
|     fn eq(&self, other: &ModuleId) -> bool { |     fn eq(&self, other: &ModuleId) -> bool { | ||||||
|         other.block.is_none() && other.local_id == DefMap::ROOT && self.krate == other.krate |         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`.
 | /// An ID of a module, **local** to a `DefMap`.
 | ||||||
| pub type LocalModuleId = Idx<nameres::ModuleData>; | pub type LocalModuleId = Idx<nameres::ModuleData>; | ||||||
| 
 | 
 | ||||||
|  | @ -642,15 +690,10 @@ impl GeneralConstId { | ||||||
|     pub fn name(self, db: &dyn DefDatabase) -> String { |     pub fn name(self, db: &dyn DefDatabase) -> String { | ||||||
|         match self { |         match self { | ||||||
|             GeneralConstId::StaticId(it) => { |             GeneralConstId::StaticId(it) => { | ||||||
|                 let loc = it.lookup(db); |                 db.static_signature(it).name.display(db, Edition::CURRENT).to_string() | ||||||
|                 let tree = loc.item_tree_id().item_tree(db); |  | ||||||
|                 let name = tree[loc.id.value].name.display(db, Edition::CURRENT); |  | ||||||
|                 name.to_string() |  | ||||||
|             } |             } | ||||||
|             GeneralConstId::ConstId(const_id) => { |             GeneralConstId::ConstId(const_id) => { | ||||||
|                 let loc = const_id.lookup(db); |                 db.const_signature(const_id).name.as_ref().map_or_else( | ||||||
|                 let tree = loc.item_tree_id().item_tree(db); |  | ||||||
|                 tree[loc.id.value].name.as_ref().map_or_else( |  | ||||||
|                     || "_".to_owned(), |                     || "_".to_owned(), | ||||||
|                     |name| name.display(db, Edition::CURRENT).to_string(), |                     |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::TraitId(it) => file_id_and_params_of_item_loc(db, it), | ||||||
|             GenericDefId::TraitAliasId(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::ImplId(it) => file_id_and_params_of_item_loc(db, it), | ||||||
|             GenericDefId::ConstId(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), |             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 { |     pub fn file_id(self, db: &dyn DefDatabase) -> HirFileId { | ||||||
|         match self { |         match self { | ||||||
|             VariantId::EnumVariantId(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::StructId(it) => it.lookup(db).id.file_id, | ||||||
|             VariantId::UnionId(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 | impl<N, ItemId> HasModule for ItemId | ||||||
| where | where | ||||||
|     N: ItemTreeNode, |     N: AstIdNode, | ||||||
|     ItemId: Lookup<Database = dyn DefDatabase, Data = ItemLoc<N>> + Copy, |     ItemId: Lookup<Database = dyn DefDatabase, Data = ItemLoc<N>> + Copy, | ||||||
| { | { | ||||||
|     #[inline] |     #[inline] | ||||||
|  | @ -1003,7 +1046,7 @@ where | ||||||
| #[inline] | #[inline] | ||||||
| fn module_for_assoc_item_loc<'db>( | fn module_for_assoc_item_loc<'db>( | ||||||
|     db: &(dyn 'db + DefDatabase), |     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 { | ) -> ModuleId { | ||||||
|     id.lookup(db).container.module(db) |     id.lookup(db).container.module(db) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -35,9 +35,9 @@ macro_rules! f { | ||||||
|     }; |     }; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| struct#0:1@58..64#14336# MyTraitMap2#0:2@31..42#ROOT2024# {#0:1@72..73#14336# | struct#0:MacroRules[8C8E, 0]@58..64#14336# MyTraitMap2#0:MacroCall[D499, 0]@31..42#ROOT2024# {#0:MacroRules[8C8E, 0]@72..73#14336# | ||||||
|     map#0:1@86..89#14336#:#0:1@89..90#14336# #0:1@89..90#14336#::#0:1@91..93#14336#std#0:1@93..96#14336#::#0:1@96..98#14336#collections#0:1@98..109#14336#::#0:1@109..111#14336#HashSet#0:1@111..118#14336#<#0:1@118..119#14336#(#0:1@119..120#14336#)#0:1@120..121#14336#>#0:1@121..122#14336#,#0:1@122..123#14336# |     map#0:MacroRules[8C8E, 0]@86..89#14336#:#0:MacroRules[8C8E, 0]@89..90#14336# #0:MacroRules[8C8E, 0]@89..90#14336#::#0:MacroRules[8C8E, 0]@91..93#14336#std#0:MacroRules[8C8E, 0]@93..96#14336#::#0:MacroRules[8C8E, 0]@96..98#14336#collections#0:MacroRules[8C8E, 0]@98..109#14336#::#0:MacroRules[8C8E, 0]@109..111#14336#HashSet#0:MacroRules[8C8E, 0]@111..118#14336#<#0:MacroRules[8C8E, 0]@118..119#14336#(#0:MacroRules[8C8E, 0]@119..120#14336#)#0:MacroRules[8C8E, 0]@120..121#14336#>#0:MacroRules[8C8E, 0]@121..122#14336#,#0:MacroRules[8C8E, 0]@122..123#14336# | ||||||
| }#0:1@132..133#14336# | }#0:MacroRules[8C8E, 0]@132..133#14336# | ||||||
| "#]],
 | "#]],
 | ||||||
|     ); |     ); | ||||||
| } | } | ||||||
|  | @ -75,12 +75,12 @@ macro_rules! f { | ||||||
|     }; |     }; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fn#0:2@30..32#ROOT2024# main#0:2@33..37#ROOT2024#(#0:2@37..38#ROOT2024#)#0:2@38..39#ROOT2024# {#0:2@40..41#ROOT2024# | fn#0:MacroCall[D499, 0]@30..32#ROOT2024# main#0:MacroCall[D499, 0]@33..37#ROOT2024#(#0:MacroCall[D499, 0]@37..38#ROOT2024#)#0:MacroCall[D499, 0]@38..39#ROOT2024# {#0:MacroCall[D499, 0]@40..41#ROOT2024# | ||||||
|     1#0:2@50..51#ROOT2024#;#0:2@51..52#ROOT2024# |     1#0:MacroCall[D499, 0]@50..51#ROOT2024#;#0:MacroCall[D499, 0]@51..52#ROOT2024# | ||||||
|     1.0#0:2@61..64#ROOT2024#;#0:2@64..65#ROOT2024# |     1.0#0:MacroCall[D499, 0]@61..64#ROOT2024#;#0:MacroCall[D499, 0]@64..65#ROOT2024# | ||||||
|     (#0:2@74..75#ROOT2024#(#0:2@75..76#ROOT2024#1#0:2@76..77#ROOT2024#,#0:2@77..78#ROOT2024# )#0:2@78..79#ROOT2024#,#0:2@79..80#ROOT2024# )#0:2@80..81#ROOT2024#.#0:2@81..82#ROOT2024#0#0:2@82..85#ROOT2024#.#0:2@82..85#ROOT2024#0#0:2@82..85#ROOT2024#;#0:2@85..86#ROOT2024# |     (#0:MacroCall[D499, 0]@74..75#ROOT2024#(#0:MacroCall[D499, 0]@75..76#ROOT2024#1#0:MacroCall[D499, 0]@76..77#ROOT2024#,#0:MacroCall[D499, 0]@77..78#ROOT2024# )#0:MacroCall[D499, 0]@78..79#ROOT2024#,#0:MacroCall[D499, 0]@79..80#ROOT2024# )#0:MacroCall[D499, 0]@80..81#ROOT2024#.#0:MacroCall[D499, 0]@81..82#ROOT2024#0#0:MacroCall[D499, 0]@82..85#ROOT2024#.#0:MacroCall[D499, 0]@82..85#ROOT2024#0#0:MacroCall[D499, 0]@82..85#ROOT2024#;#0:MacroCall[D499, 0]@85..86#ROOT2024# | ||||||
|     let#0:2@95..98#ROOT2024# x#0:2@99..100#ROOT2024# =#0:2@101..102#ROOT2024# 1#0:2@103..104#ROOT2024#;#0:2@104..105#ROOT2024# |     let#0:MacroCall[D499, 0]@95..98#ROOT2024# x#0:MacroCall[D499, 0]@99..100#ROOT2024# =#0:MacroCall[D499, 0]@101..102#ROOT2024# 1#0:MacroCall[D499, 0]@103..104#ROOT2024#;#0:MacroCall[D499, 0]@104..105#ROOT2024# | ||||||
| }#0:2@110..111#ROOT2024# | }#0:MacroCall[D499, 0]@110..111#ROOT2024# | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| "#]],
 | "#]],
 | ||||||
|  | @ -171,7 +171,7 @@ fn main(foo: ()) { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fn main(foo: ()) { |     fn main(foo: ()) { | ||||||
|         /* error: unresolved macro unresolved */"helloworld!"#0:3@236..321#ROOT2024#; |         /* error: unresolved macro unresolved */"helloworld!"#0:Fn[B9C7, 0]@236..321#ROOT2024#; | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -197,7 +197,7 @@ macro_rules! mk_struct { | ||||||
| #[macro_use] | #[macro_use] | ||||||
| mod foo; | mod foo; | ||||||
| 
 | 
 | ||||||
| struct#1:1@59..65#14336# Foo#0:2@32..35#ROOT2024#(#1:1@70..71#14336#u32#0:2@41..44#ROOT2024#)#1:1@74..75#14336#;#1:1@75..76#14336# | struct#1:MacroRules[E572, 0]@59..65#14336# Foo#0:MacroCall[BDD3, 0]@32..35#ROOT2024#(#1:MacroRules[E572, 0]@70..71#14336#u32#0:MacroCall[BDD3, 0]@41..44#ROOT2024#)#1:MacroRules[E572, 0]@74..75#14336#;#1:MacroRules[E572, 0]@75..76#14336# | ||||||
| "#]],
 | "#]],
 | ||||||
|     ); |     ); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -181,9 +181,9 @@ fn foo(&self) { | ||||||
|     self.0. 1; |     self.0. 1; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fn#0:1@45..47#ROOT2024# foo#0:1@48..51#ROOT2024#(#0:1@51..52#ROOT2024#�:1@52..53#ROOT2024#self#0:1@53..57#ROOT2024# )#0:1@57..58#ROOT2024# {#0:1@59..60#ROOT2024# | fn#0:Fn[4D85, 0]@45..47#ROOT2024# foo#0:Fn[4D85, 0]@48..51#ROOT2024#(#0:Fn[4D85, 0]@51..52#ROOT2024#�:Fn[4D85, 0]@52..53#ROOT2024#self#0:Fn[4D85, 0]@53..57#ROOT2024# )#0:Fn[4D85, 0]@57..58#ROOT2024# {#0:Fn[4D85, 0]@59..60#ROOT2024# | ||||||
|     self#0:1@65..69#ROOT2024# .#0:1@69..70#ROOT2024#0#0:1@70..71#ROOT2024#.#0:1@71..72#ROOT2024#1#0:1@73..74#ROOT2024#;#0:1@74..75#ROOT2024# |     self#0:Fn[4D85, 0]@65..69#ROOT2024# .#0:Fn[4D85, 0]@69..70#ROOT2024#0#0:Fn[4D85, 0]@70..71#ROOT2024#.#0:Fn[4D85, 0]@71..72#ROOT2024#1#0:Fn[4D85, 0]@73..74#ROOT2024#;#0:Fn[4D85, 0]@74..75#ROOT2024# | ||||||
| }#0:1@76..77#ROOT2024#"#]],
 | }#0:Fn[4D85, 0]@76..77#ROOT2024#"#]],
 | ||||||
|     ); |     ); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -171,12 +171,10 @@ pub struct DefMap { | ||||||
|     /// ExternCrateId being None implies it being imported from the general prelude import.
 |     /// ExternCrateId being None implies it being imported from the general prelude import.
 | ||||||
|     macro_use_prelude: FxHashMap<Name, (MacroId, Option<ExternCrateId>)>, |     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
 |     /// Tracks which custom derives are in scope for an item, to allow resolution of derive helper
 | ||||||
|     /// attributes.
 |     /// attributes.
 | ||||||
|     // FIXME: Figure out a better way for the IDE layer to resolve these?
 |     // 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)>>, |     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`].
 |     /// A mapping from [`hir_expand::MacroDefId`] to [`crate::MacroId`].
 | ||||||
|     pub macro_def_to_macro_id: FxHashMap<ErasedAstId, MacroId>, |     pub macro_def_to_macro_id: FxHashMap<ErasedAstId, MacroId>, | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,14 +1,28 @@ | ||||||
| //! Expansion of associated items
 | //! Expansion of associated items
 | ||||||
| 
 | 
 | ||||||
| use hir_expand::{AstId, InFile, Intern, Lookup, MacroCallKind, MacroDefKind, name::Name}; | use std::mem; | ||||||
| use syntax::ast; | 
 | ||||||
|  | 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 triomphe::Arc; | ||||||
| 
 | 
 | ||||||
| use crate::{ | use crate::{ | ||||||
|     AssocItemId, AstIdWithPath, ConstLoc, FunctionId, FunctionLoc, ImplId, ItemContainerId, |     AssocItemId, AstIdWithPath, ConstLoc, FunctionId, FunctionLoc, ImplId, ItemContainerId, | ||||||
|     ItemLoc, MacroCallId, ModuleId, TraitId, TypeAliasId, TypeAliasLoc, |     ItemLoc, MacroCallId, ModuleId, TraitId, TypeAliasId, TypeAliasLoc, | ||||||
|  |     attr::Attrs, | ||||||
|     db::DefDatabase, |     db::DefDatabase, | ||||||
|     item_tree::{AssocItem, ItemTree, ItemTreeId, MacroCall, ModItem, TreeId}, |  | ||||||
|     macro_call_as_call_id, |     macro_call_as_call_id, | ||||||
|     nameres::{ |     nameres::{ | ||||||
|         DefMap, LocalDefMap, MacroSubNs, |         DefMap, LocalDefMap, MacroSubNs, | ||||||
|  | @ -20,9 +34,8 @@ use crate::{ | ||||||
| #[derive(Debug, Clone, PartialEq, Eq)] | #[derive(Debug, Clone, PartialEq, Eq)] | ||||||
| pub struct TraitItems { | pub struct TraitItems { | ||||||
|     pub items: Box<[(Name, AssocItemId)]>, |     pub items: Box<[(Name, AssocItemId)]>, | ||||||
|     // box it as the vec is usually empty anyways
 |     // `ThinVec` as the vec is usually empty anyways
 | ||||||
|     // FIXME: AstIds are rather unstable...
 |     pub macro_calls: ThinVec<(AstId<ast::Item>, MacroCallId)>, | ||||||
|     pub macro_calls: Option<Box<Vec<(AstId<ast::Item>, MacroCallId)>>>, |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl TraitItems { | impl TraitItems { | ||||||
|  | @ -35,12 +48,12 @@ impl TraitItems { | ||||||
|         db: &dyn DefDatabase, |         db: &dyn DefDatabase, | ||||||
|         tr: TraitId, |         tr: TraitId, | ||||||
|     ) -> (Arc<TraitItems>, DefDiagnostics) { |     ) -> (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 collector = | ||||||
|         let item_tree = tree_id.item_tree(db); |             AssocItemCollector::new(db, module_id, ItemContainerId::TraitId(tr), ast_id.file_id); | ||||||
|         let (items, macro_calls, diagnostics) = |         let source = ast_id.with_value(collector.ast_id_map.get(ast_id.value)).to_node(db); | ||||||
|             collector.collect(&item_tree, tree_id.tree_id(), &item_tree[tree_id.value].items); |         let (items, macro_calls, diagnostics) = collector.collect(source.assoc_item_list()); | ||||||
| 
 | 
 | ||||||
|         (Arc::new(TraitItems { macro_calls, items }), DefDiagnostics::new(diagnostics)) |         (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)> + '_ { |     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)] | #[derive(Debug, PartialEq, Eq)] | ||||||
| pub struct ImplItems { | pub struct ImplItems { | ||||||
|     pub items: Box<[(Name, AssocItemId)]>, |     pub items: Box<[(Name, AssocItemId)]>, | ||||||
|     // box it as the vec is usually empty anyways
 |     // `ThinVec` as the vec is usually empty anyways
 | ||||||
|     // FIXME: AstIds are rather unstable...
 |     pub macro_calls: ThinVec<(AstId<ast::Item>, MacroCallId)>, | ||||||
|     pub macro_calls: Option<Box<Vec<(AstId<ast::Item>, MacroCallId)>>>, |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl ImplItems { | impl ImplItems { | ||||||
|  | @ -99,18 +111,18 @@ impl ImplItems { | ||||||
|         id: ImplId, |         id: ImplId, | ||||||
|     ) -> (Arc<ImplItems>, DefDiagnostics) { |     ) -> (Arc<ImplItems>, DefDiagnostics) { | ||||||
|         let _p = tracing::info_span!("impl_items_with_diagnostics_query").entered(); |         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 collector = | ||||||
|         let item_tree = tree_id.item_tree(db); |             AssocItemCollector::new(db, module_id, ItemContainerId::ImplId(id), ast_id.file_id); | ||||||
|         let (items, macro_calls, diagnostics) = |         let source = ast_id.with_value(collector.ast_id_map.get(ast_id.value)).to_node(db); | ||||||
|             collector.collect(&item_tree, tree_id.tree_id(), &item_tree[tree_id.value].items); |         let (items, macro_calls, diagnostics) = collector.collect(source.assoc_item_list()); | ||||||
| 
 | 
 | ||||||
|         (Arc::new(ImplItems { items, macro_calls }), DefDiagnostics::new(diagnostics)) |         (Arc::new(ImplItems { items, macro_calls }), DefDiagnostics::new(diagnostics)) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn macro_calls(&self) -> impl Iterator<Item = (AstId<ast::Item>, MacroCallId)> + '_ { |     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, |     module_id: ModuleId, | ||||||
|     def_map: &'a DefMap, |     def_map: &'a DefMap, | ||||||
|     local_def_map: &'a LocalDefMap, |     local_def_map: &'a LocalDefMap, | ||||||
|  |     ast_id_map: Arc<AstIdMap>, | ||||||
|  |     span_map: SpanMap, | ||||||
|  |     cfg_options: &'a CfgOptions, | ||||||
|  |     file_id: HirFileId, | ||||||
|     diagnostics: Vec<DefDiagnostic>, |     diagnostics: Vec<DefDiagnostic>, | ||||||
|     container: ItemContainerId, |     container: ItemContainerId, | ||||||
| 
 | 
 | ||||||
|     depth: usize, |     depth: usize, | ||||||
|     items: Vec<(Name, AssocItemId)>, |     items: Vec<(Name, AssocItemId)>, | ||||||
|     macro_calls: Vec<(AstId<ast::Item>, MacroCallId)>, |     macro_calls: ThinVec<(AstId<ast::Item>, MacroCallId)>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl<'a> AssocItemCollector<'a> { | 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); |         let (def_map, local_def_map) = module_id.local_def_map(db); | ||||||
|         Self { |         Self { | ||||||
|             db, |             db, | ||||||
|             module_id, |             module_id, | ||||||
|             def_map, |             def_map, | ||||||
|             local_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, |             container, | ||||||
|             items: Vec::new(), |             items: Vec::new(), | ||||||
| 
 | 
 | ||||||
|             depth: 0, |             depth: 0, | ||||||
|             macro_calls: Vec::new(), |             macro_calls: ThinVec::new(), | ||||||
|             diagnostics: Vec::new(), |             diagnostics: Vec::new(), | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fn collect( |     fn collect( | ||||||
|         mut self, |         mut self, | ||||||
|         item_tree: &ItemTree, |         item_list: Option<ast::AssocItemList>, | ||||||
|         tree_id: TreeId, |     ) -> (Box<[(Name, AssocItemId)]>, ThinVec<(AstId<ast::Item>, MacroCallId)>, Vec<DefDiagnostic>) | ||||||
|         assoc_items: &[AssocItem], |     { | ||||||
|     ) -> ( |         if let Some(item_list) = item_list { | ||||||
|         Box<[(Name, AssocItemId)]>, |             for item in item_list.assoc_items() { | ||||||
|         Option<Box<Vec<(AstId<ast::Item>, MacroCallId)>>>, |                 self.collect_item(item); | ||||||
|         Vec<DefDiagnostic>, |             } | ||||||
|     ) { |  | ||||||
|         self.items.reserve(assoc_items.len()); |  | ||||||
|         for &item in assoc_items { |  | ||||||
|             self.collect_item(item_tree, tree_id, item); |  | ||||||
|         } |         } | ||||||
|         ( |         self.macro_calls.shrink_to_fit(); | ||||||
|             self.items.into_boxed_slice(), |         (self.items.into_boxed_slice(), self.macro_calls, self.diagnostics) | ||||||
|             if self.macro_calls.is_empty() { None } else { Some(Box::new(self.macro_calls)) }, |  | ||||||
|             self.diagnostics, |  | ||||||
|         ) |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fn collect_item(&mut self, item_tree: &ItemTree, tree_id: TreeId, item: AssocItem) { |     fn collect_item(&mut self, item: ast::AssocItem) { | ||||||
|         let attrs = item_tree.attrs(self.db, self.module_id.krate, ModItem::from(item).into()); |         let ast_id = self.ast_id_map.ast_id(&item); | ||||||
|         if !attrs.is_cfg_enabled(self.module_id.krate.cfg_options(self.db)) { |         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.diagnostics.push(DefDiagnostic::unconfigured_code( | ||||||
|                 self.module_id.local_id, |                 self.module_id.local_id, | ||||||
|                 tree_id, |                 InFile::new(self.file_id, ast_id.erase()), | ||||||
|                 ModItem::from(item).into(), |                 cfg, | ||||||
|                 attrs.cfg().unwrap(), |                 self.cfg_options.clone(), | ||||||
|                 self.module_id.krate.cfg_options(self.db).clone(), |  | ||||||
|             )); |             )); | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|  |         let ast_id = InFile::new(self.file_id, ast_id.upcast()); | ||||||
| 
 | 
 | ||||||
|         'attrs: for attr in &*attrs { |         '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 }; |             let ast_id_with_path = AstIdWithPath { path: attr.path.clone(), ast_id }; | ||||||
| 
 | 
 | ||||||
|             match self.def_map.resolve_attr_macro( |             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 { |         match item { | ||||||
|             AssocItem::Function(id) => { |             ast::AssocItem::Fn(function) => { | ||||||
|                 let item = &item_tree[id]; |                 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 = |                 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); |                         .intern(self.db); | ||||||
|                 self.items.push((item.name.clone(), def.into())); |                 self.items.push((name.as_name(), def.into())); | ||||||
|             } |             } | ||||||
|             AssocItem::TypeAlias(id) => { |             ast::AssocItem::MacroCall(call) => { | ||||||
|                 let item = &item_tree[id]; |                 let ast_id = self.ast_id_map.ast_id(&call); | ||||||
|                 let def = |                 let ast_id = InFile::new(self.file_id, ast_id); | ||||||
|                     TypeAliasLoc { container: self.container, id: ItemTreeId::new(tree_id, id) } |                 let Some(path) = call.path() else { return }; | ||||||
|                         .intern(self.db); |                 let range = path.syntax().text_range(); | ||||||
|                 self.items.push((item.name.clone(), def.into())); |                 let Some(path) = ModPath::from_src(self.db, path, &mut |range| { | ||||||
|             } |                     self.span_map.span_for_range(range).ctx | ||||||
|             AssocItem::Const(id) => { |                 }) else { | ||||||
|                 let item = &item_tree[id]; |                     return; | ||||||
|                 let Some(name) = item.name.clone() else { return }; |                 }; | ||||||
|                 let def = ConstLoc { container: self.container, id: ItemTreeId::new(tree_id, id) } |                 let path = Interned::new(path); | ||||||
|                     .intern(self.db); |                 let ctxt = self.span_map.span_for_range(range).ctx; | ||||||
|                 self.items.push((name, def.into())); |  | ||||||
|             } |  | ||||||
|             AssocItem::MacroCall(call) => { |  | ||||||
|                 let MacroCall { ast_id, expand_to, ctxt, ref path } = item_tree[call]; |  | ||||||
| 
 | 
 | ||||||
|                 let resolver = |path: &_| { |                 let resolver = |path: &_| { | ||||||
|                     self.def_map |                     self.def_map | ||||||
|  | @ -268,10 +303,10 @@ impl<'a> AssocItemCollector<'a> { | ||||||
|                 }; |                 }; | ||||||
|                 match macro_call_as_call_id( |                 match macro_call_as_call_id( | ||||||
|                     self.db, |                     self.db, | ||||||
|                     InFile::new(tree_id.file_id(), ast_id), |                     ast_id, | ||||||
|                     path, |                     &path, | ||||||
|                     ctxt, |                     ctxt, | ||||||
|                     expand_to, |                     ExpandTo::Items, | ||||||
|                     self.module_id.krate(), |                     self.module_id.krate(), | ||||||
|                     resolver, |                     resolver, | ||||||
|                     &mut |ptr, call_id| { |                     &mut |ptr, call_id| { | ||||||
|  | @ -281,8 +316,7 @@ impl<'a> AssocItemCollector<'a> { | ||||||
|                     // FIXME: Expansion error?
 |                     // FIXME: Expansion error?
 | ||||||
|                     Ok(call_id) => match call_id.value { |                     Ok(call_id) => match call_id.value { | ||||||
|                         Some(call_id) => { |                         Some(call_id) => { | ||||||
|                             self.macro_calls |                             self.macro_calls.push((ast_id.upcast(), call_id)); | ||||||
|                                 .push((InFile::new(tree_id.file_id(), ast_id.upcast()), call_id)); |  | ||||||
|                             self.collect_macro_items(call_id); |                             self.collect_macro_items(call_id); | ||||||
|                         } |                         } | ||||||
|                         None => (), |                         None => (), | ||||||
|  | @ -291,11 +325,11 @@ impl<'a> AssocItemCollector<'a> { | ||||||
|                         self.diagnostics.push(DefDiagnostic::unresolved_macro_call( |                         self.diagnostics.push(DefDiagnostic::unresolved_macro_call( | ||||||
|                             self.module_id.local_id, |                             self.module_id.local_id, | ||||||
|                             MacroCallKind::FnLike { |                             MacroCallKind::FnLike { | ||||||
|                                 ast_id: InFile::new(tree_id.file_id(), ast_id), |                                 ast_id, | ||||||
|                                 expand_to, |                                 expand_to: ExpandTo::Items, | ||||||
|                                 eager: None, |                                 eager: None, | ||||||
|                             }, |                             }, | ||||||
|                             Clone::clone(path), |                             (*path).clone(), | ||||||
|                         )); |                         )); | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|  | @ -308,13 +342,29 @@ impl<'a> AssocItemCollector<'a> { | ||||||
|             tracing::warn!("macro expansion is too deep"); |             tracing::warn!("macro expansion is too deep"); | ||||||
|             return; |             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; |         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.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 cfg::{CfgAtom, CfgExpr, CfgOptions}; | ||||||
| use either::Either; | use either::Either; | ||||||
| use hir_expand::{ | use hir_expand::{ | ||||||
|     EditionedFileId, ExpandTo, HirFileId, InFile, MacroCallId, MacroCallKind, MacroDefId, |     EditionedFileId, ErasedAstId, ExpandTo, HirFileId, InFile, MacroCallId, MacroCallKind, | ||||||
|     MacroDefKind, |     MacroDefId, MacroDefKind, | ||||||
|     attrs::{Attr, AttrId}, |     attrs::{Attr, AttrId}, | ||||||
|     builtin::{find_builtin_attr, find_builtin_derive, find_builtin_macro}, |     builtin::{find_builtin_attr, find_builtin_derive, find_builtin_macro}, | ||||||
|     mod_path::{ModPath, PathKind}, |     mod_path::{ModPath, PathKind}, | ||||||
|  | @ -35,9 +35,8 @@ use crate::{ | ||||||
|     db::DefDatabase, |     db::DefDatabase, | ||||||
|     item_scope::{GlobId, ImportId, ImportOrExternCrate, PerNsGlobImports}, |     item_scope::{GlobId, ImportId, ImportOrExternCrate, PerNsGlobImports}, | ||||||
|     item_tree::{ |     item_tree::{ | ||||||
|         self, AttrOwner, FieldsShape, FileItemTreeId, ImportAlias, ImportKind, ItemTree, |         self, FieldsShape, FileItemTreeId, ImportAlias, ImportKind, ItemTree, ItemTreeId, | ||||||
|         ItemTreeId, ItemTreeNode, Macro2, MacroCall, MacroRules, Mod, ModItem, ModKind, TreeId, |         ItemTreeNode, Macro2, MacroCall, MacroRules, Mod, ModItem, ModKind, TreeId, UseTreeKind, | ||||||
|         UseTreeKind, |  | ||||||
|     }, |     }, | ||||||
|     macro_call_as_call_id, |     macro_call_as_call_id, | ||||||
|     nameres::{ |     nameres::{ | ||||||
|  | @ -141,6 +140,7 @@ struct ImportSource { | ||||||
|     id: UseId, |     id: UseId, | ||||||
|     is_prelude: bool, |     is_prelude: bool, | ||||||
|     kind: ImportKind, |     kind: ImportKind, | ||||||
|  |     item_tree_id: ItemTreeId<item_tree::Use>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[derive(Debug, Eq, PartialEq)] | #[derive(Debug, Eq, PartialEq)] | ||||||
|  | @ -166,7 +166,7 @@ impl Import { | ||||||
|                 path, |                 path, | ||||||
|                 alias, |                 alias, | ||||||
|                 visibility: visibility.clone(), |                 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
 |     /// 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
 |     /// 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.
 |     /// Cargo builds only on-disk files). We could and probably should add diagnostics for that.
 | ||||||
|     fn export_proc_macro( |     fn export_proc_macro(&mut self, def: ProcMacroDef, ast_id: AstId<ast::Fn>, fn_id: FunctionId) { | ||||||
|         &mut self, |  | ||||||
|         def: ProcMacroDef, |  | ||||||
|         id: ItemTreeId<item_tree::Function>, |  | ||||||
|         ast_id: AstId<ast::Fn>, |  | ||||||
|         fn_id: FunctionId, |  | ||||||
|     ) { |  | ||||||
|         let kind = def.kind.to_basedb_kind(); |         let kind = def.kind.to_basedb_kind(); | ||||||
|         let (expander, kind) = match self.proc_macros.iter().find(|(n, _, _)| n == &def.name) { |         let (expander, kind) = match self.proc_macros.iter().find(|(n, _, _)| n == &def.name) { | ||||||
|             Some(_) |             Some(_) | ||||||
|  | @ -598,7 +592,7 @@ impl DefCollector<'_> { | ||||||
| 
 | 
 | ||||||
|         let proc_macro_id = ProcMacroLoc { |         let proc_macro_id = ProcMacroLoc { | ||||||
|             container: self.def_map.crate_root(), |             container: self.def_map.crate_root(), | ||||||
|             id, |             id: ast_id, | ||||||
|             expander, |             expander, | ||||||
|             kind, |             kind, | ||||||
|             edition: self.def_map.data.edition, |             edition: self.def_map.data.edition, | ||||||
|  | @ -866,6 +860,7 @@ impl DefCollector<'_> { | ||||||
|                 kind: kind @ (ImportKind::Plain | ImportKind::TypeOnly), |                 kind: kind @ (ImportKind::Plain | ImportKind::TypeOnly), | ||||||
|                 id, |                 id, | ||||||
|                 use_tree, |                 use_tree, | ||||||
|  |                 item_tree_id, | ||||||
|                 .. |                 .. | ||||||
|             } => { |             } => { | ||||||
|                 let name = match &import.alias { |                 let name = match &import.alias { | ||||||
|  | @ -887,9 +882,33 @@ impl DefCollector<'_> { | ||||||
|                 let imp = ImportOrExternCrate::Import(ImportId { use_: id, idx: use_tree }); |                 let imp = ImportOrExternCrate::Import(ImportId { use_: id, idx: use_tree }); | ||||||
|                 tracing::debug!("resolved import {:?} ({:?}) to {:?}", name, import, def); |                 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)); |                 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); |                 tracing::debug!("glob import: {:?}", import); | ||||||
|                 let glob = GlobId { use_: id, idx: use_tree }; |                 let glob = GlobId { use_: id, idx: use_tree }; | ||||||
|                 match def.take_types() { |                 match def.take_types() { | ||||||
|  | @ -978,7 +997,7 @@ impl DefCollector<'_> { | ||||||
|                             .enum_variants(e) |                             .enum_variants(e) | ||||||
|                             .variants |                             .variants | ||||||
|                             .iter() |                             .iter() | ||||||
|                             .map(|&(variant, ref name)| { |                             .map(|&(variant, ref name, _)| { | ||||||
|                                 let res = PerNs::both(variant.into(), variant.into(), vis, None); |                                 let res = PerNs::both(variant.into(), variant.into(), vis, None); | ||||||
|                                 (Some(name.clone()), res) |                                 (Some(name.clone()), res) | ||||||
|                             }) |                             }) | ||||||
|  | @ -1150,33 +1169,8 @@ impl DefCollector<'_> { | ||||||
|         vis: Visibility, |         vis: Visibility, | ||||||
|         def_import_type: Option<ImportOrExternCrate>, |         def_import_type: Option<ImportOrExternCrate>, | ||||||
|     ) -> bool { |     ) -> 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() { |         if let Some(def) = defs.types.as_mut() { | ||||||
|             let is_extern_crate_reimport_without_prefix = || { |             def.vis = def.vis.min(vis, &self.def_map).unwrap_or(vis); | ||||||
|                 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() { |         if let Some(def) = defs.values.as_mut() { | ||||||
|             def.vis = def.vis.min(vis, &self.def_map).unwrap_or(vis); |             def.vis = def.vis.min(vis, &self.def_map).unwrap_or(vis); | ||||||
|  | @ -1648,7 +1642,8 @@ impl DefCollector<'_> { | ||||||
|                 import: |                 import: | ||||||
|                     Import { |                     Import { | ||||||
|                         ref path, |                         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()); |             let attrs = self.item_tree.attrs(db, krate, item.into()); | ||||||
|             if let Some(cfg) = attrs.cfg() { |             if let Some(cfg) = attrs.cfg() { | ||||||
|                 if !self.is_cfg_enabled(&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; |                     return; | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|  | @ -1751,7 +1765,7 @@ impl ModCollector<'_, '_> { | ||||||
|                 ModItem::Use(item_tree_id) => { |                 ModItem::Use(item_tree_id) => { | ||||||
|                     let id = UseLoc { |                     let id = UseLoc { | ||||||
|                         container: module, |                         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); |                     .intern(db); | ||||||
|                     let is_prelude = attrs.by_key(sym::prelude_import).exists(); |                     let is_prelude = attrs.by_key(sym::prelude_import).exists(); | ||||||
|  | @ -1770,16 +1784,16 @@ impl ModCollector<'_, '_> { | ||||||
|                     ) |                     ) | ||||||
|                 } |                 } | ||||||
|                 ModItem::ExternCrate(item_tree_id) => { |                 ModItem::ExternCrate(item_tree_id) => { | ||||||
|  |                     let item_tree::ExternCrate { name, visibility, alias, ast_id } = | ||||||
|  |                         &self.item_tree[item_tree_id]; | ||||||
|  | 
 | ||||||
|                     let id = ExternCrateLoc { |                     let id = ExternCrateLoc { | ||||||
|                         container: module, |                         container: module, | ||||||
|                         id: ItemTreeId::new(self.tree_id, item_tree_id), |                         id: InFile::new(self.tree_id.file_id(), *ast_id), | ||||||
|                     } |                     } | ||||||
|                     .intern(db); |                     .intern(db); | ||||||
|                     def_map.modules[self.module_id].scope.define_extern_crate_decl(id); |                     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 is_self = *name == sym::self_; | ||||||
|                     let resolved = if is_self { |                     let resolved = if is_self { | ||||||
|                         cov_mark::hit!(extern_crate_self_as); |                         cov_mark::hit!(extern_crate_self_as); | ||||||
|  | @ -1846,7 +1860,7 @@ impl ModCollector<'_, '_> { | ||||||
|                 ModItem::ExternBlock(block) => { |                 ModItem::ExternBlock(block) => { | ||||||
|                     let extern_block_id = ExternBlockLoc { |                     let extern_block_id = ExternBlockLoc { | ||||||
|                         container: module, |                         container: module, | ||||||
|                         id: ItemTreeId::new(self.tree_id, block), |                         id: InFile::new(self.file_id(), self.item_tree[block].ast_id), | ||||||
|                     } |                     } | ||||||
|                     .intern(db); |                     .intern(db); | ||||||
|                     self.def_collector.def_map.modules[self.module_id] |                     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::MacroRules(id) => self.collect_macro_rules(id, module), | ||||||
|                 ModItem::Macro2(id) => self.collect_macro_def(id, module), |                 ModItem::Macro2(id) => self.collect_macro_def(id, module), | ||||||
|                 ModItem::Impl(imp) => { |                 ModItem::Impl(imp) => { | ||||||
|                     let impl_id = |                     let impl_id = ImplLoc { | ||||||
|                         ImplLoc { container: module, id: ItemTreeId::new(self.tree_id, imp) } |                         container: module, | ||||||
|                             .intern(db); |                         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) |                     self.def_collector.def_map.modules[self.module_id].scope.define_impl(impl_id) | ||||||
|                 } |                 } | ||||||
|                 ModItem::Function(id) => { |                 ModItem::Function(id) => { | ||||||
|                     let it = &self.item_tree[id]; |                     let it = &self.item_tree[id]; | ||||||
|                     let fn_id = |                     let fn_id = FunctionLoc { | ||||||
|                         FunctionLoc { container, id: ItemTreeId::new(self.tree_id, id) }.intern(db); |                         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]); |                     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) { |                         if let Some(proc_macro) = attrs.parse_proc_macro_decl(&it.name) { | ||||||
|                             self.def_collector.export_proc_macro( |                             self.def_collector.export_proc_macro( | ||||||
|                                 proc_macro, |                                 proc_macro, | ||||||
|                                 ItemTreeId::new(self.tree_id, id), |  | ||||||
|                                 InFile::new(self.file_id(), self.item_tree[id].ast_id()), |                                 InFile::new(self.file_id(), self.item_tree[id].ast_id()), | ||||||
|                                 fn_id, |                                 fn_id, | ||||||
|                             ); |                             ); | ||||||
|  | @ -1895,7 +1913,7 @@ impl ModCollector<'_, '_> { | ||||||
|                     let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]); |                     let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]); | ||||||
|                     update_def( |                     update_def( | ||||||
|                         self.def_collector, |                         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) |                             .intern(db) | ||||||
|                             .into(), |                             .into(), | ||||||
|                         &it.name, |                         &it.name, | ||||||
|  | @ -1909,7 +1927,7 @@ impl ModCollector<'_, '_> { | ||||||
|                     let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]); |                     let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]); | ||||||
|                     update_def( |                     update_def( | ||||||
|                         self.def_collector, |                         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) |                             .intern(db) | ||||||
|                             .into(), |                             .into(), | ||||||
|                         &it.name, |                         &it.name, | ||||||
|  | @ -1919,9 +1937,11 @@ impl ModCollector<'_, '_> { | ||||||
|                 } |                 } | ||||||
|                 ModItem::Enum(id) => { |                 ModItem::Enum(id) => { | ||||||
|                     let it = &self.item_tree[id]; |                     let it = &self.item_tree[id]; | ||||||
|                     let enum_ = |                     let enum_ = EnumLoc { | ||||||
|                         EnumLoc { container: module, id: ItemTreeId::new(self.tree_id, id) } |                         container: module, | ||||||
|                             .intern(db); |                         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]); |                     let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]); | ||||||
|                     update_def(self.def_collector, enum_.into(), &it.name, vis, false); |                     update_def(self.def_collector, enum_.into(), &it.name, vis, false); | ||||||
|  | @ -1929,7 +1949,8 @@ impl ModCollector<'_, '_> { | ||||||
|                 ModItem::Const(id) => { |                 ModItem::Const(id) => { | ||||||
|                     let it = &self.item_tree[id]; |                     let it = &self.item_tree[id]; | ||||||
|                     let const_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 { |                     match &it.name { | ||||||
|                         Some(name) => { |                         Some(name) => { | ||||||
|  | @ -1951,7 +1972,7 @@ impl ModCollector<'_, '_> { | ||||||
|                     let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]); |                     let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]); | ||||||
|                     update_def( |                     update_def( | ||||||
|                         self.def_collector, |                         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) |                             .intern(db) | ||||||
|                             .into(), |                             .into(), | ||||||
|                         &it.name, |                         &it.name, | ||||||
|  | @ -1965,7 +1986,7 @@ impl ModCollector<'_, '_> { | ||||||
|                     let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]); |                     let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]); | ||||||
|                     update_def( |                     update_def( | ||||||
|                         self.def_collector, |                         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) |                             .intern(db) | ||||||
|                             .into(), |                             .into(), | ||||||
|                         &it.name, |                         &it.name, | ||||||
|  | @ -1979,9 +2000,12 @@ impl ModCollector<'_, '_> { | ||||||
|                     let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]); |                     let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]); | ||||||
|                     update_def( |                     update_def( | ||||||
|                         self.def_collector, |                         self.def_collector, | ||||||
|                         TraitAliasLoc { container: module, id: ItemTreeId::new(self.tree_id, id) } |                         TraitAliasLoc { | ||||||
|                             .intern(db) |                             container: module, | ||||||
|                             .into(), |                             id: InFile::new(self.file_id(), it.ast_id), | ||||||
|  |                         } | ||||||
|  |                         .intern(db) | ||||||
|  |                         .into(), | ||||||
|                         &it.name, |                         &it.name, | ||||||
|                         vis, |                         vis, | ||||||
|                         false, |                         false, | ||||||
|  | @ -1993,7 +2017,7 @@ impl ModCollector<'_, '_> { | ||||||
|                     let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]); |                     let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]); | ||||||
|                     update_def( |                     update_def( | ||||||
|                         self.def_collector, |                         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) |                             .intern(db) | ||||||
|                             .into(), |                             .into(), | ||||||
|                         &it.name, |                         &it.name, | ||||||
|  | @ -2110,8 +2134,10 @@ impl ModCollector<'_, '_> { | ||||||
|                         match is_enabled { |                         match is_enabled { | ||||||
|                             Err(cfg) => { |                             Err(cfg) => { | ||||||
|                                 self.emit_unconfigured_diagnostic( |                                 self.emit_unconfigured_diagnostic( | ||||||
|                                     self.tree_id, |                                     InFile::new( | ||||||
|                                     AttrOwner::ModItem(module_id.into()), |                                         self.file_id(), | ||||||
|  |                                         self.item_tree[module_id].ast_id.erase(), | ||||||
|  |                                     ), | ||||||
|                                     &cfg, |                                     &cfg, | ||||||
|                                 ); |                                 ); | ||||||
|                             } |                             } | ||||||
|  | @ -2352,7 +2378,7 @@ impl ModCollector<'_, '_> { | ||||||
| 
 | 
 | ||||||
|         let macro_id = MacroRulesLoc { |         let macro_id = MacroRulesLoc { | ||||||
|             container: module, |             container: module, | ||||||
|             id: ItemTreeId::new(self.tree_id, id), |             id: InFile::new(self.file_id(), mac.ast_id), | ||||||
|             flags, |             flags, | ||||||
|             expander, |             expander, | ||||||
|             edition: self.def_collector.def_map.data.edition, |             edition: self.def_collector.def_map.data.edition, | ||||||
|  | @ -2420,7 +2446,7 @@ impl ModCollector<'_, '_> { | ||||||
| 
 | 
 | ||||||
|         let macro_id = Macro2Loc { |         let macro_id = Macro2Loc { | ||||||
|             container: module, |             container: module, | ||||||
|             id: ItemTreeId::new(self.tree_id, id), |             id: InFile::new(self.file_id(), mac.ast_id), | ||||||
|             expander, |             expander, | ||||||
|             allow_internal_unsafe, |             allow_internal_unsafe, | ||||||
|             edition: self.def_collector.def_map.data.edition, |             edition: self.def_collector.def_map.data.edition, | ||||||
|  | @ -2565,16 +2591,16 @@ impl ModCollector<'_, '_> { | ||||||
|         self.def_collector.cfg_options.check(cfg) != Some(false) |         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.def_collector.def_map.diagnostics.push(DefDiagnostic::unconfigured_code( | ||||||
|             self.module_id, |             self.module_id, | ||||||
|             tree_id, |             ast_id, | ||||||
|             item, |  | ||||||
|             cfg.clone(), |             cfg.clone(), | ||||||
|             self.def_collector.cfg_options.clone(), |             self.def_collector.cfg_options.clone(), | ||||||
|         )); |         )); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     #[inline] | ||||||
|     fn file_id(&self) -> HirFileId { |     fn file_id(&self) -> HirFileId { | ||||||
|         self.tree_id.file_id() |         self.tree_id.file_id() | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -3,22 +3,18 @@ | ||||||
| use std::ops::Not; | use std::ops::Not; | ||||||
| 
 | 
 | ||||||
| use cfg::{CfgExpr, CfgOptions}; | 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 la_arena::Idx; | ||||||
| use syntax::ast; | use syntax::ast; | ||||||
| 
 | 
 | ||||||
| use crate::{ | use crate::{AstId, nameres::LocalModuleId}; | ||||||
|     AstId, |  | ||||||
|     item_tree::{self, AttrOwner, ItemTreeId, TreeId}, |  | ||||||
|     nameres::LocalModuleId, |  | ||||||
| }; |  | ||||||
| 
 | 
 | ||||||
| #[derive(Debug, PartialEq, Eq)] | #[derive(Debug, PartialEq, Eq)] | ||||||
| pub enum DefDiagnosticKind { | pub enum DefDiagnosticKind { | ||||||
|     UnresolvedModule { ast: AstId<ast::Module>, candidates: Box<[String]> }, |     UnresolvedModule { ast: AstId<ast::Module>, candidates: Box<[String]> }, | ||||||
|     UnresolvedExternCrate { ast: AstId<ast::ExternCrate> }, |     UnresolvedExternCrate { ast: AstId<ast::ExternCrate> }, | ||||||
|     UnresolvedImport { id: ItemTreeId<item_tree::Use>, index: Idx<ast::UseTree> }, |     UnresolvedImport { id: AstId<ast::Use>, index: Idx<ast::UseTree> }, | ||||||
|     UnconfiguredCode { tree: TreeId, item: AttrOwner, cfg: CfgExpr, opts: CfgOptions }, |     UnconfiguredCode { ast_id: ErasedAstId, cfg: CfgExpr, opts: CfgOptions }, | ||||||
|     UnresolvedMacroCall { ast: MacroCallKind, path: ModPath }, |     UnresolvedMacroCall { ast: MacroCallKind, path: ModPath }, | ||||||
|     UnimplementedBuiltinMacro { ast: AstId<ast::Macro> }, |     UnimplementedBuiltinMacro { ast: AstId<ast::Macro> }, | ||||||
|     InvalidDeriveTarget { ast: AstId<ast::Item>, id: usize }, |     InvalidDeriveTarget { ast: AstId<ast::Item>, id: usize }, | ||||||
|  | @ -28,7 +24,7 @@ pub enum DefDiagnosticKind { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[derive(Clone, Debug, PartialEq, Eq)] | #[derive(Clone, Debug, PartialEq, Eq)] | ||||||
| pub struct DefDiagnostics(Option<triomphe::Arc<Box<[DefDiagnostic]>>>); | pub struct DefDiagnostics(Option<triomphe::ThinArc<(), DefDiagnostic>>); | ||||||
| 
 | 
 | ||||||
| impl DefDiagnostics { | impl DefDiagnostics { | ||||||
|     pub fn new(diagnostics: Vec<DefDiagnostic>) -> Self { |     pub fn new(diagnostics: Vec<DefDiagnostic>) -> Self { | ||||||
|  | @ -36,12 +32,12 @@ impl DefDiagnostics { | ||||||
|             diagnostics |             diagnostics | ||||||
|                 .is_empty() |                 .is_empty() | ||||||
|                 .not() |                 .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> { |     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( |     pub(super) fn unresolved_import( | ||||||
|         container: LocalModuleId, |         container: LocalModuleId, | ||||||
|         id: ItemTreeId<item_tree::Use>, |         id: AstId<ast::Use>, | ||||||
|         index: Idx<ast::UseTree>, |         index: Idx<ast::UseTree>, | ||||||
|     ) -> Self { |     ) -> Self { | ||||||
|         Self { in_module: container, kind: DefDiagnosticKind::UnresolvedImport { id, index } } |         Self { in_module: container, kind: DefDiagnosticKind::UnresolvedImport { id, index } } | ||||||
|  | @ -92,14 +88,13 @@ impl DefDiagnostic { | ||||||
| 
 | 
 | ||||||
|     pub fn unconfigured_code( |     pub fn unconfigured_code( | ||||||
|         container: LocalModuleId, |         container: LocalModuleId, | ||||||
|         tree: TreeId, |         ast_id: ErasedAstId, | ||||||
|         item: AttrOwner, |  | ||||||
|         cfg: CfgExpr, |         cfg: CfgExpr, | ||||||
|         opts: CfgOptions, |         opts: CfgOptions, | ||||||
|     ) -> Self { |     ) -> Self { | ||||||
|         Self { |         Self { | ||||||
|             in_module: container, |             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 either::Either; | ||||||
| use hir_expand::{ | use hir_expand::{ | ||||||
|     Lookup, |  | ||||||
|     mod_path::{ModPath, PathKind}, |     mod_path::{ModPath, PathKind}, | ||||||
|     name::Name, |     name::Name, | ||||||
| }; | }; | ||||||
|  | @ -529,23 +528,22 @@ impl DefMap { | ||||||
|                     // enum variant
 |                     // enum variant
 | ||||||
|                     cov_mark::hit!(can_import_enum_variant); |                     cov_mark::hit!(can_import_enum_variant); | ||||||
| 
 | 
 | ||||||
|                     let res = |                     let res = db | ||||||
|                         db.enum_variants(e).variants.iter().find(|(_, name)| name == segment).map( |                         .enum_variants(e) | ||||||
|                             |&(variant, _)| { |                         .variants | ||||||
|                                 let item_tree_id = variant.lookup(db).id; |                         .iter() | ||||||
|                                 match item_tree_id.item_tree(db)[item_tree_id.value].shape { |                         .find(|(_, name, _)| name == segment) | ||||||
|                                     FieldsShape::Record => { |                         .map(|&(variant, _, shape)| match shape { | ||||||
|                                         PerNs::types(variant.into(), Visibility::Public, None) |                             FieldsShape::Record => { | ||||||
|                                     } |                                 PerNs::types(variant.into(), Visibility::Public, None) | ||||||
|                                     FieldsShape::Tuple | FieldsShape::Unit => PerNs::both( |                             } | ||||||
|                                         variant.into(), |                             FieldsShape::Tuple | FieldsShape::Unit => PerNs::both( | ||||||
|                                         variant.into(), |                                 variant.into(), | ||||||
|                                         Visibility::Public, |                                 variant.into(), | ||||||
|                                         None, |                                 Visibility::Public, | ||||||
|                                     ), |                                 None, | ||||||
|                                 } |                             ), | ||||||
|                             }, |                         }); | ||||||
|                         ); |  | ||||||
|                     // FIXME: Need to filter visibility here and below? Not sure.
 |                     // FIXME: Need to filter visibility here and below? Not sure.
 | ||||||
|                     return match res { |                     return match res { | ||||||
|                         Some(res) => { |                         Some(res) => { | ||||||
|  |  | ||||||
|  | @ -5,21 +5,22 @@ use base_db::Crate; | ||||||
| use hir_expand::{ | use hir_expand::{ | ||||||
|     MacroDefId, |     MacroDefId, | ||||||
|     mod_path::{ModPath, PathKind}, |     mod_path::{ModPath, PathKind}, | ||||||
|     name::Name, |     name::{AsName, Name}, | ||||||
| }; | }; | ||||||
| use intern::{Symbol, sym}; | use intern::{Symbol, sym}; | ||||||
| use itertools::Itertools as _; | use itertools::Itertools as _; | ||||||
| use rustc_hash::FxHashSet; | use rustc_hash::FxHashSet; | ||||||
| use smallvec::{SmallVec, smallvec}; | use smallvec::{SmallVec, smallvec}; | ||||||
| use span::SyntaxContext; | use span::SyntaxContext; | ||||||
|  | use syntax::ast::HasName; | ||||||
| use triomphe::Arc; | use triomphe::Arc; | ||||||
| 
 | 
 | ||||||
| use crate::{ | use crate::{ | ||||||
|     AdtId, ConstId, ConstParamId, CrateRootModuleId, DefWithBodyId, EnumId, EnumVariantId, |     AdtId, AstIdLoc, ConstId, ConstParamId, CrateRootModuleId, DefWithBodyId, EnumId, | ||||||
|     ExternBlockId, ExternCrateId, FunctionId, FxIndexMap, GenericDefId, GenericParamId, HasModule, |     EnumVariantId, ExternBlockId, ExternCrateId, FunctionId, FxIndexMap, GenericDefId, | ||||||
|     ImplId, ItemContainerId, ItemTreeLoc, LifetimeParamId, LocalModuleId, Lookup, Macro2Id, |     GenericParamId, HasModule, ImplId, ItemContainerId, LifetimeParamId, LocalModuleId, Lookup, | ||||||
|     MacroId, MacroRulesId, ModuleDefId, ModuleId, ProcMacroId, StaticId, StructId, TraitAliasId, |     Macro2Id, MacroId, MacroRulesId, ModuleDefId, ModuleId, ProcMacroId, StaticId, StructId, | ||||||
|     TraitId, TypeAliasId, TypeOrConstParamId, TypeParamId, UseId, VariantId, |     TraitAliasId, TraitId, TypeAliasId, TypeOrConstParamId, TypeParamId, UseId, VariantId, | ||||||
|     builtin_type::BuiltinType, |     builtin_type::BuiltinType, | ||||||
|     db::DefDatabase, |     db::DefDatabase, | ||||||
|     expr_store::{ |     expr_store::{ | ||||||
|  | @ -32,10 +33,10 @@ use crate::{ | ||||||
|         generics::{GenericParams, TypeOrConstParamData}, |         generics::{GenericParams, TypeOrConstParamData}, | ||||||
|     }, |     }, | ||||||
|     item_scope::{BUILTIN_SCOPE, BuiltinShadowMode, ImportOrExternCrate, ImportOrGlob, ItemScope}, |     item_scope::{BUILTIN_SCOPE, BuiltinShadowMode, ImportOrExternCrate, ImportOrGlob, ItemScope}, | ||||||
|     item_tree::ImportAlias, |  | ||||||
|     lang_item::LangItemTarget, |     lang_item::LangItemTarget, | ||||||
|     nameres::{DefMap, LocalDefMap, MacroSubNs, ResolvePathResultPrefixInfo, block_def_map}, |     nameres::{DefMap, LocalDefMap, MacroSubNs, ResolvePathResultPrefixInfo, block_def_map}, | ||||||
|     per_ns::PerNs, |     per_ns::PerNs, | ||||||
|  |     src::HasSource, | ||||||
|     type_ref::LifetimeRef, |     type_ref::LifetimeRef, | ||||||
|     visibility::{RawVisibility, Visibility}, |     visibility::{RawVisibility, Visibility}, | ||||||
| }; | }; | ||||||
|  | @ -627,14 +628,14 @@ impl<'db> Resolver<'db> { | ||||||
|             .extern_crate_decls() |             .extern_crate_decls() | ||||||
|             .filter_map(|id| { |             .filter_map(|id| { | ||||||
|                 let loc = id.lookup(db); |                 let loc = id.lookup(db); | ||||||
|                 let tree = loc.item_tree_id().item_tree(db); |                 let extern_crate = loc.source(db); | ||||||
|                 match &tree[loc.id.value].alias { |                 // If there is a rename (`as x`), extract the renamed name, or remove the `extern crate`
 | ||||||
|                     Some(alias) => match alias { |                 // if it is an underscore.
 | ||||||
|                         ImportAlias::Underscore => None, |                 extern_crate | ||||||
|                         ImportAlias::Alias(name) => Some(name.clone()), |                     .value | ||||||
|                     }, |                     .rename() | ||||||
|                     None => Some(tree[loc.id.value].name.clone()), |                     .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( | fn lookup_resolver( | ||||||
|     db: &dyn DefDatabase, |     db: &dyn DefDatabase, | ||||||
|     lookup: impl Lookup< |     lookup: impl Lookup<Database = dyn DefDatabase, Data = impl AstIdLoc<Container = impl HasResolver>>, | ||||||
|         Database = dyn DefDatabase, |  | ||||||
|         Data = impl ItemTreeLoc<Container = impl HasResolver>, |  | ||||||
|     >, |  | ||||||
| ) -> Resolver<'_> { | ) -> Resolver<'_> { | ||||||
|     lookup.lookup(db).container().resolver(db) |     lookup.lookup(db).container().resolver(db) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -4,21 +4,25 @@ use std::ops::Not as _; | ||||||
| 
 | 
 | ||||||
| use bitflags::bitflags; | use bitflags::bitflags; | ||||||
| use cfg::{CfgExpr, CfgOptions}; | use cfg::{CfgExpr, CfgOptions}; | ||||||
| use either::Either; | use hir_expand::{ | ||||||
| use hir_expand::{InFile, Intern, Lookup, name::Name}; |     InFile, Intern, Lookup, | ||||||
|  |     name::{AsName, Name}, | ||||||
|  | }; | ||||||
| use intern::{Symbol, sym}; | use intern::{Symbol, sym}; | ||||||
| use la_arena::{Arena, Idx}; | use la_arena::{Arena, Idx}; | ||||||
| use rustc_abi::{IntegerType, ReprOptions}; | use rustc_abi::{IntegerType, ReprOptions}; | ||||||
| use syntax::{ | use syntax::{ | ||||||
|     AstNode, SyntaxNodePtr, |     NodeOrToken, SyntaxNodePtr, T, | ||||||
|     ast::{self, HasGenericParams, IsString}, |     ast::{self, HasGenericParams, HasName, HasVisibility, IsString}, | ||||||
| }; | }; | ||||||
| use thin_vec::ThinVec; | use thin_vec::ThinVec; | ||||||
| use triomphe::Arc; | use triomphe::Arc; | ||||||
| 
 | 
 | ||||||
| use crate::{ | use crate::{ | ||||||
|     ConstId, EnumId, EnumVariantId, EnumVariantLoc, FunctionId, HasModule, ImplId, ItemContainerId, |     ConstId, EnumId, EnumVariantId, EnumVariantLoc, ExternBlockId, FunctionId, HasModule, ImplId, | ||||||
|     ModuleId, StaticId, StructId, TraitAliasId, TraitId, TypeAliasId, UnionId, VariantId, |     ItemContainerId, ModuleId, StaticId, StructId, TraitAliasId, TraitId, TypeAliasId, UnionId, | ||||||
|  |     VariantId, | ||||||
|  |     attr::Attrs, | ||||||
|     db::DefDatabase, |     db::DefDatabase, | ||||||
|     expr_store::{ |     expr_store::{ | ||||||
|         ExpressionStore, ExpressionStoreSourceMap, |         ExpressionStore, ExpressionStoreSourceMap, | ||||||
|  | @ -28,15 +32,17 @@ use crate::{ | ||||||
|         }, |         }, | ||||||
|     }, |     }, | ||||||
|     hir::{ExprId, PatId, generics::GenericParams}, |     hir::{ExprId, PatId, generics::GenericParams}, | ||||||
|     item_tree::{ |     item_tree::{FieldsShape, RawVisibility, visibility_from_ast}, | ||||||
|         AttrOwner, Field, FieldParent, FieldsShape, FileItemTreeId, ItemTree, ItemTreeId, ModItem, |  | ||||||
|         RawVisibility, RawVisibilityId, |  | ||||||
|     }, |  | ||||||
|     lang_item::LangItem, |     lang_item::LangItem, | ||||||
|     src::HasSource, |     src::HasSource, | ||||||
|     type_ref::{TraitRef, TypeBound, TypeRefId}, |     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)] | #[derive(Debug, PartialEq, Eq)] | ||||||
| pub struct StructSignature { | pub struct StructSignature { | ||||||
|     pub name: Name, |     pub name: Name, | ||||||
|  | @ -70,8 +76,8 @@ bitflags! { | ||||||
| impl StructSignature { | impl StructSignature { | ||||||
|     pub fn query(db: &dyn DefDatabase, id: StructId) -> (Arc<Self>, Arc<ExpressionStoreSourceMap>) { |     pub fn query(db: &dyn DefDatabase, id: StructId) -> (Arc<Self>, Arc<ExpressionStoreSourceMap>) { | ||||||
|         let loc = id.lookup(db); |         let loc = id.lookup(db); | ||||||
|         let item_tree = loc.id.item_tree(db); |         let InFile { file_id, value: source } = loc.source(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 = StructFlags::empty(); |         let mut flags = StructFlags::empty(); | ||||||
|         if attrs.by_key(sym::rustc_has_incoherent_inherent_impls).exists() { |         if attrs.by_key(sym::rustc_has_incoherent_inherent_impls).exists() { | ||||||
|  | @ -91,23 +97,23 @@ impl StructSignature { | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         let repr = attrs.repr(); |         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( |         let (store, generic_params, source_map) = lower_generic_params( | ||||||
|             db, |             db, | ||||||
|             loc.container, |             loc.container, | ||||||
|             id.into(), |             id.into(), | ||||||
|             file_id, |             file_id, | ||||||
|             value.generic_param_list(), |             source.generic_param_list(), | ||||||
|             value.where_clause(), |             source.where_clause(), | ||||||
|         ); |         ); | ||||||
|         ( |         ( | ||||||
|             Arc::new(StructSignature { |             Arc::new(StructSignature { | ||||||
|                 generic_params, |                 generic_params, | ||||||
|                 store, |                 store, | ||||||
|                 flags, |                 flags, | ||||||
|                 shape: item_tree[loc.id.value].shape, |                 shape, | ||||||
|                 name: item_tree[loc.id.value].name.clone(), |                 name: as_name_opt(source.name()), | ||||||
|                 repr, |                 repr, | ||||||
|             }), |             }), | ||||||
|             Arc::new(source_map), |             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)] | #[derive(Debug, PartialEq, Eq)] | ||||||
| pub struct UnionSignature { | pub struct UnionSignature { | ||||||
|     pub name: Name, |     pub name: Name, | ||||||
|  | @ -127,9 +142,7 @@ pub struct UnionSignature { | ||||||
| impl UnionSignature { | impl UnionSignature { | ||||||
|     pub fn query(db: &dyn DefDatabase, id: UnionId) -> (Arc<Self>, Arc<ExpressionStoreSourceMap>) { |     pub fn query(db: &dyn DefDatabase, id: UnionId) -> (Arc<Self>, Arc<ExpressionStoreSourceMap>) { | ||||||
|         let loc = id.lookup(db); |         let loc = id.lookup(db); | ||||||
|         let krate = loc.container.krate; |         let attrs = db.attrs(id.into()); | ||||||
|         let item_tree = loc.id.item_tree(db); |  | ||||||
|         let attrs = item_tree.attrs(db, krate, ModItem::from(loc.id.value).into()); |  | ||||||
|         let mut flags = StructFlags::empty(); |         let mut flags = StructFlags::empty(); | ||||||
|         if attrs.by_key(sym::rustc_has_incoherent_inherent_impls).exists() { |         if attrs.by_key(sym::rustc_has_incoherent_inherent_impls).exists() { | ||||||
|             flags |= StructFlags::RUSTC_HAS_INCOHERENT_INHERENT_IMPLS; |             flags |= StructFlags::RUSTC_HAS_INCOHERENT_INHERENT_IMPLS; | ||||||
|  | @ -140,14 +153,14 @@ impl UnionSignature { | ||||||
| 
 | 
 | ||||||
|         let repr = attrs.repr(); |         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( |         let (store, generic_params, source_map) = lower_generic_params( | ||||||
|             db, |             db, | ||||||
|             loc.container, |             loc.container, | ||||||
|             id.into(), |             id.into(), | ||||||
|             file_id, |             file_id, | ||||||
|             value.generic_param_list(), |             source.generic_param_list(), | ||||||
|             value.where_clause(), |             source.where_clause(), | ||||||
|         ); |         ); | ||||||
|         ( |         ( | ||||||
|             Arc::new(UnionSignature { |             Arc::new(UnionSignature { | ||||||
|  | @ -155,7 +168,7 @@ impl UnionSignature { | ||||||
|                 store, |                 store, | ||||||
|                 flags, |                 flags, | ||||||
|                 repr, |                 repr, | ||||||
|                 name: item_tree[loc.id.value].name.clone(), |                 name: as_name_opt(source.name()), | ||||||
|             }), |             }), | ||||||
|             Arc::new(source_map), |             Arc::new(source_map), | ||||||
|         ) |         ) | ||||||
|  | @ -181,8 +194,7 @@ pub struct EnumSignature { | ||||||
| impl EnumSignature { | impl EnumSignature { | ||||||
|     pub fn query(db: &dyn DefDatabase, id: EnumId) -> (Arc<Self>, Arc<ExpressionStoreSourceMap>) { |     pub fn query(db: &dyn DefDatabase, id: EnumId) -> (Arc<Self>, Arc<ExpressionStoreSourceMap>) { | ||||||
|         let loc = id.lookup(db); |         let loc = id.lookup(db); | ||||||
|         let item_tree = loc.id.item_tree(db); |         let attrs = db.attrs(id.into()); | ||||||
|         let attrs = item_tree.attrs(db, loc.container.krate, ModItem::from(loc.id.value).into()); |  | ||||||
|         let mut flags = EnumFlags::empty(); |         let mut flags = EnumFlags::empty(); | ||||||
|         if attrs.by_key(sym::rustc_has_incoherent_inherent_impls).exists() { |         if attrs.by_key(sym::rustc_has_incoherent_inherent_impls).exists() { | ||||||
|             flags |= EnumFlags::RUSTC_HAS_INCOHERENT_INHERENT_IMPLS; |             flags |= EnumFlags::RUSTC_HAS_INCOHERENT_INHERENT_IMPLS; | ||||||
|  | @ -190,14 +202,14 @@ impl EnumSignature { | ||||||
| 
 | 
 | ||||||
|         let repr = attrs.repr(); |         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( |         let (store, generic_params, source_map) = lower_generic_params( | ||||||
|             db, |             db, | ||||||
|             loc.container, |             loc.container, | ||||||
|             id.into(), |             id.into(), | ||||||
|             file_id, |             file_id, | ||||||
|             value.generic_param_list(), |             source.generic_param_list(), | ||||||
|             value.where_clause(), |             source.where_clause(), | ||||||
|         ); |         ); | ||||||
| 
 | 
 | ||||||
|         ( |         ( | ||||||
|  | @ -206,7 +218,7 @@ impl EnumSignature { | ||||||
|                 store, |                 store, | ||||||
|                 flags, |                 flags, | ||||||
|                 repr, |                 repr, | ||||||
|                 name: item_tree[loc.id.value].name.clone(), |                 name: as_name_opt(source.name()), | ||||||
|             }), |             }), | ||||||
|             Arc::new(source_map), |             Arc::new(source_map), | ||||||
|         ) |         ) | ||||||
|  | @ -239,10 +251,9 @@ pub struct ConstSignature { | ||||||
| impl ConstSignature { | impl ConstSignature { | ||||||
|     pub fn query(db: &dyn DefDatabase, id: ConstId) -> (Arc<Self>, Arc<ExpressionStoreSourceMap>) { |     pub fn query(db: &dyn DefDatabase, id: ConstId) -> (Arc<Self>, Arc<ExpressionStoreSourceMap>) { | ||||||
|         let loc = id.lookup(db); |         let loc = id.lookup(db); | ||||||
|         let item_tree = loc.id.item_tree(db); |  | ||||||
| 
 | 
 | ||||||
|         let module = loc.container.module(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(); |         let mut flags = ConstFlags::empty(); | ||||||
|         if attrs.by_key(sym::rustc_allow_incoherent_impl).exists() { |         if attrs.by_key(sym::rustc_allow_incoherent_impl).exists() { | ||||||
|             flags |= ConstFlags::RUSTC_ALLOW_INCOHERENT_IMPL; |             flags |= ConstFlags::RUSTC_ALLOW_INCOHERENT_IMPL; | ||||||
|  | @ -253,14 +264,14 @@ impl ConstSignature { | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         let (store, source_map, type_ref) = |         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 { |             Arc::new(ConstSignature { | ||||||
|                 store: Arc::new(store), |                 store: Arc::new(store), | ||||||
|                 type_ref, |                 type_ref, | ||||||
|                 flags, |                 flags, | ||||||
|                 name: item_tree[loc.id.value].name.clone(), |                 name: source.value.name().map(|it| it.as_name()), | ||||||
|             }), |             }), | ||||||
|             Arc::new(source_map), |             Arc::new(source_map), | ||||||
|         ) |         ) | ||||||
|  | @ -295,10 +306,9 @@ pub struct StaticSignature { | ||||||
| impl StaticSignature { | impl StaticSignature { | ||||||
|     pub fn query(db: &dyn DefDatabase, id: StaticId) -> (Arc<Self>, Arc<ExpressionStoreSourceMap>) { |     pub fn query(db: &dyn DefDatabase, id: StaticId) -> (Arc<Self>, Arc<ExpressionStoreSourceMap>) { | ||||||
|         let loc = id.lookup(db); |         let loc = id.lookup(db); | ||||||
|         let item_tree = loc.id.item_tree(db); |  | ||||||
| 
 | 
 | ||||||
|         let module = loc.container.module(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(); |         let mut flags = StaticFlags::empty(); | ||||||
|         if attrs.by_key(sym::rustc_allow_incoherent_impl).exists() { |         if attrs.by_key(sym::rustc_allow_incoherent_impl).exists() { | ||||||
|             flags |= StaticFlags::RUSTC_ALLOW_INCOHERENT_IMPL; |             flags |= StaticFlags::RUSTC_ALLOW_INCOHERENT_IMPL; | ||||||
|  | @ -323,14 +333,14 @@ impl StaticSignature { | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         let (store, source_map, type_ref) = |         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 { |             Arc::new(StaticSignature { | ||||||
|                 store: Arc::new(store), |                 store: Arc::new(store), | ||||||
|                 type_ref, |                 type_ref, | ||||||
|                 flags, |                 flags, | ||||||
|                 name: item_tree[loc.id.value].name.clone(), |                 name: as_name_opt(source.value.name()), | ||||||
|             }), |             }), | ||||||
|             Arc::new(source_map), |             Arc::new(source_map), | ||||||
|         ) |         ) | ||||||
|  | @ -407,10 +417,9 @@ pub struct TraitSignature { | ||||||
| impl TraitSignature { | impl TraitSignature { | ||||||
|     pub fn query(db: &dyn DefDatabase, id: TraitId) -> (Arc<Self>, Arc<ExpressionStoreSourceMap>) { |     pub fn query(db: &dyn DefDatabase, id: TraitId) -> (Arc<Self>, Arc<ExpressionStoreSourceMap>) { | ||||||
|         let loc = id.lookup(db); |         let loc = id.lookup(db); | ||||||
|         let item_tree = loc.id.item_tree(db); |  | ||||||
| 
 | 
 | ||||||
|         let mut flags = TraitFlags::empty(); |         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); |         let source = loc.source(db); | ||||||
|         if source.value.auto_token().is_some() { |         if source.value.auto_token().is_some() { | ||||||
|             flags.insert(TraitFlags::AUTO); |             flags.insert(TraitFlags::AUTO); | ||||||
|  | @ -446,15 +455,11 @@ impl TraitSignature { | ||||||
|             flags |= TraitFlags::SKIP_BOXED_SLICE_DURING_METHOD_DISPATCH; |             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); |         let (store, source_map, generic_params) = lower_trait(db, loc.container, source, id); | ||||||
| 
 | 
 | ||||||
|         ( |         ( | ||||||
|             Arc::new(TraitSignature { |             Arc::new(TraitSignature { store: Arc::new(store), generic_params, flags, name }), | ||||||
|                 store: Arc::new(store), |  | ||||||
|                 generic_params, |  | ||||||
|                 flags, |  | ||||||
|                 name: item_tree[loc.id.value].name.clone(), |  | ||||||
|             }), |  | ||||||
|             Arc::new(source_map), |             Arc::new(source_map), | ||||||
|         ) |         ) | ||||||
|     } |     } | ||||||
|  | @ -473,17 +478,13 @@ impl TraitAliasSignature { | ||||||
|         id: TraitAliasId, |         id: TraitAliasId, | ||||||
|     ) -> (Arc<Self>, Arc<ExpressionStoreSourceMap>) { |     ) -> (Arc<Self>, Arc<ExpressionStoreSourceMap>) { | ||||||
|         let loc = id.lookup(db); |         let loc = id.lookup(db); | ||||||
|         let item_tree = loc.id.item_tree(db); |  | ||||||
| 
 | 
 | ||||||
|         let source = loc.source(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); |         let (store, source_map, generic_params) = lower_trait_alias(db, loc.container, source, id); | ||||||
| 
 | 
 | ||||||
|         ( |         ( | ||||||
|             Arc::new(TraitAliasSignature { |             Arc::new(TraitAliasSignature { generic_params, store: Arc::new(store), name }), | ||||||
|                 generic_params, |  | ||||||
|                 store: Arc::new(store), |  | ||||||
|                 name: item_tree[loc.id.value].name.clone(), |  | ||||||
|             }), |  | ||||||
|             Arc::new(source_map), |             Arc::new(source_map), | ||||||
|         ) |         ) | ||||||
|     } |     } | ||||||
|  | @ -530,10 +531,9 @@ impl FunctionSignature { | ||||||
|     ) -> (Arc<Self>, Arc<ExpressionStoreSourceMap>) { |     ) -> (Arc<Self>, Arc<ExpressionStoreSourceMap>) { | ||||||
|         let loc = id.lookup(db); |         let loc = id.lookup(db); | ||||||
|         let module = loc.container.module(db); |         let module = loc.container.module(db); | ||||||
|         let item_tree = loc.id.item_tree(db); |  | ||||||
| 
 | 
 | ||||||
|         let mut flags = FnFlags::empty(); |         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() { |         if attrs.by_key(sym::rustc_allow_incoherent_impl).exists() { | ||||||
|             flags.insert(FnFlags::RUSTC_ALLOW_INCOHERENT_IMPL); |             flags.insert(FnFlags::RUSTC_ALLOW_INCOHERENT_IMPL); | ||||||
|         } |         } | ||||||
|  | @ -568,6 +568,7 @@ impl FunctionSignature { | ||||||
|             flags.insert(FnFlags::HAS_BODY); |             flags.insert(FnFlags::HAS_BODY); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         let name = as_name_opt(source.value.name()); | ||||||
|         let abi = source.value.abi().map(|abi| { |         let abi = source.value.abi().map(|abi| { | ||||||
|             abi.abi_string().map_or_else(|| sym::C, |it| Symbol::intern(it.text_without_quotes())) |             abi.abi_string().map_or_else(|| sym::C, |it| Symbol::intern(it.text_without_quotes())) | ||||||
|         }); |         }); | ||||||
|  | @ -588,7 +589,7 @@ impl FunctionSignature { | ||||||
|                 abi, |                 abi, | ||||||
|                 flags, |                 flags, | ||||||
|                 legacy_const_generics_indices, |                 legacy_const_generics_indices, | ||||||
|                 name: item_tree[loc.id.value].name.clone(), |                 name, | ||||||
|             }), |             }), | ||||||
|             Arc::new(source_map), |             Arc::new(source_map), | ||||||
|         ) |         ) | ||||||
|  | @ -662,14 +663,9 @@ impl TypeAliasSignature { | ||||||
|         id: TypeAliasId, |         id: TypeAliasId, | ||||||
|     ) -> (Arc<Self>, Arc<ExpressionStoreSourceMap>) { |     ) -> (Arc<Self>, Arc<ExpressionStoreSourceMap>) { | ||||||
|         let loc = id.lookup(db); |         let loc = id.lookup(db); | ||||||
|         let item_tree = loc.id.item_tree(db); |  | ||||||
| 
 | 
 | ||||||
|         let mut flags = TypeAliasFlags::empty(); |         let mut flags = TypeAliasFlags::empty(); | ||||||
|         let attrs = item_tree.attrs( |         let attrs = db.attrs(id.into()); | ||||||
|             db, |  | ||||||
|             loc.container.module(db).krate(), |  | ||||||
|             ModItem::from(loc.id.value).into(), |  | ||||||
|         ); |  | ||||||
|         if attrs.by_key(sym::rustc_has_incoherent_inherent_impls).exists() { |         if attrs.by_key(sym::rustc_has_incoherent_inherent_impls).exists() { | ||||||
|             flags.insert(TypeAliasFlags::RUSTC_HAS_INCOHERENT_INHERENT_IMPL); |             flags.insert(TypeAliasFlags::RUSTC_HAS_INCOHERENT_INHERENT_IMPL); | ||||||
|         } |         } | ||||||
|  | @ -680,6 +676,7 @@ impl TypeAliasSignature { | ||||||
|             flags.insert(TypeAliasFlags::IS_EXTERN); |             flags.insert(TypeAliasFlags::IS_EXTERN); | ||||||
|         } |         } | ||||||
|         let source = loc.source(db); |         let source = loc.source(db); | ||||||
|  |         let name = as_name_opt(source.value.name()); | ||||||
|         let (store, source_map, generic_params, bounds, ty) = |         let (store, source_map, generic_params, bounds, ty) = | ||||||
|             lower_type_alias(db, loc.container.module(db), source, id); |             lower_type_alias(db, loc.container.module(db), source, id); | ||||||
| 
 | 
 | ||||||
|  | @ -689,7 +686,7 @@ impl TypeAliasSignature { | ||||||
|                 generic_params, |                 generic_params, | ||||||
|                 flags, |                 flags, | ||||||
|                 bounds, |                 bounds, | ||||||
|                 name: item_tree[loc.id.value].name.clone(), |                 name, | ||||||
|                 ty, |                 ty, | ||||||
|             }), |             }), | ||||||
|             Arc::new(source_map), |             Arc::new(source_map), | ||||||
|  | @ -743,104 +740,41 @@ impl VariantFields { | ||||||
|         let (shape, (fields, store, source_map)) = match id { |         let (shape, (fields, store, source_map)) = match id { | ||||||
|             VariantId::EnumVariantId(id) => { |             VariantId::EnumVariantId(id) => { | ||||||
|                 let loc = id.lookup(db); |                 let loc = id.lookup(db); | ||||||
|                 let item_tree = loc.id.item_tree(db); |  | ||||||
|                 let parent = loc.parent.lookup(db); |                 let parent = loc.parent.lookup(db); | ||||||
|                 let variant = &item_tree[loc.id.value]; |                 let source = loc.source(db); | ||||||
|                 ( |                 let shape = adt_shape(source.value.kind()); | ||||||
|                     variant.shape, |                 let span_map = db.span_map(source.file_id); | ||||||
|                     lower_fields( |                 let override_visibility = visibility_from_ast( | ||||||
|                         db, |                     db, | ||||||
|                         parent.container, |                     source.value.parent_enum().visibility(), | ||||||
|                         &item_tree, |                     &mut |range| span_map.span_for_range(range).ctx, | ||||||
|                         FieldParent::EnumVariant(loc.id.value), |                 ); | ||||||
|                         loc.source(db).map(|src| { |                 let fields = lower_field_list( | ||||||
|                             variant.fields.iter().zip( |                     db, | ||||||
|                                 src.field_list() |                     parent.container, | ||||||
|                                     .map(|it| { |                     source.map(|src| src.field_list()), | ||||||
|                                         match it { |                     Some(override_visibility), | ||||||
|                                             ast::FieldList::RecordFieldList(record_field_list) => { |                 ); | ||||||
|                                                 Either::Left(record_field_list.fields().map(|it| { |                 (shape, fields) | ||||||
|                                                     (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), |  | ||||||
|                     ), |  | ||||||
|                 ) |  | ||||||
|             } |             } | ||||||
|             VariantId::StructId(id) => { |             VariantId::StructId(id) => { | ||||||
|                 let loc = id.lookup(db); |                 let loc = id.lookup(db); | ||||||
|                 let item_tree = loc.id.item_tree(db); |                 let source = loc.source(db); | ||||||
|                 let strukt = &item_tree[loc.id.value]; |                 let shape = adt_shape(source.value.kind()); | ||||||
|                 ( |                 let fields = | ||||||
|                     strukt.shape, |                     lower_field_list(db, loc.container, source.map(|src| src.field_list()), None); | ||||||
|                     lower_fields( |                 (shape, 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, |  | ||||||
|                     ), |  | ||||||
|                 ) |  | ||||||
|             } |             } | ||||||
|             VariantId::UnionId(id) => { |             VariantId::UnionId(id) => { | ||||||
|                 let loc = id.lookup(db); |                 let loc = id.lookup(db); | ||||||
|                 let item_tree = loc.id.item_tree(db); |                 let source = loc.source(db); | ||||||
|                 let union = &item_tree[loc.id.value]; |                 let fields = lower_field_list( | ||||||
|                 ( |                     db, | ||||||
|                     FieldsShape::Record, |                     loc.container, | ||||||
|                     lower_fields( |                     source.map(|src| src.record_field_list().map(ast::FieldList::RecordFieldList)), | ||||||
|                         db, |                     None, | ||||||
|                         loc.container, |                 ); | ||||||
|                         &item_tree, |                 (FieldsShape::Record, fields) | ||||||
|                         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(), |  | ||||||
|                             ) |  | ||||||
|                         }), |  | ||||||
|                         None, |  | ||||||
|                     ), |  | ||||||
|                 ) |  | ||||||
|             } |             } | ||||||
|         }; |         }; | ||||||
| 
 | 
 | ||||||
|  | @ -860,39 +794,81 @@ impl VariantFields { | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fn lower_fields<'a>( | fn lower_field_list( | ||||||
|     db: &dyn DefDatabase, |     db: &dyn DefDatabase, | ||||||
|     module: ModuleId, |     module: ModuleId, | ||||||
|     item_tree: &ItemTree, |     fields: InFile<Option<ast::FieldList>>, | ||||||
|     parent: FieldParent, |     override_visibility: Option<RawVisibility>, | ||||||
|     fields: InFile<impl Iterator<Item = (&'a Field, (SyntaxNodePtr, Option<ast::Type>))>>, | ) -> (Arena<FieldData>, ExpressionStore, ExpressionStoreSourceMap) { | ||||||
|     override_visibility: Option<RawVisibilityId>, |     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) { | ) -> (Arena<FieldData>, ExpressionStore, ExpressionStoreSourceMap) { | ||||||
|     let mut arena = Arena::new(); |     let mut arena = Arena::new(); | ||||||
|     let cfg_options = module.krate.cfg_options(db); |     let cfg_options = module.krate.cfg_options(db); | ||||||
|     let mut col = ExprCollector::new(db, module, fields.file_id); |     let mut col = ExprCollector::new(db, module, fields.file_id); | ||||||
|     for (idx, (field, (ptr, ty))) in fields.value.enumerate() { |     let mut idx = 0; | ||||||
|         let attr_owner = AttrOwner::make_field_indexed(parent, idx); |     for (ty, field) in fields.value { | ||||||
|         let attrs = item_tree.attrs(db, module.krate, attr_owner); |         match Attrs::is_cfg_enabled_for(db, &field, col.span_map(), cfg_options) { | ||||||
|         if attrs.is_cfg_enabled(cfg_options) { |             Ok(()) => { | ||||||
|             arena.alloc(FieldData { |                 let type_ref = | ||||||
|                 name: field.name.clone(), |                     col.lower_type_ref_opt(ty, &mut ExprCollector::impl_trait_error_allocator); | ||||||
|                 type_ref: col |                 let visibility = override_visibility.clone().unwrap_or_else(|| { | ||||||
|                     .lower_type_ref_opt(ty, &mut ExprCollector::impl_trait_error_allocator), |                     visibility_from_ast(db, field.visibility(), &mut |range| { | ||||||
|                 visibility: item_tree[override_visibility.unwrap_or(field.visibility)].clone(), |                         col.span_map().span_for_range(range).ctx | ||||||
|                 is_unsafe: field.is_unsafe, |                     }) | ||||||
|             }); |                 }); | ||||||
|         } else { |                 let is_unsafe = field | ||||||
|             col.source_map.diagnostics.push( |                     .syntax() | ||||||
|                 crate::expr_store::ExpressionStoreDiagnostics::InactiveCode { |                     .children_with_tokens() | ||||||
|                     node: InFile::new(fields.file_id, ptr), |                     .filter_map(NodeOrToken::into_token) | ||||||
|                     cfg: attrs.cfg().unwrap(), |                     .any(|token| token.kind() == T![unsafe]); | ||||||
|                     opts: cfg_options.clone(), |                 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, SyntaxNodePtr::new(field.syntax())), | ||||||
|  |                         cfg, | ||||||
|  |                         opts: cfg_options.clone(), | ||||||
|  |                     }, | ||||||
|  |                 ); | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     let store = col.store.finish(); |     let store = col.store.finish(); | ||||||
|  |     arena.shrink_to_fit(); | ||||||
|     (arena, store, col.source_map) |     (arena, store, col.source_map) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -905,7 +881,7 @@ pub struct InactiveEnumVariantCode { | ||||||
| 
 | 
 | ||||||
| #[derive(Debug, Clone, PartialEq, Eq)] | #[derive(Debug, Clone, PartialEq, Eq)] | ||||||
| pub struct EnumVariants { | pub struct EnumVariants { | ||||||
|     pub variants: Box<[(EnumVariantId, Name)]>, |     pub variants: Box<[(EnumVariantId, Name, FieldsShape)]>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl EnumVariants { | impl EnumVariants { | ||||||
|  | @ -914,30 +890,38 @@ impl EnumVariants { | ||||||
|         e: EnumId, |         e: EnumId, | ||||||
|     ) -> (Arc<EnumVariants>, Option<Arc<ThinVec<InactiveEnumVariantCode>>>) { |     ) -> (Arc<EnumVariants>, Option<Arc<ThinVec<InactiveEnumVariantCode>>>) { | ||||||
|         let loc = e.lookup(db); |         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 mut diagnostics = ThinVec::new(); | ||||||
|         let cfg_options = loc.container.krate.cfg_options(db); |         let cfg_options = loc.container.krate.cfg_options(db); | ||||||
|         let mut index = 0; |         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| { |             .filter_map(|variant| { | ||||||
|                 let attrs = item_tree.attrs(db, loc.container.krate, variant.into()); |                 let ast_id = ast_id_map.ast_id(&variant); | ||||||
|                 if attrs.is_cfg_enabled(cfg_options) { |                 match Attrs::is_cfg_enabled_for(db, &variant, span_map.as_ref(), cfg_options) { | ||||||
|                     let enum_variant = EnumVariantLoc { |                     Ok(()) => { | ||||||
|                         id: ItemTreeId::new(loc.id.tree_id(), variant), |                         let enum_variant = | ||||||
|                         parent: e, |                             EnumVariantLoc { id: source.with_value(ast_id), parent: e, index } | ||||||
|                         index, |                                 .intern(db); | ||||||
|  |                         index += 1; | ||||||
|  |                         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, | ||||||
|  |                             cfg, | ||||||
|  |                             opts: cfg_options.clone(), | ||||||
|  |                         }); | ||||||
|  |                         None | ||||||
|                     } |                     } | ||||||
|                     .intern(db); |  | ||||||
|                     index += 1; |  | ||||||
|                     Some((enum_variant, item_tree[variant].name.clone())) |  | ||||||
|                 } else { |  | ||||||
|                     diagnostics.push(InactiveEnumVariantCode { |  | ||||||
|                         ast_id: item_tree[variant].ast_id, |  | ||||||
|                         cfg: attrs.cfg().unwrap(), |  | ||||||
|                         opts: cfg_options.clone(), |  | ||||||
|                     }); |  | ||||||
|                     None |  | ||||||
|                 } |                 } | ||||||
|             }) |             }) | ||||||
|             .collect(); |             .collect(); | ||||||
|  | @ -949,12 +933,18 @@ impl EnumVariants { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn variant(&self, name: &Name) -> Option<EnumVariantId> { |     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)
 |     // [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 { |     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
 |             // The condition check order is slightly modified from rustc
 | ||||||
|             // to improve performance by early returning with relatively fast checks
 |             // to improve performance by early returning with relatively fast checks
 | ||||||
|             let variant = &db.variant_fields(v.into()); |             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.
 | //! Utilities for mapping between hir IDs and the surface syntax.
 | ||||||
| 
 | 
 | ||||||
| use either::Either; | use either::Either; | ||||||
| use hir_expand::InFile; | use hir_expand::{AstId, InFile}; | ||||||
| use la_arena::ArenaMap; | use la_arena::{Arena, ArenaMap, Idx}; | ||||||
| use syntax::{AstNode, AstPtr, ast}; | use syntax::{AstNode, AstPtr, ast}; | ||||||
| 
 | 
 | ||||||
| use crate::{ | use crate::{ | ||||||
|     GenericDefId, ItemTreeLoc, LocalFieldId, LocalLifetimeParamId, LocalTypeOrConstParamId, Lookup, |     AstIdLoc, GenericDefId, LocalFieldId, LocalLifetimeParamId, LocalTypeOrConstParamId, Lookup, | ||||||
|     UseId, VariantId, |     UseId, VariantId, attr::Attrs, db::DefDatabase, | ||||||
|     db::DefDatabase, |  | ||||||
|     item_tree::{AttrOwner, FieldParent, ItemTreeNode}, |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| pub trait HasSource { | pub trait HasSource { | ||||||
|  | @ -23,18 +21,13 @@ pub trait HasSource { | ||||||
| 
 | 
 | ||||||
| impl<T> HasSource for T | impl<T> HasSource for T | ||||||
| where | where | ||||||
|     T: ItemTreeLoc, |     T: AstIdLoc, | ||||||
|     T::Id: ItemTreeNode, |  | ||||||
| { | { | ||||||
|     type Value = <T::Id as ItemTreeNode>::Source; |     type Value = T::Ast; | ||||||
|     fn ast_ptr(&self, db: &dyn DefDatabase) -> InFile<AstPtr<Self::Value>> { |     fn ast_ptr(&self, db: &dyn DefDatabase) -> InFile<AstPtr<Self::Value>> { | ||||||
|         let id = self.item_tree_id(); |         let id = self.ast_id(); | ||||||
|         let file_id = id.file_id(); |         let ast_id_map = db.ast_id_map(id.file_id); | ||||||
|         let tree = id.item_tree(db); |         InFile::new(id.file_id, ast_id_map.get(id.value)) | ||||||
|         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())) |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -43,18 +36,37 @@ pub trait HasChildSource<ChildId> { | ||||||
|     fn child_source(&self, db: &dyn DefDatabase) -> InFile<ArenaMap<ChildId, Self::Value>>; |     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 { | impl HasChildSource<la_arena::Idx<ast::UseTree>> for UseId { | ||||||
|     type Value = ast::UseTree; |     type Value = ast::UseTree; | ||||||
|     fn child_source( |     fn child_source( | ||||||
|         &self, |         &self, | ||||||
|         db: &dyn DefDatabase, |         db: &dyn DefDatabase, | ||||||
|     ) -> InFile<ArenaMap<la_arena::Idx<ast::UseTree>, Self::Value>> { |     ) -> InFile<ArenaMap<la_arena::Idx<ast::UseTree>, Self::Value>> { | ||||||
|         let loc = &self.lookup(db); |         let loc = self.lookup(db); | ||||||
|         let use_ = &loc.id.item_tree(db)[loc.id.value]; |         InFile::new(loc.id.file_id, use_tree_source_map(db, loc.id).into_iter().collect()) | ||||||
|         InFile::new( |  | ||||||
|             loc.id.file_id(), |  | ||||||
|             use_.use_tree_source_map(db, loc.id.file_id()).into_iter().collect(), |  | ||||||
|         ) |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -124,49 +136,30 @@ impl HasChildSource<LocalFieldId> for VariantId { | ||||||
|     type Value = Either<ast::TupleField, ast::RecordField>; |     type Value = Either<ast::TupleField, ast::RecordField>; | ||||||
| 
 | 
 | ||||||
|     fn child_source(&self, db: &dyn DefDatabase) -> InFile<ArenaMap<LocalFieldId, Self::Value>> { |     fn child_source(&self, db: &dyn DefDatabase) -> InFile<ArenaMap<LocalFieldId, Self::Value>> { | ||||||
|         let item_tree; |         let (src, container) = match *self { | ||||||
|         let (src, parent, container) = match *self { |  | ||||||
|             VariantId::EnumVariantId(it) => { |             VariantId::EnumVariantId(it) => { | ||||||
|                 let lookup = it.lookup(db); |                 let lookup = it.lookup(db); | ||||||
|                 item_tree = lookup.id.item_tree(db); |                 (lookup.source(db).map(|it| it.kind()), lookup.parent.lookup(db).container) | ||||||
|                 ( |  | ||||||
|                     lookup.source(db).map(|it| it.kind()), |  | ||||||
|                     FieldParent::EnumVariant(lookup.id.value), |  | ||||||
|                     lookup.parent.lookup(db).container, |  | ||||||
|                 ) |  | ||||||
|             } |             } | ||||||
|             VariantId::StructId(it) => { |             VariantId::StructId(it) => { | ||||||
|                 let lookup = it.lookup(db); |                 let lookup = it.lookup(db); | ||||||
|                 item_tree = lookup.id.item_tree(db); |                 (lookup.source(db).map(|it| it.kind()), lookup.container) | ||||||
|                 ( |  | ||||||
|                     lookup.source(db).map(|it| it.kind()), |  | ||||||
|                     FieldParent::Struct(lookup.id.value), |  | ||||||
|                     lookup.container, |  | ||||||
|                 ) |  | ||||||
|             } |             } | ||||||
|             VariantId::UnionId(it) => { |             VariantId::UnionId(it) => { | ||||||
|                 let lookup = it.lookup(db); |                 let lookup = it.lookup(db); | ||||||
|                 item_tree = lookup.id.item_tree(db); |                 (lookup.source(db).map(|it| it.kind()), lookup.container) | ||||||
|                 ( |  | ||||||
|                     lookup.source(db).map(|it| it.kind()), |  | ||||||
|                     FieldParent::Union(lookup.id.value), |  | ||||||
|                     lookup.container, |  | ||||||
|                 ) |  | ||||||
|             } |             } | ||||||
|         }; |         }; | ||||||
| 
 |         let span_map = db.span_map(src.file_id); | ||||||
|         let mut map = ArenaMap::new(); |         let mut map = ArenaMap::new(); | ||||||
|         match &src.value { |         match &src.value { | ||||||
|             ast::StructKind::Tuple(fl) => { |             ast::StructKind::Tuple(fl) => { | ||||||
|                 let cfg_options = container.krate.cfg_options(db); |                 let cfg_options = container.krate.cfg_options(db); | ||||||
|                 let mut idx = 0; |                 let mut idx = 0; | ||||||
|                 for (i, fd) in fl.fields().enumerate() { |                 for fd in fl.fields() { | ||||||
|                     let attrs = item_tree.attrs( |                     let enabled = | ||||||
|                         db, |                         Attrs::is_cfg_enabled_for(db, &fd, span_map.as_ref(), cfg_options).is_ok(); | ||||||
|                         container.krate, |                     if !enabled { | ||||||
|                         AttrOwner::make_field_indexed(parent, i), |  | ||||||
|                     ); |  | ||||||
|                     if !attrs.is_cfg_enabled(cfg_options) { |  | ||||||
|                         continue; |                         continue; | ||||||
|                     } |                     } | ||||||
|                     map.insert( |                     map.insert( | ||||||
|  | @ -179,13 +172,10 @@ impl HasChildSource<LocalFieldId> for VariantId { | ||||||
|             ast::StructKind::Record(fl) => { |             ast::StructKind::Record(fl) => { | ||||||
|                 let cfg_options = container.krate.cfg_options(db); |                 let cfg_options = container.krate.cfg_options(db); | ||||||
|                 let mut idx = 0; |                 let mut idx = 0; | ||||||
|                 for (i, fd) in fl.fields().enumerate() { |                 for fd in fl.fields() { | ||||||
|                     let attrs = item_tree.attrs( |                     let enabled = | ||||||
|                         db, |                         Attrs::is_cfg_enabled_for(db, &fd, span_map.as_ref(), cfg_options).is_ok(); | ||||||
|                         container.krate, |                     if !enabled { | ||||||
|                         AttrOwner::make_field_indexed(parent, i), |  | ||||||
|                     ); |  | ||||||
|                     if !attrs.is_cfg_enabled(cfg_options) { |  | ||||||
|                         continue; |                         continue; | ||||||
|                     } |                     } | ||||||
|                     map.insert( |                     map.insert( | ||||||
|  | @ -195,7 +185,7 @@ impl HasChildSource<LocalFieldId> for VariantId { | ||||||
|                     idx += 1; |                     idx += 1; | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             _ => (), |             ast::StructKind::Unit => (), | ||||||
|         } |         } | ||||||
|         InFile::new(src.file_id, map) |         InFile::new(src.file_id, map) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -2,16 +2,18 @@ | ||||||
| 
 | 
 | ||||||
| use std::iter; | use std::iter; | ||||||
| 
 | 
 | ||||||
| use hir_expand::Lookup; | use hir_expand::{InFile, Lookup}; | ||||||
| use la_arena::ArenaMap; | use la_arena::ArenaMap; | ||||||
|  | use syntax::ast::{self, HasVisibility}; | ||||||
| use triomphe::Arc; | use triomphe::Arc; | ||||||
| 
 | 
 | ||||||
| use crate::{ | use crate::{ | ||||||
|     ConstId, FunctionId, HasModule, ItemContainerId, ItemLoc, ItemTreeLoc, LocalFieldId, |     ConstId, FunctionId, HasModule, ItemContainerId, LocalFieldId, LocalModuleId, ModuleId, | ||||||
|     LocalModuleId, ModuleId, TraitId, TypeAliasId, VariantId, |     TraitId, TypeAliasId, VariantId, | ||||||
|     db::DefDatabase, |     db::DefDatabase, | ||||||
|     nameres::DefMap, |     nameres::DefMap, | ||||||
|     resolver::{HasResolver, Resolver}, |     resolver::{HasResolver, Resolver}, | ||||||
|  |     src::HasSource, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| pub use crate::item_tree::{RawVisibility, VisibilityExplicitness}; | 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() { |     for (field_id, field_data) in fields.iter() { | ||||||
|         res.insert(field_id, Visibility::resolve(db, &resolver, &field_data.visibility)); |         res.insert(field_id, Visibility::resolve(db, &resolver, &field_data.visibility)); | ||||||
|     } |     } | ||||||
|  |     res.shrink_to_fit(); | ||||||
|     Arc::new(res) |     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.
 | /// Resolve visibility of a function.
 | ||||||
| pub(crate) fn function_visibility_query(db: &dyn DefDatabase, def: FunctionId) -> Visibility { | pub(crate) fn function_visibility_query(db: &dyn DefDatabase, def: FunctionId) -> Visibility { | ||||||
|     let resolver = def.resolver(db); |  | ||||||
|     let loc = def.lookup(db); |     let loc = def.lookup(db); | ||||||
|     let tree = loc.item_tree_id().item_tree(db); |     let resolver = def.resolver(db); | ||||||
|     if let ItemContainerId::TraitId(trait_id) = loc.container { |     trait_item_visibility(db, &resolver, loc.container).unwrap_or_else(|| { | ||||||
|         trait_vis(db, &resolver, trait_id) |         let source = loc.source(db); | ||||||
|     } else { |         visibility_from_ast(db, &resolver, source.map(|src| src.visibility())) | ||||||
|         Visibility::resolve(db, &resolver, &tree[tree[loc.id.value].visibility]) |     }) | ||||||
|     } |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /// Resolve visibility of a const.
 | /// Resolve visibility of a const.
 | ||||||
| pub(crate) fn const_visibility_query(db: &dyn DefDatabase, def: ConstId) -> Visibility { | pub(crate) fn const_visibility_query(db: &dyn DefDatabase, def: ConstId) -> Visibility { | ||||||
|     let resolver = def.resolver(db); |  | ||||||
|     let loc = def.lookup(db); |     let loc = def.lookup(db); | ||||||
|     let tree = loc.item_tree_id().item_tree(db); |     let resolver = def.resolver(db); | ||||||
|     if let ItemContainerId::TraitId(trait_id) = loc.container { |     trait_item_visibility(db, &resolver, loc.container).unwrap_or_else(|| { | ||||||
|         trait_vis(db, &resolver, trait_id) |         let source = loc.source(db); | ||||||
|     } else { |         visibility_from_ast(db, &resolver, source.map(|src| src.visibility())) | ||||||
|         Visibility::resolve(db, &resolver, &tree[tree[loc.id.value].visibility]) |     }) | ||||||
|     } |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /// Resolve visibility of a type alias.
 | /// Resolve visibility of a type alias.
 | ||||||
| pub(crate) fn type_alias_visibility_query(db: &dyn DefDatabase, def: TypeAliasId) -> Visibility { | pub(crate) fn type_alias_visibility_query(db: &dyn DefDatabase, def: TypeAliasId) -> Visibility { | ||||||
|     let resolver = def.resolver(db); |  | ||||||
|     let loc = def.lookup(db); |     let loc = def.lookup(db); | ||||||
|     let tree = loc.item_tree_id().item_tree(db); |     let resolver = def.resolver(db); | ||||||
|     if let ItemContainerId::TraitId(trait_id) = loc.container { |     trait_item_visibility(db, &resolver, loc.container).unwrap_or_else(|| { | ||||||
|         trait_vis(db, &resolver, trait_id) |         let source = loc.source(db); | ||||||
|     } else { |         visibility_from_ast(db, &resolver, source.map(|src| src.visibility())) | ||||||
|         Visibility::resolve(db, &resolver, &tree[tree[loc.id.value].visibility]) |     }) | ||||||
|     } |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[inline] | pub(crate) fn trait_visibility( | ||||||
| fn trait_vis(db: &dyn DefDatabase, resolver: &Resolver<'_>, trait_id: TraitId) -> Visibility { |     db: &dyn DefDatabase, | ||||||
|     let ItemLoc { id: tree_id, .. } = trait_id.lookup(db); |     resolver: &Resolver<'_>, | ||||||
|     let item_tree = tree_id.item_tree(db); |     def: TraitId, | ||||||
|     let tr_def = &item_tree[tree_id.value]; | ) -> Visibility { | ||||||
|     Visibility::resolve(db, resolver, &item_tree[tr_def.visibility]) |     let loc = def.lookup(db); | ||||||
|  |     let source = loc.source(db); | ||||||
|  |     visibility_from_ast(db, resolver, source.map(|src| src.visibility())) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -277,8 +277,8 @@ mod tests { | ||||||
|         assert_eq!(quoted.to_string(), "hello"); |         assert_eq!(quoted.to_string(), "hello"); | ||||||
|         let t = format!("{quoted:#?}"); |         let t = format!("{quoted:#?}"); | ||||||
|         expect![[r#" |         expect![[r#" | ||||||
|             SUBTREE $$ 937550:0@0..0#ROOT2024 937550:0@0..0#ROOT2024 |             SUBTREE $$ 937550:Root[0000, 0]@0..0#ROOT2024 937550:Root[0000, 0]@0..0#ROOT2024 | ||||||
|               IDENT   hello 937550:0@0..0#ROOT2024"#]]
 |               IDENT   hello 937550:Root[0000, 0]@0..0#ROOT2024"#]]
 | ||||||
|         .assert_eq(&t); |         .assert_eq(&t); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -60,6 +60,7 @@ pub trait ExpandDatabase: RootQueryDb { | ||||||
|     fn proc_macros_for_crate(&self, krate: Crate) -> Option<Arc<CrateProcMacros>>; |     fn proc_macros_for_crate(&self, krate: Crate) -> Option<Arc<CrateProcMacros>>; | ||||||
| 
 | 
 | ||||||
|     #[salsa::invoke(ast_id_map)] |     #[salsa::invoke(ast_id_map)] | ||||||
|  |     #[salsa::lru(1024)] | ||||||
|     fn ast_id_map(&self, file_id: HirFileId) -> Arc<AstIdMap>; |     fn ast_id_map(&self, file_id: HirFileId) -> Arc<AstIdMap>; | ||||||
| 
 | 
 | ||||||
|     #[salsa::transparent] |     #[salsa::transparent] | ||||||
|  |  | ||||||
|  | @ -106,7 +106,7 @@ impl FileRange { | ||||||
| /// It is stable across reparses, and can be used as salsa key/value.
 | /// It is stable across reparses, and can be used as salsa key/value.
 | ||||||
| pub type AstId<N> = crate::InFile<FileAstId<N>>; | pub type AstId<N> = crate::InFile<FileAstId<N>>; | ||||||
| 
 | 
 | ||||||
| impl<N: AstIdNode> AstId<N> { | impl<N: AstNode> AstId<N> { | ||||||
|     pub fn to_node(&self, db: &dyn ExpandDatabase) -> N { |     pub fn to_node(&self, db: &dyn ExpandDatabase) -> N { | ||||||
|         self.to_ptr(db).to_node(&db.parse_or_expand(self.file_id)) |         self.to_ptr(db).to_node(&db.parse_or_expand(self.file_id)) | ||||||
|     } |     } | ||||||
|  | @ -122,6 +122,13 @@ impl<N: AstIdNode> AstId<N> { | ||||||
|     pub fn erase(&self) -> ErasedAstId { |     pub fn erase(&self) -> ErasedAstId { | ||||||
|         crate::InFile::new(self.file_id, self.value.erase()) |         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>; | pub type ErasedAstId = crate::InFile<ErasedFileAstId>; | ||||||
|  |  | ||||||
|  | @ -817,7 +817,7 @@ pub(crate) fn adt_datum_query( | ||||||
|                 .enum_variants(id) |                 .enum_variants(id) | ||||||
|                 .variants |                 .variants | ||||||
|                 .iter() |                 .iter() | ||||||
|                 .map(|&(variant_id, _)| variant_id_to_fields(variant_id.into())) |                 .map(|&(variant_id, _, _)| variant_id_to_fields(variant_id.into())) | ||||||
|                 .collect(); |                 .collect(); | ||||||
|             (rust_ir::AdtKind::Enum, variants) |             (rust_ir::AdtKind::Enum, variants) | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  | @ -397,7 +397,7 @@ impl<'a> DeclValidator<'a> { | ||||||
|     fn validate_enum_variants(&mut self, enum_id: EnumId) { |     fn validate_enum_variants(&mut self, enum_id: EnumId) { | ||||||
|         let data = self.db.enum_variants(enum_id); |         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); |             self.validate_enum_variant_fields(*variant_id); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | @ -405,7 +405,7 @@ impl<'a> DeclValidator<'a> { | ||||||
|         let mut enum_variants_replacements = data |         let mut enum_variants_replacements = data | ||||||
|             .variants |             .variants | ||||||
|             .iter() |             .iter() | ||||||
|             .filter_map(|(_, name)| { |             .filter_map(|(_, name, _)| { | ||||||
|                 to_camel_case(&name.display_no_db(edition).to_smolstr()).map(|new_name| { |                 to_camel_case(&name.display_no_db(edition).to_smolstr()).map(|new_name| { | ||||||
|                     Replacement { |                     Replacement { | ||||||
|                         current_name: name.clone(), |                         current_name: name.clone(), | ||||||
|  |  | ||||||
|  | @ -465,7 +465,7 @@ impl PatCx for MatchCheckCtx<'_> { | ||||||
|                     ConstructorSet::NoConstructors |                     ConstructorSet::NoConstructors | ||||||
|                 } else { |                 } else { | ||||||
|                     let mut variants = IndexVec::with_capacity(enum_data.variants.len()); |                     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( |                         let is_uninhabited = is_enum_variant_uninhabited_from( | ||||||
|                             cx.db, |                             cx.db, | ||||||
|                             variant, |                             variant, | ||||||
|  |  | ||||||
|  | @ -71,7 +71,7 @@ pub(crate) fn has_drop_glue(db: &dyn HirDatabase, ty: Ty, env: Arc<TraitEnvironm | ||||||
|                     .enum_variants(id) |                     .enum_variants(id) | ||||||
|                     .variants |                     .variants | ||||||
|                     .iter() |                     .iter() | ||||||
|                     .map(|&(variant, _)| { |                     .map(|&(variant, _, _)| { | ||||||
|                         db.field_types(variant.into()) |                         db.field_types(variant.into()) | ||||||
|                             .iter() |                             .iter() | ||||||
|                             .map(|(_, field_ty)| { |                             .map(|(_, field_ty)| { | ||||||
|  |  | ||||||
|  | @ -115,7 +115,7 @@ impl UninhabitedFrom<'_> { | ||||||
|             AdtId::EnumId(e) => { |             AdtId::EnumId(e) => { | ||||||
|                 let enum_data = self.db.enum_variants(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); |                     let variant_inhabitedness = self.visit_variant(variant.into(), subst); | ||||||
|                     match variant_inhabitedness { |                     match variant_inhabitedness { | ||||||
|                         Break(VisiblyUninhabited) => (), |                         Break(VisiblyUninhabited) => (), | ||||||
|  |  | ||||||
|  | @ -60,7 +60,7 @@ pub fn layout_of_adt_query( | ||||||
|             let r = variants |             let r = variants | ||||||
|                 .variants |                 .variants | ||||||
|                 .iter() |                 .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<_>, _>>()?; |                 .collect::<Result<SmallVec<_>, _>>()?; | ||||||
|             (r, db.enum_signature(e).repr.unwrap_or_default(), false) |             (r, db.enum_signature(e).repr.unwrap_or_default(), false) | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  | @ -2771,12 +2771,15 @@ impl Evaluator<'_> { | ||||||
|             Err(e) => { |             Err(e) => { | ||||||
|                 let db = self.db; |                 let db = self.db; | ||||||
|                 let loc = variant.lookup(db); |                 let loc = variant.lookup(db); | ||||||
|                 let enum_loc = loc.parent.lookup(db); |  | ||||||
|                 let edition = self.crate_id.data(self.db).edition; |                 let edition = self.crate_id.data(self.db).edition; | ||||||
|                 let name = format!( |                 let name = format!( | ||||||
|                     "{}::{}", |                     "{}::{}", | ||||||
|                     enum_loc.id.item_tree(db)[enum_loc.id.value].name.display(db, edition), |                     self.db.enum_signature(loc.parent).name.display(db, edition), | ||||||
|                     loc.id.item_tree(db)[loc.id.value].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))) |                 Err(MirEvalError::ConstEvalError(name, Box::new(e))) | ||||||
|             } |             } | ||||||
|  |  | ||||||
|  | @ -65,9 +65,7 @@ impl Evaluator<'_> { | ||||||
|                 Some(abi) => *abi == sym::rust_dash_intrinsic, |                 Some(abi) => *abi == sym::rust_dash_intrinsic, | ||||||
|                 None => match def.lookup(self.db).container { |                 None => match def.lookup(self.db).container { | ||||||
|                     hir_def::ItemContainerId::ExternBlockId(block) => { |                     hir_def::ItemContainerId::ExternBlockId(block) => { | ||||||
|                         let id = block.lookup(self.db).id; |                         self.db.extern_block_abi(block) == Some(sym::rust_dash_intrinsic) | ||||||
|                         id.item_tree(self.db)[id.value].abi.as_ref() |  | ||||||
|                             == Some(&sym::rust_dash_intrinsic) |  | ||||||
|                     } |                     } | ||||||
|                     _ => false, |                     _ => false, | ||||||
|                 }, |                 }, | ||||||
|  | @ -87,8 +85,7 @@ impl Evaluator<'_> { | ||||||
|         } |         } | ||||||
|         let is_extern_c = match def.lookup(self.db).container { |         let is_extern_c = match def.lookup(self.db).container { | ||||||
|             hir_def::ItemContainerId::ExternBlockId(block) => { |             hir_def::ItemContainerId::ExternBlockId(block) => { | ||||||
|                 let id = block.lookup(self.db).id; |                 self.db.extern_block_abi(block) == Some(sym::C) | ||||||
|                 id.item_tree(self.db)[id.value].abi.as_ref() == Some(&sym::C) |  | ||||||
|             } |             } | ||||||
|             _ => false, |             _ => false, | ||||||
|         }; |         }; | ||||||
|  |  | ||||||
|  | @ -1922,11 +1922,14 @@ impl<'ctx> MirLowerCtx<'ctx> { | ||||||
|                 let edition = self.edition(); |                 let edition = self.edition(); | ||||||
|                 let db = self.db; |                 let db = self.db; | ||||||
|                 let loc = variant.lookup(db); |                 let loc = variant.lookup(db); | ||||||
|                 let enum_loc = loc.parent.lookup(db); |  | ||||||
|                 let name = format!( |                 let name = format!( | ||||||
|                     "{}::{}", |                     "{}::{}", | ||||||
|                     enum_loc.id.item_tree(db)[enum_loc.id.value].name.display(db, edition), |                     self.db.enum_signature(loc.parent).name.display(db, edition), | ||||||
|                     loc.id.item_tree(db)[loc.id.value].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))) |                 Err(MirLowerError::ConstEvalError(name.into(), Box::new(e))) | ||||||
|             } |             } | ||||||
|  |  | ||||||
|  | @ -63,16 +63,15 @@ impl MirBody { | ||||||
|             } |             } | ||||||
|             hir_def::DefWithBodyId::VariantId(id) => { |             hir_def::DefWithBodyId::VariantId(id) => { | ||||||
|                 let loc = id.lookup(db); |                 let loc = id.lookup(db); | ||||||
|                 let enum_loc = loc.parent.lookup(db); |                 let edition = this.display_target.edition; | ||||||
|                 w!( |                 w!( | ||||||
|                     this, |                     this, | ||||||
|                     "enum {}::{} = ", |                     "enum {}::{} = ", | ||||||
|                     enum_loc.id.item_tree(db)[enum_loc.id.value] |                     db.enum_signature(loc.parent).name.display(db, edition), | ||||||
|                         .name |                     db.enum_variants(loc.parent) | ||||||
|                         .display(db, this.display_target.edition), |                         .variant_name_by_id(id) | ||||||
|                     loc.id.item_tree(db)[loc.id.value] |                         .unwrap() | ||||||
|                         .name |                         .display(db, edition), | ||||||
|                         .display(db, this.display_target.edition), |  | ||||||
|                 ) |                 ) | ||||||
|             } |             } | ||||||
|         }); |         }); | ||||||
|  |  | ||||||
|  | @ -479,7 +479,7 @@ pub(crate) fn visit_module( | ||||||
|                     visit_body(db, &body, cb); |                     visit_body(db, &body, cb); | ||||||
|                 } |                 } | ||||||
|                 ModuleDefId::AdtId(hir_def::AdtId::EnumId(it)) => { |                 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()); |                         let body = db.body(it.into()); | ||||||
|                         cb(it.into()); |                         cb(it.into()); | ||||||
|                         visit_body(db, &body, cb); |                         visit_body(db, &body, cb); | ||||||
|  |  | ||||||
|  | @ -353,6 +353,7 @@ impl SomeStruct { | ||||||
|             "impl_self_ty_with_diagnostics_shim".to_owned(), |             "impl_self_ty_with_diagnostics_shim".to_owned(), | ||||||
|             "struct_signature_shim".to_owned(), |             "struct_signature_shim".to_owned(), | ||||||
|             "struct_signature_with_source_map_shim".to_owned(), |             "struct_signature_with_source_map_shim".to_owned(), | ||||||
|  |             "attrs_shim".to_owned(), | ||||||
|             "type_for_adt_tracked".to_owned(), |             "type_for_adt_tracked".to_owned(), | ||||||
|         ]; |         ]; | ||||||
| 
 | 
 | ||||||
|  | @ -442,6 +443,6 @@ fn main() { | ||||||
|                 let _inference_result = db.infer(def); |                 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); |     let loc = func.lookup(db); | ||||||
|     match loc.container { |     match loc.container { | ||||||
|         hir_def::ItemContainerId::ExternBlockId(block) => { |         hir_def::ItemContainerId::ExternBlockId(block) => { | ||||||
|             let id = block.lookup(db).id; |             let is_intrinsic_block = db.extern_block_abi(block) == Some(sym::rust_dash_intrinsic); | ||||||
|             let is_intrinsic_block = |  | ||||||
|                 id.item_tree(db)[id.value].abi.as_ref() == Some(&sym::rust_dash_intrinsic); |  | ||||||
|             if is_intrinsic_block { |             if is_intrinsic_block { | ||||||
|                 // legacy intrinsics
 |                 // legacy intrinsics
 | ||||||
|                 // extern "rust-intrinsic" intrinsics are unsafe unless they have the rustc_safe_intrinsic attribute
 |                 // 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::StructId(s) => add_constraints_from_variant(VariantId::StructId(s)), | ||||||
|                     AdtId::UnionId(u) => add_constraints_from_variant(VariantId::UnionId(u)), |                     AdtId::UnionId(u) => add_constraints_from_variant(VariantId::UnionId(u)), | ||||||
|                     AdtId::EnumId(e) => { |                     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)) |                             add_constraints_from_variant(VariantId::EnumVariantId(variant)) | ||||||
|                         }); |                         }); | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
|  | @ -52,12 +52,14 @@ use hir_def::{ | ||||||
|         BindingAnnotation, BindingId, Expr, ExprId, ExprOrPatId, LabelId, Pat, |         BindingAnnotation, BindingId, Expr, ExprId, ExprOrPatId, LabelId, Pat, | ||||||
|         generics::{LifetimeParamData, TypeOrConstParamData, TypeParamProvenance}, |         generics::{LifetimeParamData, TypeOrConstParamData, TypeParamProvenance}, | ||||||
|     }, |     }, | ||||||
|     item_tree::{AttrOwner, FieldParent, ImportAlias, ItemTreeFieldId, ItemTreeNode}, |     item_tree::ImportAlias, | ||||||
|     layout::{self, ReprOptions, TargetDataLayout}, |     layout::{self, ReprOptions, TargetDataLayout}, | ||||||
|     nameres::{self, diagnostics::DefDiagnostic}, |     nameres::{self, diagnostics::DefDiagnostic}, | ||||||
|     per_ns::PerNs, |     per_ns::PerNs, | ||||||
|     resolver::{HasResolver, Resolver}, |     resolver::{HasResolver, Resolver}, | ||||||
|     signatures::{ImplFlags, StaticFlags, TraitFlags, VariantFields}, |     signatures::{ImplFlags, StaticFlags, TraitFlags, VariantFields}, | ||||||
|  |     src::HasSource as _, | ||||||
|  |     visibility::visibility_from_ast, | ||||||
| }; | }; | ||||||
| use hir_expand::{ | use hir_expand::{ | ||||||
|     AstId, MacroCallKind, RenderedExpandError, ValueResult, attrs::collect_attrs, |     AstId, MacroCallKind, RenderedExpandError, ValueResult, attrs::collect_attrs, | ||||||
|  | @ -81,11 +83,11 @@ use itertools::Itertools; | ||||||
| use nameres::diagnostics::DefDiagnosticKind; | use nameres::diagnostics::DefDiagnosticKind; | ||||||
| use rustc_hash::FxHashSet; | use rustc_hash::FxHashSet; | ||||||
| use smallvec::SmallVec; | use smallvec::SmallVec; | ||||||
| use span::{Edition, FileId}; | use span::{AstIdNode, Edition, FileId}; | ||||||
| use stdx::{format_to, impl_from, never}; | use stdx::{format_to, impl_from, never}; | ||||||
| use syntax::{ | use syntax::{ | ||||||
|     AstNode, AstPtr, SmolStr, SyntaxNode, SyntaxNodePtr, T, TextRange, ToSmolStr, |     AstNode, AstPtr, SmolStr, SyntaxNode, SyntaxNodePtr, T, TextRange, ToSmolStr, | ||||||
|     ast::{self, HasAttrs as _, HasName}, |     ast::{self, HasAttrs as _, HasName, HasVisibility as _}, | ||||||
|     format_smolstr, |     format_smolstr, | ||||||
| }; | }; | ||||||
| use triomphe::{Arc, ThinArc}; | use triomphe::{Arc, ThinArc}; | ||||||
|  | @ -687,7 +689,7 @@ impl Module { | ||||||
|                             let source_map = db.enum_signature_with_source_map(e.id).1; |                             let source_map = db.enum_signature_with_source_map(e.id).1; | ||||||
|                             expr_store_diagnostics(db, acc, &source_map); |                             expr_store_diagnostics(db, acc, &source_map); | ||||||
|                             let (variants, diagnostics) = db.enum_variants_with_diagnostics(e.id); |                             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); |                             let ast_id_map = db.ast_id_map(file); | ||||||
|                             if let Some(diagnostics) = &diagnostics { |                             if let Some(diagnostics) = &diagnostics { | ||||||
|                                 for diag in diagnostics.iter() { |                                 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; |                                 let source_map = db.variant_fields_with_source_map(v.into()).1; | ||||||
|                                 push_ty_diagnostics( |                                 push_ty_diagnostics( | ||||||
|                                     db, |                                     db, | ||||||
|  | @ -742,12 +744,10 @@ impl Module { | ||||||
|             GenericDef::Impl(impl_def).diagnostics(db, acc); |             GenericDef::Impl(impl_def).diagnostics(db, acc); | ||||||
| 
 | 
 | ||||||
|             let loc = impl_def.id.lookup(db); |             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; |             let source_map = db.impl_signature_with_source_map(impl_def.id).1; | ||||||
|             expr_store_diagnostics(db, acc, &source_map); |             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) { |             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
 |                 // 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
 |                 // 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) { |             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) { |             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); |             let trait_ = impl_def.trait_(db); | ||||||
|  | @ -808,11 +808,11 @@ impl Module { | ||||||
|                 // unsafe negative impl
 |                 // unsafe negative impl
 | ||||||
|                 (true, _, true, _) | |                 (true, _, true, _) | | ||||||
|                 // unsafe impl for safe trait
 |                 // 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
 |                 // safe impl for unsafe trait
 | ||||||
|                 (false, true, false, _) | |                 (false, true, false, _) | | ||||||
|                 // safe impl of dangling drop
 |                 // 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 { |                         TraitImplRedundantAssocItems { | ||||||
|                             trait_, |                             trait_, | ||||||
|                             file_id, |                             file_id, | ||||||
|                             impl_: ast_id_map.get(node.ast_id()), |                             impl_: ast_id_map.get(loc.id.value), | ||||||
|                             assoc_item: (name, assoc_item), |                             assoc_item: (name, assoc_item), | ||||||
|                         } |                         } | ||||||
|                         .into(), |                         .into(), | ||||||
|  | @ -889,7 +889,7 @@ impl Module { | ||||||
|                 if !missing.is_empty() { |                 if !missing.is_empty() { | ||||||
|                     acc.push( |                     acc.push( | ||||||
|                         TraitImplMissingAssocItems { |                         TraitImplMissingAssocItems { | ||||||
|                             impl_: ast_id_map.get(node.ast_id()), |                             impl_: ast_id_map.get(loc.id.value), | ||||||
|                             file_id, |                             file_id, | ||||||
|                             missing, |                             missing, | ||||||
|                         } |                         } | ||||||
|  | @ -1076,73 +1076,25 @@ fn emit_def_diagnostic_( | ||||||
|             ) |             ) | ||||||
|         } |         } | ||||||
|         DefDiagnosticKind::UnresolvedImport { id, index } => { |         DefDiagnosticKind::UnresolvedImport { id, index } => { | ||||||
|             let file_id = id.file_id(); |             let file_id = id.file_id; | ||||||
|             let item_tree = id.item_tree(db); |  | ||||||
|             let import = &item_tree[id.value]; |  | ||||||
| 
 | 
 | ||||||
|             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( |             acc.push( | ||||||
|                 UnresolvedImport { decl: InFile::new(file_id, AstPtr::new(&use_tree)) }.into(), |                 UnresolvedImport { decl: InFile::new(file_id, AstPtr::new(&use_tree)) }.into(), | ||||||
|             ); |             ); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         DefDiagnosticKind::UnconfiguredCode { tree, item, cfg, opts } => { |         DefDiagnosticKind::UnconfiguredCode { ast_id, cfg, opts } => { | ||||||
|             let item_tree = tree.item_tree(db); |             let ast_id_map = db.ast_id_map(ast_id.file_id); | ||||||
|             let ast_id_map = db.ast_id_map(tree.file_id()); |             let ptr = ast_id_map.get_erased(ast_id.value); | ||||||
|             // FIXME: This parses... We could probably store relative ranges for the children things
 |             acc.push( | ||||||
|             // here in the item tree?
 |                 InactiveCode { | ||||||
|             (|| { |                     node: InFile::new(ast_id.file_id, ptr), | ||||||
|                 let process_field_list = |                     cfg: cfg.clone(), | ||||||
|                     |field_list: Option<_>, idx: ItemTreeFieldId| match field_list? { |                     opts: opts.clone(), | ||||||
|                         ast::FieldList::RecordFieldList(it) => Some(SyntaxNodePtr::new( |                 } | ||||||
|                             it.fields().nth(idx.into_raw().into_u32() as usize)?.syntax(), |                 .into(), | ||||||
|                         )), |             ); | ||||||
|                         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(), |  | ||||||
|                     ), |  | ||||||
|                 }; |  | ||||||
|                 acc.push( |  | ||||||
|                     InactiveCode { |  | ||||||
|                         node: InFile::new(tree.file_id(), ptr), |  | ||||||
|                         cfg: cfg.clone(), |  | ||||||
|                         opts: opts.clone(), |  | ||||||
|                     } |  | ||||||
|                     .into(), |  | ||||||
|                 ); |  | ||||||
|                 Some(()) |  | ||||||
|             })(); |  | ||||||
|         } |         } | ||||||
|         DefDiagnosticKind::UnresolvedMacroCall { ast, path } => { |         DefDiagnosticKind::UnresolvedMacroCall { ast, path } => { | ||||||
|             let (node, precise_location) = precise_macro_call_location(ast, db); |             let (node, precise_location) = precise_macro_call_location(ast, db); | ||||||
|  | @ -1478,12 +1430,8 @@ impl Struct { | ||||||
| impl HasVisibility for Struct { | impl HasVisibility for Struct { | ||||||
|     fn visibility(&self, db: &dyn HirDatabase) -> Visibility { |     fn visibility(&self, db: &dyn HirDatabase) -> Visibility { | ||||||
|         let loc = self.id.lookup(db); |         let loc = self.id.lookup(db); | ||||||
|         let item_tree = loc.id.item_tree(db); |         let source = loc.source(db); | ||||||
|         Visibility::resolve( |         visibility_from_ast(db, &self.id.resolver(db), source.map(|src| src.visibility())) | ||||||
|             db, |  | ||||||
|             &self.id.resolver(db), |  | ||||||
|             &item_tree[item_tree[loc.id.value].visibility], |  | ||||||
|         ) |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -1536,12 +1484,8 @@ impl Union { | ||||||
| impl HasVisibility for Union { | impl HasVisibility for Union { | ||||||
|     fn visibility(&self, db: &dyn HirDatabase) -> Visibility { |     fn visibility(&self, db: &dyn HirDatabase) -> Visibility { | ||||||
|         let loc = self.id.lookup(db); |         let loc = self.id.lookup(db); | ||||||
|         let item_tree = loc.id.item_tree(db); |         let source = loc.source(db); | ||||||
|         Visibility::resolve( |         visibility_from_ast(db, &self.id.resolver(db), source.map(|src| src.visibility())) | ||||||
|             db, |  | ||||||
|             &self.id.resolver(db), |  | ||||||
|             &item_tree[item_tree[loc.id.value].visibility], |  | ||||||
|         ) |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -1560,7 +1504,7 @@ impl Enum { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn variants(self, db: &dyn HirDatabase) -> Vec<Variant> { |     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 { |     pub fn num_variants(self, db: &dyn HirDatabase) -> usize { | ||||||
|  | @ -1629,12 +1573,8 @@ impl Enum { | ||||||
| impl HasVisibility for Enum { | impl HasVisibility for Enum { | ||||||
|     fn visibility(&self, db: &dyn HirDatabase) -> Visibility { |     fn visibility(&self, db: &dyn HirDatabase) -> Visibility { | ||||||
|         let loc = self.id.lookup(db); |         let loc = self.id.lookup(db); | ||||||
|         let item_tree = loc.id.item_tree(db); |         let source = loc.source(db); | ||||||
|         Visibility::resolve( |         visibility_from_ast(db, &self.id.resolver(db), source.map(|src| src.visibility())) | ||||||
|             db, |  | ||||||
|             &self.id.resolver(db), |  | ||||||
|             &item_tree[item_tree[loc.id.value].visibility], |  | ||||||
|         ) |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -2708,10 +2648,9 @@ impl ExternCrateDecl { | ||||||
| 
 | 
 | ||||||
|     pub fn resolved_crate(self, db: &dyn HirDatabase) -> Option<Crate> { |     pub fn resolved_crate(self, db: &dyn HirDatabase) -> Option<Crate> { | ||||||
|         let loc = self.id.lookup(db); |         let loc = self.id.lookup(db); | ||||||
|         let item_tree = loc.id.item_tree(db); |  | ||||||
|         let krate = loc.container.krate(); |         let krate = loc.container.krate(); | ||||||
|         let name = &item_tree[loc.id.value].name; |         let name = self.name(db); | ||||||
|         if *name == sym::self_ { |         if name == sym::self_ { | ||||||
|             Some(krate.into()) |             Some(krate.into()) | ||||||
|         } else { |         } else { | ||||||
|             krate.data(db).dependencies.iter().find_map(|dep| { |             krate.data(db).dependencies.iter().find_map(|dep| { | ||||||
|  | @ -2722,25 +2661,29 @@ impl ExternCrateDecl { | ||||||
| 
 | 
 | ||||||
|     pub fn name(self, db: &dyn HirDatabase) -> Name { |     pub fn name(self, db: &dyn HirDatabase) -> Name { | ||||||
|         let loc = self.id.lookup(db); |         let loc = self.id.lookup(db); | ||||||
|         let item_tree = loc.id.item_tree(db); |         let source = loc.source(db); | ||||||
|         item_tree[loc.id.value].name.clone() |         as_name_opt(source.value.name_ref()) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn alias(self, db: &dyn HirDatabase) -> Option<ImportAlias> { |     pub fn alias(self, db: &dyn HirDatabase) -> Option<ImportAlias> { | ||||||
|         let loc = self.id.lookup(db); |         let loc = self.id.lookup(db); | ||||||
|         let item_tree = loc.id.item_tree(db); |         let source = loc.source(db); | ||||||
|         item_tree[loc.id.value].alias.clone() |         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.
 |     /// Returns the name under which this crate is made accessible, taking `_` into account.
 | ||||||
|     pub fn alias_or_name(self, db: &dyn HirDatabase) -> Option<Name> { |     pub fn alias_or_name(self, db: &dyn HirDatabase) -> Option<Name> { | ||||||
|         let loc = self.id.lookup(db); |         match self.alias(db) { | ||||||
|         let item_tree = loc.id.item_tree(db); |  | ||||||
| 
 |  | ||||||
|         match &item_tree[loc.id.value].alias { |  | ||||||
|             Some(ImportAlias::Underscore) => None, |             Some(ImportAlias::Underscore) => None, | ||||||
|             Some(ImportAlias::Alias(alias)) => Some(alias.clone()), |             Some(ImportAlias::Alias(alias)) => Some(alias), | ||||||
|             None => Some(item_tree[loc.id.value].name.clone()), |             None => Some(self.name(db)), | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | @ -2748,12 +2691,8 @@ impl ExternCrateDecl { | ||||||
| impl HasVisibility for ExternCrateDecl { | impl HasVisibility for ExternCrateDecl { | ||||||
|     fn visibility(&self, db: &dyn HirDatabase) -> Visibility { |     fn visibility(&self, db: &dyn HirDatabase) -> Visibility { | ||||||
|         let loc = self.id.lookup(db); |         let loc = self.id.lookup(db); | ||||||
|         let item_tree = loc.id.item_tree(db); |         let source = loc.source(db); | ||||||
|         Visibility::resolve( |         visibility_from_ast(db, &self.id.resolver(db), source.map(|src| src.visibility())) | ||||||
|             db, |  | ||||||
|             &self.id.resolver(db), |  | ||||||
|             &item_tree[item_tree[loc.id.value].visibility], |  | ||||||
|         ) |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -2873,12 +2812,8 @@ impl Static { | ||||||
| impl HasVisibility for Static { | impl HasVisibility for Static { | ||||||
|     fn visibility(&self, db: &dyn HirDatabase) -> Visibility { |     fn visibility(&self, db: &dyn HirDatabase) -> Visibility { | ||||||
|         let loc = self.id.lookup(db); |         let loc = self.id.lookup(db); | ||||||
|         let item_tree = loc.id.item_tree(db); |         let source = loc.source(db); | ||||||
|         Visibility::resolve( |         visibility_from_ast(db, &self.id.resolver(db), source.map(|src| src.visibility())) | ||||||
|             db, |  | ||||||
|             &self.id.resolver(db), |  | ||||||
|             &item_tree[item_tree[loc.id.value].visibility], |  | ||||||
|         ) |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -2967,11 +2902,7 @@ impl Trait { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fn all_macro_calls(&self, db: &dyn HirDatabase) -> Box<[(AstId<ast::Item>, MacroCallId)]> { |     fn all_macro_calls(&self, db: &dyn HirDatabase) -> Box<[(AstId<ast::Item>, MacroCallId)]> { | ||||||
|         db.trait_items(self.id) |         db.trait_items(self.id).macro_calls.to_vec().into_boxed_slice() | ||||||
|             .macro_calls |  | ||||||
|             .as_ref() |  | ||||||
|             .map(|it| it.as_ref().clone().into_boxed_slice()) |  | ||||||
|             .unwrap_or_default() |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /// `#[rust_analyzer::completions(...)]` mode.
 |     /// `#[rust_analyzer::completions(...)]` mode.
 | ||||||
|  | @ -2983,12 +2914,8 @@ impl Trait { | ||||||
| impl HasVisibility for Trait { | impl HasVisibility for Trait { | ||||||
|     fn visibility(&self, db: &dyn HirDatabase) -> Visibility { |     fn visibility(&self, db: &dyn HirDatabase) -> Visibility { | ||||||
|         let loc = self.id.lookup(db); |         let loc = self.id.lookup(db); | ||||||
|         let item_tree = loc.id.item_tree(db); |         let source = loc.source(db); | ||||||
|         Visibility::resolve( |         visibility_from_ast(db, &self.id.resolver(db), source.map(|src| src.visibility())) | ||||||
|             db, |  | ||||||
|             &self.id.resolver(db), |  | ||||||
|             &item_tree[item_tree[loc.id.value].visibility], |  | ||||||
|         ) |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -3010,12 +2937,8 @@ impl TraitAlias { | ||||||
| impl HasVisibility for TraitAlias { | impl HasVisibility for TraitAlias { | ||||||
|     fn visibility(&self, db: &dyn HirDatabase) -> Visibility { |     fn visibility(&self, db: &dyn HirDatabase) -> Visibility { | ||||||
|         let loc = self.id.lookup(db); |         let loc = self.id.lookup(db); | ||||||
|         let item_tree = loc.id.item_tree(db); |         let source = loc.source(db); | ||||||
|         Visibility::resolve( |         visibility_from_ast(db, &self.id.resolver(db), source.map(|src| src.visibility())) | ||||||
|             db, |  | ||||||
|             &self.id.resolver(db), |  | ||||||
|             &item_tree[item_tree[loc.id.value].visibility], |  | ||||||
|         ) |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -3163,25 +3086,23 @@ impl Macro { | ||||||
|         match self.id { |         match self.id { | ||||||
|             MacroId::Macro2Id(id) => { |             MacroId::Macro2Id(id) => { | ||||||
|                 let loc = id.lookup(db); |                 let loc = id.lookup(db); | ||||||
|                 let item_tree = loc.id.item_tree(db); |                 let source = loc.source(db); | ||||||
|                 item_tree[loc.id.value].name.clone() |                 as_name_opt(source.value.name()) | ||||||
|             } |             } | ||||||
|             MacroId::MacroRulesId(id) => { |             MacroId::MacroRulesId(id) => { | ||||||
|                 let loc = id.lookup(db); |                 let loc = id.lookup(db); | ||||||
|                 let item_tree = loc.id.item_tree(db); |                 let source = loc.source(db); | ||||||
|                 item_tree[loc.id.value].name.clone() |                 as_name_opt(source.value.name()) | ||||||
|             } |             } | ||||||
|             MacroId::ProcMacroId(id) => { |             MacroId::ProcMacroId(id) => { | ||||||
|                 let loc = id.lookup(db); |                 let loc = id.lookup(db); | ||||||
|                 let item_tree = loc.id.item_tree(db); |                 let source = loc.source(db); | ||||||
|                 match loc.kind { |                 match loc.kind { | ||||||
|                     ProcMacroKind::CustomDerive => db |                     ProcMacroKind::CustomDerive => db | ||||||
|                         .attrs(id.into()) |                         .attrs(id.into()) | ||||||
|                         .parse_proc_macro_derive() |                         .parse_proc_macro_derive() | ||||||
|                         .map_or_else(|| item_tree[loc.id.value].name.clone(), |(it, _)| it), |                         .map_or_else(|| as_name_opt(source.value.name()), |(it, _)| it), | ||||||
|                     ProcMacroKind::Bang | ProcMacroKind::Attr => { |                     ProcMacroKind::Bang | ProcMacroKind::Attr => as_name_opt(source.value.name()), | ||||||
|                         item_tree[loc.id.value].name.clone() |  | ||||||
|                     } |  | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  | @ -3278,12 +3199,8 @@ impl HasVisibility for Macro { | ||||||
|         match self.id { |         match self.id { | ||||||
|             MacroId::Macro2Id(id) => { |             MacroId::Macro2Id(id) => { | ||||||
|                 let loc = id.lookup(db); |                 let loc = id.lookup(db); | ||||||
|                 let item_tree = loc.id.item_tree(db); |                 let source = loc.source(db); | ||||||
|                 Visibility::resolve( |                 visibility_from_ast(db, &id.resolver(db), source.map(|src| src.visibility())) | ||||||
|                     db, |  | ||||||
|                     &id.resolver(db), |  | ||||||
|                     &item_tree[item_tree[loc.id.value].visibility], |  | ||||||
|                 ) |  | ||||||
|             } |             } | ||||||
|             MacroId::MacroRulesId(_) => Visibility::Public, |             MacroId::MacroRulesId(_) => Visibility::Public, | ||||||
|             MacroId::ProcMacroId(_) => Visibility::Public, |             MacroId::ProcMacroId(_) => Visibility::Public, | ||||||
|  | @ -3437,7 +3354,7 @@ fn as_assoc_item<'db, ID, DEF, LOC>( | ||||||
| where | where | ||||||
|     ID: Lookup<Database = dyn DefDatabase, Data = AssocItemLoc<LOC>>, |     ID: Lookup<Database = dyn DefDatabase, Data = AssocItemLoc<LOC>>, | ||||||
|     DEF: From<ID>, |     DEF: From<ID>, | ||||||
|     LOC: ItemTreeNode, |     LOC: AstIdNode, | ||||||
| { | { | ||||||
|     match id.lookup(db).container { |     match id.lookup(db).container { | ||||||
|         ItemContainerId::TraitId(_) | ItemContainerId::ImplId(_) => Some(ctor(DEF::from(id))), |         ItemContainerId::TraitId(_) | ItemContainerId::ImplId(_) => Some(ctor(DEF::from(id))), | ||||||
|  | @ -3453,7 +3370,7 @@ fn as_extern_assoc_item<'db, ID, DEF, LOC>( | ||||||
| where | where | ||||||
|     ID: Lookup<Database = dyn DefDatabase, Data = AssocItemLoc<LOC>>, |     ID: Lookup<Database = dyn DefDatabase, Data = AssocItemLoc<LOC>>, | ||||||
|     DEF: From<ID>, |     DEF: From<ID>, | ||||||
|     LOC: ItemTreeNode, |     LOC: AstIdNode, | ||||||
| { | { | ||||||
|     match id.lookup(db).container { |     match id.lookup(db).container { | ||||||
|         ItemContainerId::ExternBlockId(_) => Some(ctor(DEF::from(id))), |         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)]> { |     fn all_macro_calls(&self, db: &dyn HirDatabase) -> Box<[(AstId<ast::Item>, MacroCallId)]> { | ||||||
|         db.impl_items(self.id) |         db.impl_items(self.id).macro_calls.to_vec().into_boxed_slice() | ||||||
|             .macro_calls |  | ||||||
|             .as_ref() |  | ||||||
|             .map(|it| it.as_ref().clone().into_boxed_slice()) |  | ||||||
|             .unwrap_or_default() |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -6510,3 +6423,7 @@ pub fn resolve_absolute_path<'a, I: Iterator<Item = Symbol> + Clone + 'a>( | ||||||
|         }) |         }) | ||||||
|         .flatten() |         .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 either::Either; | ||||||
| use hir_expand::{HirFileId, attrs::collect_attrs}; | use hir_expand::{HirFileId, attrs::collect_attrs}; | ||||||
|  | use span::AstIdNode; | ||||||
| use syntax::{AstPtr, ast}; | use syntax::{AstPtr, ast}; | ||||||
| 
 | 
 | ||||||
| use hir_def::{ | 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, |     LifetimeParamId, Lookup, MacroId, ModuleDefId, ModuleId, TraitId, TypeOrConstParamId, | ||||||
|     VariantId, |     VariantId, | ||||||
|     db::DefDatabase, |     db::DefDatabase, | ||||||
|  | @ -19,7 +20,6 @@ use hir_def::{ | ||||||
|     }, |     }, | ||||||
|     hir::generics::GenericParams, |     hir::generics::GenericParams, | ||||||
|     item_scope::ItemScope, |     item_scope::ItemScope, | ||||||
|     item_tree::ItemTreeNode, |  | ||||||
|     nameres::DefMap, |     nameres::DefMap, | ||||||
|     src::{HasChildSource, HasSource}, |     src::{HasChildSource, HasSource}, | ||||||
| }; | }; | ||||||
|  | @ -113,7 +113,7 @@ impl ChildBySource for ItemScope { | ||||||
|             ids.iter().for_each(|&id| { |             ids.iter().for_each(|&id| { | ||||||
|                 if let MacroId::MacroRulesId(id) = id { |                 if let MacroId::MacroRulesId(id) = id { | ||||||
|                     let loc = id.lookup(db); |                     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); |                         res[keys::MACRO_RULES].insert(loc.ast_ptr(db).value, id); | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|  | @ -199,16 +199,14 @@ impl ChildBySource for VariantId { | ||||||
| impl ChildBySource for EnumId { | impl ChildBySource for EnumId { | ||||||
|     fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap, file_id: HirFileId) { |     fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap, file_id: HirFileId) { | ||||||
|         let loc = &self.lookup(db); |         let loc = &self.lookup(db); | ||||||
|         if file_id != loc.id.file_id() { |         if file_id != loc.id.file_id { | ||||||
|             return; |             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, _)| { |         db.enum_variants(*self).variants.iter().for_each(|&(variant, _, _)| { | ||||||
|             res[keys::ENUM_VARIANT] |             res[keys::ENUM_VARIANT].insert(ast_id_map.get(variant.lookup(db).id.value), variant); | ||||||
|                 .insert(ast_id_map.get(tree[variant.lookup(db).id.value].ast_id), variant); |  | ||||||
|         }); |         }); | ||||||
|         let (_, source_map) = db.enum_signature_with_source_map(*self); |         let (_, source_map) = db.enum_signature_with_source_map(*self); | ||||||
|         source_map |         source_map | ||||||
|  | @ -287,15 +285,14 @@ fn insert_item_loc<ID, N, Data>( | ||||||
|     res: &mut DynMap, |     res: &mut DynMap, | ||||||
|     file_id: HirFileId, |     file_id: HirFileId, | ||||||
|     id: ID, |     id: ID, | ||||||
|     key: Key<N::Source, ID>, |     key: Key<N, ID>, | ||||||
| ) where | ) where | ||||||
|     ID: Lookup<Database = dyn DefDatabase, Data = Data> + 'static, |     ID: Lookup<Database = dyn DefDatabase, Data = Data> + 'static, | ||||||
|     Data: ItemTreeLoc<Id = N>, |     Data: AstIdLoc<Ast = N>, | ||||||
|     N: ItemTreeNode, |     N: AstIdNode + 'static, | ||||||
|     N::Source: 'static, |  | ||||||
| { | { | ||||||
|     let loc = id.lookup(db); |     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) |         res[key].insert(loc.ast_ptr(db).value, id) | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -3,7 +3,9 @@ | ||||||
| // FIXME: Move more of the nameres independent tests from
 | // FIXME: Move more of the nameres independent tests from
 | ||||||
| // crates\hir-def\src\macro_expansion_tests\mod.rs to this
 | // crates\hir-def\src\macro_expansion_tests\mod.rs to this
 | ||||||
| use expect_test::expect; | use expect_test::expect; | ||||||
| use span::{Edition, EditionedFileId, ErasedFileAstId, FileId, Span, SpanAnchor, SyntaxContext}; | use span::{ | ||||||
|  |     Edition, EditionedFileId, FileId, ROOT_ERASED_FILE_AST_ID, Span, SpanAnchor, SyntaxContext, | ||||||
|  | }; | ||||||
| use stdx::format_to; | use stdx::format_to; | ||||||
| use tt::{TextRange, TextSize}; | use tt::{TextRange, TextSize}; | ||||||
| 
 | 
 | ||||||
|  | @ -24,7 +26,7 @@ fn check_( | ||||||
|         def_edition, |         def_edition, | ||||||
|         SpanAnchor { |         SpanAnchor { | ||||||
|             file_id: EditionedFileId::new(FileId::from_raw(0), def_edition), |             file_id: EditionedFileId::new(FileId::from_raw(0), def_edition), | ||||||
|             ast_id: ErasedFileAstId::from_raw(0), |             ast_id: ROOT_ERASED_FILE_AST_ID, | ||||||
|         }, |         }, | ||||||
|         SyntaxContext::root(Edition::CURRENT), |         SyntaxContext::root(Edition::CURRENT), | ||||||
|         decl, |         decl, | ||||||
|  | @ -37,7 +39,7 @@ fn check_( | ||||||
|     }; |     }; | ||||||
|     let call_anchor = SpanAnchor { |     let call_anchor = SpanAnchor { | ||||||
|         file_id: EditionedFileId::new(FileId::from_raw(1), call_edition), |         file_id: EditionedFileId::new(FileId::from_raw(1), call_edition), | ||||||
|         ast_id: ErasedFileAstId::from_raw(0), |         ast_id: ROOT_ERASED_FILE_AST_ID, | ||||||
|     }; |     }; | ||||||
|     let arg_tt = syntax_bridge::parse_to_token_tree( |     let arg_tt = syntax_bridge::parse_to_token_tree( | ||||||
|         call_edition, |         call_edition, | ||||||
|  | @ -110,8 +112,8 @@ fn unbalanced_brace() { | ||||||
| "#,
 | "#,
 | ||||||
|         r#""#, |         r#""#, | ||||||
|         expect![[r#" |         expect![[r#" | ||||||
|             SUBTREE $$ 1:0@0..0#ROOT2024 1:0@0..0#ROOT2024 |             SUBTREE $$ 1:Root[0000, 0]@0..0#ROOT2024 1:Root[0000, 0]@0..0#ROOT2024 | ||||||
|               SUBTREE {} 0:0@9..10#ROOT2024 0:0@11..12#ROOT2024 |               SUBTREE {} 0:Root[0000, 0]@9..10#ROOT2024 0:Root[0000, 0]@11..12#ROOT2024 | ||||||
| 
 | 
 | ||||||
|             {}"#]],
 |             {}"#]],
 | ||||||
|     ); |     ); | ||||||
|  | @ -133,25 +135,25 @@ fn token_mapping_smoke_test() { | ||||||
| struct MyTraitMap2 | struct MyTraitMap2 | ||||||
| "#,
 | "#,
 | ||||||
|         expect![[r#" |         expect![[r#" | ||||||
|             SUBTREE $$ 1:0@0..20#ROOT2024 1:0@0..20#ROOT2024 |             SUBTREE $$ 1:Root[0000, 0]@0..20#ROOT2024 1:Root[0000, 0]@0..20#ROOT2024 | ||||||
|               IDENT   struct 0:0@34..40#ROOT2024 |               IDENT   struct 0:Root[0000, 0]@34..40#ROOT2024 | ||||||
|               IDENT   MyTraitMap2 1:0@8..19#ROOT2024 |               IDENT   MyTraitMap2 1:Root[0000, 0]@8..19#ROOT2024 | ||||||
|               SUBTREE {} 0:0@48..49#ROOT2024 0:0@100..101#ROOT2024 |               SUBTREE {} 0:Root[0000, 0]@48..49#ROOT2024 0:Root[0000, 0]@100..101#ROOT2024 | ||||||
|                 IDENT   map 0:0@58..61#ROOT2024 |                 IDENT   map 0:Root[0000, 0]@58..61#ROOT2024 | ||||||
|                 PUNCH   : [alone] 0:0@61..62#ROOT2024 |                 PUNCH   : [alone] 0:Root[0000, 0]@61..62#ROOT2024 | ||||||
|                 PUNCH   : [joint] 0:0@63..64#ROOT2024 |                 PUNCH   : [joint] 0:Root[0000, 0]@63..64#ROOT2024 | ||||||
|                 PUNCH   : [alone] 0:0@64..65#ROOT2024 |                 PUNCH   : [alone] 0:Root[0000, 0]@64..65#ROOT2024 | ||||||
|                 IDENT   std 0:0@65..68#ROOT2024 |                 IDENT   std 0:Root[0000, 0]@65..68#ROOT2024 | ||||||
|                 PUNCH   : [joint] 0:0@68..69#ROOT2024 |                 PUNCH   : [joint] 0:Root[0000, 0]@68..69#ROOT2024 | ||||||
|                 PUNCH   : [alone] 0:0@69..70#ROOT2024 |                 PUNCH   : [alone] 0:Root[0000, 0]@69..70#ROOT2024 | ||||||
|                 IDENT   collections 0:0@70..81#ROOT2024 |                 IDENT   collections 0:Root[0000, 0]@70..81#ROOT2024 | ||||||
|                 PUNCH   : [joint] 0:0@81..82#ROOT2024 |                 PUNCH   : [joint] 0:Root[0000, 0]@81..82#ROOT2024 | ||||||
|                 PUNCH   : [alone] 0:0@82..83#ROOT2024 |                 PUNCH   : [alone] 0:Root[0000, 0]@82..83#ROOT2024 | ||||||
|                 IDENT   HashSet 0:0@83..90#ROOT2024 |                 IDENT   HashSet 0:Root[0000, 0]@83..90#ROOT2024 | ||||||
|                 PUNCH   < [alone] 0:0@90..91#ROOT2024 |                 PUNCH   < [alone] 0:Root[0000, 0]@90..91#ROOT2024 | ||||||
|                 SUBTREE () 0:0@91..92#ROOT2024 0:0@92..93#ROOT2024 |                 SUBTREE () 0:Root[0000, 0]@91..92#ROOT2024 0:Root[0000, 0]@92..93#ROOT2024 | ||||||
|                 PUNCH   > [joint] 0:0@93..94#ROOT2024 |                 PUNCH   > [joint] 0:Root[0000, 0]@93..94#ROOT2024 | ||||||
|                 PUNCH   , [alone] 0:0@94..95#ROOT2024 |                 PUNCH   , [alone] 0:Root[0000, 0]@94..95#ROOT2024 | ||||||
| 
 | 
 | ||||||
|             struct MyTraitMap2 { |             struct MyTraitMap2 { | ||||||
|                 map: ::std::collections::HashSet<()>, |                 map: ::std::collections::HashSet<()>, | ||||||
|  | @ -180,28 +182,28 @@ fn main() { | ||||||
| } | } | ||||||
| "#,
 | "#,
 | ||||||
|         expect![[r#" |         expect![[r#" | ||||||
|             SUBTREE $$ 1:0@0..63#ROOT2024 1:0@0..63#ROOT2024 |             SUBTREE $$ 1:Root[0000, 0]@0..63#ROOT2024 1:Root[0000, 0]@0..63#ROOT2024 | ||||||
|               IDENT   fn 1:0@1..3#ROOT2024 |               IDENT   fn 1:Root[0000, 0]@1..3#ROOT2024 | ||||||
|               IDENT   main 1:0@4..8#ROOT2024 |               IDENT   main 1:Root[0000, 0]@4..8#ROOT2024 | ||||||
|               SUBTREE () 1:0@8..9#ROOT2024 1:0@9..10#ROOT2024 |               SUBTREE () 1:Root[0000, 0]@8..9#ROOT2024 1:Root[0000, 0]@9..10#ROOT2024 | ||||||
|               SUBTREE {} 1:0@11..12#ROOT2024 1:0@61..62#ROOT2024 |               SUBTREE {} 1:Root[0000, 0]@11..12#ROOT2024 1:Root[0000, 0]@61..62#ROOT2024 | ||||||
|                 LITERAL Integer 1 1:0@17..18#ROOT2024 |                 LITERAL Integer 1 1:Root[0000, 0]@17..18#ROOT2024 | ||||||
|                 PUNCH   ; [alone] 1:0@18..19#ROOT2024 |                 PUNCH   ; [alone] 1:Root[0000, 0]@18..19#ROOT2024 | ||||||
|                 LITERAL Float 1.0 1:0@24..27#ROOT2024 |                 LITERAL Float 1.0 1:Root[0000, 0]@24..27#ROOT2024 | ||||||
|                 PUNCH   ; [alone] 1:0@27..28#ROOT2024 |                 PUNCH   ; [alone] 1:Root[0000, 0]@27..28#ROOT2024 | ||||||
|                 SUBTREE () 1:0@33..34#ROOT2024 1:0@39..40#ROOT2024 |                 SUBTREE () 1:Root[0000, 0]@33..34#ROOT2024 1:Root[0000, 0]@39..40#ROOT2024 | ||||||
|                   SUBTREE () 1:0@34..35#ROOT2024 1:0@37..38#ROOT2024 |                   SUBTREE () 1:Root[0000, 0]@34..35#ROOT2024 1:Root[0000, 0]@37..38#ROOT2024 | ||||||
|                     LITERAL Integer 1 1:0@35..36#ROOT2024 |                     LITERAL Integer 1 1:Root[0000, 0]@35..36#ROOT2024 | ||||||
|                     PUNCH   , [alone] 1:0@36..37#ROOT2024 |                     PUNCH   , [alone] 1:Root[0000, 0]@36..37#ROOT2024 | ||||||
|                   PUNCH   , [alone] 1:0@38..39#ROOT2024 |                   PUNCH   , [alone] 1:Root[0000, 0]@38..39#ROOT2024 | ||||||
|                 PUNCH   . [alone] 1:0@40..41#ROOT2024 |                 PUNCH   . [alone] 1:Root[0000, 0]@40..41#ROOT2024 | ||||||
|                 LITERAL Float 0.0 1:0@41..44#ROOT2024 |                 LITERAL Float 0.0 1:Root[0000, 0]@41..44#ROOT2024 | ||||||
|                 PUNCH   ; [alone] 1:0@44..45#ROOT2024 |                 PUNCH   ; [alone] 1:Root[0000, 0]@44..45#ROOT2024 | ||||||
|                 IDENT   let 1:0@50..53#ROOT2024 |                 IDENT   let 1:Root[0000, 0]@50..53#ROOT2024 | ||||||
|                 IDENT   x 1:0@54..55#ROOT2024 |                 IDENT   x 1:Root[0000, 0]@54..55#ROOT2024 | ||||||
|                 PUNCH   = [alone] 1:0@56..57#ROOT2024 |                 PUNCH   = [alone] 1:Root[0000, 0]@56..57#ROOT2024 | ||||||
|                 LITERAL Integer 1 1:0@58..59#ROOT2024 |                 LITERAL Integer 1 1:Root[0000, 0]@58..59#ROOT2024 | ||||||
|                 PUNCH   ; [alone] 1:0@59..60#ROOT2024 |                 PUNCH   ; [alone] 1:Root[0000, 0]@59..60#ROOT2024 | ||||||
| 
 | 
 | ||||||
|             fn main(){ |             fn main(){ | ||||||
|                 1; |                 1; | ||||||
|  | @ -227,14 +229,14 @@ fn expr_2021() { | ||||||
|     const { 1 }, |     const { 1 }, | ||||||
| "#,
 | "#,
 | ||||||
|         expect![[r#" |         expect![[r#" | ||||||
|             SUBTREE $$ 1:0@0..25#ROOT2024 1:0@0..25#ROOT2024 |             SUBTREE $$ 1:Root[0000, 0]@0..25#ROOT2024 1:Root[0000, 0]@0..25#ROOT2024 | ||||||
|               IDENT   _ 1:0@5..6#ROOT2024 |               IDENT   _ 1:Root[0000, 0]@5..6#ROOT2024 | ||||||
|               PUNCH   ; [joint] 0:0@36..37#ROOT2024 |               PUNCH   ; [joint] 0:Root[0000, 0]@36..37#ROOT2024 | ||||||
|               SUBTREE () 0:0@34..35#ROOT2024 0:0@34..35#ROOT2024 |               SUBTREE () 0:Root[0000, 0]@34..35#ROOT2024 0:Root[0000, 0]@34..35#ROOT2024 | ||||||
|                 IDENT   const 1:0@12..17#ROOT2024 |                 IDENT   const 1:Root[0000, 0]@12..17#ROOT2024 | ||||||
|                 SUBTREE {} 1:0@18..19#ROOT2024 1:0@22..23#ROOT2024 |                 SUBTREE {} 1:Root[0000, 0]@18..19#ROOT2024 1:Root[0000, 0]@22..23#ROOT2024 | ||||||
|                   LITERAL Integer 1 1:0@20..21#ROOT2024 |                   LITERAL Integer 1 1:Root[0000, 0]@20..21#ROOT2024 | ||||||
|               PUNCH   ; [alone] 0:0@39..40#ROOT2024 |               PUNCH   ; [alone] 0:Root[0000, 0]@39..40#ROOT2024 | ||||||
| 
 | 
 | ||||||
|             _; |             _; | ||||||
|             (const  { |             (const  { | ||||||
|  | @ -255,13 +257,13 @@ fn expr_2021() { | ||||||
|         expect![[r#" |         expect![[r#" | ||||||
|             ExpandError { |             ExpandError { | ||||||
|                 inner: ( |                 inner: ( | ||||||
|                     1:0@5..6#ROOT2024, |                     1:Root[0000, 0]@5..6#ROOT2024, | ||||||
|                     NoMatchingRule, |                     NoMatchingRule, | ||||||
|                 ), |                 ), | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             SUBTREE $$ 1:0@0..8#ROOT2024 1:0@0..8#ROOT2024 |             SUBTREE $$ 1:Root[0000, 0]@0..8#ROOT2024 1:Root[0000, 0]@0..8#ROOT2024 | ||||||
|               PUNCH   ; [alone] 0:0@39..40#ROOT2024 |               PUNCH   ; [alone] 0:Root[0000, 0]@39..40#ROOT2024 | ||||||
| 
 | 
 | ||||||
|             ;"#]],
 |             ;"#]],
 | ||||||
|     ); |     ); | ||||||
|  | @ -279,13 +281,13 @@ fn expr_2021() { | ||||||
|         expect![[r#" |         expect![[r#" | ||||||
|             ExpandError { |             ExpandError { | ||||||
|                 inner: ( |                 inner: ( | ||||||
|                     1:0@5..10#ROOT2024, |                     1:Root[0000, 0]@5..10#ROOT2024, | ||||||
|                     NoMatchingRule, |                     NoMatchingRule, | ||||||
|                 ), |                 ), | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             SUBTREE $$ 1:0@0..18#ROOT2024 1:0@0..18#ROOT2024 |             SUBTREE $$ 1:Root[0000, 0]@0..18#ROOT2024 1:Root[0000, 0]@0..18#ROOT2024 | ||||||
|               PUNCH   ; [alone] 0:0@39..40#ROOT2024 |               PUNCH   ; [alone] 0:Root[0000, 0]@39..40#ROOT2024 | ||||||
| 
 | 
 | ||||||
|             ;"#]],
 |             ;"#]],
 | ||||||
|     ); |     ); | ||||||
|  | @ -305,26 +307,26 @@ fn expr_2021() { | ||||||
|     break 'foo bar, |     break 'foo bar, | ||||||
| "#,
 | "#,
 | ||||||
|         expect![[r#" |         expect![[r#" | ||||||
|             SUBTREE $$ 1:0@0..76#ROOT2024 1:0@0..76#ROOT2024 |             SUBTREE $$ 1:Root[0000, 0]@0..76#ROOT2024 1:Root[0000, 0]@0..76#ROOT2024 | ||||||
|               LITERAL Integer 4 1:0@5..6#ROOT2024 |               LITERAL Integer 4 1:Root[0000, 0]@5..6#ROOT2024 | ||||||
|               PUNCH   ; [joint] 0:0@41..42#ROOT2024 |               PUNCH   ; [joint] 0:Root[0000, 0]@41..42#ROOT2024 | ||||||
|               LITERAL Str literal 1:0@12..21#ROOT2024 |               LITERAL Str literal 1:Root[0000, 0]@12..21#ROOT2024 | ||||||
|               PUNCH   ; [joint] 0:0@41..42#ROOT2024 |               PUNCH   ; [joint] 0:Root[0000, 0]@41..42#ROOT2024 | ||||||
|               SUBTREE () 0:0@39..40#ROOT2024 0:0@39..40#ROOT2024 |               SUBTREE () 0:Root[0000, 0]@39..40#ROOT2024 0:Root[0000, 0]@39..40#ROOT2024 | ||||||
|                 IDENT   funcall 1:0@27..34#ROOT2024 |                 IDENT   funcall 1:Root[0000, 0]@27..34#ROOT2024 | ||||||
|                 SUBTREE () 1:0@34..35#ROOT2024 1:0@35..36#ROOT2024 |                 SUBTREE () 1:Root[0000, 0]@34..35#ROOT2024 1:Root[0000, 0]@35..36#ROOT2024 | ||||||
|               PUNCH   ; [joint] 0:0@41..42#ROOT2024 |               PUNCH   ; [joint] 0:Root[0000, 0]@41..42#ROOT2024 | ||||||
|               SUBTREE () 0:0@39..40#ROOT2024 0:0@39..40#ROOT2024 |               SUBTREE () 0:Root[0000, 0]@39..40#ROOT2024 0:Root[0000, 0]@39..40#ROOT2024 | ||||||
|                 IDENT   future 1:0@42..48#ROOT2024 |                 IDENT   future 1:Root[0000, 0]@42..48#ROOT2024 | ||||||
|                 PUNCH   . [alone] 1:0@48..49#ROOT2024 |                 PUNCH   . [alone] 1:Root[0000, 0]@48..49#ROOT2024 | ||||||
|                 IDENT   await 1:0@49..54#ROOT2024 |                 IDENT   await 1:Root[0000, 0]@49..54#ROOT2024 | ||||||
|               PUNCH   ; [joint] 0:0@41..42#ROOT2024 |               PUNCH   ; [joint] 0:Root[0000, 0]@41..42#ROOT2024 | ||||||
|               SUBTREE () 0:0@39..40#ROOT2024 0:0@39..40#ROOT2024 |               SUBTREE () 0:Root[0000, 0]@39..40#ROOT2024 0:Root[0000, 0]@39..40#ROOT2024 | ||||||
|                 IDENT   break 1:0@60..65#ROOT2024 |                 IDENT   break 1:Root[0000, 0]@60..65#ROOT2024 | ||||||
|                 PUNCH   ' [joint] 1:0@66..67#ROOT2024 |                 PUNCH   ' [joint] 1:Root[0000, 0]@66..67#ROOT2024 | ||||||
|                 IDENT   foo 1:0@67..70#ROOT2024 |                 IDENT   foo 1:Root[0000, 0]@67..70#ROOT2024 | ||||||
|                 IDENT   bar 1:0@71..74#ROOT2024 |                 IDENT   bar 1:Root[0000, 0]@71..74#ROOT2024 | ||||||
|               PUNCH   ; [alone] 0:0@44..45#ROOT2024 |               PUNCH   ; [alone] 0:Root[0000, 0]@44..45#ROOT2024 | ||||||
| 
 | 
 | ||||||
|             4; |             4; | ||||||
|             "literal"; |             "literal"; | ||||||
|  | @ -346,13 +348,13 @@ fn expr_2021() { | ||||||
|         expect![[r#" |         expect![[r#" | ||||||
|             ExpandError { |             ExpandError { | ||||||
|                 inner: ( |                 inner: ( | ||||||
|                     1:0@5..6#ROOT2024, |                     1:Root[0000, 0]@5..6#ROOT2024, | ||||||
|                     NoMatchingRule, |                     NoMatchingRule, | ||||||
|                 ), |                 ), | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             SUBTREE $$ 1:0@0..8#ROOT2024 1:0@0..8#ROOT2024 |             SUBTREE $$ 1:Root[0000, 0]@0..8#ROOT2024 1:Root[0000, 0]@0..8#ROOT2024 | ||||||
|               PUNCH   ; [alone] 0:0@44..45#ROOT2024 |               PUNCH   ; [alone] 0:Root[0000, 0]@44..45#ROOT2024 | ||||||
| 
 | 
 | ||||||
|             ;"#]],
 |             ;"#]],
 | ||||||
|     ); |     ); | ||||||
|  | @ -370,88 +372,88 @@ fn minus_belongs_to_literal() { | ||||||
|     check( |     check( | ||||||
|         "-1", |         "-1", | ||||||
|         expect![[r#" |         expect![[r#" | ||||||
|             SUBTREE $$ 1:0@0..2#ROOT2024 1:0@0..2#ROOT2024 |             SUBTREE $$ 1:Root[0000, 0]@0..2#ROOT2024 1:Root[0000, 0]@0..2#ROOT2024 | ||||||
|               PUNCH   - [alone] 0:0@10..11#ROOT2024 |               PUNCH   - [alone] 0:Root[0000, 0]@10..11#ROOT2024 | ||||||
|               LITERAL Integer 1 0:0@11..12#ROOT2024 |               LITERAL Integer 1 0:Root[0000, 0]@11..12#ROOT2024 | ||||||
| 
 | 
 | ||||||
|             -1"#]],
 |             -1"#]],
 | ||||||
|     ); |     ); | ||||||
|     check( |     check( | ||||||
|         "- 1", |         "- 1", | ||||||
|         expect![[r#" |         expect![[r#" | ||||||
|             SUBTREE $$ 1:0@0..3#ROOT2024 1:0@0..3#ROOT2024 |             SUBTREE $$ 1:Root[0000, 0]@0..3#ROOT2024 1:Root[0000, 0]@0..3#ROOT2024 | ||||||
|               PUNCH   - [alone] 0:0@10..11#ROOT2024 |               PUNCH   - [alone] 0:Root[0000, 0]@10..11#ROOT2024 | ||||||
|               LITERAL Integer 1 0:0@11..12#ROOT2024 |               LITERAL Integer 1 0:Root[0000, 0]@11..12#ROOT2024 | ||||||
| 
 | 
 | ||||||
|             -1"#]],
 |             -1"#]],
 | ||||||
|     ); |     ); | ||||||
|     check( |     check( | ||||||
|         "-2", |         "-2", | ||||||
|         expect![[r#" |         expect![[r#" | ||||||
|             SUBTREE $$ 1:0@0..2#ROOT2024 1:0@0..2#ROOT2024 |             SUBTREE $$ 1:Root[0000, 0]@0..2#ROOT2024 1:Root[0000, 0]@0..2#ROOT2024 | ||||||
|               PUNCH   - [alone] 0:0@25..26#ROOT2024 |               PUNCH   - [alone] 0:Root[0000, 0]@25..26#ROOT2024 | ||||||
|               LITERAL Integer 2 0:0@27..28#ROOT2024 |               LITERAL Integer 2 0:Root[0000, 0]@27..28#ROOT2024 | ||||||
| 
 | 
 | ||||||
|             -2"#]],
 |             -2"#]],
 | ||||||
|     ); |     ); | ||||||
|     check( |     check( | ||||||
|         "- 2", |         "- 2", | ||||||
|         expect![[r#" |         expect![[r#" | ||||||
|             SUBTREE $$ 1:0@0..3#ROOT2024 1:0@0..3#ROOT2024 |             SUBTREE $$ 1:Root[0000, 0]@0..3#ROOT2024 1:Root[0000, 0]@0..3#ROOT2024 | ||||||
|               PUNCH   - [alone] 0:0@25..26#ROOT2024 |               PUNCH   - [alone] 0:Root[0000, 0]@25..26#ROOT2024 | ||||||
|               LITERAL Integer 2 0:0@27..28#ROOT2024 |               LITERAL Integer 2 0:Root[0000, 0]@27..28#ROOT2024 | ||||||
| 
 | 
 | ||||||
|             -2"#]],
 |             -2"#]],
 | ||||||
|     ); |     ); | ||||||
|     check( |     check( | ||||||
|         "-3.0", |         "-3.0", | ||||||
|         expect![[r#" |         expect![[r#" | ||||||
|             SUBTREE $$ 1:0@0..4#ROOT2024 1:0@0..4#ROOT2024 |             SUBTREE $$ 1:Root[0000, 0]@0..4#ROOT2024 1:Root[0000, 0]@0..4#ROOT2024 | ||||||
|               PUNCH   - [alone] 0:0@43..44#ROOT2024 |               PUNCH   - [alone] 0:Root[0000, 0]@43..44#ROOT2024 | ||||||
|               LITERAL Float 3.0 0:0@45..48#ROOT2024 |               LITERAL Float 3.0 0:Root[0000, 0]@45..48#ROOT2024 | ||||||
| 
 | 
 | ||||||
|             -3.0"#]],
 |             -3.0"#]],
 | ||||||
|     ); |     ); | ||||||
|     check( |     check( | ||||||
|         "- 3.0", |         "- 3.0", | ||||||
|         expect![[r#" |         expect![[r#" | ||||||
|             SUBTREE $$ 1:0@0..5#ROOT2024 1:0@0..5#ROOT2024 |             SUBTREE $$ 1:Root[0000, 0]@0..5#ROOT2024 1:Root[0000, 0]@0..5#ROOT2024 | ||||||
|               PUNCH   - [alone] 0:0@43..44#ROOT2024 |               PUNCH   - [alone] 0:Root[0000, 0]@43..44#ROOT2024 | ||||||
|               LITERAL Float 3.0 0:0@45..48#ROOT2024 |               LITERAL Float 3.0 0:Root[0000, 0]@45..48#ROOT2024 | ||||||
| 
 | 
 | ||||||
|             -3.0"#]],
 |             -3.0"#]],
 | ||||||
|     ); |     ); | ||||||
|     check( |     check( | ||||||
|         "@1", |         "@1", | ||||||
|         expect![[r#" |         expect![[r#" | ||||||
|             SUBTREE $$ 1:0@0..2#ROOT2024 1:0@0..2#ROOT2024 |             SUBTREE $$ 1:Root[0000, 0]@0..2#ROOT2024 1:Root[0000, 0]@0..2#ROOT2024 | ||||||
|               LITERAL Integer 1 1:0@1..2#ROOT2024 |               LITERAL Integer 1 1:Root[0000, 0]@1..2#ROOT2024 | ||||||
| 
 | 
 | ||||||
|             1"#]],
 |             1"#]],
 | ||||||
|     ); |     ); | ||||||
|     check( |     check( | ||||||
|         "@-1", |         "@-1", | ||||||
|         expect![[r#" |         expect![[r#" | ||||||
|             SUBTREE $$ 1:0@0..3#ROOT2024 1:0@0..3#ROOT2024 |             SUBTREE $$ 1:Root[0000, 0]@0..3#ROOT2024 1:Root[0000, 0]@0..3#ROOT2024 | ||||||
|               PUNCH   - [alone] 1:0@1..2#ROOT2024 |               PUNCH   - [alone] 1:Root[0000, 0]@1..2#ROOT2024 | ||||||
|               LITERAL Integer 1 1:0@2..3#ROOT2024 |               LITERAL Integer 1 1:Root[0000, 0]@2..3#ROOT2024 | ||||||
| 
 | 
 | ||||||
|             -1"#]],
 |             -1"#]],
 | ||||||
|     ); |     ); | ||||||
|     check( |     check( | ||||||
|         "@1.0", |         "@1.0", | ||||||
|         expect![[r#" |         expect![[r#" | ||||||
|             SUBTREE $$ 1:0@0..4#ROOT2024 1:0@0..4#ROOT2024 |             SUBTREE $$ 1:Root[0000, 0]@0..4#ROOT2024 1:Root[0000, 0]@0..4#ROOT2024 | ||||||
|               LITERAL Float 1.0 1:0@1..4#ROOT2024 |               LITERAL Float 1.0 1:Root[0000, 0]@1..4#ROOT2024 | ||||||
| 
 | 
 | ||||||
|             1.0"#]],
 |             1.0"#]],
 | ||||||
|     ); |     ); | ||||||
|     check( |     check( | ||||||
|         "@-1.0", |         "@-1.0", | ||||||
|         expect![[r#" |         expect![[r#" | ||||||
|             SUBTREE $$ 1:0@0..5#ROOT2024 1:0@0..5#ROOT2024 |             SUBTREE $$ 1:Root[0000, 0]@0..5#ROOT2024 1:Root[0000, 0]@0..5#ROOT2024 | ||||||
|               PUNCH   - [alone] 1:0@1..2#ROOT2024 |               PUNCH   - [alone] 1:Root[0000, 0]@1..2#ROOT2024 | ||||||
|               LITERAL Float 1.0 1:0@2..5#ROOT2024 |               LITERAL Float 1.0 1:Root[0000, 0]@2..5#ROOT2024 | ||||||
| 
 | 
 | ||||||
|             -1.0"#]],
 |             -1.0"#]],
 | ||||||
|     ); |     ); | ||||||
|  | @ -460,16 +462,16 @@ fn minus_belongs_to_literal() { | ||||||
|         expect![[r#" |         expect![[r#" | ||||||
|             ExpandError { |             ExpandError { | ||||||
|                 inner: ( |                 inner: ( | ||||||
|                     1:0@1..2#ROOT2024, |                     1:Root[0000, 0]@1..2#ROOT2024, | ||||||
|                     BindingError( |                     BindingError( | ||||||
|                         "expected literal", |                         "expected literal", | ||||||
|                     ), |                     ), | ||||||
|                 ), |                 ), | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             SUBTREE $$ 1:0@0..6#ROOT2024 1:0@0..6#ROOT2024 |             SUBTREE $$ 1:Root[0000, 0]@0..6#ROOT2024 1:Root[0000, 0]@0..6#ROOT2024 | ||||||
|               PUNCH   - [joint] 1:0@1..2#ROOT2024 |               PUNCH   - [joint] 1:Root[0000, 0]@1..2#ROOT2024 | ||||||
|               PUNCH   - [alone] 1:0@2..3#ROOT2024 |               PUNCH   - [alone] 1:Root[0000, 0]@2..3#ROOT2024 | ||||||
| 
 | 
 | ||||||
|             --"#]],
 |             --"#]],
 | ||||||
|     ); |     ); | ||||||
|  |  | ||||||
|  | @ -22,9 +22,10 @@ pub const HAS_GLOBAL_SPANS: u32 = 3; | ||||||
| pub const RUST_ANALYZER_SPAN_SUPPORT: u32 = 4; | pub const RUST_ANALYZER_SPAN_SUPPORT: u32 = 4; | ||||||
| /// Whether literals encode their kind as an additional u32 field and idents their rawness as a u32 field.
 | /// Whether literals encode their kind as an additional u32 field and idents their rawness as a u32 field.
 | ||||||
| pub const EXTENDED_LEAF_DATA: u32 = 5; | pub const EXTENDED_LEAF_DATA: u32 = 5; | ||||||
|  | pub const HASHED_AST_ID: u32 = 6; | ||||||
| 
 | 
 | ||||||
| /// Current API version of the proc-macro protocol.
 | /// Current API version of the proc-macro protocol.
 | ||||||
| pub const CURRENT_API_VERSION: u32 = EXTENDED_LEAF_DATA; | pub const CURRENT_API_VERSION: u32 = HASHED_AST_ID; | ||||||
| 
 | 
 | ||||||
| /// Represents requests sent from the client to the proc-macro-srv.
 | /// Represents requests sent from the client to the proc-macro-srv.
 | ||||||
| #[derive(Debug, Serialize, Deserialize)] | #[derive(Debug, Serialize, Deserialize)] | ||||||
|  | @ -54,7 +55,7 @@ pub enum SpanMode { | ||||||
|     Id, |     Id, | ||||||
| 
 | 
 | ||||||
|     /// Rust Analyzer-specific span handling mode.
 |     /// Rust Analyzer-specific span handling mode.
 | ||||||
|     RustAnalyzer, |     RustAnalyzer { fixup_ast_id: u32 }, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /// Represents responses sent from the proc-macro-srv to the client.
 | /// Represents responses sent from the proc-macro-srv to the client.
 | ||||||
|  | @ -201,7 +202,9 @@ type ProtocolWrite<W: Write> = for<'o, 'msg> fn(out: &'o mut W, msg: &'msg str) | ||||||
| #[cfg(test)] | #[cfg(test)] | ||||||
| mod tests { | mod tests { | ||||||
|     use intern::{Symbol, sym}; |     use intern::{Symbol, sym}; | ||||||
|     use span::{Edition, ErasedFileAstId, Span, SpanAnchor, SyntaxContext, TextRange, TextSize}; |     use span::{ | ||||||
|  |         Edition, ROOT_ERASED_FILE_AST_ID, Span, SpanAnchor, SyntaxContext, TextRange, TextSize, | ||||||
|  |     }; | ||||||
|     use tt::{ |     use tt::{ | ||||||
|         Delimiter, DelimiterKind, Ident, Leaf, Literal, Punct, Spacing, TopSubtree, |         Delimiter, DelimiterKind, Ident, Leaf, Literal, Punct, Spacing, TopSubtree, | ||||||
|         TopSubtreeBuilder, |         TopSubtreeBuilder, | ||||||
|  | @ -215,7 +218,7 @@ mod tests { | ||||||
|                 span::FileId::from_raw(0xe4e4e), |                 span::FileId::from_raw(0xe4e4e), | ||||||
|                 span::Edition::CURRENT, |                 span::Edition::CURRENT, | ||||||
|             ), |             ), | ||||||
|             ast_id: ErasedFileAstId::from_raw(0), |             ast_id: ROOT_ERASED_FILE_AST_ID, | ||||||
|         }; |         }; | ||||||
| 
 | 
 | ||||||
|         let mut builder = TopSubtreeBuilder::new(Delimiter { |         let mut builder = TopSubtreeBuilder::new(Delimiter { | ||||||
|  | @ -305,7 +308,7 @@ mod tests { | ||||||
|     #[test] |     #[test] | ||||||
|     fn test_proc_macro_rpc_works() { |     fn test_proc_macro_rpc_works() { | ||||||
|         let tt = fixture_token_tree(); |         let tt = fixture_token_tree(); | ||||||
|         for v in RUST_ANALYZER_SPAN_SUPPORT..=CURRENT_API_VERSION { |         for v in HASHED_AST_ID..=CURRENT_API_VERSION { | ||||||
|             let mut span_data_table = Default::default(); |             let mut span_data_table = Default::default(); | ||||||
|             let task = ExpandMacro { |             let task = ExpandMacro { | ||||||
|                 data: ExpandMacroData { |                 data: ExpandMacroData { | ||||||
|  |  | ||||||
|  | @ -8,6 +8,7 @@ use std::{ | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| use paths::AbsPath; | use paths::AbsPath; | ||||||
|  | use span::FIXUP_ERASED_FILE_AST_ID_MARKER; | ||||||
| use stdx::JodChild; | use stdx::JodChild; | ||||||
| 
 | 
 | ||||||
| use crate::{ | use crate::{ | ||||||
|  | @ -15,8 +16,7 @@ use crate::{ | ||||||
|     legacy_protocol::{ |     legacy_protocol::{ | ||||||
|         json::{read_json, write_json}, |         json::{read_json, write_json}, | ||||||
|         msg::{ |         msg::{ | ||||||
|             CURRENT_API_VERSION, Message, RUST_ANALYZER_SPAN_SUPPORT, Request, Response, |             CURRENT_API_VERSION, HASHED_AST_ID, Message, Request, Response, ServerConfig, SpanMode, | ||||||
|             ServerConfig, SpanMode, |  | ||||||
|         }, |         }, | ||||||
|     }, |     }, | ||||||
| }; | }; | ||||||
|  | @ -71,7 +71,9 @@ impl ProcMacroServerProcess { | ||||||
|             Ok(v) => { |             Ok(v) => { | ||||||
|                 tracing::info!("Proc-macro server version: {v}"); |                 tracing::info!("Proc-macro server version: {v}"); | ||||||
|                 srv.version = v; |                 srv.version = v; | ||||||
|                 if srv.version >= RUST_ANALYZER_SPAN_SUPPORT { |                 if srv.version >= HASHED_AST_ID { | ||||||
|  |                     // We don't enable spans on versions prior to `HASHED_AST_ID`, because their ast id layout
 | ||||||
|  |                     // is different.
 | ||||||
|                     if let Ok(mode) = srv.enable_rust_analyzer_spans() { |                     if let Ok(mode) = srv.enable_rust_analyzer_spans() { | ||||||
|                         srv.mode = mode; |                         srv.mode = mode; | ||||||
|                     } |                     } | ||||||
|  | @ -111,7 +113,11 @@ impl ProcMacroServerProcess { | ||||||
| 
 | 
 | ||||||
|     /// Enable support for rust-analyzer span mode if the server supports it.
 |     /// Enable support for rust-analyzer span mode if the server supports it.
 | ||||||
|     fn enable_rust_analyzer_spans(&self) -> Result<SpanMode, ServerError> { |     fn enable_rust_analyzer_spans(&self) -> Result<SpanMode, ServerError> { | ||||||
|         let request = Request::SetConfig(ServerConfig { span_mode: SpanMode::RustAnalyzer }); |         let request = Request::SetConfig(ServerConfig { | ||||||
|  |             span_mode: SpanMode::RustAnalyzer { | ||||||
|  |                 fixup_ast_id: FIXUP_ERASED_FILE_AST_ID_MARKER.into_raw(), | ||||||
|  |             }, | ||||||
|  |         }); | ||||||
|         let response = self.send_task(request)?; |         let response = self.send_task(request)?; | ||||||
| 
 | 
 | ||||||
|         match response { |         match response { | ||||||
|  |  | ||||||
|  | @ -26,7 +26,7 @@ pub(crate) fn run() -> io::Result<()> { | ||||||
|     let write_response = |msg: msg::Response| msg.write(write_json, &mut io::stdout().lock()); |     let write_response = |msg: msg::Response| msg.write(write_json, &mut io::stdout().lock()); | ||||||
| 
 | 
 | ||||||
|     let env = EnvSnapshot::default(); |     let env = EnvSnapshot::default(); | ||||||
|     let srv = proc_macro_srv::ProcMacroSrv::new(&env); |     let mut srv = proc_macro_srv::ProcMacroSrv::new(&env); | ||||||
| 
 | 
 | ||||||
|     let mut span_mode = SpanMode::Id; |     let mut span_mode = SpanMode::Id; | ||||||
| 
 | 
 | ||||||
|  | @ -78,7 +78,7 @@ pub(crate) fn run() -> io::Result<()> { | ||||||
|                         }) |                         }) | ||||||
|                         .map_err(msg::PanicMessage) |                         .map_err(msg::PanicMessage) | ||||||
|                     }), |                     }), | ||||||
|                     SpanMode::RustAnalyzer => msg::Response::ExpandMacroExtended({ |                     SpanMode::RustAnalyzer { .. } => msg::Response::ExpandMacroExtended({ | ||||||
|                         let mut span_data_table = deserialize_span_data_index_map(&span_data_table); |                         let mut span_data_table = deserialize_span_data_index_map(&span_data_table); | ||||||
| 
 | 
 | ||||||
|                         let def_site = span_data_table[def_site]; |                         let def_site = span_data_table[def_site]; | ||||||
|  | @ -122,6 +122,9 @@ pub(crate) fn run() -> io::Result<()> { | ||||||
|             msg::Request::ApiVersionCheck {} => msg::Response::ApiVersionCheck(CURRENT_API_VERSION), |             msg::Request::ApiVersionCheck {} => msg::Response::ApiVersionCheck(CURRENT_API_VERSION), | ||||||
|             msg::Request::SetConfig(config) => { |             msg::Request::SetConfig(config) => { | ||||||
|                 span_mode = config.span_mode; |                 span_mode = config.span_mode; | ||||||
|  |                 if let SpanMode::RustAnalyzer { fixup_ast_id } = span_mode { | ||||||
|  |                     srv.set_fixup_ast_id(fixup_ast_id); | ||||||
|  |                 } | ||||||
|                 msg::Response::SetConfig(config) |                 msg::Response::SetConfig(config) | ||||||
|             } |             } | ||||||
|         }; |         }; | ||||||
|  |  | ||||||
|  | @ -3,6 +3,7 @@ | ||||||
| mod version; | mod version; | ||||||
| 
 | 
 | ||||||
| use proc_macro::bridge; | use proc_macro::bridge; | ||||||
|  | use span::ErasedFileAstId; | ||||||
| use std::{fmt, fs, io, time::SystemTime}; | use std::{fmt, fs, io, time::SystemTime}; | ||||||
| 
 | 
 | ||||||
| use libloading::Library; | use libloading::Library; | ||||||
|  | @ -161,14 +162,20 @@ impl Expander { | ||||||
|         def_site: S, |         def_site: S, | ||||||
|         call_site: S, |         call_site: S, | ||||||
|         mixed_site: S, |         mixed_site: S, | ||||||
|  |         fixup_ast_id: ErasedFileAstId, | ||||||
|     ) -> Result<TopSubtree<S>, String> |     ) -> Result<TopSubtree<S>, String> | ||||||
|     where |     where | ||||||
|         <S::Server as bridge::server::Types>::TokenStream: Default, |         <S::Server as bridge::server::Types>::TokenStream: Default, | ||||||
|     { |     { | ||||||
|         let result = self |         let result = self.inner.proc_macros.expand( | ||||||
|             .inner |             macro_name, | ||||||
|             .proc_macros |             macro_body, | ||||||
|             .expand(macro_name, macro_body, attributes, def_site, call_site, mixed_site); |             attributes, | ||||||
|  |             def_site, | ||||||
|  |             call_site, | ||||||
|  |             mixed_site, | ||||||
|  |             fixup_ast_id, | ||||||
|  |         ); | ||||||
|         result.map_err(|e| e.into_string().unwrap_or_default()) |         result.map_err(|e| e.into_string().unwrap_or_default()) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -41,7 +41,7 @@ use std::{ | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| use paths::{Utf8Path, Utf8PathBuf}; | use paths::{Utf8Path, Utf8PathBuf}; | ||||||
| use span::{Span, TokenId}; | use span::{ErasedFileAstId, FIXUP_ERASED_FILE_AST_ID_MARKER, Span, TokenId}; | ||||||
| 
 | 
 | ||||||
| use crate::server_impl::TokenStream; | use crate::server_impl::TokenStream; | ||||||
| 
 | 
 | ||||||
|  | @ -57,11 +57,16 @@ pub const RUSTC_VERSION_STRING: &str = env!("RUSTC_VERSION"); | ||||||
| pub struct ProcMacroSrv<'env> { | pub struct ProcMacroSrv<'env> { | ||||||
|     expanders: Mutex<HashMap<Utf8PathBuf, Arc<dylib::Expander>>>, |     expanders: Mutex<HashMap<Utf8PathBuf, Arc<dylib::Expander>>>, | ||||||
|     env: &'env EnvSnapshot, |     env: &'env EnvSnapshot, | ||||||
|  |     fixup_ast_id: ErasedFileAstId, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl<'env> ProcMacroSrv<'env> { | impl<'env> ProcMacroSrv<'env> { | ||||||
|     pub fn new(env: &'env EnvSnapshot) -> Self { |     pub fn new(env: &'env EnvSnapshot) -> Self { | ||||||
|         Self { expanders: Default::default(), env } |         Self { expanders: Default::default(), env, fixup_ast_id: FIXUP_ERASED_FILE_AST_ID_MARKER } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn set_fixup_ast_id(&mut self, fixup_ast_id: u32) { | ||||||
|  |         self.fixup_ast_id = ErasedFileAstId::from_raw(fixup_ast_id); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -101,6 +106,7 @@ impl ProcMacroSrv<'_> { | ||||||
|                             def_site, |                             def_site, | ||||||
|                             call_site, |                             call_site, | ||||||
|                             mixed_site, |                             mixed_site, | ||||||
|  |                             self.fixup_ast_id, | ||||||
|                         ) |                         ) | ||||||
|                         .map(|tt| tt.0) |                         .map(|tt| tt.0) | ||||||
|                 }); |                 }); | ||||||
|  | @ -156,25 +162,41 @@ impl ProcMacroSrv<'_> { | ||||||
| 
 | 
 | ||||||
| pub trait ProcMacroSrvSpan: Copy + Send { | pub trait ProcMacroSrvSpan: Copy + Send { | ||||||
|     type Server: proc_macro::bridge::server::Server<TokenStream = TokenStream<Self>>; |     type Server: proc_macro::bridge::server::Server<TokenStream = TokenStream<Self>>; | ||||||
|     fn make_server(call_site: Self, def_site: Self, mixed_site: Self) -> Self::Server; |     fn make_server( | ||||||
|  |         call_site: Self, | ||||||
|  |         def_site: Self, | ||||||
|  |         mixed_site: Self, | ||||||
|  |         fixup_ast_id: ErasedFileAstId, | ||||||
|  |     ) -> Self::Server; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl ProcMacroSrvSpan for TokenId { | impl ProcMacroSrvSpan for TokenId { | ||||||
|     type Server = server_impl::token_id::TokenIdServer; |     type Server = server_impl::token_id::TokenIdServer; | ||||||
| 
 | 
 | ||||||
|     fn make_server(call_site: Self, def_site: Self, mixed_site: Self) -> Self::Server { |     fn make_server( | ||||||
|  |         call_site: Self, | ||||||
|  |         def_site: Self, | ||||||
|  |         mixed_site: Self, | ||||||
|  |         _fixup_ast_id: ErasedFileAstId, | ||||||
|  |     ) -> Self::Server { | ||||||
|         Self::Server { call_site, def_site, mixed_site } |         Self::Server { call_site, def_site, mixed_site } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| impl ProcMacroSrvSpan for Span { | impl ProcMacroSrvSpan for Span { | ||||||
|     type Server = server_impl::rust_analyzer_span::RaSpanServer; |     type Server = server_impl::rust_analyzer_span::RaSpanServer; | ||||||
|     fn make_server(call_site: Self, def_site: Self, mixed_site: Self) -> Self::Server { |     fn make_server( | ||||||
|  |         call_site: Self, | ||||||
|  |         def_site: Self, | ||||||
|  |         mixed_site: Self, | ||||||
|  |         fixup_ast_id: ErasedFileAstId, | ||||||
|  |     ) -> Self::Server { | ||||||
|         Self::Server { |         Self::Server { | ||||||
|             call_site, |             call_site, | ||||||
|             def_site, |             def_site, | ||||||
|             mixed_site, |             mixed_site, | ||||||
|             tracked_env_vars: Default::default(), |             tracked_env_vars: Default::default(), | ||||||
|             tracked_paths: Default::default(), |             tracked_paths: Default::default(), | ||||||
|  |             fixup_ast_id, | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1,6 +1,7 @@ | ||||||
| //! Proc macro ABI
 | //! Proc macro ABI
 | ||||||
| 
 | 
 | ||||||
| use proc_macro::bridge; | use proc_macro::bridge; | ||||||
|  | use span::ErasedFileAstId; | ||||||
| 
 | 
 | ||||||
| use crate::{ProcMacroKind, ProcMacroSrvSpan, server_impl::TopSubtree}; | use crate::{ProcMacroKind, ProcMacroSrvSpan, server_impl::TopSubtree}; | ||||||
| 
 | 
 | ||||||
|  | @ -22,6 +23,7 @@ impl ProcMacros { | ||||||
|         def_site: S, |         def_site: S, | ||||||
|         call_site: S, |         call_site: S, | ||||||
|         mixed_site: S, |         mixed_site: S, | ||||||
|  |         fixup_ast_id: ErasedFileAstId, | ||||||
|     ) -> Result<TopSubtree<S>, crate::PanicMessage> { |     ) -> Result<TopSubtree<S>, crate::PanicMessage> { | ||||||
|         let parsed_body = crate::server_impl::TokenStream::with_subtree(macro_body); |         let parsed_body = crate::server_impl::TokenStream::with_subtree(macro_body); | ||||||
| 
 | 
 | ||||||
|  | @ -37,7 +39,7 @@ impl ProcMacros { | ||||||
|                 { |                 { | ||||||
|                     let res = client.run( |                     let res = client.run( | ||||||
|                         &bridge::server::SameThread, |                         &bridge::server::SameThread, | ||||||
|                         S::make_server(call_site, def_site, mixed_site), |                         S::make_server(call_site, def_site, mixed_site, fixup_ast_id), | ||||||
|                         parsed_body, |                         parsed_body, | ||||||
|                         cfg!(debug_assertions), |                         cfg!(debug_assertions), | ||||||
|                     ); |                     ); | ||||||
|  | @ -48,7 +50,7 @@ impl ProcMacros { | ||||||
|                 bridge::client::ProcMacro::Bang { name, client } if *name == macro_name => { |                 bridge::client::ProcMacro::Bang { name, client } if *name == macro_name => { | ||||||
|                     let res = client.run( |                     let res = client.run( | ||||||
|                         &bridge::server::SameThread, |                         &bridge::server::SameThread, | ||||||
|                         S::make_server(call_site, def_site, mixed_site), |                         S::make_server(call_site, def_site, mixed_site, fixup_ast_id), | ||||||
|                         parsed_body, |                         parsed_body, | ||||||
|                         cfg!(debug_assertions), |                         cfg!(debug_assertions), | ||||||
|                     ); |                     ); | ||||||
|  | @ -59,7 +61,7 @@ impl ProcMacros { | ||||||
|                 bridge::client::ProcMacro::Attr { name, client } if *name == macro_name => { |                 bridge::client::ProcMacro::Attr { name, client } if *name == macro_name => { | ||||||
|                     let res = client.run( |                     let res = client.run( | ||||||
|                         &bridge::server::SameThread, |                         &bridge::server::SameThread, | ||||||
|                         S::make_server(call_site, def_site, mixed_site), |                         S::make_server(call_site, def_site, mixed_site, fixup_ast_id), | ||||||
|                         parsed_attributes, |                         parsed_attributes, | ||||||
|                         parsed_body, |                         parsed_body, | ||||||
|                         cfg!(debug_assertions), |                         cfg!(debug_assertions), | ||||||
|  |  | ||||||
|  | @ -11,7 +11,7 @@ use std::{ | ||||||
| 
 | 
 | ||||||
| use intern::Symbol; | use intern::Symbol; | ||||||
| use proc_macro::bridge::{self, server}; | use proc_macro::bridge::{self, server}; | ||||||
| use span::{FIXUP_ERASED_FILE_AST_ID_MARKER, Span}; | use span::{ErasedFileAstId, Span}; | ||||||
| use tt::{TextRange, TextSize}; | use tt::{TextRange, TextSize}; | ||||||
| 
 | 
 | ||||||
| use crate::server_impl::{from_token_tree, literal_from_str, token_stream::TokenStreamBuilder}; | use crate::server_impl::{from_token_tree, literal_from_str, token_stream::TokenStreamBuilder}; | ||||||
|  | @ -28,6 +28,7 @@ pub struct RaSpanServer { | ||||||
|     pub call_site: Span, |     pub call_site: Span, | ||||||
|     pub def_site: Span, |     pub def_site: Span, | ||||||
|     pub mixed_site: Span, |     pub mixed_site: Span, | ||||||
|  |     pub fixup_ast_id: ErasedFileAstId, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl server::Types for RaSpanServer { | impl server::Types for RaSpanServer { | ||||||
|  | @ -181,10 +182,10 @@ impl server::Span for RaSpanServer { | ||||||
|     fn join(&mut self, first: Self::Span, second: Self::Span) -> Option<Self::Span> { |     fn join(&mut self, first: Self::Span, second: Self::Span) -> Option<Self::Span> { | ||||||
|         // We can't modify the span range for fixup spans, those are meaningful to fixup, so just
 |         // We can't modify the span range for fixup spans, those are meaningful to fixup, so just
 | ||||||
|         // prefer the non-fixup span.
 |         // prefer the non-fixup span.
 | ||||||
|         if first.anchor.ast_id == FIXUP_ERASED_FILE_AST_ID_MARKER { |         if first.anchor.ast_id == self.fixup_ast_id { | ||||||
|             return Some(second); |             return Some(second); | ||||||
|         } |         } | ||||||
|         if second.anchor.ast_id == FIXUP_ERASED_FILE_AST_ID_MARKER { |         if second.anchor.ast_id == self.fixup_ast_id { | ||||||
|             return Some(first); |             return Some(first); | ||||||
|         } |         } | ||||||
|         // FIXME: Once we can talk back to the client, implement a "long join" request for anchors
 |         // FIXME: Once we can talk back to the client, implement a "long join" request for anchors
 | ||||||
|  | @ -213,7 +214,7 @@ impl server::Span for RaSpanServer { | ||||||
|         end: Bound<usize>, |         end: Bound<usize>, | ||||||
|     ) -> Option<Self::Span> { |     ) -> Option<Self::Span> { | ||||||
|         // We can't modify the span range for fixup spans, those are meaningful to fixup.
 |         // We can't modify the span range for fixup spans, those are meaningful to fixup.
 | ||||||
|         if span.anchor.ast_id == FIXUP_ERASED_FILE_AST_ID_MARKER { |         if span.anchor.ast_id == self.fixup_ast_id { | ||||||
|             return Some(span); |             return Some(span); | ||||||
|         } |         } | ||||||
|         let length = span.range.len().into(); |         let length = span.range.len().into(); | ||||||
|  | @ -256,7 +257,7 @@ impl server::Span for RaSpanServer { | ||||||
| 
 | 
 | ||||||
|     fn end(&mut self, span: Self::Span) -> Self::Span { |     fn end(&mut self, span: Self::Span) -> Self::Span { | ||||||
|         // We can't modify the span range for fixup spans, those are meaningful to fixup.
 |         // We can't modify the span range for fixup spans, those are meaningful to fixup.
 | ||||||
|         if span.anchor.ast_id == FIXUP_ERASED_FILE_AST_ID_MARKER { |         if span.anchor.ast_id == self.fixup_ast_id { | ||||||
|             return span; |             return span; | ||||||
|         } |         } | ||||||
|         Span { range: TextRange::empty(span.range.end()), ..span } |         Span { range: TextRange::empty(span.range.end()), ..span } | ||||||
|  | @ -264,7 +265,7 @@ impl server::Span for RaSpanServer { | ||||||
| 
 | 
 | ||||||
|     fn start(&mut self, span: Self::Span) -> Self::Span { |     fn start(&mut self, span: Self::Span) -> Self::Span { | ||||||
|         // We can't modify the span range for fixup spans, those are meaningful to fixup.
 |         // We can't modify the span range for fixup spans, those are meaningful to fixup.
 | ||||||
|         if span.anchor.ast_id == FIXUP_ERASED_FILE_AST_ID_MARKER { |         if span.anchor.ast_id == self.fixup_ast_id { | ||||||
|             return span; |             return span; | ||||||
|         } |         } | ||||||
|         Span { range: TextRange::empty(span.range.start()), ..span } |         Span { range: TextRange::empty(span.range.start()), ..span } | ||||||
|  | @ -318,7 +319,7 @@ mod tests { | ||||||
|             range: TextRange::empty(TextSize::new(0)), |             range: TextRange::empty(TextSize::new(0)), | ||||||
|             anchor: span::SpanAnchor { |             anchor: span::SpanAnchor { | ||||||
|                 file_id: EditionedFileId::current_edition(FileId::from_raw(0)), |                 file_id: EditionedFileId::current_edition(FileId::from_raw(0)), | ||||||
|                 ast_id: span::ErasedFileAstId::from_raw(0), |                 ast_id: span::ROOT_ERASED_FILE_AST_ID, | ||||||
|             }, |             }, | ||||||
|             ctx: SyntaxContext::root(span::Edition::CURRENT), |             ctx: SyntaxContext::root(span::Edition::CURRENT), | ||||||
|         }; |         }; | ||||||
|  | @ -360,7 +361,7 @@ mod tests { | ||||||
|             range: TextRange::empty(TextSize::new(0)), |             range: TextRange::empty(TextSize::new(0)), | ||||||
|             anchor: span::SpanAnchor { |             anchor: span::SpanAnchor { | ||||||
|                 file_id: EditionedFileId::current_edition(FileId::from_raw(0)), |                 file_id: EditionedFileId::current_edition(FileId::from_raw(0)), | ||||||
|                 ast_id: span::ErasedFileAstId::from_raw(0), |                 ast_id: span::ROOT_ERASED_FILE_AST_ID, | ||||||
|             }, |             }, | ||||||
|             ctx: SyntaxContext::root(span::Edition::CURRENT), |             ctx: SyntaxContext::root(span::Edition::CURRENT), | ||||||
|         }; |         }; | ||||||
|  |  | ||||||
|  | @ -21,14 +21,14 @@ fn test_derive_empty() { | ||||||
| 
 | 
 | ||||||
|             SUBTREE $$ 1 1"#]],
 |             SUBTREE $$ 1 1"#]],
 | ||||||
|         expect![[r#" |         expect![[r#" | ||||||
|             SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024 |             SUBTREE $$ 42:Root[0000, 0]@0..100#ROOT2024 42:Root[0000, 0]@0..100#ROOT2024 | ||||||
|               IDENT   struct 42:2@0..6#ROOT2024 |               IDENT   struct 42:Root[0000, 0]@0..6#ROOT2024 | ||||||
|               IDENT   S 42:2@7..8#ROOT2024 |               IDENT   S 42:Root[0000, 0]@7..8#ROOT2024 | ||||||
|               PUNCH   ; [alone] 42:2@8..9#ROOT2024 |               PUNCH   ; [alone] 42:Root[0000, 0]@8..9#ROOT2024 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|             SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024"#]],
 |             SUBTREE $$ 42:Root[0000, 0]@0..100#ROOT2024 42:Root[0000, 0]@0..100#ROOT2024"#]],
 | ||||||
|     ); |     ); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -52,19 +52,19 @@ fn test_derive_error() { | ||||||
|                 LITERAL Str #[derive(DeriveError)] struct S ; 1 |                 LITERAL Str #[derive(DeriveError)] struct S ; 1 | ||||||
|               PUNCH   ; [alone] 1"#]],
 |               PUNCH   ; [alone] 1"#]],
 | ||||||
|         expect![[r#" |         expect![[r#" | ||||||
|             SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024 |             SUBTREE $$ 42:Root[0000, 0]@0..100#ROOT2024 42:Root[0000, 0]@0..100#ROOT2024 | ||||||
|               IDENT   struct 42:2@0..6#ROOT2024 |               IDENT   struct 42:Root[0000, 0]@0..6#ROOT2024 | ||||||
|               IDENT   S 42:2@7..8#ROOT2024 |               IDENT   S 42:Root[0000, 0]@7..8#ROOT2024 | ||||||
|               PUNCH   ; [alone] 42:2@8..9#ROOT2024 |               PUNCH   ; [alone] 42:Root[0000, 0]@8..9#ROOT2024 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|             SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024 |             SUBTREE $$ 42:Root[0000, 0]@0..100#ROOT2024 42:Root[0000, 0]@0..100#ROOT2024 | ||||||
|               IDENT   compile_error 42:2@0..100#ROOT2024 |               IDENT   compile_error 42:Root[0000, 0]@0..100#ROOT2024 | ||||||
|               PUNCH   ! [alone] 42:2@0..100#ROOT2024 |               PUNCH   ! [alone] 42:Root[0000, 0]@0..100#ROOT2024 | ||||||
|               SUBTREE () 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024 |               SUBTREE () 42:Root[0000, 0]@0..100#ROOT2024 42:Root[0000, 0]@0..100#ROOT2024 | ||||||
|                 LITERAL Str #[derive(DeriveError)] struct S ; 42:2@0..100#ROOT2024 |                 LITERAL Str #[derive(DeriveError)] struct S ; 42:Root[0000, 0]@0..100#ROOT2024 | ||||||
|               PUNCH   ; [alone] 42:2@0..100#ROOT2024"#]],
 |               PUNCH   ; [alone] 42:Root[0000, 0]@0..100#ROOT2024"#]],
 | ||||||
|     ); |     ); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -94,25 +94,25 @@ fn test_fn_like_macro_noop() { | ||||||
|               PUNCH   , [alone] 1 |               PUNCH   , [alone] 1 | ||||||
|               SUBTREE [] 1 1"#]],
 |               SUBTREE [] 1 1"#]],
 | ||||||
|         expect![[r#" |         expect![[r#" | ||||||
|             SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024 |             SUBTREE $$ 42:Root[0000, 0]@0..100#ROOT2024 42:Root[0000, 0]@0..100#ROOT2024 | ||||||
|               IDENT   ident 42:2@0..5#ROOT2024 |               IDENT   ident 42:Root[0000, 0]@0..5#ROOT2024 | ||||||
|               PUNCH   , [alone] 42:2@5..6#ROOT2024 |               PUNCH   , [alone] 42:Root[0000, 0]@5..6#ROOT2024 | ||||||
|               LITERAL Integer 0 42:2@7..8#ROOT2024 |               LITERAL Integer 0 42:Root[0000, 0]@7..8#ROOT2024 | ||||||
|               PUNCH   , [alone] 42:2@8..9#ROOT2024 |               PUNCH   , [alone] 42:Root[0000, 0]@8..9#ROOT2024 | ||||||
|               LITERAL Integer 1 42:2@10..11#ROOT2024 |               LITERAL Integer 1 42:Root[0000, 0]@10..11#ROOT2024 | ||||||
|               PUNCH   , [alone] 42:2@11..12#ROOT2024 |               PUNCH   , [alone] 42:Root[0000, 0]@11..12#ROOT2024 | ||||||
|               SUBTREE [] 42:2@13..14#ROOT2024 42:2@14..15#ROOT2024 |               SUBTREE [] 42:Root[0000, 0]@13..14#ROOT2024 42:Root[0000, 0]@14..15#ROOT2024 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|             SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024 |             SUBTREE $$ 42:Root[0000, 0]@0..100#ROOT2024 42:Root[0000, 0]@0..100#ROOT2024 | ||||||
|               IDENT   ident 42:2@0..5#ROOT2024 |               IDENT   ident 42:Root[0000, 0]@0..5#ROOT2024 | ||||||
|               PUNCH   , [alone] 42:2@5..6#ROOT2024 |               PUNCH   , [alone] 42:Root[0000, 0]@5..6#ROOT2024 | ||||||
|               LITERAL Integer 0 42:2@7..8#ROOT2024 |               LITERAL Integer 0 42:Root[0000, 0]@7..8#ROOT2024 | ||||||
|               PUNCH   , [alone] 42:2@8..9#ROOT2024 |               PUNCH   , [alone] 42:Root[0000, 0]@8..9#ROOT2024 | ||||||
|               LITERAL Integer 1 42:2@10..11#ROOT2024 |               LITERAL Integer 1 42:Root[0000, 0]@10..11#ROOT2024 | ||||||
|               PUNCH   , [alone] 42:2@11..12#ROOT2024 |               PUNCH   , [alone] 42:Root[0000, 0]@11..12#ROOT2024 | ||||||
|               SUBTREE [] 42:2@13..14#ROOT2024 42:2@14..15#ROOT2024"#]],
 |               SUBTREE [] 42:Root[0000, 0]@13..14#ROOT2024 42:Root[0000, 0]@14..15#ROOT2024"#]],
 | ||||||
|     ); |     ); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -134,17 +134,17 @@ fn test_fn_like_macro_clone_ident_subtree() { | ||||||
|               PUNCH   , [alone] 1 |               PUNCH   , [alone] 1 | ||||||
|               SUBTREE [] 1 1"#]],
 |               SUBTREE [] 1 1"#]],
 | ||||||
|         expect![[r#" |         expect![[r#" | ||||||
|             SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024 |             SUBTREE $$ 42:Root[0000, 0]@0..100#ROOT2024 42:Root[0000, 0]@0..100#ROOT2024 | ||||||
|               IDENT   ident 42:2@0..5#ROOT2024 |               IDENT   ident 42:Root[0000, 0]@0..5#ROOT2024 | ||||||
|               PUNCH   , [alone] 42:2@5..6#ROOT2024 |               PUNCH   , [alone] 42:Root[0000, 0]@5..6#ROOT2024 | ||||||
|               SUBTREE [] 42:2@7..8#ROOT2024 42:2@8..9#ROOT2024 |               SUBTREE [] 42:Root[0000, 0]@7..8#ROOT2024 42:Root[0000, 0]@8..9#ROOT2024 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|             SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024 |             SUBTREE $$ 42:Root[0000, 0]@0..100#ROOT2024 42:Root[0000, 0]@0..100#ROOT2024 | ||||||
|               IDENT   ident 42:2@0..5#ROOT2024 |               IDENT   ident 42:Root[0000, 0]@0..5#ROOT2024 | ||||||
|               PUNCH   , [alone] 42:2@5..6#ROOT2024 |               PUNCH   , [alone] 42:Root[0000, 0]@5..6#ROOT2024 | ||||||
|               SUBTREE [] 42:2@7..9#ROOT2024 42:2@7..9#ROOT2024"#]],
 |               SUBTREE [] 42:Root[0000, 0]@7..9#ROOT2024 42:Root[0000, 0]@7..9#ROOT2024"#]],
 | ||||||
|     ); |     ); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -162,13 +162,13 @@ fn test_fn_like_macro_clone_raw_ident() { | ||||||
|             SUBTREE $$ 1 1 |             SUBTREE $$ 1 1 | ||||||
|               IDENT   r#async 1"#]],
 |               IDENT   r#async 1"#]],
 | ||||||
|         expect![[r#" |         expect![[r#" | ||||||
|             SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024 |             SUBTREE $$ 42:Root[0000, 0]@0..100#ROOT2024 42:Root[0000, 0]@0..100#ROOT2024 | ||||||
|               IDENT   r#async 42:2@0..7#ROOT2024 |               IDENT   r#async 42:Root[0000, 0]@0..7#ROOT2024 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|             SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024 |             SUBTREE $$ 42:Root[0000, 0]@0..100#ROOT2024 42:Root[0000, 0]@0..100#ROOT2024 | ||||||
|               IDENT   r#async 42:2@0..7#ROOT2024"#]],
 |               IDENT   r#async 42:Root[0000, 0]@0..7#ROOT2024"#]],
 | ||||||
|     ); |     ); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -187,14 +187,14 @@ fn test_fn_like_fn_like_span_join() { | ||||||
|             SUBTREE $$ 1 1 |             SUBTREE $$ 1 1 | ||||||
|               IDENT   r#joined 1"#]],
 |               IDENT   r#joined 1"#]],
 | ||||||
|         expect![[r#" |         expect![[r#" | ||||||
|             SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024 |             SUBTREE $$ 42:Root[0000, 0]@0..100#ROOT2024 42:Root[0000, 0]@0..100#ROOT2024 | ||||||
|               IDENT   foo 42:2@0..3#ROOT2024 |               IDENT   foo 42:Root[0000, 0]@0..3#ROOT2024 | ||||||
|               IDENT   bar 42:2@8..11#ROOT2024 |               IDENT   bar 42:Root[0000, 0]@8..11#ROOT2024 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|             SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024 |             SUBTREE $$ 42:Root[0000, 0]@0..100#ROOT2024 42:Root[0000, 0]@0..100#ROOT2024 | ||||||
|               IDENT   r#joined 42:2@0..11#ROOT2024"#]],
 |               IDENT   r#joined 42:Root[0000, 0]@0..11#ROOT2024"#]],
 | ||||||
|     ); |     ); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -216,17 +216,17 @@ fn test_fn_like_fn_like_span_ops() { | ||||||
|               IDENT   resolved_at_def_site 1 |               IDENT   resolved_at_def_site 1 | ||||||
|               IDENT   start_span 1"#]],
 |               IDENT   start_span 1"#]],
 | ||||||
|         expect![[r#" |         expect![[r#" | ||||||
|             SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024 |             SUBTREE $$ 42:Root[0000, 0]@0..100#ROOT2024 42:Root[0000, 0]@0..100#ROOT2024 | ||||||
|               IDENT   set_def_site 42:2@0..12#ROOT2024 |               IDENT   set_def_site 42:Root[0000, 0]@0..12#ROOT2024 | ||||||
|               IDENT   resolved_at_def_site 42:2@13..33#ROOT2024 |               IDENT   resolved_at_def_site 42:Root[0000, 0]@13..33#ROOT2024 | ||||||
|               IDENT   start_span 42:2@34..44#ROOT2024 |               IDENT   start_span 42:Root[0000, 0]@34..44#ROOT2024 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|             SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024 |             SUBTREE $$ 42:Root[0000, 0]@0..100#ROOT2024 42:Root[0000, 0]@0..100#ROOT2024 | ||||||
|               IDENT   set_def_site 41:1@0..150#ROOT2024 |               IDENT   set_def_site 41:Root[0000, 0]@0..150#ROOT2024 | ||||||
|               IDENT   resolved_at_def_site 42:2@13..33#ROOT2024 |               IDENT   resolved_at_def_site 42:Root[0000, 0]@13..33#ROOT2024 | ||||||
|               IDENT   start_span 42:2@34..34#ROOT2024"#]],
 |               IDENT   start_span 42:Root[0000, 0]@34..34#ROOT2024"#]],
 | ||||||
|     ); |     ); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -259,28 +259,28 @@ fn test_fn_like_mk_literals() { | ||||||
|               PUNCH   - [alone] 1 |               PUNCH   - [alone] 1 | ||||||
|               LITERAL Integer 123 1"#]],
 |               LITERAL Integer 123 1"#]],
 | ||||||
|         expect![[r#" |         expect![[r#" | ||||||
|             SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024 |             SUBTREE $$ 42:Root[0000, 0]@0..100#ROOT2024 42:Root[0000, 0]@0..100#ROOT2024 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|             SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024 |             SUBTREE $$ 42:Root[0000, 0]@0..100#ROOT2024 42:Root[0000, 0]@0..100#ROOT2024 | ||||||
|               LITERAL ByteStr byte_string 42:2@0..100#ROOT2024 |               LITERAL ByteStr byte_string 42:Root[0000, 0]@0..100#ROOT2024 | ||||||
|               LITERAL Char c 42:2@0..100#ROOT2024 |               LITERAL Char c 42:Root[0000, 0]@0..100#ROOT2024 | ||||||
|               LITERAL Str string 42:2@0..100#ROOT2024 |               LITERAL Str string 42:Root[0000, 0]@0..100#ROOT2024 | ||||||
|               LITERAL Str -string 42:2@0..100#ROOT2024 |               LITERAL Str -string 42:Root[0000, 0]@0..100#ROOT2024 | ||||||
|               LITERAL CStr cstring 42:2@0..100#ROOT2024 |               LITERAL CStr cstring 42:Root[0000, 0]@0..100#ROOT2024 | ||||||
|               LITERAL Float 3.14f64 42:2@0..100#ROOT2024 |               LITERAL Float 3.14f64 42:Root[0000, 0]@0..100#ROOT2024 | ||||||
|               PUNCH   - [alone] 42:2@0..100#ROOT2024 |               PUNCH   - [alone] 42:Root[0000, 0]@0..100#ROOT2024 | ||||||
|               LITERAL Float 3.14f64 42:2@0..100#ROOT2024 |               LITERAL Float 3.14f64 42:Root[0000, 0]@0..100#ROOT2024 | ||||||
|               LITERAL Float 3.14 42:2@0..100#ROOT2024 |               LITERAL Float 3.14 42:Root[0000, 0]@0..100#ROOT2024 | ||||||
|               PUNCH   - [alone] 42:2@0..100#ROOT2024 |               PUNCH   - [alone] 42:Root[0000, 0]@0..100#ROOT2024 | ||||||
|               LITERAL Float 3.14 42:2@0..100#ROOT2024 |               LITERAL Float 3.14 42:Root[0000, 0]@0..100#ROOT2024 | ||||||
|               LITERAL Integer 123i64 42:2@0..100#ROOT2024 |               LITERAL Integer 123i64 42:Root[0000, 0]@0..100#ROOT2024 | ||||||
|               PUNCH   - [alone] 42:2@0..100#ROOT2024 |               PUNCH   - [alone] 42:Root[0000, 0]@0..100#ROOT2024 | ||||||
|               LITERAL Integer 123i64 42:2@0..100#ROOT2024 |               LITERAL Integer 123i64 42:Root[0000, 0]@0..100#ROOT2024 | ||||||
|               LITERAL Integer 123 42:2@0..100#ROOT2024 |               LITERAL Integer 123 42:Root[0000, 0]@0..100#ROOT2024 | ||||||
|               PUNCH   - [alone] 42:2@0..100#ROOT2024 |               PUNCH   - [alone] 42:Root[0000, 0]@0..100#ROOT2024 | ||||||
|               LITERAL Integer 123 42:2@0..100#ROOT2024"#]],
 |               LITERAL Integer 123 42:Root[0000, 0]@0..100#ROOT2024"#]],
 | ||||||
|     ); |     ); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -298,13 +298,13 @@ fn test_fn_like_mk_idents() { | ||||||
|               IDENT   standard 1 |               IDENT   standard 1 | ||||||
|               IDENT   r#raw 1"#]],
 |               IDENT   r#raw 1"#]],
 | ||||||
|         expect![[r#" |         expect![[r#" | ||||||
|             SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024 |             SUBTREE $$ 42:Root[0000, 0]@0..100#ROOT2024 42:Root[0000, 0]@0..100#ROOT2024 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|             SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024 |             SUBTREE $$ 42:Root[0000, 0]@0..100#ROOT2024 42:Root[0000, 0]@0..100#ROOT2024 | ||||||
|               IDENT   standard 42:2@0..100#ROOT2024 |               IDENT   standard 42:Root[0000, 0]@0..100#ROOT2024 | ||||||
|               IDENT   r#raw 42:2@0..100#ROOT2024"#]],
 |               IDENT   r#raw 42:Root[0000, 0]@0..100#ROOT2024"#]],
 | ||||||
|     ); |     ); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -360,51 +360,51 @@ fn test_fn_like_macro_clone_literals() { | ||||||
|               PUNCH   , [alone] 1 |               PUNCH   , [alone] 1 | ||||||
|               LITERAL CStr null 1"#]],
 |               LITERAL CStr null 1"#]],
 | ||||||
|         expect![[r#" |         expect![[r#" | ||||||
|             SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024 |             SUBTREE $$ 42:Root[0000, 0]@0..100#ROOT2024 42:Root[0000, 0]@0..100#ROOT2024 | ||||||
|               LITERAL Integer 1u16 42:2@0..4#ROOT2024 |               LITERAL Integer 1u16 42:Root[0000, 0]@0..4#ROOT2024 | ||||||
|               PUNCH   , [alone] 42:2@4..5#ROOT2024 |               PUNCH   , [alone] 42:Root[0000, 0]@4..5#ROOT2024 | ||||||
|               LITERAL Integer 2_u32 42:2@6..11#ROOT2024 |               LITERAL Integer 2_u32 42:Root[0000, 0]@6..11#ROOT2024 | ||||||
|               PUNCH   , [alone] 42:2@11..12#ROOT2024 |               PUNCH   , [alone] 42:Root[0000, 0]@11..12#ROOT2024 | ||||||
|               PUNCH   - [alone] 42:2@13..14#ROOT2024 |               PUNCH   - [alone] 42:Root[0000, 0]@13..14#ROOT2024 | ||||||
|               LITERAL Integer 4i64 42:2@14..18#ROOT2024 |               LITERAL Integer 4i64 42:Root[0000, 0]@14..18#ROOT2024 | ||||||
|               PUNCH   , [alone] 42:2@18..19#ROOT2024 |               PUNCH   , [alone] 42:Root[0000, 0]@18..19#ROOT2024 | ||||||
|               LITERAL Float 3.14f32 42:2@20..27#ROOT2024 |               LITERAL Float 3.14f32 42:Root[0000, 0]@20..27#ROOT2024 | ||||||
|               PUNCH   , [alone] 42:2@27..28#ROOT2024 |               PUNCH   , [alone] 42:Root[0000, 0]@27..28#ROOT2024 | ||||||
|               LITERAL Str hello bridge 42:2@29..43#ROOT2024 |               LITERAL Str hello bridge 42:Root[0000, 0]@29..43#ROOT2024 | ||||||
|               PUNCH   , [alone] 42:2@43..44#ROOT2024 |               PUNCH   , [alone] 42:Root[0000, 0]@43..44#ROOT2024 | ||||||
|               LITERAL Str suffixedsuffix 42:2@45..61#ROOT2024 |               LITERAL Str suffixedsuffix 42:Root[0000, 0]@45..61#ROOT2024 | ||||||
|               PUNCH   , [alone] 42:2@61..62#ROOT2024 |               PUNCH   , [alone] 42:Root[0000, 0]@61..62#ROOT2024 | ||||||
|               LITERAL StrRaw(2) raw 42:2@63..73#ROOT2024 |               LITERAL StrRaw(2) raw 42:Root[0000, 0]@63..73#ROOT2024 | ||||||
|               PUNCH   , [alone] 42:2@73..74#ROOT2024 |               PUNCH   , [alone] 42:Root[0000, 0]@73..74#ROOT2024 | ||||||
|               LITERAL Char a 42:2@75..78#ROOT2024 |               LITERAL Char a 42:Root[0000, 0]@75..78#ROOT2024 | ||||||
|               PUNCH   , [alone] 42:2@78..79#ROOT2024 |               PUNCH   , [alone] 42:Root[0000, 0]@78..79#ROOT2024 | ||||||
|               LITERAL Byte b 42:2@80..84#ROOT2024 |               LITERAL Byte b 42:Root[0000, 0]@80..84#ROOT2024 | ||||||
|               PUNCH   , [alone] 42:2@84..85#ROOT2024 |               PUNCH   , [alone] 42:Root[0000, 0]@84..85#ROOT2024 | ||||||
|               LITERAL CStr null 42:2@86..93#ROOT2024 |               LITERAL CStr null 42:Root[0000, 0]@86..93#ROOT2024 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|             SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024 |             SUBTREE $$ 42:Root[0000, 0]@0..100#ROOT2024 42:Root[0000, 0]@0..100#ROOT2024 | ||||||
|               LITERAL Integer 1u16 42:2@0..4#ROOT2024 |               LITERAL Integer 1u16 42:Root[0000, 0]@0..4#ROOT2024 | ||||||
|               PUNCH   , [alone] 42:2@4..5#ROOT2024 |               PUNCH   , [alone] 42:Root[0000, 0]@4..5#ROOT2024 | ||||||
|               LITERAL Integer 2_u32 42:2@6..11#ROOT2024 |               LITERAL Integer 2_u32 42:Root[0000, 0]@6..11#ROOT2024 | ||||||
|               PUNCH   , [alone] 42:2@11..12#ROOT2024 |               PUNCH   , [alone] 42:Root[0000, 0]@11..12#ROOT2024 | ||||||
|               PUNCH   - [alone] 42:2@13..14#ROOT2024 |               PUNCH   - [alone] 42:Root[0000, 0]@13..14#ROOT2024 | ||||||
|               LITERAL Integer 4i64 42:2@14..18#ROOT2024 |               LITERAL Integer 4i64 42:Root[0000, 0]@14..18#ROOT2024 | ||||||
|               PUNCH   , [alone] 42:2@18..19#ROOT2024 |               PUNCH   , [alone] 42:Root[0000, 0]@18..19#ROOT2024 | ||||||
|               LITERAL Float 3.14f32 42:2@20..27#ROOT2024 |               LITERAL Float 3.14f32 42:Root[0000, 0]@20..27#ROOT2024 | ||||||
|               PUNCH   , [alone] 42:2@27..28#ROOT2024 |               PUNCH   , [alone] 42:Root[0000, 0]@27..28#ROOT2024 | ||||||
|               LITERAL Str hello bridge 42:2@29..43#ROOT2024 |               LITERAL Str hello bridge 42:Root[0000, 0]@29..43#ROOT2024 | ||||||
|               PUNCH   , [alone] 42:2@43..44#ROOT2024 |               PUNCH   , [alone] 42:Root[0000, 0]@43..44#ROOT2024 | ||||||
|               LITERAL Str suffixedsuffix 42:2@45..61#ROOT2024 |               LITERAL Str suffixedsuffix 42:Root[0000, 0]@45..61#ROOT2024 | ||||||
|               PUNCH   , [alone] 42:2@61..62#ROOT2024 |               PUNCH   , [alone] 42:Root[0000, 0]@61..62#ROOT2024 | ||||||
|               LITERAL StrRaw(2) raw 42:2@63..73#ROOT2024 |               LITERAL StrRaw(2) raw 42:Root[0000, 0]@63..73#ROOT2024 | ||||||
|               PUNCH   , [alone] 42:2@73..74#ROOT2024 |               PUNCH   , [alone] 42:Root[0000, 0]@73..74#ROOT2024 | ||||||
|               LITERAL Char a 42:2@75..78#ROOT2024 |               LITERAL Char a 42:Root[0000, 0]@75..78#ROOT2024 | ||||||
|               PUNCH   , [alone] 42:2@78..79#ROOT2024 |               PUNCH   , [alone] 42:Root[0000, 0]@78..79#ROOT2024 | ||||||
|               LITERAL Byte b 42:2@80..84#ROOT2024 |               LITERAL Byte b 42:Root[0000, 0]@80..84#ROOT2024 | ||||||
|               PUNCH   , [alone] 42:2@84..85#ROOT2024 |               PUNCH   , [alone] 42:Root[0000, 0]@84..85#ROOT2024 | ||||||
|               LITERAL CStr null 42:2@86..93#ROOT2024"#]],
 |               LITERAL CStr null 42:Root[0000, 0]@86..93#ROOT2024"#]],
 | ||||||
|     ); |     ); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -442,33 +442,33 @@ fn test_fn_like_macro_negative_literals() { | ||||||
|               PUNCH   - [alone] 1 |               PUNCH   - [alone] 1 | ||||||
|               LITERAL Float 2.7 1"#]],
 |               LITERAL Float 2.7 1"#]],
 | ||||||
|         expect![[r#" |         expect![[r#" | ||||||
|             SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024 |             SUBTREE $$ 42:Root[0000, 0]@0..100#ROOT2024 42:Root[0000, 0]@0..100#ROOT2024 | ||||||
|               PUNCH   - [alone] 42:2@0..1#ROOT2024 |               PUNCH   - [alone] 42:Root[0000, 0]@0..1#ROOT2024 | ||||||
|               LITERAL Integer 1u16 42:2@1..5#ROOT2024 |               LITERAL Integer 1u16 42:Root[0000, 0]@1..5#ROOT2024 | ||||||
|               PUNCH   , [alone] 42:2@5..6#ROOT2024 |               PUNCH   , [alone] 42:Root[0000, 0]@5..6#ROOT2024 | ||||||
|               PUNCH   - [alone] 42:2@7..8#ROOT2024 |               PUNCH   - [alone] 42:Root[0000, 0]@7..8#ROOT2024 | ||||||
|               LITERAL Integer 2_u32 42:2@9..14#ROOT2024 |               LITERAL Integer 2_u32 42:Root[0000, 0]@9..14#ROOT2024 | ||||||
|               PUNCH   , [alone] 42:2@14..15#ROOT2024 |               PUNCH   , [alone] 42:Root[0000, 0]@14..15#ROOT2024 | ||||||
|               PUNCH   - [alone] 42:2@16..17#ROOT2024 |               PUNCH   - [alone] 42:Root[0000, 0]@16..17#ROOT2024 | ||||||
|               LITERAL Float 3.14f32 42:2@17..24#ROOT2024 |               LITERAL Float 3.14f32 42:Root[0000, 0]@17..24#ROOT2024 | ||||||
|               PUNCH   , [alone] 42:2@24..25#ROOT2024 |               PUNCH   , [alone] 42:Root[0000, 0]@24..25#ROOT2024 | ||||||
|               PUNCH   - [alone] 42:2@26..27#ROOT2024 |               PUNCH   - [alone] 42:Root[0000, 0]@26..27#ROOT2024 | ||||||
|               LITERAL Float 2.7 42:2@28..31#ROOT2024 |               LITERAL Float 2.7 42:Root[0000, 0]@28..31#ROOT2024 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|             SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024 |             SUBTREE $$ 42:Root[0000, 0]@0..100#ROOT2024 42:Root[0000, 0]@0..100#ROOT2024 | ||||||
|               PUNCH   - [alone] 42:2@0..1#ROOT2024 |               PUNCH   - [alone] 42:Root[0000, 0]@0..1#ROOT2024 | ||||||
|               LITERAL Integer 1u16 42:2@1..5#ROOT2024 |               LITERAL Integer 1u16 42:Root[0000, 0]@1..5#ROOT2024 | ||||||
|               PUNCH   , [alone] 42:2@5..6#ROOT2024 |               PUNCH   , [alone] 42:Root[0000, 0]@5..6#ROOT2024 | ||||||
|               PUNCH   - [alone] 42:2@7..8#ROOT2024 |               PUNCH   - [alone] 42:Root[0000, 0]@7..8#ROOT2024 | ||||||
|               LITERAL Integer 2_u32 42:2@9..14#ROOT2024 |               LITERAL Integer 2_u32 42:Root[0000, 0]@9..14#ROOT2024 | ||||||
|               PUNCH   , [alone] 42:2@14..15#ROOT2024 |               PUNCH   , [alone] 42:Root[0000, 0]@14..15#ROOT2024 | ||||||
|               PUNCH   - [alone] 42:2@16..17#ROOT2024 |               PUNCH   - [alone] 42:Root[0000, 0]@16..17#ROOT2024 | ||||||
|               LITERAL Float 3.14f32 42:2@17..24#ROOT2024 |               LITERAL Float 3.14f32 42:Root[0000, 0]@17..24#ROOT2024 | ||||||
|               PUNCH   , [alone] 42:2@24..25#ROOT2024 |               PUNCH   , [alone] 42:Root[0000, 0]@24..25#ROOT2024 | ||||||
|               PUNCH   - [alone] 42:2@26..27#ROOT2024 |               PUNCH   - [alone] 42:Root[0000, 0]@26..27#ROOT2024 | ||||||
|               LITERAL Float 2.7 42:2@28..31#ROOT2024"#]],
 |               LITERAL Float 2.7 42:Root[0000, 0]@28..31#ROOT2024"#]],
 | ||||||
|     ); |     ); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -498,21 +498,21 @@ fn test_attr_macro() { | ||||||
|                 LITERAL Str #[attr_error(some arguments)] mod m {} 1 |                 LITERAL Str #[attr_error(some arguments)] mod m {} 1 | ||||||
|               PUNCH   ; [alone] 1"#]],
 |               PUNCH   ; [alone] 1"#]],
 | ||||||
|         expect![[r#" |         expect![[r#" | ||||||
|             SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024 |             SUBTREE $$ 42:Root[0000, 0]@0..100#ROOT2024 42:Root[0000, 0]@0..100#ROOT2024 | ||||||
|               IDENT   mod 42:2@0..3#ROOT2024 |               IDENT   mod 42:Root[0000, 0]@0..3#ROOT2024 | ||||||
|               IDENT   m 42:2@4..5#ROOT2024 |               IDENT   m 42:Root[0000, 0]@4..5#ROOT2024 | ||||||
|               SUBTREE {} 42:2@6..7#ROOT2024 42:2@7..8#ROOT2024 |               SUBTREE {} 42:Root[0000, 0]@6..7#ROOT2024 42:Root[0000, 0]@7..8#ROOT2024 | ||||||
| 
 | 
 | ||||||
|             SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024 |             SUBTREE $$ 42:Root[0000, 0]@0..100#ROOT2024 42:Root[0000, 0]@0..100#ROOT2024 | ||||||
|               IDENT   some 42:2@0..4#ROOT2024 |               IDENT   some 42:Root[0000, 0]@0..4#ROOT2024 | ||||||
|               IDENT   arguments 42:2@5..14#ROOT2024 |               IDENT   arguments 42:Root[0000, 0]@5..14#ROOT2024 | ||||||
| 
 | 
 | ||||||
|             SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024 |             SUBTREE $$ 42:Root[0000, 0]@0..100#ROOT2024 42:Root[0000, 0]@0..100#ROOT2024 | ||||||
|               IDENT   compile_error 42:2@0..100#ROOT2024 |               IDENT   compile_error 42:Root[0000, 0]@0..100#ROOT2024 | ||||||
|               PUNCH   ! [alone] 42:2@0..100#ROOT2024 |               PUNCH   ! [alone] 42:Root[0000, 0]@0..100#ROOT2024 | ||||||
|               SUBTREE () 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024 |               SUBTREE () 42:Root[0000, 0]@0..100#ROOT2024 42:Root[0000, 0]@0..100#ROOT2024 | ||||||
|                 LITERAL Str #[attr_error(some arguments)] mod m {} 42:2@0..100#ROOT2024 |                 LITERAL Str #[attr_error(some arguments)] mod m {} 42:Root[0000, 0]@0..100#ROOT2024 | ||||||
|               PUNCH   ; [alone] 42:2@0..100#ROOT2024"#]],
 |               PUNCH   ; [alone] 42:Root[0000, 0]@0..100#ROOT2024"#]],
 | ||||||
|     ); |     ); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,7 +1,10 @@ | ||||||
| //! utils used in proc-macro tests
 | //! utils used in proc-macro tests
 | ||||||
| 
 | 
 | ||||||
| use expect_test::Expect; | use expect_test::Expect; | ||||||
| use span::{EditionedFileId, ErasedFileAstId, FileId, Span, SpanAnchor, SyntaxContext, TokenId}; | use span::{ | ||||||
|  |     EditionedFileId, FIXUP_ERASED_FILE_AST_ID_MARKER, FileId, ROOT_ERASED_FILE_AST_ID, Span, | ||||||
|  |     SpanAnchor, SyntaxContext, TokenId, | ||||||
|  | }; | ||||||
| use tt::TextRange; | use tt::TextRange; | ||||||
| 
 | 
 | ||||||
| use crate::{EnvSnapshot, ProcMacroSrv, dylib, proc_macro_test_dylib_path}; | use crate::{EnvSnapshot, ProcMacroSrv, dylib, proc_macro_test_dylib_path}; | ||||||
|  | @ -65,8 +68,17 @@ fn assert_expand_impl( | ||||||
|     let input_ts_string = format!("{input_ts:?}"); |     let input_ts_string = format!("{input_ts:?}"); | ||||||
|     let attr_ts_string = attr_ts.as_ref().map(|it| format!("{it:?}")); |     let attr_ts_string = attr_ts.as_ref().map(|it| format!("{it:?}")); | ||||||
| 
 | 
 | ||||||
|     let res = |     let res = expander | ||||||
|         expander.expand(macro_name, input_ts, attr_ts, def_site, call_site, mixed_site).unwrap(); |         .expand( | ||||||
|  |             macro_name, | ||||||
|  |             input_ts, | ||||||
|  |             attr_ts, | ||||||
|  |             def_site, | ||||||
|  |             call_site, | ||||||
|  |             mixed_site, | ||||||
|  |             FIXUP_ERASED_FILE_AST_ID_MARKER, | ||||||
|  |         ) | ||||||
|  |         .unwrap(); | ||||||
|     expect.assert_eq(&format!( |     expect.assert_eq(&format!( | ||||||
|         "{input_ts_string}\n\n{}\n\n{res:?}", |         "{input_ts_string}\n\n{}\n\n{res:?}", | ||||||
|         attr_ts_string.unwrap_or_default() |         attr_ts_string.unwrap_or_default() | ||||||
|  | @ -76,7 +88,7 @@ fn assert_expand_impl( | ||||||
|         range: TextRange::new(0.into(), 150.into()), |         range: TextRange::new(0.into(), 150.into()), | ||||||
|         anchor: SpanAnchor { |         anchor: SpanAnchor { | ||||||
|             file_id: EditionedFileId::current_edition(FileId::from_raw(41)), |             file_id: EditionedFileId::current_edition(FileId::from_raw(41)), | ||||||
|             ast_id: ErasedFileAstId::from_raw(1), |             ast_id: ROOT_ERASED_FILE_AST_ID, | ||||||
|         }, |         }, | ||||||
|         ctx: SyntaxContext::root(span::Edition::CURRENT), |         ctx: SyntaxContext::root(span::Edition::CURRENT), | ||||||
|     }; |     }; | ||||||
|  | @ -84,7 +96,7 @@ fn assert_expand_impl( | ||||||
|         range: TextRange::new(0.into(), 100.into()), |         range: TextRange::new(0.into(), 100.into()), | ||||||
|         anchor: SpanAnchor { |         anchor: SpanAnchor { | ||||||
|             file_id: EditionedFileId::current_edition(FileId::from_raw(42)), |             file_id: EditionedFileId::current_edition(FileId::from_raw(42)), | ||||||
|             ast_id: ErasedFileAstId::from_raw(2), |             ast_id: ROOT_ERASED_FILE_AST_ID, | ||||||
|         }, |         }, | ||||||
|         ctx: SyntaxContext::root(span::Edition::CURRENT), |         ctx: SyntaxContext::root(span::Edition::CURRENT), | ||||||
|     }; |     }; | ||||||
|  | @ -98,7 +110,17 @@ fn assert_expand_impl( | ||||||
|     let fixture_string = format!("{fixture:?}"); |     let fixture_string = format!("{fixture:?}"); | ||||||
|     let attr_string = attr.as_ref().map(|it| format!("{it:?}")); |     let attr_string = attr.as_ref().map(|it| format!("{it:?}")); | ||||||
| 
 | 
 | ||||||
|     let res = expander.expand(macro_name, fixture, attr, def_site, call_site, mixed_site).unwrap(); |     let res = expander | ||||||
|  |         .expand( | ||||||
|  |             macro_name, | ||||||
|  |             fixture, | ||||||
|  |             attr, | ||||||
|  |             def_site, | ||||||
|  |             call_site, | ||||||
|  |             mixed_site, | ||||||
|  |             FIXUP_ERASED_FILE_AST_ID_MARKER, | ||||||
|  |         ) | ||||||
|  |         .unwrap(); | ||||||
|     expect_spanned |     expect_spanned | ||||||
|         .assert_eq(&format!("{fixture_string}\n\n{}\n\n{res:#?}", attr_string.unwrap_or_default())); |         .assert_eq(&format!("{fixture_string}\n\n{}\n\n{res:#?}", attr_string.unwrap_or_default())); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -22,6 +22,9 @@ vfs.workspace = true | ||||||
| syntax.workspace = true | syntax.workspace = true | ||||||
| stdx.workspace = true | stdx.workspace = true | ||||||
| 
 | 
 | ||||||
|  | [dev-dependencies] | ||||||
|  | syntax.workspace = true | ||||||
|  | 
 | ||||||
| [features] | [features] | ||||||
| default = ["salsa"] | default = ["salsa"] | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							|  | @ -6,7 +6,10 @@ mod hygiene; | ||||||
| mod map; | mod map; | ||||||
| 
 | 
 | ||||||
| pub use self::{ | pub use self::{ | ||||||
|     ast_id::{AstIdMap, AstIdNode, ErasedFileAstId, FileAstId}, |     ast_id::{ | ||||||
|  |         AstIdMap, AstIdNode, ErasedFileAstId, FIXUP_ERASED_FILE_AST_ID_MARKER, FileAstId, | ||||||
|  |         ROOT_ERASED_FILE_AST_ID, | ||||||
|  |     }, | ||||||
|     hygiene::{SyntaxContext, Transparency}, |     hygiene::{SyntaxContext, Transparency}, | ||||||
|     map::{RealSpanMap, SpanMap}, |     map::{RealSpanMap, SpanMap}, | ||||||
| }; | }; | ||||||
|  | @ -15,19 +18,6 @@ pub use syntax::Edition; | ||||||
| pub use text_size::{TextRange, TextSize}; | pub use text_size::{TextRange, TextSize}; | ||||||
| pub use vfs::FileId; | pub use vfs::FileId; | ||||||
| 
 | 
 | ||||||
| // The first index is always the root node's AstId
 |  | ||||||
| /// The root ast id always points to the encompassing file, using this in spans is discouraged as
 |  | ||||||
| /// any range relative to it will be effectively absolute, ruining the entire point of anchored
 |  | ||||||
| /// relative text ranges.
 |  | ||||||
| pub const ROOT_ERASED_FILE_AST_ID: ErasedFileAstId = ErasedFileAstId::from_raw(0); |  | ||||||
| 
 |  | ||||||
| /// FileId used as the span for syntax node fixups. Any Span containing this file id is to be
 |  | ||||||
| /// considered fake.
 |  | ||||||
| pub const FIXUP_ERASED_FILE_AST_ID_MARKER: ErasedFileAstId = |  | ||||||
|     // we pick the second to last for this in case we ever consider making this a NonMaxU32, this
 |  | ||||||
|     // is required to be stable for the proc-macro-server
 |  | ||||||
|     ErasedFileAstId::from_raw(!0 - 1); |  | ||||||
| 
 |  | ||||||
| pub type Span = SpanData<SyntaxContext>; | pub type Span = SpanData<SyntaxContext>; | ||||||
| 
 | 
 | ||||||
| impl Span { | impl Span { | ||||||
|  | @ -60,7 +50,7 @@ impl<Ctx: fmt::Debug> fmt::Debug for SpanData<Ctx> { | ||||||
|         if f.alternate() { |         if f.alternate() { | ||||||
|             fmt::Debug::fmt(&self.anchor.file_id.file_id().index(), f)?; |             fmt::Debug::fmt(&self.anchor.file_id.file_id().index(), f)?; | ||||||
|             f.write_char(':')?; |             f.write_char(':')?; | ||||||
|             fmt::Debug::fmt(&self.anchor.ast_id.into_raw(), f)?; |             write!(f, "{:#?}", self.anchor.ast_id)?; | ||||||
|             f.write_char('@')?; |             f.write_char('@')?; | ||||||
|             fmt::Debug::fmt(&self.range, f)?; |             fmt::Debug::fmt(&self.range, f)?; | ||||||
|             f.write_char('#')?; |             f.write_char('#')?; | ||||||
|  | @ -85,7 +75,7 @@ impl fmt::Display for Span { | ||||||
|     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||||||
|         fmt::Debug::fmt(&self.anchor.file_id.file_id().index(), f)?; |         fmt::Debug::fmt(&self.anchor.file_id.file_id().index(), f)?; | ||||||
|         f.write_char(':')?; |         f.write_char(':')?; | ||||||
|         fmt::Debug::fmt(&self.anchor.ast_id.into_raw(), f)?; |         write!(f, "{:#?}", self.anchor.ast_id)?; | ||||||
|         f.write_char('@')?; |         f.write_char('@')?; | ||||||
|         fmt::Debug::fmt(&self.range, f)?; |         fmt::Debug::fmt(&self.range, f)?; | ||||||
|         f.write_char('#')?; |         f.write_char('#')?; | ||||||
|  | @ -101,7 +91,7 @@ pub struct SpanAnchor { | ||||||
| 
 | 
 | ||||||
| impl fmt::Debug for SpanAnchor { | impl fmt::Debug for SpanAnchor { | ||||||
|     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||||||
|         f.debug_tuple("SpanAnchor").field(&self.file_id).field(&self.ast_id.into_raw()).finish() |         f.debug_tuple("SpanAnchor").field(&self.file_id).field(&self.ast_id).finish() | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -169,7 +169,7 @@ impl fmt::Display for RealSpanMap { | ||||||
|     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||||||
|         writeln!(f, "RealSpanMap({:?}):", self.file_id)?; |         writeln!(f, "RealSpanMap({:?}):", self.file_id)?; | ||||||
|         for span in self.pairs.iter() { |         for span in self.pairs.iter() { | ||||||
|             writeln!(f, "{}: {}", u32::from(span.0), span.1.into_raw())?; |             writeln!(f, "{}: {:#?}", u32::from(span.0), span.1)?; | ||||||
|         } |         } | ||||||
|         Ok(()) |         Ok(()) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -30,6 +30,16 @@ impl ast::Name { | ||||||
|     pub fn text(&self) -> TokenText<'_> { |     pub fn text(&self) -> TokenText<'_> { | ||||||
|         text_of_first_token(self.syntax()) |         text_of_first_token(self.syntax()) | ||||||
|     } |     } | ||||||
|  |     pub fn text_non_mutable(&self) -> &str { | ||||||
|  |         fn first_token(green_ref: &GreenNodeData) -> &GreenTokenData { | ||||||
|  |             green_ref.children().next().and_then(NodeOrToken::into_token).unwrap() | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         match self.syntax().green() { | ||||||
|  |             Cow::Borrowed(green_ref) => first_token(green_ref).text(), | ||||||
|  |             Cow::Owned(_) => unreachable!(), | ||||||
|  |         } | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl ast::NameRef { | impl ast::NameRef { | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Lukas Wirth
						Lukas Wirth