aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_def/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_def/src')
-rw-r--r--crates/hir_def/src/adt.rs47
-rw-r--r--crates/hir_def/src/attr.rs146
-rw-r--r--crates/hir_def/src/body.rs17
-rw-r--r--crates/hir_def/src/body/lower.rs33
-rw-r--r--crates/hir_def/src/data.rs5
-rw-r--r--crates/hir_def/src/db.rs7
-rw-r--r--crates/hir_def/src/generics.rs9
-rw-r--r--crates/hir_def/src/item_scope.rs2
-rw-r--r--crates/hir_def/src/item_tree.rs43
-rw-r--r--crates/hir_def/src/item_tree/lower.rs53
-rw-r--r--crates/hir_def/src/lang_item.rs77
-rw-r--r--crates/hir_def/src/lib.rs30
-rw-r--r--crates/hir_def/src/nameres/collector.rs121
-rw-r--r--crates/hir_def/src/nameres/tests/macros.rs31
-rw-r--r--crates/hir_def/src/path/lower.rs4
-rw-r--r--crates/hir_def/src/type_ref.rs10
16 files changed, 388 insertions, 247 deletions
diff --git a/crates/hir_def/src/adt.rs b/crates/hir_def/src/adt.rs
index eafa3abb6..236d6f1b7 100644
--- a/crates/hir_def/src/adt.rs
+++ b/crates/hir_def/src/adt.rs
@@ -3,6 +3,7 @@
3use std::sync::Arc; 3use std::sync::Arc;
4 4
5use arena::{map::ArenaMap, Arena}; 5use arena::{map::ArenaMap, Arena};
6use base_db::CrateId;
6use either::Either; 7use either::Either;
7use hir_expand::{ 8use hir_expand::{
8 name::{AsName, Name}, 9 name::{AsName, Name},
@@ -66,8 +67,13 @@ pub enum ReprKind {
66 Other, 67 Other,
67} 68}
68 69
69fn repr_from_value(item_tree: &ItemTree, of: AttrOwner) -> Option<ReprKind> { 70fn repr_from_value(
70 item_tree.attrs(of).by_key("repr").tt_values().find_map(parse_repr_tt) 71 db: &dyn DefDatabase,
72 krate: CrateId,
73 item_tree: &ItemTree,
74 of: AttrOwner,
75) -> Option<ReprKind> {
76 item_tree.attrs(db, krate, of).by_key("repr").tt_values().find_map(parse_repr_tt)
71} 77}
72 78
73fn parse_repr_tt(tt: &Subtree) -> Option<ReprKind> { 79fn parse_repr_tt(tt: &Subtree) -> Option<ReprKind> {
@@ -86,12 +92,13 @@ fn parse_repr_tt(tt: &Subtree) -> Option<ReprKind> {
86impl StructData { 92impl StructData {
87 pub(crate) fn struct_data_query(db: &dyn DefDatabase, id: StructId) -> Arc<StructData> { 93 pub(crate) fn struct_data_query(db: &dyn DefDatabase, id: StructId) -> Arc<StructData> {
88 let loc = id.lookup(db); 94 let loc = id.lookup(db);
95 let krate = loc.container.module(db).krate;
89 let item_tree = db.item_tree(loc.id.file_id); 96 let item_tree = db.item_tree(loc.id.file_id);
90 let repr = repr_from_value(&item_tree, ModItem::from(loc.id.value).into()); 97 let repr = repr_from_value(db, krate, &item_tree, ModItem::from(loc.id.value).into());
91 let cfg_options = db.crate_graph()[loc.container.module(db).krate].cfg_options.clone(); 98 let cfg_options = db.crate_graph()[loc.container.module(db).krate].cfg_options.clone();
92 99
93 let strukt = &item_tree[loc.id.value]; 100 let strukt = &item_tree[loc.id.value];
94 let variant_data = lower_fields(&item_tree, &cfg_options, &strukt.fields, None); 101 let variant_data = lower_fields(db, krate, &item_tree, &cfg_options, &strukt.fields, None);
95 Arc::new(StructData { 102 Arc::new(StructData {
96 name: strukt.name.clone(), 103 name: strukt.name.clone(),
97 variant_data: Arc::new(variant_data), 104 variant_data: Arc::new(variant_data),
@@ -100,12 +107,13 @@ impl StructData {
100 } 107 }
101 pub(crate) fn union_data_query(db: &dyn DefDatabase, id: UnionId) -> Arc<StructData> { 108 pub(crate) fn union_data_query(db: &dyn DefDatabase, id: UnionId) -> Arc<StructData> {
102 let loc = id.lookup(db); 109 let loc = id.lookup(db);
110 let krate = loc.container.module(db).krate;
103 let item_tree = db.item_tree(loc.id.file_id); 111 let item_tree = db.item_tree(loc.id.file_id);
104 let repr = repr_from_value(&item_tree, ModItem::from(loc.id.value).into()); 112 let repr = repr_from_value(db, krate, &item_tree, ModItem::from(loc.id.value).into());
105 let cfg_options = db.crate_graph()[loc.container.module(db).krate].cfg_options.clone(); 113 let cfg_options = db.crate_graph()[loc.container.module(db).krate].cfg_options.clone();
106 114
107 let union = &item_tree[loc.id.value]; 115 let union = &item_tree[loc.id.value];
108 let variant_data = lower_fields(&item_tree, &cfg_options, &union.fields, None); 116 let variant_data = lower_fields(db, krate, &item_tree, &cfg_options, &union.fields, None);
109 117
110 Arc::new(StructData { 118 Arc::new(StructData {
111 name: union.name.clone(), 119 name: union.name.clone(),
@@ -118,16 +126,23 @@ impl StructData {
118impl EnumData { 126impl EnumData {
119 pub(crate) fn enum_data_query(db: &dyn DefDatabase, e: EnumId) -> Arc<EnumData> { 127 pub(crate) fn enum_data_query(db: &dyn DefDatabase, e: EnumId) -> Arc<EnumData> {
120 let loc = e.lookup(db); 128 let loc = e.lookup(db);
129 let krate = loc.container.module(db).krate;
121 let item_tree = db.item_tree(loc.id.file_id); 130 let item_tree = db.item_tree(loc.id.file_id);
122 let cfg_options = db.crate_graph()[loc.container.module(db).krate].cfg_options.clone(); 131 let cfg_options = db.crate_graph()[krate].cfg_options.clone();
123 132
124 let enum_ = &item_tree[loc.id.value]; 133 let enum_ = &item_tree[loc.id.value];
125 let mut variants = Arena::new(); 134 let mut variants = Arena::new();
126 for var_id in enum_.variants.clone() { 135 for var_id in enum_.variants.clone() {
127 if item_tree.attrs(var_id.into()).is_cfg_enabled(&cfg_options) { 136 if item_tree.attrs(db, krate, var_id.into()).is_cfg_enabled(&cfg_options) {
128 let var = &item_tree[var_id]; 137 let var = &item_tree[var_id];
129 let var_data = 138 let var_data = lower_fields(
130 lower_fields(&item_tree, &cfg_options, &var.fields, Some(enum_.visibility)); 139 db,
140 krate,
141 &item_tree,
142 &cfg_options,
143 &var.fields,
144 Some(enum_.visibility),
145 );
131 146
132 variants.alloc(EnumVariantData { 147 variants.alloc(EnumVariantData {
133 name: var.name.clone(), 148 name: var.name.clone(),
@@ -170,7 +185,7 @@ fn lower_enum(
170 .variant_list() 185 .variant_list()
171 .into_iter() 186 .into_iter()
172 .flat_map(|it| it.variants()) 187 .flat_map(|it| it.variants())
173 .filter(|var| expander.is_cfg_enabled(var)); 188 .filter(|var| expander.is_cfg_enabled(db, var));
174 for var in variants { 189 for var in variants {
175 trace.alloc( 190 trace.alloc(
176 || var.clone(), 191 || var.clone(),
@@ -262,7 +277,7 @@ fn lower_struct(
262 match &ast.value { 277 match &ast.value {
263 ast::StructKind::Tuple(fl) => { 278 ast::StructKind::Tuple(fl) => {
264 for (i, fd) in fl.fields().enumerate() { 279 for (i, fd) in fl.fields().enumerate() {
265 if !expander.is_cfg_enabled(&fd) { 280 if !expander.is_cfg_enabled(db, &fd) {
266 continue; 281 continue;
267 } 282 }
268 283
@@ -279,7 +294,7 @@ fn lower_struct(
279 } 294 }
280 ast::StructKind::Record(fl) => { 295 ast::StructKind::Record(fl) => {
281 for fd in fl.fields() { 296 for fd in fl.fields() {
282 if !expander.is_cfg_enabled(&fd) { 297 if !expander.is_cfg_enabled(db, &fd) {
283 continue; 298 continue;
284 } 299 }
285 300
@@ -299,6 +314,8 @@ fn lower_struct(
299} 314}
300 315
301fn lower_fields( 316fn lower_fields(
317 db: &dyn DefDatabase,
318 krate: CrateId,
302 item_tree: &ItemTree, 319 item_tree: &ItemTree,
303 cfg_options: &CfgOptions, 320 cfg_options: &CfgOptions,
304 fields: &Fields, 321 fields: &Fields,
@@ -308,7 +325,7 @@ fn lower_fields(
308 Fields::Record(flds) => { 325 Fields::Record(flds) => {
309 let mut arena = Arena::new(); 326 let mut arena = Arena::new();
310 for field_id in flds.clone() { 327 for field_id in flds.clone() {
311 if item_tree.attrs(field_id.into()).is_cfg_enabled(cfg_options) { 328 if item_tree.attrs(db, krate, field_id.into()).is_cfg_enabled(cfg_options) {
312 arena.alloc(lower_field(item_tree, &item_tree[field_id], override_visibility)); 329 arena.alloc(lower_field(item_tree, &item_tree[field_id], override_visibility));
313 } 330 }
314 } 331 }
@@ -317,7 +334,7 @@ fn lower_fields(
317 Fields::Tuple(flds) => { 334 Fields::Tuple(flds) => {
318 let mut arena = Arena::new(); 335 let mut arena = Arena::new();
319 for field_id in flds.clone() { 336 for field_id in flds.clone() {
320 if item_tree.attrs(field_id.into()).is_cfg_enabled(cfg_options) { 337 if item_tree.attrs(db, krate, field_id.into()).is_cfg_enabled(cfg_options) {
321 arena.alloc(lower_field(item_tree, &item_tree[field_id], override_visibility)); 338 arena.alloc(lower_field(item_tree, &item_tree[field_id], override_visibility));
322 } 339 }
323 } 340 }
diff --git a/crates/hir_def/src/attr.rs b/crates/hir_def/src/attr.rs
index c64b78445..9cd0b72aa 100644
--- a/crates/hir_def/src/attr.rs
+++ b/crates/hir_def/src/attr.rs
@@ -2,6 +2,7 @@
2 2
3use std::{ops, sync::Arc}; 3use std::{ops, sync::Arc};
4 4
5use base_db::CrateId;
5use cfg::{CfgExpr, CfgOptions}; 6use cfg::{CfgExpr, CfgOptions};
6use either::Either; 7use either::Either;
7use hir_expand::{hygiene::Hygiene, AstId, InFile}; 8use hir_expand::{hygiene::Hygiene, AstId, InFile};
@@ -38,12 +39,16 @@ impl From<Documentation> for String {
38 } 39 }
39} 40}
40 41
42/// Syntactical attributes, without filtering of `cfg_attr`s.
41#[derive(Default, Debug, Clone, PartialEq, Eq)] 43#[derive(Default, Debug, Clone, PartialEq, Eq)]
42pub struct Attrs { 44pub struct RawAttrs {
43 entries: Option<Arc<[Attr]>>, 45 entries: Option<Arc<[Attr]>>,
44} 46}
45 47
46impl ops::Deref for Attrs { 48#[derive(Default, Debug, Clone, PartialEq, Eq)]
49pub struct Attrs(RawAttrs);
50
51impl ops::Deref for RawAttrs {
47 type Target = [Attr]; 52 type Target = [Attr];
48 53
49 fn deref(&self) -> &[Attr] { 54 fn deref(&self) -> &[Attr] {
@@ -54,19 +59,88 @@ impl ops::Deref for Attrs {
54 } 59 }
55} 60}
56 61
62impl ops::Deref for Attrs {
63 type Target = [Attr];
64
65 fn deref(&self) -> &[Attr] {
66 match &self.0.entries {
67 Some(it) => &*it,
68 None => &[],
69 }
70 }
71}
72
73impl RawAttrs {
74 pub const EMPTY: Self = Self { entries: None };
75
76 pub(crate) fn new(owner: &dyn AttrsOwner, hygiene: &Hygiene) -> Self {
77 let (inner_attrs, inner_docs) = inner_attributes(owner.syntax())
78 .map_or((None, None), |(attrs, docs)| ((Some(attrs), Some(docs))));
79
80 let outer_attrs = owner.attrs().filter(|attr| attr.excl_token().is_none());
81 let attrs = outer_attrs
82 .chain(inner_attrs.into_iter().flatten())
83 .map(|attr| (attr.syntax().text_range().start(), Attr::from_src(attr, hygiene)));
84
85 let outer_docs =
86 ast::CommentIter::from_syntax_node(owner.syntax()).filter(ast::Comment::is_outer);
87 let docs = outer_docs.chain(inner_docs.into_iter().flatten()).map(|docs_text| {
88 (
89 docs_text.syntax().text_range().start(),
90 docs_text.doc_comment().map(|doc| Attr {
91 input: Some(AttrInput::Literal(SmolStr::new(doc))),
92 path: ModPath::from(hir_expand::name!(doc)),
93 }),
94 )
95 });
96 // sort here by syntax node offset because the source can have doc attributes and doc strings be interleaved
97 let attrs: Vec<_> = docs.chain(attrs).sorted_by_key(|&(offset, _)| offset).collect();
98 let entries = if attrs.is_empty() {
99 // Avoid heap allocation
100 None
101 } else {
102 Some(attrs.into_iter().flat_map(|(_, attr)| attr).collect())
103 };
104 Self { entries }
105 }
106
107 fn from_attrs_owner(db: &dyn DefDatabase, owner: InFile<&dyn AttrsOwner>) -> Self {
108 let hygiene = Hygiene::new(db.upcast(), owner.file_id);
109 Self::new(owner.value, &hygiene)
110 }
111
112 pub(crate) fn merge(&self, other: Self) -> Self {
113 match (&self.entries, &other.entries) {
114 (None, None) => Self::EMPTY,
115 (Some(entries), None) | (None, Some(entries)) => {
116 Self { entries: Some(entries.clone()) }
117 }
118 (Some(a), Some(b)) => {
119 Self { entries: Some(a.iter().chain(b.iter()).cloned().collect()) }
120 }
121 }
122 }
123
124 /// Processes `cfg_attr`s, returning the resulting semantic `Attrs`.
125 pub(crate) fn filter(self, _db: &dyn DefDatabase, _krate: CrateId) -> Attrs {
126 // FIXME actually implement this
127 Attrs(self)
128 }
129}
130
57impl Attrs { 131impl Attrs {
58 pub const EMPTY: Attrs = Attrs { entries: None }; 132 pub const EMPTY: Self = Self(RawAttrs::EMPTY);
59 133
60 pub(crate) fn attrs_query(db: &dyn DefDatabase, def: AttrDefId) -> Attrs { 134 pub(crate) fn attrs_query(db: &dyn DefDatabase, def: AttrDefId) -> Attrs {
61 match def { 135 let raw_attrs = match def {
62 AttrDefId::ModuleId(module) => { 136 AttrDefId::ModuleId(module) => {
63 let def_map = db.crate_def_map(module.krate); 137 let def_map = db.crate_def_map(module.krate);
64 let mod_data = &def_map[module.local_id]; 138 let mod_data = &def_map[module.local_id];
65 match mod_data.declaration_source(db) { 139 match mod_data.declaration_source(db) {
66 Some(it) => { 140 Some(it) => {
67 Attrs::from_attrs_owner(db, it.as_ref().map(|it| it as &dyn AttrsOwner)) 141 RawAttrs::from_attrs_owner(db, it.as_ref().map(|it| it as &dyn AttrsOwner))
68 } 142 }
69 None => Attrs::from_attrs_owner( 143 None => RawAttrs::from_attrs_owner(
70 db, 144 db,
71 mod_data.definition_source(db).as_ref().map(|src| match src { 145 mod_data.definition_source(db).as_ref().map(|src| match src {
72 ModuleSource::SourceFile(file) => file as &dyn AttrsOwner, 146 ModuleSource::SourceFile(file) => file as &dyn AttrsOwner,
@@ -78,14 +152,14 @@ impl Attrs {
78 AttrDefId::FieldId(it) => { 152 AttrDefId::FieldId(it) => {
79 let src = it.parent.child_source(db); 153 let src = it.parent.child_source(db);
80 match &src.value[it.local_id] { 154 match &src.value[it.local_id] {
81 Either::Left(_tuple) => Attrs::default(), 155 Either::Left(_tuple) => RawAttrs::default(),
82 Either::Right(record) => Attrs::from_attrs_owner(db, src.with_value(record)), 156 Either::Right(record) => RawAttrs::from_attrs_owner(db, src.with_value(record)),
83 } 157 }
84 } 158 }
85 AttrDefId::EnumVariantId(var_id) => { 159 AttrDefId::EnumVariantId(var_id) => {
86 let src = var_id.parent.child_source(db); 160 let src = var_id.parent.child_source(db);
87 let src = src.as_ref().map(|it| &it[var_id.local_id]); 161 let src = src.as_ref().map(|it| &it[var_id.local_id]);
88 Attrs::from_attrs_owner(db, src.map(|it| it as &dyn AttrsOwner)) 162 RawAttrs::from_attrs_owner(db, src.map(|it| it as &dyn AttrsOwner))
89 } 163 }
90 AttrDefId::AdtId(it) => match it { 164 AttrDefId::AdtId(it) => match it {
91 AdtId::StructId(it) => attrs_from_item_tree(it.lookup(db).id, db), 165 AdtId::StructId(it) => attrs_from_item_tree(it.lookup(db).id, db),
@@ -101,53 +175,19 @@ impl Attrs {
101 AttrDefId::StaticId(it) => attrs_from_item_tree(it.lookup(db).id, db), 175 AttrDefId::StaticId(it) => attrs_from_item_tree(it.lookup(db).id, db),
102 AttrDefId::FunctionId(it) => attrs_from_item_tree(it.lookup(db).id, db), 176 AttrDefId::FunctionId(it) => attrs_from_item_tree(it.lookup(db).id, db),
103 AttrDefId::TypeAliasId(it) => attrs_from_item_tree(it.lookup(db).id, db), 177 AttrDefId::TypeAliasId(it) => attrs_from_item_tree(it.lookup(db).id, db),
104 }
105 }
106
107 pub fn from_attrs_owner(db: &dyn DefDatabase, owner: InFile<&dyn AttrsOwner>) -> Attrs {
108 let hygiene = Hygiene::new(db.upcast(), owner.file_id);
109 Attrs::new(owner.value, &hygiene)
110 }
111
112 pub(crate) fn new(owner: &dyn AttrsOwner, hygiene: &Hygiene) -> Attrs {
113 let (inner_attrs, inner_docs) = inner_attributes(owner.syntax())
114 .map_or((None, None), |(attrs, docs)| ((Some(attrs), Some(docs))));
115
116 let outer_attrs = owner.attrs().filter(|attr| attr.excl_token().is_none());
117 let attrs = outer_attrs
118 .chain(inner_attrs.into_iter().flatten())
119 .map(|attr| (attr.syntax().text_range().start(), Attr::from_src(attr, hygiene)));
120
121 let outer_docs =
122 ast::CommentIter::from_syntax_node(owner.syntax()).filter(ast::Comment::is_outer);
123 let docs = outer_docs.chain(inner_docs.into_iter().flatten()).map(|docs_text| {
124 (
125 docs_text.syntax().text_range().start(),
126 docs_text.doc_comment().map(|doc| Attr {
127 input: Some(AttrInput::Literal(SmolStr::new(doc))),
128 path: ModPath::from(hir_expand::name!(doc)),
129 }),
130 )
131 });
132 // sort here by syntax node offset because the source can have doc attributes and doc strings be interleaved
133 let attrs: Vec<_> = docs.chain(attrs).sorted_by_key(|&(offset, _)| offset).collect();
134 let entries = if attrs.is_empty() {
135 // Avoid heap allocation
136 None
137 } else {
138 Some(attrs.into_iter().flat_map(|(_, attr)| attr).collect())
139 }; 178 };
140 Attrs { entries } 179
180 raw_attrs.filter(db, def.krate(db))
141 } 181 }
142 182
143 pub fn merge(&self, other: Attrs) -> Attrs { 183 pub fn merge(&self, other: Attrs) -> Attrs {
144 match (&self.entries, &other.entries) { 184 match (&self.0.entries, &other.0.entries) {
145 (None, None) => Attrs { entries: None }, 185 (None, None) => Attrs::EMPTY,
146 (Some(entries), None) | (None, Some(entries)) => { 186 (Some(entries), None) | (None, Some(entries)) => {
147 Attrs { entries: Some(entries.clone()) } 187 Attrs(RawAttrs { entries: Some(entries.clone()) })
148 } 188 }
149 (Some(a), Some(b)) => { 189 (Some(a), Some(b)) => {
150 Attrs { entries: Some(a.iter().chain(b.iter()).cloned().collect()) } 190 Attrs(RawAttrs { entries: Some(a.iter().chain(b.iter()).cloned().collect()) })
151 } 191 }
152 } 192 }
153 } 193 }
@@ -291,16 +331,16 @@ impl<'a> AttrQuery<'a> {
291 } 331 }
292} 332}
293 333
294fn attrs_from_ast<N>(src: AstId<N>, db: &dyn DefDatabase) -> Attrs 334fn attrs_from_ast<N>(src: AstId<N>, db: &dyn DefDatabase) -> RawAttrs
295where 335where
296 N: ast::AttrsOwner, 336 N: ast::AttrsOwner,
297{ 337{
298 let src = InFile::new(src.file_id, src.to_node(db.upcast())); 338 let src = InFile::new(src.file_id, src.to_node(db.upcast()));
299 Attrs::from_attrs_owner(db, src.as_ref().map(|it| it as &dyn AttrsOwner)) 339 RawAttrs::from_attrs_owner(db, src.as_ref().map(|it| it as &dyn AttrsOwner))
300} 340}
301 341
302fn attrs_from_item_tree<N: ItemTreeNode>(id: ItemTreeId<N>, db: &dyn DefDatabase) -> Attrs { 342fn attrs_from_item_tree<N: ItemTreeNode>(id: ItemTreeId<N>, db: &dyn DefDatabase) -> RawAttrs {
303 let tree = db.item_tree(id.file_id); 343 let tree = db.item_tree(id.file_id);
304 let mod_item = N::id_to_mod_item(id.value); 344 let mod_item = N::id_to_mod_item(id.value);
305 tree.attrs(mod_item.into()).clone() 345 tree.raw_attrs(mod_item.into()).clone()
306} 346}
diff --git a/crates/hir_def/src/body.rs b/crates/hir_def/src/body.rs
index c5d6f5fb0..998b82601 100644
--- a/crates/hir_def/src/body.rs
+++ b/crates/hir_def/src/body.rs
@@ -24,7 +24,7 @@ use test_utils::mark;
24pub(crate) use lower::LowerCtx; 24pub(crate) use lower::LowerCtx;
25 25
26use crate::{ 26use crate::{
27 attr::Attrs, 27 attr::{Attrs, RawAttrs},
28 db::DefDatabase, 28 db::DefDatabase,
29 expr::{Expr, ExprId, Pat, PatId}, 29 expr::{Expr, ExprId, Pat, PatId},
30 item_scope::BuiltinShadowMode, 30 item_scope::BuiltinShadowMode,
@@ -40,6 +40,7 @@ use crate::{
40pub(crate) struct CfgExpander { 40pub(crate) struct CfgExpander {
41 cfg_options: CfgOptions, 41 cfg_options: CfgOptions,
42 hygiene: Hygiene, 42 hygiene: Hygiene,
43 krate: CrateId,
43} 44}
44 45
45pub(crate) struct Expander { 46pub(crate) struct Expander {
@@ -65,15 +66,15 @@ impl CfgExpander {
65 ) -> CfgExpander { 66 ) -> CfgExpander {
66 let hygiene = Hygiene::new(db.upcast(), current_file_id); 67 let hygiene = Hygiene::new(db.upcast(), current_file_id);
67 let cfg_options = db.crate_graph()[krate].cfg_options.clone(); 68 let cfg_options = db.crate_graph()[krate].cfg_options.clone();
68 CfgExpander { cfg_options, hygiene } 69 CfgExpander { cfg_options, hygiene, krate }
69 } 70 }
70 71
71 pub(crate) fn parse_attrs(&self, owner: &dyn ast::AttrsOwner) -> Attrs { 72 pub(crate) fn parse_attrs(&self, db: &dyn DefDatabase, owner: &dyn ast::AttrsOwner) -> Attrs {
72 Attrs::new(owner, &self.hygiene) 73 RawAttrs::new(owner, &self.hygiene).filter(db, self.krate)
73 } 74 }
74 75
75 pub(crate) fn is_cfg_enabled(&self, owner: &dyn ast::AttrsOwner) -> bool { 76 pub(crate) fn is_cfg_enabled(&self, db: &dyn DefDatabase, owner: &dyn ast::AttrsOwner) -> bool {
76 let attrs = self.parse_attrs(owner); 77 let attrs = self.parse_attrs(db, owner);
77 attrs.is_cfg_enabled(&self.cfg_options) 78 attrs.is_cfg_enabled(&self.cfg_options)
78 } 79 }
79} 80}
@@ -189,8 +190,8 @@ impl Expander {
189 InFile { file_id: self.current_file_id, value } 190 InFile { file_id: self.current_file_id, value }
190 } 191 }
191 192
192 pub(crate) fn parse_attrs(&self, owner: &dyn ast::AttrsOwner) -> Attrs { 193 pub(crate) fn parse_attrs(&self, db: &dyn DefDatabase, owner: &dyn ast::AttrsOwner) -> Attrs {
193 self.cfg_expander.parse_attrs(owner) 194 self.cfg_expander.parse_attrs(db, owner)
194 } 195 }
195 196
196 pub(crate) fn cfg_options(&self) -> &CfgOptions { 197 pub(crate) fn cfg_options(&self) -> &CfgOptions {
diff --git a/crates/hir_def/src/body/lower.rs b/crates/hir_def/src/body/lower.rs
index bdba4c33e..0f404be1b 100644
--- a/crates/hir_def/src/body/lower.rs
+++ b/crates/hir_def/src/body/lower.rs
@@ -233,8 +233,7 @@ impl ExprCollector<'_> {
233 let res = self.collect_block(block); 233 let res = self.collect_block(block);
234 match &mut self.body.exprs[res] { 234 match &mut self.body.exprs[res] {
235 Expr::Block { label: block_label, .. } => { 235 Expr::Block { label: block_label, .. } => {
236 *block_label = 236 *block_label = label.lifetime().map(|t| Name::new_lifetime(&t))
237 label.lifetime_token().map(|t| Name::new_lifetime(&t))
238 } 237 }
239 _ => unreachable!(), 238 _ => unreachable!(),
240 } 239 }
@@ -254,10 +253,7 @@ impl ExprCollector<'_> {
254 self.alloc_expr( 253 self.alloc_expr(
255 Expr::Loop { 254 Expr::Loop {
256 body, 255 body,
257 label: e 256 label: e.label().and_then(|l| l.lifetime()).map(|l| Name::new_lifetime(&l)),
258 .label()
259 .and_then(|l| l.lifetime_token())
260 .map(|l| Name::new_lifetime(&l)),
261 }, 257 },
262 syntax_ptr, 258 syntax_ptr,
263 ) 259 )
@@ -288,7 +284,7 @@ impl ExprCollector<'_> {
288 body: match_expr, 284 body: match_expr,
289 label: e 285 label: e
290 .label() 286 .label()
291 .and_then(|l| l.lifetime_token()) 287 .and_then(|l| l.lifetime())
292 .map(|l| Name::new_lifetime(&l)), 288 .map(|l| Name::new_lifetime(&l)),
293 }, 289 },
294 syntax_ptr, 290 syntax_ptr,
@@ -301,10 +297,7 @@ impl ExprCollector<'_> {
301 Expr::While { 297 Expr::While {
302 condition, 298 condition,
303 body, 299 body,
304 label: e 300 label: e.label().and_then(|l| l.lifetime()).map(|l| Name::new_lifetime(&l)),
305 .label()
306 .and_then(|l| l.lifetime_token())
307 .map(|l| Name::new_lifetime(&l)),
308 }, 301 },
309 syntax_ptr, 302 syntax_ptr,
310 ) 303 )
@@ -318,10 +311,7 @@ impl ExprCollector<'_> {
318 iterable, 311 iterable,
319 pat, 312 pat,
320 body, 313 body,
321 label: e 314 label: e.label().and_then(|l| l.lifetime()).map(|l| Name::new_lifetime(&l)),
322 .label()
323 .and_then(|l| l.lifetime_token())
324 .map(|l| Name::new_lifetime(&l)),
325 }, 315 },
326 syntax_ptr, 316 syntax_ptr,
327 ) 317 )
@@ -380,13 +370,13 @@ impl ExprCollector<'_> {
380 self.alloc_expr(path, syntax_ptr) 370 self.alloc_expr(path, syntax_ptr)
381 } 371 }
382 ast::Expr::ContinueExpr(e) => self.alloc_expr( 372 ast::Expr::ContinueExpr(e) => self.alloc_expr(
383 Expr::Continue { label: e.lifetime_token().map(|l| Name::new_lifetime(&l)) }, 373 Expr::Continue { label: e.lifetime().map(|l| Name::new_lifetime(&l)) },
384 syntax_ptr, 374 syntax_ptr,
385 ), 375 ),
386 ast::Expr::BreakExpr(e) => { 376 ast::Expr::BreakExpr(e) => {
387 let expr = e.expr().map(|e| self.collect_expr(e)); 377 let expr = e.expr().map(|e| self.collect_expr(e));
388 self.alloc_expr( 378 self.alloc_expr(
389 Expr::Break { expr, label: e.lifetime_token().map(|l| Name::new_lifetime(&l)) }, 379 Expr::Break { expr, label: e.lifetime().map(|l| Name::new_lifetime(&l)) },
390 syntax_ptr, 380 syntax_ptr,
391 ) 381 )
392 } 382 }
@@ -772,7 +762,10 @@ impl ExprCollector<'_> {
772 | ast::Item::Module(_) 762 | ast::Item::Module(_)
773 | ast::Item::MacroCall(_) => return None, 763 | ast::Item::MacroCall(_) => return None,
774 ast::Item::MacroRules(def) => { 764 ast::Item::MacroRules(def) => {
775 return Some(Either::Right(def)); 765 return Some(Either::Right(ast::Macro::from(def)));
766 }
767 ast::Item::MacroDef(def) => {
768 return Some(Either::Right(ast::Macro::from(def)));
776 } 769 }
777 }; 770 };
778 771
@@ -800,7 +793,7 @@ impl ExprCollector<'_> {
800 } 793 }
801 Either::Right(e) => { 794 Either::Right(e) => {
802 let mac = MacroDefId { 795 let mac = MacroDefId {
803 krate: Some(self.expander.module.krate), 796 krate: self.expander.module.krate,
804 ast_id: Some(self.expander.ast_id(&e)), 797 ast_id: Some(self.expander.ast_id(&e)),
805 kind: MacroDefKind::Declarative, 798 kind: MacroDefKind::Declarative,
806 local_inner: false, 799 local_inner: false,
@@ -970,7 +963,7 @@ impl ExprCollector<'_> {
970 /// Returns `None` (and emits diagnostics) when `owner` if `#[cfg]`d out, and `Some(())` when 963 /// Returns `None` (and emits diagnostics) when `owner` if `#[cfg]`d out, and `Some(())` when
971 /// not. 964 /// not.
972 fn check_cfg(&mut self, owner: &dyn ast::AttrsOwner) -> Option<()> { 965 fn check_cfg(&mut self, owner: &dyn ast::AttrsOwner) -> Option<()> {
973 match self.expander.parse_attrs(owner).cfg() { 966 match self.expander.parse_attrs(self.db, owner).cfg() {
974 Some(cfg) => { 967 Some(cfg) => {
975 if self.expander.cfg_options().check(&cfg) != Some(false) { 968 if self.expander.cfg_options().check(&cfg) != Some(false) {
976 return Some(()); 969 return Some(());
diff --git a/crates/hir_def/src/data.rs b/crates/hir_def/src/data.rs
index dd3a906af..e7b7724f7 100644
--- a/crates/hir_def/src/data.rs
+++ b/crates/hir_def/src/data.rs
@@ -35,6 +35,7 @@ pub struct FunctionData {
35impl FunctionData { 35impl FunctionData {
36 pub(crate) fn fn_data_query(db: &dyn DefDatabase, func: FunctionId) -> Arc<FunctionData> { 36 pub(crate) fn fn_data_query(db: &dyn DefDatabase, func: FunctionId) -> Arc<FunctionData> {
37 let loc = func.lookup(db); 37 let loc = func.lookup(db);
38 let krate = loc.container.module(db).krate;
38 let item_tree = db.item_tree(loc.id.file_id); 39 let item_tree = db.item_tree(loc.id.file_id);
39 let func = &item_tree[loc.id.value]; 40 let func = &item_tree[loc.id.value];
40 41
@@ -42,7 +43,7 @@ impl FunctionData {
42 name: func.name.clone(), 43 name: func.name.clone(),
43 params: func.params.to_vec(), 44 params: func.params.to_vec(),
44 ret_type: func.ret_type.clone(), 45 ret_type: func.ret_type.clone(),
45 attrs: item_tree.attrs(ModItem::from(loc.id.value).into()).clone(), 46 attrs: item_tree.attrs(db, krate, ModItem::from(loc.id.value).into()).clone(),
46 has_self_param: func.has_self_param, 47 has_self_param: func.has_self_param,
47 has_body: func.has_body, 48 has_body: func.has_body,
48 is_unsafe: func.is_unsafe, 49 is_unsafe: func.is_unsafe,
@@ -233,7 +234,7 @@ fn collect_items(
233 match item { 234 match item {
234 AssocItem::Function(id) => { 235 AssocItem::Function(id) => {
235 let item = &item_tree[id]; 236 let item = &item_tree[id];
236 let attrs = item_tree.attrs(ModItem::from(id).into()); 237 let attrs = item_tree.attrs(db, module.krate, ModItem::from(id).into());
237 if !attrs.is_cfg_enabled(&cfg_options) { 238 if !attrs.is_cfg_enabled(&cfg_options) {
238 continue; 239 continue;
239 } 240 }
diff --git a/crates/hir_def/src/db.rs b/crates/hir_def/src/db.rs
index 7f250da33..d1a459066 100644
--- a/crates/hir_def/src/db.rs
+++ b/crates/hir_def/src/db.rs
@@ -16,8 +16,8 @@ use crate::{
16 lang_item::{LangItemTarget, LangItems}, 16 lang_item::{LangItemTarget, LangItems},
17 nameres::CrateDefMap, 17 nameres::CrateDefMap,
18 AttrDefId, ConstId, ConstLoc, DefWithBodyId, EnumId, EnumLoc, FunctionId, FunctionLoc, 18 AttrDefId, ConstId, ConstLoc, DefWithBodyId, EnumId, EnumLoc, FunctionId, FunctionLoc,
19 GenericDefId, ImplId, ImplLoc, ModuleId, StaticId, StaticLoc, StructId, StructLoc, TraitId, 19 GenericDefId, ImplId, ImplLoc, StaticId, StaticLoc, StructId, StructLoc, TraitId, TraitLoc,
20 TraitLoc, TypeAliasId, TypeAliasLoc, UnionId, UnionLoc, 20 TypeAliasId, TypeAliasLoc, UnionId, UnionLoc,
21}; 21};
22 22
23#[salsa::query_group(InternDatabaseStorage)] 23#[salsa::query_group(InternDatabaseStorage)]
@@ -95,9 +95,6 @@ pub trait DefDatabase: InternDatabase + AstDatabase + Upcast<dyn AstDatabase> {
95 #[salsa::invoke(Attrs::attrs_query)] 95 #[salsa::invoke(Attrs::attrs_query)]
96 fn attrs(&self, def: AttrDefId) -> Attrs; 96 fn attrs(&self, def: AttrDefId) -> Attrs;
97 97
98 #[salsa::invoke(LangItems::module_lang_items_query)]
99 fn module_lang_items(&self, module: ModuleId) -> Option<Arc<LangItems>>;
100
101 #[salsa::invoke(LangItems::crate_lang_items_query)] 98 #[salsa::invoke(LangItems::crate_lang_items_query)]
102 fn crate_lang_items(&self, krate: CrateId) -> Arc<LangItems>; 99 fn crate_lang_items(&self, krate: CrateId) -> Arc<LangItems>;
103 100
diff --git a/crates/hir_def/src/generics.rs b/crates/hir_def/src/generics.rs
index 924046435..41134d23b 100644
--- a/crates/hir_def/src/generics.rs
+++ b/crates/hir_def/src/generics.rs
@@ -260,9 +260,8 @@ impl GenericParams {
260 self.fill_bounds(&lower_ctx, &type_param, Either::Left(type_ref)); 260 self.fill_bounds(&lower_ctx, &type_param, Either::Left(type_ref));
261 } 261 }
262 for lifetime_param in params.lifetime_params() { 262 for lifetime_param in params.lifetime_params() {
263 let name = lifetime_param 263 let name =
264 .lifetime_token() 264 lifetime_param.lifetime().map_or_else(Name::missing, |lt| Name::new_lifetime(&lt));
265 .map_or_else(Name::missing, |tok| Name::new_lifetime(&tok));
266 let param = LifetimeParamData { name: name.clone() }; 265 let param = LifetimeParamData { name: name.clone() };
267 let param_id = self.lifetimes.alloc(param); 266 let param_id = self.lifetimes.alloc(param);
268 sm.lifetime_params.insert(param_id, lifetime_param.clone()); 267 sm.lifetime_params.insert(param_id, lifetime_param.clone());
@@ -275,8 +274,8 @@ impl GenericParams {
275 for pred in where_clause.predicates() { 274 for pred in where_clause.predicates() {
276 let target = if let Some(type_ref) = pred.ty() { 275 let target = if let Some(type_ref) = pred.ty() {
277 Either::Left(TypeRef::from_ast(lower_ctx, type_ref)) 276 Either::Left(TypeRef::from_ast(lower_ctx, type_ref))
278 } else if let Some(lifetime_tok) = pred.lifetime_token() { 277 } else if let Some(lifetime) = pred.lifetime() {
279 Either::Right(LifetimeRef::from_token(lifetime_tok)) 278 Either::Right(LifetimeRef::new(&lifetime))
280 } else { 279 } else {
281 continue; 280 continue;
282 }; 281 };
diff --git a/crates/hir_def/src/item_scope.rs b/crates/hir_def/src/item_scope.rs
index a8b3fe844..62ab3b2bd 100644
--- a/crates/hir_def/src/item_scope.rs
+++ b/crates/hir_def/src/item_scope.rs
@@ -363,7 +363,7 @@ impl ItemInNs {
363 ModuleDefId::TypeAliasId(id) => id.lookup(db).module(db).krate, 363 ModuleDefId::TypeAliasId(id) => id.lookup(db).module(db).krate,
364 ModuleDefId::BuiltinType(_) => return None, 364 ModuleDefId::BuiltinType(_) => return None,
365 }, 365 },
366 ItemInNs::Macros(id) => return id.krate, 366 ItemInNs::Macros(id) => return Some(id.krate),
367 }) 367 })
368 } 368 }
369} 369}
diff --git a/crates/hir_def/src/item_tree.rs b/crates/hir_def/src/item_tree.rs
index 1c9babf37..5eb7cae7f 100644
--- a/crates/hir_def/src/item_tree.rs
+++ b/crates/hir_def/src/item_tree.rs
@@ -13,6 +13,7 @@ use std::{
13 13
14use arena::{Arena, Idx, RawId}; 14use arena::{Arena, Idx, RawId};
15use ast::{AstNode, AttrsOwner, NameOwner, StructKind}; 15use ast::{AstNode, AttrsOwner, NameOwner, StructKind};
16use base_db::CrateId;
16use either::Either; 17use either::Either;
17use hir_expand::{ 18use hir_expand::{
18 ast_id_map::FileAstId, 19 ast_id_map::FileAstId,
@@ -26,7 +27,7 @@ use syntax::{ast, match_ast};
26use test_utils::mark; 27use test_utils::mark;
27 28
28use crate::{ 29use crate::{
29 attr::Attrs, 30 attr::{Attrs, RawAttrs},
30 db::DefDatabase, 31 db::DefDatabase,
31 generics::GenericParams, 32 generics::GenericParams,
32 path::{path, AssociatedTypeBinding, GenericArgs, ImportAlias, ModPath, Path, PathKind}, 33 path::{path, AssociatedTypeBinding, GenericArgs, ImportAlias, ModPath, Path, PathKind},
@@ -67,7 +68,7 @@ impl GenericParamsId {
67#[derive(Debug, Eq, PartialEq)] 68#[derive(Debug, Eq, PartialEq)]
68pub struct ItemTree { 69pub struct ItemTree {
69 top_level: SmallVec<[ModItem; 1]>, 70 top_level: SmallVec<[ModItem; 1]>,
70 attrs: FxHashMap<AttrOwner, Attrs>, 71 attrs: FxHashMap<AttrOwner, RawAttrs>,
71 inner_items: FxHashMap<FileAstId<ast::Item>, SmallVec<[ModItem; 1]>>, 72 inner_items: FxHashMap<FileAstId<ast::Item>, SmallVec<[ModItem; 1]>>,
72 73
73 data: Option<Box<ItemTreeData>>, 74 data: Option<Box<ItemTreeData>>,
@@ -88,7 +89,7 @@ impl ItemTree {
88 let mut item_tree = match_ast! { 89 let mut item_tree = match_ast! {
89 match syntax { 90 match syntax {
90 ast::SourceFile(file) => { 91 ast::SourceFile(file) => {
91 top_attrs = Some(Attrs::new(&file, &hygiene)); 92 top_attrs = Some(RawAttrs::new(&file, &hygiene));
92 ctx.lower_module_items(&file) 93 ctx.lower_module_items(&file)
93 }, 94 },
94 ast::MacroItems(items) => { 95 ast::MacroItems(items) => {
@@ -143,6 +144,7 @@ impl ItemTree {
143 mods, 144 mods,
144 macro_calls, 145 macro_calls,
145 macro_rules, 146 macro_rules,
147 macro_defs,
146 exprs, 148 exprs,
147 vis, 149 vis,
148 generics, 150 generics,
@@ -164,6 +166,7 @@ impl ItemTree {
164 mods.shrink_to_fit(); 166 mods.shrink_to_fit();
165 macro_calls.shrink_to_fit(); 167 macro_calls.shrink_to_fit();
166 macro_rules.shrink_to_fit(); 168 macro_rules.shrink_to_fit();
169 macro_defs.shrink_to_fit();
167 exprs.shrink_to_fit(); 170 exprs.shrink_to_fit();
168 171
169 vis.arena.shrink_to_fit(); 172 vis.arena.shrink_to_fit();
@@ -178,12 +181,16 @@ impl ItemTree {
178 } 181 }
179 182
180 /// Returns the inner attributes of the source file. 183 /// Returns the inner attributes of the source file.
181 pub fn top_level_attrs(&self) -> &Attrs { 184 pub fn top_level_attrs(&self, db: &dyn DefDatabase, krate: CrateId) -> Attrs {
182 self.attrs.get(&AttrOwner::TopLevel).unwrap_or(&Attrs::EMPTY) 185 self.attrs.get(&AttrOwner::TopLevel).unwrap_or(&RawAttrs::EMPTY).clone().filter(db, krate)
183 } 186 }
184 187
185 pub fn attrs(&self, of: AttrOwner) -> &Attrs { 188 pub(crate) fn raw_attrs(&self, of: AttrOwner) -> &RawAttrs {
186 self.attrs.get(&of).unwrap_or(&Attrs::EMPTY) 189 self.attrs.get(&of).unwrap_or(&RawAttrs::EMPTY)
190 }
191
192 pub fn attrs(&self, db: &dyn DefDatabase, krate: CrateId, of: AttrOwner) -> Attrs {
193 self.raw_attrs(of).clone().filter(db, krate)
187 } 194 }
188 195
189 /// Returns the lowered inner items that `ast` corresponds to. 196 /// Returns the lowered inner items that `ast` corresponds to.
@@ -283,6 +290,7 @@ struct ItemTreeData {
283 mods: Arena<Mod>, 290 mods: Arena<Mod>,
284 macro_calls: Arena<MacroCall>, 291 macro_calls: Arena<MacroCall>,
285 macro_rules: Arena<MacroRules>, 292 macro_rules: Arena<MacroRules>,
293 macro_defs: Arena<MacroDef>,
286 exprs: Arena<Expr>, 294 exprs: Arena<Expr>,
287 295
288 vis: ItemVisibilities, 296 vis: ItemVisibilities,
@@ -431,6 +439,7 @@ mod_items! {
431 Mod in mods -> ast::Module, 439 Mod in mods -> ast::Module,
432 MacroCall in macro_calls -> ast::MacroCall, 440 MacroCall in macro_calls -> ast::MacroCall,
433 MacroRules in macro_rules -> ast::MacroRules, 441 MacroRules in macro_rules -> ast::MacroRules,
442 MacroDef in macro_defs -> ast::MacroDef,
434} 443}
435 444
436macro_rules! impl_index { 445macro_rules! impl_index {
@@ -640,17 +649,19 @@ pub struct MacroCall {
640 649
641#[derive(Debug, Clone, Eq, PartialEq)] 650#[derive(Debug, Clone, Eq, PartialEq)]
642pub struct MacroRules { 651pub struct MacroRules {
643 /// For `macro_rules!` declarations, this is the name of the declared macro. 652 /// The name of the declared macro.
644 pub name: Name, 653 pub name: Name,
645 /// Has `#[macro_export]`.
646 pub is_export: bool,
647 /// Has `#[macro_export(local_inner_macros)]`.
648 pub is_local_inner: bool,
649 /// Has `#[rustc_builtin_macro]`.
650 pub is_builtin: bool,
651 pub ast_id: FileAstId<ast::MacroRules>, 654 pub ast_id: FileAstId<ast::MacroRules>,
652} 655}
653 656
657/// "Macros 2.0" macro definition.
658#[derive(Debug, Clone, Eq, PartialEq)]
659pub struct MacroDef {
660 pub name: Name,
661 pub visibility: RawVisibilityId,
662 pub ast_id: FileAstId<ast::MacroDef>,
663}
664
654// NB: There's no `FileAstId` for `Expr`. The only case where this would be useful is for array 665// NB: There's no `FileAstId` for `Expr`. The only case where this would be useful is for array
655// lengths, but we don't do much with them yet. 666// lengths, but we don't do much with them yet.
656#[derive(Debug, Clone, Eq, PartialEq)] 667#[derive(Debug, Clone, Eq, PartialEq)]
@@ -680,7 +691,8 @@ impl ModItem {
680 | ModItem::Trait(_) 691 | ModItem::Trait(_)
681 | ModItem::Impl(_) 692 | ModItem::Impl(_)
682 | ModItem::Mod(_) 693 | ModItem::Mod(_)
683 | ModItem::MacroRules(_) => None, 694 | ModItem::MacroRules(_)
695 | ModItem::MacroDef(_) => None,
684 ModItem::MacroCall(call) => Some(AssocItem::MacroCall(*call)), 696 ModItem::MacroCall(call) => Some(AssocItem::MacroCall(*call)),
685 ModItem::Const(konst) => Some(AssocItem::Const(*konst)), 697 ModItem::Const(konst) => Some(AssocItem::Const(*konst)),
686 ModItem::TypeAlias(alias) => Some(AssocItem::TypeAlias(*alias)), 698 ModItem::TypeAlias(alias) => Some(AssocItem::TypeAlias(*alias)),
@@ -708,6 +720,7 @@ impl ModItem {
708 ModItem::Mod(it) => tree[it.index].ast_id().upcast(), 720 ModItem::Mod(it) => tree[it.index].ast_id().upcast(),
709 ModItem::MacroCall(it) => tree[it.index].ast_id().upcast(), 721 ModItem::MacroCall(it) => tree[it.index].ast_id().upcast(),
710 ModItem::MacroRules(it) => tree[it.index].ast_id().upcast(), 722 ModItem::MacroRules(it) => tree[it.index].ast_id().upcast(),
723 ModItem::MacroDef(it) => tree[it.index].ast_id().upcast(),
711 } 724 }
712 } 725 }
713} 726}
diff --git a/crates/hir_def/src/item_tree/lower.rs b/crates/hir_def/src/item_tree/lower.rs
index b39d7fb7a..c8f090c22 100644
--- a/crates/hir_def/src/item_tree/lower.rs
+++ b/crates/hir_def/src/item_tree/lower.rs
@@ -10,7 +10,6 @@ use syntax::{
10}; 10};
11 11
12use crate::{ 12use crate::{
13 attr::Attrs,
14 generics::{GenericParams, TypeParamData, TypeParamProvenance}, 13 generics::{GenericParams, TypeParamData, TypeParamProvenance},
15 type_ref::LifetimeRef, 14 type_ref::LifetimeRef,
16}; 15};
@@ -101,10 +100,11 @@ impl Ctx {
101 | ast::Item::ExternCrate(_) 100 | ast::Item::ExternCrate(_)
102 | ast::Item::Use(_) 101 | ast::Item::Use(_)
103 | ast::Item::MacroCall(_) 102 | ast::Item::MacroCall(_)
104 | ast::Item::MacroRules(_) => {} 103 | ast::Item::MacroRules(_)
104 | ast::Item::MacroDef(_) => {}
105 }; 105 };
106 106
107 let attrs = Attrs::new(item, &self.hygiene); 107 let attrs = RawAttrs::new(item, &self.hygiene);
108 let items = match item { 108 let items = match item {
109 ast::Item::Struct(ast) => self.lower_struct(ast).map(Into::into), 109 ast::Item::Struct(ast) => self.lower_struct(ast).map(Into::into),
110 ast::Item::Union(ast) => self.lower_union(ast).map(Into::into), 110 ast::Item::Union(ast) => self.lower_union(ast).map(Into::into),
@@ -122,6 +122,7 @@ impl Ctx {
122 ast::Item::ExternCrate(ast) => self.lower_extern_crate(ast).map(Into::into), 122 ast::Item::ExternCrate(ast) => self.lower_extern_crate(ast).map(Into::into),
123 ast::Item::MacroCall(ast) => self.lower_macro_call(ast).map(Into::into), 123 ast::Item::MacroCall(ast) => self.lower_macro_call(ast).map(Into::into),
124 ast::Item::MacroRules(ast) => self.lower_macro_rules(ast).map(Into::into), 124 ast::Item::MacroRules(ast) => self.lower_macro_rules(ast).map(Into::into),
125 ast::Item::MacroDef(ast) => self.lower_macro_def(ast).map(Into::into),
125 ast::Item::ExternBlock(ast) => { 126 ast::Item::ExternBlock(ast) => {
126 Some(ModItems(self.lower_extern_block(ast).into_iter().collect::<SmallVec<_>>())) 127 Some(ModItems(self.lower_extern_block(ast).into_iter().collect::<SmallVec<_>>()))
127 } 128 }
@@ -136,7 +137,7 @@ impl Ctx {
136 items 137 items
137 } 138 }
138 139
139 fn add_attrs(&mut self, item: AttrOwner, attrs: Attrs) { 140 fn add_attrs(&mut self, item: AttrOwner, attrs: RawAttrs) {
140 match self.tree.attrs.entry(item) { 141 match self.tree.attrs.entry(item) {
141 Entry::Occupied(mut entry) => { 142 Entry::Occupied(mut entry) => {
142 *entry.get_mut() = entry.get().merge(attrs); 143 *entry.get_mut() = entry.get().merge(attrs);
@@ -203,7 +204,7 @@ impl Ctx {
203 for field in fields.fields() { 204 for field in fields.fields() {
204 if let Some(data) = self.lower_record_field(&field) { 205 if let Some(data) = self.lower_record_field(&field) {
205 let idx = self.data().fields.alloc(data); 206 let idx = self.data().fields.alloc(data);
206 self.add_attrs(idx.into(), Attrs::new(&field, &self.hygiene)); 207 self.add_attrs(idx.into(), RawAttrs::new(&field, &self.hygiene));
207 } 208 }
208 } 209 }
209 let end = self.next_field_idx(); 210 let end = self.next_field_idx();
@@ -223,7 +224,7 @@ impl Ctx {
223 for (i, field) in fields.fields().enumerate() { 224 for (i, field) in fields.fields().enumerate() {
224 let data = self.lower_tuple_field(i, &field); 225 let data = self.lower_tuple_field(i, &field);
225 let idx = self.data().fields.alloc(data); 226 let idx = self.data().fields.alloc(data);
226 self.add_attrs(idx.into(), Attrs::new(&field, &self.hygiene)); 227 self.add_attrs(idx.into(), RawAttrs::new(&field, &self.hygiene));
227 } 228 }
228 let end = self.next_field_idx(); 229 let end = self.next_field_idx();
229 IdRange::new(start..end) 230 IdRange::new(start..end)
@@ -268,7 +269,7 @@ impl Ctx {
268 for variant in variants.variants() { 269 for variant in variants.variants() {
269 if let Some(data) = self.lower_variant(&variant) { 270 if let Some(data) = self.lower_variant(&variant) {
270 let idx = self.data().variants.alloc(data); 271 let idx = self.data().variants.alloc(data);
271 self.add_attrs(idx.into(), Attrs::new(&variant, &self.hygiene)); 272 self.add_attrs(idx.into(), RawAttrs::new(&variant, &self.hygiene));
272 } 273 }
273 } 274 }
274 let end = self.next_variant_idx(); 275 let end = self.next_variant_idx();
@@ -298,12 +299,12 @@ impl Ctx {
298 ast::SelfParamKind::Owned => self_type, 299 ast::SelfParamKind::Owned => self_type,
299 ast::SelfParamKind::Ref => TypeRef::Reference( 300 ast::SelfParamKind::Ref => TypeRef::Reference(
300 Box::new(self_type), 301 Box::new(self_type),
301 self_param.lifetime_token().map(LifetimeRef::from_token), 302 self_param.lifetime().as_ref().map(LifetimeRef::new),
302 Mutability::Shared, 303 Mutability::Shared,
303 ), 304 ),
304 ast::SelfParamKind::MutRef => TypeRef::Reference( 305 ast::SelfParamKind::MutRef => TypeRef::Reference(
305 Box::new(self_type), 306 Box::new(self_type),
306 self_param.lifetime_token().map(LifetimeRef::from_token), 307 self_param.lifetime().as_ref().map(LifetimeRef::new),
307 Mutability::Mut, 308 Mutability::Mut,
308 ), 309 ),
309 } 310 }
@@ -436,7 +437,7 @@ impl Ctx {
436 self.with_inherited_visibility(visibility, |this| { 437 self.with_inherited_visibility(visibility, |this| {
437 list.assoc_items() 438 list.assoc_items()
438 .filter_map(|item| { 439 .filter_map(|item| {
439 let attrs = Attrs::new(&item, &this.hygiene); 440 let attrs = RawAttrs::new(&item, &this.hygiene);
440 this.collect_inner_items(item.syntax()); 441 this.collect_inner_items(item.syntax());
441 this.lower_assoc_item(&item).map(|item| { 442 this.lower_assoc_item(&item).map(|item| {
442 this.add_attrs(ModItem::from(item).into(), attrs); 443 this.add_attrs(ModItem::from(item).into(), attrs);
@@ -473,7 +474,7 @@ impl Ctx {
473 .filter_map(|item| { 474 .filter_map(|item| {
474 self.collect_inner_items(item.syntax()); 475 self.collect_inner_items(item.syntax());
475 let assoc = self.lower_assoc_item(&item)?; 476 let assoc = self.lower_assoc_item(&item)?;
476 let attrs = Attrs::new(&item, &self.hygiene); 477 let attrs = RawAttrs::new(&item, &self.hygiene);
477 self.add_attrs(ModItem::from(assoc).into(), attrs); 478 self.add_attrs(ModItem::from(assoc).into(), attrs);
478 Some(assoc) 479 Some(assoc)
479 }) 480 })
@@ -537,28 +538,20 @@ impl Ctx {
537 538
538 fn lower_macro_rules(&mut self, m: &ast::MacroRules) -> Option<FileItemTreeId<MacroRules>> { 539 fn lower_macro_rules(&mut self, m: &ast::MacroRules) -> Option<FileItemTreeId<MacroRules>> {
539 let name = m.name().map(|it| it.as_name())?; 540 let name = m.name().map(|it| it.as_name())?;
540 let attrs = Attrs::new(m, &self.hygiene);
541
542 let ast_id = self.source_ast_id_map.ast_id(m); 541 let ast_id = self.source_ast_id_map.ast_id(m);
543 542
544 // FIXME: cfg_attr 543 let res = MacroRules { name, ast_id };
545 let export_attr = attrs.by_key("macro_export"); 544 Some(id(self.data().macro_rules.alloc(res)))
545 }
546 546
547 let is_export = export_attr.exists(); 547 fn lower_macro_def(&mut self, m: &ast::MacroDef) -> Option<FileItemTreeId<MacroDef>> {
548 let is_local_inner = if is_export { 548 let name = m.name().map(|it| it.as_name())?;
549 export_attr.tt_values().map(|it| &it.token_trees).flatten().any(|it| match it {
550 tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) => {
551 ident.text.contains("local_inner_macros")
552 }
553 _ => false,
554 })
555 } else {
556 false
557 };
558 549
559 let is_builtin = attrs.by_key("rustc_builtin_macro").exists(); 550 let ast_id = self.source_ast_id_map.ast_id(m);
560 let res = MacroRules { name, is_export, is_builtin, is_local_inner, ast_id }; 551 let visibility = self.lower_visibility(m);
561 Some(id(self.data().macro_rules.alloc(res))) 552
553 let res = MacroDef { name, ast_id, visibility };
554 Some(id(self.data().macro_defs.alloc(res)))
562 } 555 }
563 556
564 fn lower_extern_block(&mut self, block: &ast::ExternBlock) -> Vec<ModItem> { 557 fn lower_extern_block(&mut self, block: &ast::ExternBlock) -> Vec<ModItem> {
@@ -566,7 +559,7 @@ impl Ctx {
566 list.extern_items() 559 list.extern_items()
567 .filter_map(|item| { 560 .filter_map(|item| {
568 self.collect_inner_items(item.syntax()); 561 self.collect_inner_items(item.syntax());
569 let attrs = Attrs::new(&item, &self.hygiene); 562 let attrs = RawAttrs::new(&item, &self.hygiene);
570 let id: ModItem = match item { 563 let id: ModItem = match item {
571 ast::ExternItem::Fn(ast) => { 564 ast::ExternItem::Fn(ast) => {
572 let func_id = self.lower_function(&ast)?; 565 let func_id = self.lower_function(&ast)?;
diff --git a/crates/hir_def/src/lang_item.rs b/crates/hir_def/src/lang_item.rs
index 063eadccb..30188b740 100644
--- a/crates/hir_def/src/lang_item.rs
+++ b/crates/hir_def/src/lang_item.rs
@@ -8,8 +8,8 @@ use rustc_hash::FxHashMap;
8use syntax::SmolStr; 8use syntax::SmolStr;
9 9
10use crate::{ 10use crate::{
11 db::DefDatabase, AdtId, AttrDefId, CrateId, EnumId, FunctionId, ImplId, ModuleDefId, ModuleId, 11 db::DefDatabase, AdtId, AttrDefId, CrateId, EnumId, FunctionId, ImplId, ModuleDefId, StaticId,
12 StaticId, StructId, TraitId, 12 StructId, TraitId,
13}; 13};
14 14
15#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 15#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -84,27 +84,34 @@ impl LangItems {
84 84
85 let crate_def_map = db.crate_def_map(krate); 85 let crate_def_map = db.crate_def_map(krate);
86 86
87 crate_def_map 87 for (_, module_data) in crate_def_map.modules.iter() {
88 .modules 88 for impl_def in module_data.scope.impls() {
89 .iter() 89 lang_items.collect_lang_item(db, impl_def, LangItemTarget::ImplDefId)
90 .filter_map(|(local_id, _)| db.module_lang_items(ModuleId { krate, local_id })) 90 }
91 .for_each(|it| lang_items.items.extend(it.items.iter().map(|(k, v)| (k.clone(), *v))));
92
93 Arc::new(lang_items)
94 }
95 91
96 pub(crate) fn module_lang_items_query( 92 for def in module_data.scope.declarations() {
97 db: &dyn DefDatabase, 93 match def {
98 module: ModuleId, 94 ModuleDefId::TraitId(trait_) => {
99 ) -> Option<Arc<LangItems>> { 95 lang_items.collect_lang_item(db, trait_, LangItemTarget::TraitId)
100 let _p = profile::span("module_lang_items_query"); 96 }
101 let mut lang_items = LangItems::default(); 97 ModuleDefId::AdtId(AdtId::EnumId(e)) => {
102 lang_items.collect_lang_items(db, module); 98 lang_items.collect_lang_item(db, e, LangItemTarget::EnumId)
103 if lang_items.items.is_empty() { 99 }
104 None 100 ModuleDefId::AdtId(AdtId::StructId(s)) => {
105 } else { 101 lang_items.collect_lang_item(db, s, LangItemTarget::StructId)
106 Some(Arc::new(lang_items)) 102 }
103 ModuleDefId::FunctionId(f) => {
104 lang_items.collect_lang_item(db, f, LangItemTarget::FunctionId)
105 }
106 ModuleDefId::StaticId(s) => {
107 lang_items.collect_lang_item(db, s, LangItemTarget::StaticId)
108 }
109 _ => {}
110 }
111 }
107 } 112 }
113
114 Arc::new(lang_items)
108 } 115 }
109 116
110 /// Salsa query. Look for a lang item, starting from the specified crate and recursively 117 /// Salsa query. Look for a lang item, starting from the specified crate and recursively
@@ -126,34 +133,6 @@ impl LangItems {
126 .find_map(|dep| db.lang_item(dep.crate_id, item.clone())) 133 .find_map(|dep| db.lang_item(dep.crate_id, item.clone()))
127 } 134 }
128 135
129 fn collect_lang_items(&mut self, db: &dyn DefDatabase, module: ModuleId) {
130 // Look for impl targets
131 let def_map = db.crate_def_map(module.krate);
132 let module_data = &def_map[module.local_id];
133 for impl_def in module_data.scope.impls() {
134 self.collect_lang_item(db, impl_def, LangItemTarget::ImplDefId)
135 }
136
137 for def in module_data.scope.declarations() {
138 match def {
139 ModuleDefId::TraitId(trait_) => {
140 self.collect_lang_item(db, trait_, LangItemTarget::TraitId)
141 }
142 ModuleDefId::AdtId(AdtId::EnumId(e)) => {
143 self.collect_lang_item(db, e, LangItemTarget::EnumId)
144 }
145 ModuleDefId::AdtId(AdtId::StructId(s)) => {
146 self.collect_lang_item(db, s, LangItemTarget::StructId)
147 }
148 ModuleDefId::FunctionId(f) => {
149 self.collect_lang_item(db, f, LangItemTarget::FunctionId)
150 }
151 ModuleDefId::StaticId(s) => self.collect_lang_item(db, s, LangItemTarget::StaticId),
152 _ => {}
153 }
154 }
155 }
156
157 fn collect_lang_item<T>( 136 fn collect_lang_item<T>(
158 &mut self, 137 &mut self,
159 db: &dyn DefDatabase, 138 db: &dyn DefDatabase,
diff --git a/crates/hir_def/src/lib.rs b/crates/hir_def/src/lib.rs
index 7e2199a9c..ba09a9126 100644
--- a/crates/hir_def/src/lib.rs
+++ b/crates/hir_def/src/lib.rs
@@ -425,6 +425,16 @@ impl HasModule for AdtId {
425 } 425 }
426} 426}
427 427
428impl HasModule for VariantId {
429 fn module(&self, db: &dyn db::DefDatabase) -> ModuleId {
430 match self {
431 VariantId::EnumVariantId(it) => it.parent.lookup(db).container.module(db),
432 VariantId::StructId(it) => it.lookup(db).container.module(db),
433 VariantId::UnionId(it) => it.lookup(db).container.module(db),
434 }
435 }
436}
437
428impl HasModule for DefWithBodyId { 438impl HasModule for DefWithBodyId {
429 fn module(&self, db: &dyn db::DefDatabase) -> ModuleId { 439 fn module(&self, db: &dyn db::DefDatabase) -> ModuleId {
430 match self { 440 match self {
@@ -465,6 +475,26 @@ impl HasModule for StaticLoc {
465 } 475 }
466} 476}
467 477
478impl AttrDefId {
479 pub fn krate(&self, db: &dyn db::DefDatabase) -> CrateId {
480 match self {
481 AttrDefId::ModuleId(it) => it.krate,
482 AttrDefId::FieldId(it) => it.parent.module(db).krate,
483 AttrDefId::AdtId(it) => it.module(db).krate,
484 AttrDefId::FunctionId(it) => it.lookup(db).module(db).krate,
485 AttrDefId::EnumVariantId(it) => it.parent.lookup(db).container.module(db).krate,
486 AttrDefId::StaticId(it) => it.lookup(db).module(db).krate,
487 AttrDefId::ConstId(it) => it.lookup(db).module(db).krate,
488 AttrDefId::TraitId(it) => it.lookup(db).container.module(db).krate,
489 AttrDefId::TypeAliasId(it) => it.lookup(db).module(db).krate,
490 AttrDefId::ImplId(it) => it.lookup(db).container.module(db).krate,
491 // FIXME: `MacroDefId` should store the defining module, then this can implement
492 // `HasModule`
493 AttrDefId::MacroDefId(it) => it.krate,
494 }
495 }
496}
497
468/// A helper trait for converting to MacroCallId 498/// A helper trait for converting to MacroCallId
469pub trait AsMacroCall { 499pub trait AsMacroCall {
470 fn as_call_id( 500 fn as_call_id(
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs
index 85cc342c4..b114a6fe4 100644
--- a/crates/hir_def/src/nameres/collector.rs
+++ b/crates/hir_def/src/nameres/collector.rs
@@ -26,7 +26,8 @@ use crate::{
26 db::DefDatabase, 26 db::DefDatabase,
27 item_scope::{ImportType, PerNsGlobImports}, 27 item_scope::{ImportType, PerNsGlobImports},
28 item_tree::{ 28 item_tree::{
29 self, ItemTree, ItemTreeId, MacroCall, MacroRules, Mod, ModItem, ModKind, StructDefKind, 29 self, FileItemTreeId, ItemTree, ItemTreeId, MacroCall, MacroRules, Mod, ModItem, ModKind,
30 StructDefKind,
30 }, 31 },
31 nameres::{ 32 nameres::{
32 diagnostics::DefDiagnostic, mod_resolution::ModDir, path_resolution::ReachedFixedPoint, 33 diagnostics::DefDiagnostic, mod_resolution::ModDir, path_resolution::ReachedFixedPoint,
@@ -220,17 +221,20 @@ impl DefCollector<'_> {
220 let item_tree = self.db.item_tree(file_id.into()); 221 let item_tree = self.db.item_tree(file_id.into());
221 let module_id = self.def_map.root; 222 let module_id = self.def_map.root;
222 self.def_map.modules[module_id].origin = ModuleOrigin::CrateRoot { definition: file_id }; 223 self.def_map.modules[module_id].origin = ModuleOrigin::CrateRoot { definition: file_id };
223 let mut root_collector = ModCollector { 224 if item_tree
224 def_collector: &mut *self, 225 .top_level_attrs(self.db, self.def_map.krate)
225 macro_depth: 0, 226 .cfg()
226 module_id, 227 .map_or(true, |cfg| self.cfg_options.check(&cfg) != Some(false))
227 file_id: file_id.into(),
228 item_tree: &item_tree,
229 mod_dir: ModDir::root(),
230 };
231 if item_tree.top_level_attrs().cfg().map_or(true, |cfg| root_collector.is_cfg_enabled(&cfg))
232 { 228 {
233 root_collector.collect(item_tree.top_level_items()); 229 ModCollector {
230 def_collector: &mut *self,
231 macro_depth: 0,
232 module_id,
233 file_id: file_id.into(),
234 item_tree: &item_tree,
235 mod_dir: ModDir::root(),
236 }
237 .collect(item_tree.top_level_items());
234 } 238 }
235 239
236 // main name resolution fixed-point loop. 240 // main name resolution fixed-point loop.
@@ -309,13 +313,13 @@ impl DefCollector<'_> {
309 let macro_def = match self.proc_macros.iter().find(|(n, _)| n == name) { 313 let macro_def = match self.proc_macros.iter().find(|(n, _)| n == name) {
310 Some((_, expander)) => MacroDefId { 314 Some((_, expander)) => MacroDefId {
311 ast_id: None, 315 ast_id: None,
312 krate: Some(self.def_map.krate), 316 krate: self.def_map.krate,
313 kind: MacroDefKind::ProcMacro(*expander), 317 kind: MacroDefKind::ProcMacro(*expander),
314 local_inner: false, 318 local_inner: false,
315 }, 319 },
316 None => MacroDefId { 320 None => MacroDefId {
317 ast_id: None, 321 ast_id: None,
318 krate: Some(self.def_map.krate), 322 krate: self.def_map.krate,
319 kind: MacroDefKind::ProcMacro(ProcMacroExpander::dummy(self.def_map.krate)), 323 kind: MacroDefKind::ProcMacro(ProcMacroExpander::dummy(self.def_map.krate)),
320 local_inner: false, 324 local_inner: false,
321 }, 325 },
@@ -784,14 +788,6 @@ impl DefCollector<'_> {
784 directive: &DeriveDirective, 788 directive: &DeriveDirective,
785 path: &ModPath, 789 path: &ModPath,
786 ) -> Option<MacroDefId> { 790 ) -> Option<MacroDefId> {
787 if let Some(name) = path.as_ident() {
788 // FIXME this should actually be handled with the normal name
789 // resolution; the std lib defines built-in stubs for the derives,
790 // but these are new-style `macro`s, which we don't support yet
791 if let Some(def_id) = find_builtin_derive(name) {
792 return Some(def_id);
793 }
794 }
795 let resolved_res = self.def_map.resolve_path_fp_with_macro( 791 let resolved_res = self.def_map.resolve_path_fp_with_macro(
796 self.db, 792 self.db,
797 ResolveMode::Other, 793 ResolveMode::Other,
@@ -912,6 +908,8 @@ struct ModCollector<'a, 'b> {
912 908
913impl ModCollector<'_, '_> { 909impl ModCollector<'_, '_> {
914 fn collect(&mut self, items: &[ModItem]) { 910 fn collect(&mut self, items: &[ModItem]) {
911 let krate = self.def_collector.def_map.krate;
912
915 // Note: don't assert that inserted value is fresh: it's simply not true 913 // Note: don't assert that inserted value is fresh: it's simply not true
916 // for macros. 914 // for macros.
917 self.def_collector.mod_dirs.insert(self.module_id, self.mod_dir.clone()); 915 self.def_collector.mod_dirs.insert(self.module_id, self.mod_dir.clone());
@@ -928,7 +926,7 @@ impl ModCollector<'_, '_> {
928 // `#[macro_use] extern crate` is hoisted to imports macros before collecting 926 // `#[macro_use] extern crate` is hoisted to imports macros before collecting
929 // any other items. 927 // any other items.
930 for item in items { 928 for item in items {
931 let attrs = self.item_tree.attrs((*item).into()); 929 let attrs = self.item_tree.attrs(self.def_collector.db, krate, (*item).into());
932 if attrs.cfg().map_or(true, |cfg| self.is_cfg_enabled(&cfg)) { 930 if attrs.cfg().map_or(true, |cfg| self.is_cfg_enabled(&cfg)) {
933 if let ModItem::ExternCrate(id) = item { 931 if let ModItem::ExternCrate(id) = item {
934 let import = self.item_tree[*id].clone(); 932 let import = self.item_tree[*id].clone();
@@ -940,7 +938,7 @@ impl ModCollector<'_, '_> {
940 } 938 }
941 939
942 for &item in items { 940 for &item in items {
943 let attrs = self.item_tree.attrs(item.into()); 941 let attrs = self.item_tree.attrs(self.def_collector.db, krate, item.into());
944 if let Some(cfg) = attrs.cfg() { 942 if let Some(cfg) = attrs.cfg() {
945 if !self.is_cfg_enabled(&cfg) { 943 if !self.is_cfg_enabled(&cfg) {
946 self.emit_unconfigured_diagnostic(item, &cfg); 944 self.emit_unconfigured_diagnostic(item, &cfg);
@@ -953,7 +951,7 @@ impl ModCollector<'_, '_> {
953 951
954 let mut def = None; 952 let mut def = None;
955 match item { 953 match item {
956 ModItem::Mod(m) => self.collect_module(&self.item_tree[m], attrs), 954 ModItem::Mod(m) => self.collect_module(&self.item_tree[m], &attrs),
957 ModItem::Import(import_id) => { 955 ModItem::Import(import_id) => {
958 self.def_collector.unresolved_imports.push(ImportDirective { 956 self.def_collector.unresolved_imports.push(ImportDirective {
959 module_id: self.module_id, 957 module_id: self.module_id,
@@ -975,7 +973,41 @@ impl ModCollector<'_, '_> {
975 }) 973 })
976 } 974 }
977 ModItem::MacroCall(mac) => self.collect_macro_call(&self.item_tree[mac]), 975 ModItem::MacroCall(mac) => self.collect_macro_call(&self.item_tree[mac]),
978 ModItem::MacroRules(mac) => self.collect_macro_rules(&self.item_tree[mac]), 976 ModItem::MacroRules(id) => self.collect_macro_rules(id),
977 ModItem::MacroDef(id) => {
978 let mac = &self.item_tree[id];
979 let ast_id = InFile::new(self.file_id, mac.ast_id.upcast());
980
981 // "Macro 2.0" is not currently supported by rust-analyzer, but libcore uses it
982 // to define builtin macros, so we support at least that part.
983 let attrs = self.item_tree.attrs(
984 self.def_collector.db,
985 krate,
986 ModItem::from(id).into(),
987 );
988 if attrs.by_key("rustc_builtin_macro").exists() {
989 let krate = self.def_collector.def_map.krate;
990 let macro_id = find_builtin_macro(&mac.name, krate, ast_id)
991 .or_else(|| find_builtin_derive(&mac.name, krate, ast_id));
992 if let Some(macro_id) = macro_id {
993 let vis = self
994 .def_collector
995 .def_map
996 .resolve_visibility(
997 self.def_collector.db,
998 self.module_id,
999 &self.item_tree[mac.visibility],
1000 )
1001 .unwrap_or(Visibility::Public);
1002 self.def_collector.update(
1003 self.module_id,
1004 &[(Some(mac.name.clone()), PerNs::macros(macro_id, vis))],
1005 vis,
1006 ImportType::Named,
1007 );
1008 }
1009 }
1010 }
979 ModItem::Impl(imp) => { 1011 ModItem::Impl(imp) => {
980 let module = ModuleId { 1012 let module = ModuleId {
981 krate: self.def_collector.def_map.krate, 1013 krate: self.def_collector.def_map.krate,
@@ -989,7 +1021,7 @@ impl ModCollector<'_, '_> {
989 ModItem::Function(id) => { 1021 ModItem::Function(id) => {
990 let func = &self.item_tree[id]; 1022 let func = &self.item_tree[id];
991 1023
992 self.collect_proc_macro_def(&func.name, attrs); 1024 self.collect_proc_macro_def(&func.name, &attrs);
993 1025
994 def = Some(DefData { 1026 def = Some(DefData {
995 id: FunctionLoc { 1027 id: FunctionLoc {
@@ -1009,7 +1041,7 @@ impl ModCollector<'_, '_> {
1009 // FIXME: check attrs to see if this is an attribute macro invocation; 1041 // FIXME: check attrs to see if this is an attribute macro invocation;
1010 // in which case we don't add the invocation, just a single attribute 1042 // in which case we don't add the invocation, just a single attribute
1011 // macro invocation 1043 // macro invocation
1012 self.collect_derives(attrs, it.ast_id.upcast()); 1044 self.collect_derives(&attrs, it.ast_id.upcast());
1013 1045
1014 def = Some(DefData { 1046 def = Some(DefData {
1015 id: StructLoc { container, id: ItemTreeId::new(self.file_id, id) } 1047 id: StructLoc { container, id: ItemTreeId::new(self.file_id, id) }
@@ -1026,7 +1058,7 @@ impl ModCollector<'_, '_> {
1026 // FIXME: check attrs to see if this is an attribute macro invocation; 1058 // FIXME: check attrs to see if this is an attribute macro invocation;
1027 // in which case we don't add the invocation, just a single attribute 1059 // in which case we don't add the invocation, just a single attribute
1028 // macro invocation 1060 // macro invocation
1029 self.collect_derives(attrs, it.ast_id.upcast()); 1061 self.collect_derives(&attrs, it.ast_id.upcast());
1030 1062
1031 def = Some(DefData { 1063 def = Some(DefData {
1032 id: UnionLoc { container, id: ItemTreeId::new(self.file_id, id) } 1064 id: UnionLoc { container, id: ItemTreeId::new(self.file_id, id) }
@@ -1043,7 +1075,7 @@ impl ModCollector<'_, '_> {
1043 // FIXME: check attrs to see if this is an attribute macro invocation; 1075 // FIXME: check attrs to see if this is an attribute macro invocation;
1044 // in which case we don't add the invocation, just a single attribute 1076 // in which case we don't add the invocation, just a single attribute
1045 // macro invocation 1077 // macro invocation
1046 self.collect_derives(attrs, it.ast_id.upcast()); 1078 self.collect_derives(&attrs, it.ast_id.upcast());
1047 1079
1048 def = Some(DefData { 1080 def = Some(DefData {
1049 id: EnumLoc { container, id: ItemTreeId::new(self.file_id, id) } 1081 id: EnumLoc { container, id: ItemTreeId::new(self.file_id, id) }
@@ -1279,18 +1311,35 @@ impl ModCollector<'_, '_> {
1279 self.def_collector.resolve_proc_macro(&macro_name); 1311 self.def_collector.resolve_proc_macro(&macro_name);
1280 } 1312 }
1281 1313
1282 fn collect_macro_rules(&mut self, mac: &MacroRules) { 1314 fn collect_macro_rules(&mut self, id: FileItemTreeId<MacroRules>) {
1283 let ast_id = InFile::new(self.file_id, mac.ast_id); 1315 let krate = self.def_collector.def_map.krate;
1316 let mac = &self.item_tree[id];
1317 let attrs = self.item_tree.attrs(self.def_collector.db, krate, ModItem::from(id).into());
1318 let ast_id = InFile::new(self.file_id, mac.ast_id.upcast());
1319
1320 let export_attr = attrs.by_key("macro_export");
1321
1322 let is_export = export_attr.exists();
1323 let is_local_inner = if is_export {
1324 export_attr.tt_values().map(|it| &it.token_trees).flatten().any(|it| match it {
1325 tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) => {
1326 ident.text.contains("local_inner_macros")
1327 }
1328 _ => false,
1329 })
1330 } else {
1331 false
1332 };
1284 1333
1285 // Case 1: builtin macros 1334 // Case 1: builtin macros
1286 if mac.is_builtin { 1335 if attrs.by_key("rustc_builtin_macro").exists() {
1287 let krate = self.def_collector.def_map.krate; 1336 let krate = self.def_collector.def_map.krate;
1288 if let Some(macro_id) = find_builtin_macro(&mac.name, krate, ast_id) { 1337 if let Some(macro_id) = find_builtin_macro(&mac.name, krate, ast_id) {
1289 self.def_collector.define_macro( 1338 self.def_collector.define_macro(
1290 self.module_id, 1339 self.module_id,
1291 mac.name.clone(), 1340 mac.name.clone(),
1292 macro_id, 1341 macro_id,
1293 mac.is_export, 1342 is_export,
1294 ); 1343 );
1295 return; 1344 return;
1296 } 1345 }
@@ -1299,11 +1348,11 @@ impl ModCollector<'_, '_> {
1299 // Case 2: normal `macro_rules!` macro 1348 // Case 2: normal `macro_rules!` macro
1300 let macro_id = MacroDefId { 1349 let macro_id = MacroDefId {
1301 ast_id: Some(ast_id), 1350 ast_id: Some(ast_id),
1302 krate: Some(self.def_collector.def_map.krate), 1351 krate: self.def_collector.def_map.krate,
1303 kind: MacroDefKind::Declarative, 1352 kind: MacroDefKind::Declarative,
1304 local_inner: mac.is_local_inner, 1353 local_inner: is_local_inner,
1305 }; 1354 };
1306 self.def_collector.define_macro(self.module_id, mac.name.clone(), macro_id, mac.is_export); 1355 self.def_collector.define_macro(self.module_id, mac.name.clone(), macro_id, is_export);
1307 } 1356 }
1308 1357
1309 fn collect_macro_call(&mut self, mac: &MacroCall) { 1358 fn collect_macro_call(&mut self, mac: &MacroCall) {
diff --git a/crates/hir_def/src/nameres/tests/macros.rs b/crates/hir_def/src/nameres/tests/macros.rs
index 305fca0f9..6fe2ee78a 100644
--- a/crates/hir_def/src/nameres/tests/macros.rs
+++ b/crates/hir_def/src/nameres/tests/macros.rs
@@ -633,15 +633,44 @@ pub struct bar;
633fn expand_derive() { 633fn expand_derive() {
634 let map = compute_crate_def_map( 634 let map = compute_crate_def_map(
635 " 635 "
636 //- /main.rs 636 //- /main.rs crate:main deps:core
637 use core::*;
638
637 #[derive(Copy, Clone)] 639 #[derive(Copy, Clone)]
638 struct Foo; 640 struct Foo;
641
642 //- /core.rs crate:core
643 #[rustc_builtin_macro]
644 pub macro Copy {}
645
646 #[rustc_builtin_macro]
647 pub macro Clone {}
639 ", 648 ",
640 ); 649 );
641 assert_eq!(map.modules[map.root].scope.impls().len(), 2); 650 assert_eq!(map.modules[map.root].scope.impls().len(), 2);
642} 651}
643 652
644#[test] 653#[test]
654fn resolve_builtin_derive() {
655 check(
656 r#"
657//- /main.rs crate:main deps:core
658use core::*;
659
660//- /core.rs crate:core
661#[rustc_builtin_macro]
662pub macro Clone {}
663
664pub trait Clone {}
665"#,
666 expect![[r#"
667 crate
668 Clone: t m
669 "#]],
670 );
671}
672
673#[test]
645fn macro_expansion_overflow() { 674fn macro_expansion_overflow() {
646 mark::check!(macro_expansion_overflow); 675 mark::check!(macro_expansion_overflow);
647 check( 676 check(
diff --git a/crates/hir_def/src/path/lower.rs b/crates/hir_def/src/path/lower.rs
index 609925012..8a01e6eea 100644
--- a/crates/hir_def/src/path/lower.rs
+++ b/crates/hir_def/src/path/lower.rs
@@ -169,8 +169,8 @@ pub(super) fn lower_generic_args(
169 } 169 }
170 } 170 }
171 ast::GenericArg::LifetimeArg(lifetime_arg) => { 171 ast::GenericArg::LifetimeArg(lifetime_arg) => {
172 if let Some(lifetime) = lifetime_arg.lifetime_token() { 172 if let Some(lifetime) = lifetime_arg.lifetime() {
173 let lifetime_ref = LifetimeRef::from_token(lifetime); 173 let lifetime_ref = LifetimeRef::new(&lifetime);
174 args.push(GenericArg::Lifetime(lifetime_ref)) 174 args.push(GenericArg::Lifetime(lifetime_ref))
175 } 175 }
176 } 176 }
diff --git a/crates/hir_def/src/type_ref.rs b/crates/hir_def/src/type_ref.rs
index 347ceabb9..ae93d0d10 100644
--- a/crates/hir_def/src/type_ref.rs
+++ b/crates/hir_def/src/type_ref.rs
@@ -1,7 +1,7 @@
1//! HIR for references to types. Paths in these are not yet resolved. They can 1//! HIR for references to types. Paths in these are not yet resolved. They can
2//! be directly created from an ast::TypeRef, without further queries. 2//! be directly created from an ast::TypeRef, without further queries.
3use hir_expand::name::Name; 3use hir_expand::name::Name;
4use syntax::{ast, SyntaxToken}; 4use syntax::ast;
5 5
6use crate::{body::LowerCtx, path::Path}; 6use crate::{body::LowerCtx, path::Path};
7 7
@@ -80,8 +80,8 @@ impl LifetimeRef {
80 LifetimeRef { name } 80 LifetimeRef { name }
81 } 81 }
82 82
83 pub(crate) fn from_token(token: SyntaxToken) -> Self { 83 pub(crate) fn new(lifetime: &ast::Lifetime) -> Self {
84 LifetimeRef { name: Name::new_lifetime(&token) } 84 LifetimeRef { name: Name::new_lifetime(lifetime) }
85 } 85 }
86 86
87 pub fn missing() -> LifetimeRef { 87 pub fn missing() -> LifetimeRef {
@@ -127,7 +127,7 @@ impl TypeRef {
127 } 127 }
128 ast::Type::RefType(inner) => { 128 ast::Type::RefType(inner) => {
129 let inner_ty = TypeRef::from_ast_opt(&ctx, inner.ty()); 129 let inner_ty = TypeRef::from_ast_opt(&ctx, inner.ty());
130 let lifetime = inner.lifetime_token().map(|t| LifetimeRef::from_token(t)); 130 let lifetime = inner.lifetime().map(|lt| LifetimeRef::new(&lt));
131 let mutability = Mutability::from_mutable(inner.mut_token().is_some()); 131 let mutability = Mutability::from_mutable(inner.mut_token().is_some());
132 TypeRef::Reference(Box::new(inner_ty), lifetime, mutability) 132 TypeRef::Reference(Box::new(inner_ty), lifetime, mutability)
133 } 133 }
@@ -259,7 +259,7 @@ impl TypeBound {
259 } 259 }
260 ast::TypeBoundKind::ForType(_) => TypeBound::Error, // FIXME ForType 260 ast::TypeBoundKind::ForType(_) => TypeBound::Error, // FIXME ForType
261 ast::TypeBoundKind::Lifetime(lifetime) => { 261 ast::TypeBoundKind::Lifetime(lifetime) => {
262 TypeBound::Lifetime(LifetimeRef::from_token(lifetime)) 262 TypeBound::Lifetime(LifetimeRef::new(&lifetime))
263 } 263 }
264 } 264 }
265 } 265 }