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.rs6
-rw-r--r--crates/hir_def/src/attr.rs146
-rw-r--r--crates/hir_def/src/body/lower.rs27
-rw-r--r--crates/hir_def/src/body/tests.rs2
-rw-r--r--crates/hir_def/src/data.rs62
-rw-r--r--crates/hir_def/src/db.rs4
-rw-r--r--crates/hir_def/src/generics.rs14
-rw-r--r--crates/hir_def/src/item_tree.rs68
-rw-r--r--crates/hir_def/src/item_tree/lower.rs41
-rw-r--r--crates/hir_def/src/nameres.rs2
-rw-r--r--crates/hir_def/src/nameres/collector.rs58
-rw-r--r--crates/hir_def/src/nameres/tests.rs19
-rw-r--r--crates/hir_def/src/nameres/tests/diagnostics.rs19
-rw-r--r--crates/hir_def/src/src.rs16
14 files changed, 327 insertions, 157 deletions
diff --git a/crates/hir_def/src/adt.rs b/crates/hir_def/src/adt.rs
index 1b9bb8235..58e35353b 100644
--- a/crates/hir_def/src/adt.rs
+++ b/crates/hir_def/src/adt.rs
@@ -94,7 +94,7 @@ impl StructData {
94 pub(crate) fn struct_data_query(db: &dyn DefDatabase, id: StructId) -> Arc<StructData> { 94 pub(crate) fn struct_data_query(db: &dyn DefDatabase, id: StructId) -> Arc<StructData> {
95 let loc = id.lookup(db); 95 let loc = id.lookup(db);
96 let krate = loc.container.krate; 96 let krate = loc.container.krate;
97 let item_tree = db.item_tree(loc.id.file_id); 97 let item_tree = loc.id.item_tree(db);
98 let repr = repr_from_value(db, krate, &item_tree, ModItem::from(loc.id.value).into()); 98 let repr = repr_from_value(db, krate, &item_tree, ModItem::from(loc.id.value).into());
99 let cfg_options = db.crate_graph()[loc.container.krate].cfg_options.clone(); 99 let cfg_options = db.crate_graph()[loc.container.krate].cfg_options.clone();
100 100
@@ -110,7 +110,7 @@ impl StructData {
110 pub(crate) fn union_data_query(db: &dyn DefDatabase, id: UnionId) -> Arc<StructData> { 110 pub(crate) fn union_data_query(db: &dyn DefDatabase, id: UnionId) -> Arc<StructData> {
111 let loc = id.lookup(db); 111 let loc = id.lookup(db);
112 let krate = loc.container.krate; 112 let krate = loc.container.krate;
113 let item_tree = db.item_tree(loc.id.file_id); 113 let item_tree = loc.id.item_tree(db);
114 let repr = repr_from_value(db, krate, &item_tree, ModItem::from(loc.id.value).into()); 114 let repr = repr_from_value(db, krate, &item_tree, ModItem::from(loc.id.value).into());
115 let cfg_options = db.crate_graph()[loc.container.krate].cfg_options.clone(); 115 let cfg_options = db.crate_graph()[loc.container.krate].cfg_options.clone();
116 116
@@ -130,7 +130,7 @@ impl EnumData {
130 pub(crate) fn enum_data_query(db: &dyn DefDatabase, e: EnumId) -> Arc<EnumData> { 130 pub(crate) fn enum_data_query(db: &dyn DefDatabase, e: EnumId) -> Arc<EnumData> {
131 let loc = e.lookup(db); 131 let loc = e.lookup(db);
132 let krate = loc.container.krate; 132 let krate = loc.container.krate;
133 let item_tree = db.item_tree(loc.id.file_id); 133 let item_tree = loc.id.item_tree(db);
134 let cfg_options = db.crate_graph()[krate].cfg_options.clone(); 134 let cfg_options = db.crate_graph()[krate].cfg_options.clone();
135 135
136 let enum_ = &item_tree[loc.id.value]; 136 let enum_ = &item_tree[loc.id.value];
diff --git a/crates/hir_def/src/attr.rs b/crates/hir_def/src/attr.rs
index b0b4b5052..e4c84afbf 100644
--- a/crates/hir_def/src/attr.rs
+++ b/crates/hir_def/src/attr.rs
@@ -76,37 +76,23 @@ impl ops::Deref for Attrs {
76impl RawAttrs { 76impl RawAttrs {
77 pub(crate) const EMPTY: Self = Self { entries: None }; 77 pub(crate) const EMPTY: Self = Self { entries: None };
78 78
79 pub(crate) fn new(owner: &dyn AttrsOwner, hygiene: &Hygiene) -> Self { 79 pub(crate) fn new(owner: &dyn ast::AttrsOwner, hygiene: &Hygiene) -> Self {
80 let attrs: Vec<_> = collect_attrs(owner).collect(); 80 let entries = collect_attrs(owner)
81 let entries = if attrs.is_empty() { 81 .enumerate()
82 // Avoid heap allocation 82 .flat_map(|(i, attr)| match attr {
83 None 83 Either::Left(attr) => Attr::from_src(attr, hygiene, i as u32),
84 } else { 84 Either::Right(comment) => comment.doc_comment().map(|doc| Attr {
85 Some( 85 index: i as u32,
86 attrs 86 input: Some(AttrInput::Literal(SmolStr::new(doc))),
87 .into_iter() 87 path: ModPath::from(hir_expand::name!(doc)),
88 .enumerate() 88 }),
89 .flat_map(|(i, attr)| match attr { 89 })
90 Either::Left(attr) => Attr::from_src(attr, hygiene).map(|attr| (i, attr)), 90 .collect::<Arc<_>>();
91 Either::Right(comment) => comment.doc_comment().map(|doc| { 91
92 ( 92 Self { entries: if entries.is_empty() { None } else { Some(entries) } }
93 i,
94 Attr {
95 index: 0,
96 input: Some(AttrInput::Literal(SmolStr::new(doc))),
97 path: ModPath::from(hir_expand::name!(doc)),
98 },
99 )
100 }),
101 })
102 .map(|(i, attr)| Attr { index: i as u32, ..attr })
103 .collect(),
104 )
105 };
106 Self { entries }
107 } 93 }
108 94
109 fn from_attrs_owner(db: &dyn DefDatabase, owner: InFile<&dyn AttrsOwner>) -> Self { 95 fn from_attrs_owner(db: &dyn DefDatabase, owner: InFile<&dyn ast::AttrsOwner>) -> Self {
110 let hygiene = Hygiene::new(db.upcast(), owner.file_id); 96 let hygiene = Hygiene::new(db.upcast(), owner.file_id);
111 Self::new(owner.value, &hygiene) 97 Self::new(owner.value, &hygiene)
112 } 98 }
@@ -136,16 +122,15 @@ impl RawAttrs {
136 let new_attrs = self 122 let new_attrs = self
137 .iter() 123 .iter()
138 .flat_map(|attr| -> SmallVec<[_; 1]> { 124 .flat_map(|attr| -> SmallVec<[_; 1]> {
139 let attr = attr.clone();
140 let is_cfg_attr = 125 let is_cfg_attr =
141 attr.path.as_ident().map_or(false, |name| *name == hir_expand::name![cfg_attr]); 126 attr.path.as_ident().map_or(false, |name| *name == hir_expand::name![cfg_attr]);
142 if !is_cfg_attr { 127 if !is_cfg_attr {
143 return smallvec![attr]; 128 return smallvec![attr.clone()];
144 } 129 }
145 130
146 let subtree = match &attr.input { 131 let subtree = match &attr.input {
147 Some(AttrInput::TokenTree(it)) => it, 132 Some(AttrInput::TokenTree(it)) => it,
148 _ => return smallvec![attr], 133 _ => return smallvec![attr.clone()],
149 }; 134 };
150 135
151 // Input subtree is: `(cfg, $(attr),+)` 136 // Input subtree is: `(cfg, $(attr),+)`
@@ -157,11 +142,13 @@ impl RawAttrs {
157 let cfg = parts.next().unwrap(); 142 let cfg = parts.next().unwrap();
158 let cfg = Subtree { delimiter: subtree.delimiter, token_trees: cfg.to_vec() }; 143 let cfg = Subtree { delimiter: subtree.delimiter, token_trees: cfg.to_vec() };
159 let cfg = CfgExpr::parse(&cfg); 144 let cfg = CfgExpr::parse(&cfg);
145 let index = attr.index;
160 let attrs = parts.filter(|a| !a.is_empty()).filter_map(|attr| { 146 let attrs = parts.filter(|a| !a.is_empty()).filter_map(|attr| {
161 let tree = Subtree { delimiter: None, token_trees: attr.to_vec() }; 147 let tree = Subtree { delimiter: None, token_trees: attr.to_vec() };
162 let attr = ast::Attr::parse(&format!("#[{}]", tree)).ok()?; 148 let attr = ast::Attr::parse(&format!("#[{}]", tree)).ok()?;
163 let hygiene = Hygiene::new_unhygienic(); // FIXME 149 // FIXME hygiene
164 Attr::from_src(attr, &hygiene) 150 let hygiene = Hygiene::new_unhygienic();
151 Attr::from_src(attr, &hygiene, index)
165 }); 152 });
166 153
167 let cfg_options = &crate_graph[krate].cfg_options; 154 let cfg_options = &crate_graph[krate].cfg_options;
@@ -191,7 +178,7 @@ impl Attrs {
191 Some(it) => { 178 Some(it) => {
192 let raw_attrs = RawAttrs::from_attrs_owner( 179 let raw_attrs = RawAttrs::from_attrs_owner(
193 db, 180 db,
194 it.as_ref().map(|it| it as &dyn AttrsOwner), 181 it.as_ref().map(|it| it as &dyn ast::AttrsOwner),
195 ); 182 );
196 match mod_data.definition_source(db) { 183 match mod_data.definition_source(db) {
197 InFile { file_id, value: ModuleSource::SourceFile(file) } => raw_attrs 184 InFile { file_id, value: ModuleSource::SourceFile(file) } => raw_attrs
@@ -202,9 +189,9 @@ impl Attrs {
202 None => RawAttrs::from_attrs_owner( 189 None => RawAttrs::from_attrs_owner(
203 db, 190 db,
204 mod_data.definition_source(db).as_ref().map(|src| match src { 191 mod_data.definition_source(db).as_ref().map(|src| match src {
205 ModuleSource::SourceFile(file) => file as &dyn AttrsOwner, 192 ModuleSource::SourceFile(file) => file as &dyn ast::AttrsOwner,
206 ModuleSource::Module(module) => module as &dyn AttrsOwner, 193 ModuleSource::Module(module) => module as &dyn ast::AttrsOwner,
207 ModuleSource::BlockExpr(block) => block as &dyn AttrsOwner, 194 ModuleSource::BlockExpr(block) => block as &dyn ast::AttrsOwner,
208 }), 195 }),
209 ), 196 ),
210 } 197 }
@@ -262,7 +249,7 @@ impl Attrs {
262 let mut res = ArenaMap::default(); 249 let mut res = ArenaMap::default();
263 250
264 for (id, var) in src.value.iter() { 251 for (id, var) in src.value.iter() {
265 let attrs = RawAttrs::from_attrs_owner(db, src.with_value(var as &dyn AttrsOwner)) 252 let attrs = RawAttrs::from_attrs_owner(db, src.with_value(var as &dyn ast::AttrsOwner))
266 .filter(db, krate); 253 .filter(db, krate);
267 254
268 res.insert(id, attrs) 255 res.insert(id, attrs)
@@ -293,6 +280,13 @@ impl Attrs {
293 Arc::new(res) 280 Arc::new(res)
294 } 281 }
295 282
283 /// Constructs a map that maps the lowered `Attr`s in this `Attrs` back to its original syntax nodes.
284 ///
285 /// `owner` must be the original owner of the attributes.
286 pub fn source_map(&self, owner: &dyn ast::AttrsOwner) -> AttrSourceMap {
287 AttrSourceMap { attrs: collect_attrs(owner).collect() }
288 }
289
296 pub fn by_key(&self, key: &'static str) -> AttrQuery<'_> { 290 pub fn by_key(&self, key: &'static str) -> AttrQuery<'_> {
297 AttrQuery { attrs: self, key } 291 AttrQuery { attrs: self, key }
298 } 292 }
@@ -317,15 +311,34 @@ impl Attrs {
317 AttrInput::Literal(s) => Some(s), 311 AttrInput::Literal(s) => Some(s),
318 AttrInput::TokenTree(_) => None, 312 AttrInput::TokenTree(_) => None,
319 }); 313 });
320 // FIXME: Replace `Itertools::intersperse` with `Iterator::intersperse[_with]` until the 314 let indent = docs
321 // libstd api gets stabilized (https://github.com/rust-lang/rust/issues/79524). 315 .clone()
322 let docs = Itertools::intersperse(docs, &SmolStr::new_inline("\n")) 316 .flat_map(|s| s.lines())
323 .map(|it| it.as_str()) 317 .filter(|line| !line.chars().all(|c| c.is_whitespace()))
324 .collect::<String>(); 318 .map(|line| line.chars().take_while(|c| c.is_whitespace()).count())
325 if docs.is_empty() { 319 .min()
320 .unwrap_or(0);
321 let mut buf = String::new();
322 for doc in docs {
323 // str::lines doesn't yield anything for the empty string
324 if !doc.is_empty() {
325 buf.extend(Itertools::intersperse(
326 doc.lines().map(|line| {
327 line.char_indices()
328 .nth(indent)
329 .map_or(line, |(offset, _)| &line[offset..])
330 .trim_end()
331 }),
332 "\n",
333 ));
334 }
335 buf.push('\n');
336 }
337 buf.pop();
338 if buf.is_empty() {
326 None 339 None
327 } else { 340 } else {
328 Some(Documentation(docs)) 341 Some(Documentation(buf))
329 } 342 }
330 } 343 }
331} 344}
@@ -365,6 +378,24 @@ fn inner_attributes(
365 Some((attrs, docs)) 378 Some((attrs, docs))
366} 379}
367 380
381pub struct AttrSourceMap {
382 attrs: Vec<Either<ast::Attr, ast::Comment>>,
383}
384
385impl AttrSourceMap {
386 /// Maps the lowered `Attr` back to its original syntax node.
387 ///
388 /// `attr` must come from the `owner` used for AttrSourceMap
389 ///
390 /// Note that the returned syntax node might be a `#[cfg_attr]`, or a doc comment, instead of
391 /// the attribute represented by `Attr`.
392 pub fn source_of(&self, attr: &Attr) -> &Either<ast::Attr, ast::Comment> {
393 self.attrs
394 .get(attr.index as usize)
395 .unwrap_or_else(|| panic!("cannot find `Attr` at index {}", attr.index))
396 }
397}
398
368#[derive(Debug, Clone, PartialEq, Eq)] 399#[derive(Debug, Clone, PartialEq, Eq)]
369pub struct Attr { 400pub struct Attr {
370 index: u32, 401 index: u32,
@@ -381,7 +412,7 @@ pub enum AttrInput {
381} 412}
382 413
383impl Attr { 414impl Attr {
384 fn from_src(ast: ast::Attr, hygiene: &Hygiene) -> Option<Attr> { 415 fn from_src(ast: ast::Attr, hygiene: &Hygiene, index: u32) -> Option<Attr> {
385 let path = ModPath::from_src(ast.path()?, hygiene)?; 416 let path = ModPath::from_src(ast.path()?, hygiene)?;
386 let input = if let Some(lit) = ast.literal() { 417 let input = if let Some(lit) = ast.literal() {
387 let value = match lit.kind() { 418 let value = match lit.kind() {
@@ -394,7 +425,7 @@ impl Attr {
394 } else { 425 } else {
395 None 426 None
396 }; 427 };
397 Some(Attr { index: 0, path, input }) 428 Some(Attr { index, path, input })
398 } 429 }
399 430
400 /// Maps this lowered `Attr` back to its original syntax node. 431 /// Maps this lowered `Attr` back to its original syntax node.
@@ -403,7 +434,7 @@ impl Attr {
403 /// 434 ///
404 /// Note that the returned syntax node might be a `#[cfg_attr]`, or a doc comment, instead of 435 /// Note that the returned syntax node might be a `#[cfg_attr]`, or a doc comment, instead of
405 /// the attribute represented by `Attr`. 436 /// the attribute represented by `Attr`.
406 pub fn to_src(&self, owner: &dyn AttrsOwner) -> Either<ast::Attr, ast::Comment> { 437 pub fn to_src(&self, owner: &dyn ast::AttrsOwner) -> Either<ast::Attr, ast::Comment> {
407 collect_attrs(owner).nth(self.index as usize).unwrap_or_else(|| { 438 collect_attrs(owner).nth(self.index as usize).unwrap_or_else(|| {
408 panic!("cannot find `Attr` at index {} in {}", self.index, owner.syntax()) 439 panic!("cannot find `Attr` at index {} in {}", self.index, owner.syntax())
409 }) 440 })
@@ -448,6 +479,13 @@ impl Attr {
448 _ => None, 479 _ => None,
449 } 480 }
450 } 481 }
482
483 pub fn string_value(&self) -> Option<&SmolStr> {
484 match self.input.as_ref()? {
485 AttrInput::Literal(it) => Some(it),
486 _ => None,
487 }
488 }
451} 489}
452 490
453#[derive(Debug, Clone, Copy)] 491#[derive(Debug, Clone, Copy)]
@@ -475,7 +513,7 @@ impl<'a> AttrQuery<'a> {
475 self.attrs().next().is_some() 513 self.attrs().next().is_some()
476 } 514 }
477 515
478 pub(crate) fn attrs(self) -> impl Iterator<Item = &'a Attr> { 516 pub fn attrs(self) -> impl Iterator<Item = &'a Attr> + Clone {
479 let key = self.key; 517 let key = self.key;
480 self.attrs 518 self.attrs
481 .iter() 519 .iter()
@@ -488,16 +526,18 @@ where
488 N: ast::AttrsOwner, 526 N: ast::AttrsOwner,
489{ 527{
490 let src = InFile::new(src.file_id, src.to_node(db.upcast())); 528 let src = InFile::new(src.file_id, src.to_node(db.upcast()));
491 RawAttrs::from_attrs_owner(db, src.as_ref().map(|it| it as &dyn AttrsOwner)) 529 RawAttrs::from_attrs_owner(db, src.as_ref().map(|it| it as &dyn ast::AttrsOwner))
492} 530}
493 531
494fn attrs_from_item_tree<N: ItemTreeNode>(id: ItemTreeId<N>, db: &dyn DefDatabase) -> RawAttrs { 532fn attrs_from_item_tree<N: ItemTreeNode>(id: ItemTreeId<N>, db: &dyn DefDatabase) -> RawAttrs {
495 let tree = db.item_tree(id.file_id); 533 let tree = id.item_tree(db);
496 let mod_item = N::id_to_mod_item(id.value); 534 let mod_item = N::id_to_mod_item(id.value);
497 tree.raw_attrs(mod_item.into()).clone() 535 tree.raw_attrs(mod_item.into()).clone()
498} 536}
499 537
500fn collect_attrs(owner: &dyn AttrsOwner) -> impl Iterator<Item = Either<ast::Attr, ast::Comment>> { 538fn collect_attrs(
539 owner: &dyn ast::AttrsOwner,
540) -> impl Iterator<Item = Either<ast::Attr, ast::Comment>> {
501 let (inner_attrs, inner_docs) = inner_attributes(owner.syntax()) 541 let (inner_attrs, inner_docs) = inner_attributes(owner.syntax())
502 .map_or((None, None), |(attrs, docs)| ((Some(attrs), Some(docs)))); 542 .map_or((None, None), |(attrs, docs)| ((Some(attrs), Some(docs))));
503 543
diff --git a/crates/hir_def/src/body/lower.rs b/crates/hir_def/src/body/lower.rs
index 60b25db56..19f5065d1 100644
--- a/crates/hir_def/src/body/lower.rs
+++ b/crates/hir_def/src/body/lower.rs
@@ -177,12 +177,15 @@ impl ExprCollector<'_> {
177 } 177 }
178 178
179 fn collect_expr(&mut self, expr: ast::Expr) -> ExprId { 179 fn collect_expr(&mut self, expr: ast::Expr) -> ExprId {
180 self.maybe_collect_expr(expr).unwrap_or_else(|| self.missing_expr())
181 }
182
183 /// Returns `None` if the expression is `#[cfg]`d out.
184 fn maybe_collect_expr(&mut self, expr: ast::Expr) -> Option<ExprId> {
180 let syntax_ptr = AstPtr::new(&expr); 185 let syntax_ptr = AstPtr::new(&expr);
181 if self.check_cfg(&expr).is_none() { 186 self.check_cfg(&expr)?;
182 return self.missing_expr();
183 }
184 187
185 match expr { 188 Some(match expr {
186 ast::Expr::IfExpr(e) => { 189 ast::Expr::IfExpr(e) => {
187 let then_branch = self.collect_block_opt(e.then_branch()); 190 let then_branch = self.collect_block_opt(e.then_branch());
188 191
@@ -211,8 +214,9 @@ impl ExprCollector<'_> {
211 guard: None, 214 guard: None,
212 }, 215 },
213 ]; 216 ];
214 return self 217 return Some(
215 .alloc_expr(Expr::Match { expr: match_expr, arms }, syntax_ptr); 218 self.alloc_expr(Expr::Match { expr: match_expr, arms }, syntax_ptr),
219 );
216 } 220 }
217 }, 221 },
218 }; 222 };
@@ -283,8 +287,9 @@ impl ExprCollector<'_> {
283 ]; 287 ];
284 let match_expr = 288 let match_expr =
285 self.alloc_expr_desugared(Expr::Match { expr: match_expr, arms }); 289 self.alloc_expr_desugared(Expr::Match { expr: match_expr, arms });
286 return self 290 return Some(
287 .alloc_expr(Expr::Loop { body: match_expr, label }, syntax_ptr); 291 self.alloc_expr(Expr::Loop { body: match_expr, label }, syntax_ptr),
292 );
288 } 293 }
289 }, 294 },
290 }; 295 };
@@ -301,7 +306,7 @@ impl ExprCollector<'_> {
301 ast::Expr::CallExpr(e) => { 306 ast::Expr::CallExpr(e) => {
302 let callee = self.collect_expr_opt(e.expr()); 307 let callee = self.collect_expr_opt(e.expr());
303 let args = if let Some(arg_list) = e.arg_list() { 308 let args = if let Some(arg_list) = e.arg_list() {
304 arg_list.args().map(|e| self.collect_expr(e)).collect() 309 arg_list.args().filter_map(|e| self.maybe_collect_expr(e)).collect()
305 } else { 310 } else {
306 Vec::new() 311 Vec::new()
307 }; 312 };
@@ -310,7 +315,7 @@ impl ExprCollector<'_> {
310 ast::Expr::MethodCallExpr(e) => { 315 ast::Expr::MethodCallExpr(e) => {
311 let receiver = self.collect_expr_opt(e.receiver()); 316 let receiver = self.collect_expr_opt(e.receiver());
312 let args = if let Some(arg_list) = e.arg_list() { 317 let args = if let Some(arg_list) = e.arg_list() {
313 arg_list.args().map(|e| self.collect_expr(e)).collect() 318 arg_list.args().filter_map(|e| self.maybe_collect_expr(e)).collect()
314 } else { 319 } else {
315 Vec::new() 320 Vec::new()
316 }; 321 };
@@ -538,7 +543,7 @@ impl ExprCollector<'_> {
538 self.alloc_expr(Expr::Missing, syntax_ptr) 543 self.alloc_expr(Expr::Missing, syntax_ptr)
539 } 544 }
540 } 545 }
541 } 546 })
542 } 547 }
543 548
544 fn collect_macro_call<F: FnMut(&mut Self, Option<T>), T: ast::AstNode>( 549 fn collect_macro_call<F: FnMut(&mut Self, Option<T>), T: ast::AstNode>(
diff --git a/crates/hir_def/src/body/tests.rs b/crates/hir_def/src/body/tests.rs
index f8e6f70e8..faa133297 100644
--- a/crates/hir_def/src/body/tests.rs
+++ b/crates/hir_def/src/body/tests.rs
@@ -137,7 +137,7 @@ fn f() {
137 include!(invalid); 137 include!(invalid);
138 //^^^^^^^^^^^^^^^^^ could not convert tokens 138 //^^^^^^^^^^^^^^^^^ could not convert tokens
139 include!("does not exist"); 139 include!("does not exist");
140 //^^^^^^^^^^^^^^^^^^^^^^^^^^ could not convert tokens 140 //^^^^^^^^^^^^^^^^^^^^^^^^^^ failed to load file `does not exist`
141 141
142 env!(invalid); 142 env!(invalid);
143 //^^^^^^^^^^^^^ could not convert tokens 143 //^^^^^^^^^^^^^ could not convert tokens
diff --git a/crates/hir_def/src/data.rs b/crates/hir_def/src/data.rs
index 1a27f7bf2..0be868ba2 100644
--- a/crates/hir_def/src/data.rs
+++ b/crates/hir_def/src/data.rs
@@ -9,7 +9,7 @@ use crate::{
9 attr::Attrs, 9 attr::Attrs,
10 body::Expander, 10 body::Expander,
11 db::DefDatabase, 11 db::DefDatabase,
12 item_tree::{AssocItem, FunctionQualifier, ItemTreeId, ModItem}, 12 item_tree::{AssocItem, FunctionQualifier, ItemTreeId, ModItem, Param},
13 type_ref::{TypeBound, TypeRef}, 13 type_ref::{TypeBound, TypeRef},
14 visibility::RawVisibility, 14 visibility::RawVisibility,
15 AssocContainerId, AssocItemId, ConstId, ConstLoc, FunctionId, FunctionLoc, HasModule, ImplId, 15 AssocContainerId, AssocItemId, ConstId, ConstLoc, FunctionId, FunctionLoc, HasModule, ImplId,
@@ -36,19 +36,38 @@ impl 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 krate = loc.container.module(db).krate;
39 let item_tree = db.item_tree(loc.id.file_id); 39 let crate_graph = db.crate_graph();
40 let cfg_options = &crate_graph[krate].cfg_options;
41 let item_tree = loc.id.item_tree(db);
40 let func = &item_tree[loc.id.value]; 42 let func = &item_tree[loc.id.value];
41 43
44 let enabled_params = func
45 .params
46 .clone()
47 .filter(|&param| item_tree.attrs(db, krate, param.into()).is_cfg_enabled(cfg_options));
48
49 // If last cfg-enabled param is a `...` param, it's a varargs function.
50 let is_varargs = enabled_params
51 .clone()
52 .next_back()
53 .map_or(false, |param| matches!(item_tree[param], Param::Varargs));
54
42 Arc::new(FunctionData { 55 Arc::new(FunctionData {
43 name: func.name.clone(), 56 name: func.name.clone(),
44 params: func.params.iter().map(|id| item_tree[*id].clone()).collect(), 57 params: enabled_params
58 .clone()
59 .filter_map(|id| match &item_tree[id] {
60 Param::Normal(ty) => Some(item_tree[*ty].clone()),
61 Param::Varargs => None,
62 })
63 .collect(),
45 ret_type: item_tree[func.ret_type].clone(), 64 ret_type: item_tree[func.ret_type].clone(),
46 attrs: item_tree.attrs(db, krate, ModItem::from(loc.id.value).into()), 65 attrs: item_tree.attrs(db, krate, ModItem::from(loc.id.value).into()),
47 has_self_param: func.has_self_param, 66 has_self_param: func.has_self_param,
48 has_body: func.has_body, 67 has_body: func.has_body,
49 qualifier: func.qualifier.clone(), 68 qualifier: func.qualifier.clone(),
50 is_in_extern_block: func.is_in_extern_block, 69 is_in_extern_block: func.is_in_extern_block,
51 is_varargs: func.is_varargs, 70 is_varargs,
52 visibility: item_tree[func.visibility].clone(), 71 visibility: item_tree[func.visibility].clone(),
53 }) 72 })
54 } 73 }
@@ -70,7 +89,7 @@ impl TypeAliasData {
70 typ: TypeAliasId, 89 typ: TypeAliasId,
71 ) -> Arc<TypeAliasData> { 90 ) -> Arc<TypeAliasData> {
72 let loc = typ.lookup(db); 91 let loc = typ.lookup(db);
73 let item_tree = db.item_tree(loc.id.file_id); 92 let item_tree = loc.id.item_tree(db);
74 let typ = &item_tree[loc.id.value]; 93 let typ = &item_tree[loc.id.value];
75 94
76 Arc::new(TypeAliasData { 95 Arc::new(TypeAliasData {
@@ -96,23 +115,23 @@ pub struct TraitData {
96impl TraitData { 115impl TraitData {
97 pub(crate) fn trait_data_query(db: &dyn DefDatabase, tr: TraitId) -> Arc<TraitData> { 116 pub(crate) fn trait_data_query(db: &dyn DefDatabase, tr: TraitId) -> Arc<TraitData> {
98 let tr_loc = tr.lookup(db); 117 let tr_loc = tr.lookup(db);
99 let item_tree = db.item_tree(tr_loc.id.file_id); 118 let item_tree = tr_loc.id.item_tree(db);
100 let tr_def = &item_tree[tr_loc.id.value]; 119 let tr_def = &item_tree[tr_loc.id.value];
101 let name = tr_def.name.clone(); 120 let name = tr_def.name.clone();
102 let is_auto = tr_def.is_auto; 121 let is_auto = tr_def.is_auto;
103 let is_unsafe = tr_def.is_unsafe; 122 let is_unsafe = tr_def.is_unsafe;
104 let module_id = tr_loc.container; 123 let module_id = tr_loc.container;
105 let container = AssocContainerId::TraitId(tr); 124 let container = AssocContainerId::TraitId(tr);
106 let mut expander = Expander::new(db, tr_loc.id.file_id, module_id);
107 let visibility = item_tree[tr_def.visibility].clone(); 125 let visibility = item_tree[tr_def.visibility].clone();
108 let bounds = tr_def.bounds.clone(); 126 let bounds = tr_def.bounds.clone();
127 let mut expander = Expander::new(db, tr_loc.id.file_id(), module_id);
109 128
110 let items = collect_items( 129 let items = collect_items(
111 db, 130 db,
112 module_id, 131 module_id,
113 &mut expander, 132 &mut expander,
114 tr_def.items.iter().copied(), 133 tr_def.items.iter().copied(),
115 tr_loc.id.file_id, 134 tr_loc.id.file_id(),
116 container, 135 container,
117 100, 136 100,
118 ); 137 );
@@ -148,21 +167,21 @@ impl ImplData {
148 let _p = profile::span("impl_data_query"); 167 let _p = profile::span("impl_data_query");
149 let impl_loc = id.lookup(db); 168 let impl_loc = id.lookup(db);
150 169
151 let item_tree = db.item_tree(impl_loc.id.file_id); 170 let item_tree = impl_loc.id.item_tree(db);
152 let impl_def = &item_tree[impl_loc.id.value]; 171 let impl_def = &item_tree[impl_loc.id.value];
153 let target_trait = impl_def.target_trait.map(|id| item_tree[id].clone()); 172 let target_trait = impl_def.target_trait.map(|id| item_tree[id].clone());
154 let target_type = item_tree[impl_def.target_type].clone(); 173 let target_type = item_tree[impl_def.target_type].clone();
155 let is_negative = impl_def.is_negative; 174 let is_negative = impl_def.is_negative;
156 let module_id = impl_loc.container; 175 let module_id = impl_loc.container;
157 let container = AssocContainerId::ImplId(id); 176 let container = AssocContainerId::ImplId(id);
158 let mut expander = Expander::new(db, impl_loc.id.file_id, module_id); 177 let mut expander = Expander::new(db, impl_loc.id.file_id(), module_id);
159 178
160 let items = collect_items( 179 let items = collect_items(
161 db, 180 db,
162 module_id, 181 module_id,
163 &mut expander, 182 &mut expander,
164 impl_def.items.iter().copied(), 183 impl_def.items.iter().copied(),
165 impl_loc.id.file_id, 184 impl_loc.id.file_id(),
166 container, 185 container,
167 100, 186 100,
168 ); 187 );
@@ -183,7 +202,7 @@ pub struct ConstData {
183impl ConstData { 202impl ConstData {
184 pub(crate) fn const_data_query(db: &dyn DefDatabase, konst: ConstId) -> Arc<ConstData> { 203 pub(crate) fn const_data_query(db: &dyn DefDatabase, konst: ConstId) -> Arc<ConstData> {
185 let loc = konst.lookup(db); 204 let loc = konst.lookup(db);
186 let item_tree = db.item_tree(loc.id.file_id); 205 let item_tree = loc.id.item_tree(db);
187 let konst = &item_tree[loc.id.value]; 206 let konst = &item_tree[loc.id.value];
188 207
189 Arc::new(ConstData { 208 Arc::new(ConstData {
@@ -206,7 +225,7 @@ pub struct StaticData {
206impl StaticData { 225impl StaticData {
207 pub(crate) fn static_data_query(db: &dyn DefDatabase, konst: StaticId) -> Arc<StaticData> { 226 pub(crate) fn static_data_query(db: &dyn DefDatabase, konst: StaticId) -> Arc<StaticData> {
208 let node = konst.lookup(db); 227 let node = konst.lookup(db);
209 let item_tree = db.item_tree(node.id.file_id); 228 let item_tree = node.id.item_tree(db);
210 let statik = &item_tree[node.id.value]; 229 let statik = &item_tree[node.id.value];
211 230
212 Arc::new(StaticData { 231 Arc::new(StaticData {
@@ -232,22 +251,23 @@ fn collect_items(
232 return Vec::new(); 251 return Vec::new();
233 } 252 }
234 253
235 let item_tree = db.item_tree(file_id); 254 let item_tree = db.file_item_tree(file_id);
236 let cfg_options = db.crate_graph()[module.krate].cfg_options.clone(); 255 let crate_graph = db.crate_graph();
256 let cfg_options = &crate_graph[module.krate].cfg_options;
237 257
238 let mut items = Vec::new(); 258 let mut items = Vec::new();
239 for item in assoc_items { 259 for item in assoc_items {
260 let attrs = item_tree.attrs(db, module.krate, ModItem::from(item).into());
261 if !attrs.is_cfg_enabled(cfg_options) {
262 continue;
263 }
264
240 match item { 265 match item {
241 AssocItem::Function(id) => { 266 AssocItem::Function(id) => {
242 let item = &item_tree[id]; 267 let item = &item_tree[id];
243 let attrs = item_tree.attrs(db, module.krate, ModItem::from(id).into());
244 if !attrs.is_cfg_enabled(&cfg_options) {
245 continue;
246 }
247 let def = FunctionLoc { container, id: ItemTreeId::new(file_id, id) }.intern(db); 268 let def = FunctionLoc { container, id: ItemTreeId::new(file_id, id) }.intern(db);
248 items.push((item.name.clone(), def.into())); 269 items.push((item.name.clone(), def.into()));
249 } 270 }
250 // FIXME: cfg?
251 AssocItem::Const(id) => { 271 AssocItem::Const(id) => {
252 let item = &item_tree[id]; 272 let item = &item_tree[id];
253 let name = match item.name.clone() { 273 let name = match item.name.clone() {
@@ -272,7 +292,7 @@ fn collect_items(
272 if let Ok(res) = res { 292 if let Ok(res) = res {
273 if let Some((mark, mac)) = res.value { 293 if let Some((mark, mac)) = res.value {
274 let src: InFile<ast::MacroItems> = expander.to_source(mac); 294 let src: InFile<ast::MacroItems> = expander.to_source(mac);
275 let item_tree = db.item_tree(src.file_id); 295 let item_tree = db.file_item_tree(src.file_id);
276 let iter = 296 let iter =
277 item_tree.top_level_items().iter().filter_map(ModItem::as_assoc_item); 297 item_tree.top_level_items().iter().filter_map(ModItem::as_assoc_item);
278 items.extend(collect_items( 298 items.extend(collect_items(
diff --git a/crates/hir_def/src/db.rs b/crates/hir_def/src/db.rs
index cca5a086b..276caf5b3 100644
--- a/crates/hir_def/src/db.rs
+++ b/crates/hir_def/src/db.rs
@@ -48,8 +48,8 @@ pub trait InternDatabase: SourceDatabase {
48 48
49#[salsa::query_group(DefDatabaseStorage)] 49#[salsa::query_group(DefDatabaseStorage)]
50pub trait DefDatabase: InternDatabase + AstDatabase + Upcast<dyn AstDatabase> { 50pub trait DefDatabase: InternDatabase + AstDatabase + Upcast<dyn AstDatabase> {
51 #[salsa::invoke(ItemTree::item_tree_query)] 51 #[salsa::invoke(ItemTree::file_item_tree_query)]
52 fn item_tree(&self, file_id: HirFileId) -> Arc<ItemTree>; 52 fn file_item_tree(&self, file_id: HirFileId) -> Arc<ItemTree>;
53 53
54 #[salsa::invoke(crate_def_map_wait)] 54 #[salsa::invoke(crate_def_map_wait)]
55 #[salsa::transparent] 55 #[salsa::transparent]
diff --git a/crates/hir_def/src/generics.rs b/crates/hir_def/src/generics.rs
index a056ab797..7c6cbff11 100644
--- a/crates/hir_def/src/generics.rs
+++ b/crates/hir_def/src/generics.rs
@@ -97,43 +97,43 @@ impl GenericParams {
97 let generics = match def { 97 let generics = match def {
98 GenericDefId::FunctionId(id) => { 98 GenericDefId::FunctionId(id) => {
99 let id = id.lookup(db).id; 99 let id = id.lookup(db).id;
100 let tree = db.item_tree(id.file_id); 100 let tree = id.item_tree(db);
101 let item = &tree[id.value]; 101 let item = &tree[id.value];
102 tree[item.generic_params].clone() 102 tree[item.generic_params].clone()
103 } 103 }
104 GenericDefId::AdtId(AdtId::StructId(id)) => { 104 GenericDefId::AdtId(AdtId::StructId(id)) => {
105 let id = id.lookup(db).id; 105 let id = id.lookup(db).id;
106 let tree = db.item_tree(id.file_id); 106 let tree = id.item_tree(db);
107 let item = &tree[id.value]; 107 let item = &tree[id.value];
108 tree[item.generic_params].clone() 108 tree[item.generic_params].clone()
109 } 109 }
110 GenericDefId::AdtId(AdtId::EnumId(id)) => { 110 GenericDefId::AdtId(AdtId::EnumId(id)) => {
111 let id = id.lookup(db).id; 111 let id = id.lookup(db).id;
112 let tree = db.item_tree(id.file_id); 112 let tree = id.item_tree(db);
113 let item = &tree[id.value]; 113 let item = &tree[id.value];
114 tree[item.generic_params].clone() 114 tree[item.generic_params].clone()
115 } 115 }
116 GenericDefId::AdtId(AdtId::UnionId(id)) => { 116 GenericDefId::AdtId(AdtId::UnionId(id)) => {
117 let id = id.lookup(db).id; 117 let id = id.lookup(db).id;
118 let tree = db.item_tree(id.file_id); 118 let tree = id.item_tree(db);
119 let item = &tree[id.value]; 119 let item = &tree[id.value];
120 tree[item.generic_params].clone() 120 tree[item.generic_params].clone()
121 } 121 }
122 GenericDefId::TraitId(id) => { 122 GenericDefId::TraitId(id) => {
123 let id = id.lookup(db).id; 123 let id = id.lookup(db).id;
124 let tree = db.item_tree(id.file_id); 124 let tree = id.item_tree(db);
125 let item = &tree[id.value]; 125 let item = &tree[id.value];
126 tree[item.generic_params].clone() 126 tree[item.generic_params].clone()
127 } 127 }
128 GenericDefId::TypeAliasId(id) => { 128 GenericDefId::TypeAliasId(id) => {
129 let id = id.lookup(db).id; 129 let id = id.lookup(db).id;
130 let tree = db.item_tree(id.file_id); 130 let tree = id.item_tree(db);
131 let item = &tree[id.value]; 131 let item = &tree[id.value];
132 tree[item.generic_params].clone() 132 tree[item.generic_params].clone()
133 } 133 }
134 GenericDefId::ImplId(id) => { 134 GenericDefId::ImplId(id) => {
135 let id = id.lookup(db).id; 135 let id = id.lookup(db).id;
136 let tree = db.item_tree(id.file_id); 136 let tree = id.item_tree(db);
137 let item = &tree[id.value]; 137 let item = &tree[id.value];
138 tree[item.generic_params].clone() 138 tree[item.generic_params].clone()
139 } 139 }
diff --git a/crates/hir_def/src/item_tree.rs b/crates/hir_def/src/item_tree.rs
index 4477bdd36..ae2475b4e 100644
--- a/crates/hir_def/src/item_tree.rs
+++ b/crates/hir_def/src/item_tree.rs
@@ -76,7 +76,7 @@ pub struct ItemTree {
76} 76}
77 77
78impl ItemTree { 78impl ItemTree {
79 pub(crate) fn item_tree_query(db: &dyn DefDatabase, file_id: HirFileId) -> Arc<ItemTree> { 79 pub(crate) fn file_item_tree_query(db: &dyn DefDatabase, file_id: HirFileId) -> Arc<ItemTree> {
80 let _p = profile::span("item_tree_query").detail(|| format!("{:?}", file_id)); 80 let _p = profile::span("item_tree_query").detail(|| format!("{:?}", file_id));
81 let syntax = if let Some(node) = db.parse_or_expand(file_id) { 81 let syntax = if let Some(node) = db.parse_or_expand(file_id) {
82 if node.kind() == SyntaxKind::ERROR { 82 if node.kind() == SyntaxKind::ERROR {
@@ -138,6 +138,7 @@ impl ItemTree {
138 imports, 138 imports,
139 extern_crates, 139 extern_crates,
140 functions, 140 functions,
141 params,
141 structs, 142 structs,
142 fields, 143 fields,
143 unions, 144 unions,
@@ -161,6 +162,7 @@ impl ItemTree {
161 imports.shrink_to_fit(); 162 imports.shrink_to_fit();
162 extern_crates.shrink_to_fit(); 163 extern_crates.shrink_to_fit();
163 functions.shrink_to_fit(); 164 functions.shrink_to_fit();
165 params.shrink_to_fit();
164 structs.shrink_to_fit(); 166 structs.shrink_to_fit();
165 fields.shrink_to_fit(); 167 fields.shrink_to_fit();
166 unions.shrink_to_fit(); 168 unions.shrink_to_fit();
@@ -307,6 +309,7 @@ struct ItemTreeData {
307 imports: Arena<Import>, 309 imports: Arena<Import>,
308 extern_crates: Arena<ExternCrate>, 310 extern_crates: Arena<ExternCrate>,
309 functions: Arena<Function>, 311 functions: Arena<Function>,
312 params: Arena<Param>,
310 structs: Arena<Struct>, 313 structs: Arena<Struct>,
311 fields: Arena<Field>, 314 fields: Arena<Field>,
312 unions: Arena<Union>, 315 unions: Arena<Union>,
@@ -338,6 +341,7 @@ pub enum AttrOwner {
338 341
339 Variant(Idx<Variant>), 342 Variant(Idx<Variant>),
340 Field(Idx<Field>), 343 Field(Idx<Field>),
344 Param(Idx<Param>),
341} 345}
342 346
343macro_rules! from_attrs { 347macro_rules! from_attrs {
@@ -352,7 +356,7 @@ macro_rules! from_attrs {
352 }; 356 };
353} 357}
354 358
355from_attrs!(ModItem(ModItem), Variant(Idx<Variant>), Field(Idx<Field>)); 359from_attrs!(ModItem(ModItem), Variant(Idx<Variant>), Field(Idx<Field>), Param(Idx<Param>));
356 360
357/// Trait implemented by all item nodes in the item tree. 361/// Trait implemented by all item nodes in the item tree.
358pub trait ItemTreeNode: Clone { 362pub trait ItemTreeNode: Clone {
@@ -401,7 +405,47 @@ impl<N: ItemTreeNode> fmt::Debug for FileItemTreeId<N> {
401 } 405 }
402} 406}
403 407
404pub type ItemTreeId<N> = InFile<FileItemTreeId<N>>; 408#[derive(Debug)]
409pub struct ItemTreeId<N: ItemTreeNode> {
410 file: HirFileId,
411 pub value: FileItemTreeId<N>,
412}
413
414impl<N: ItemTreeNode> ItemTreeId<N> {
415 pub fn new(file: HirFileId, idx: FileItemTreeId<N>) -> Self {
416 Self { file, value: idx }
417 }
418
419 pub fn file_id(self) -> HirFileId {
420 self.file
421 }
422
423 pub fn item_tree(self, db: &dyn DefDatabase) -> Arc<ItemTree> {
424 db.file_item_tree(self.file)
425 }
426}
427
428impl<N: ItemTreeNode> Copy for ItemTreeId<N> {}
429impl<N: ItemTreeNode> Clone for ItemTreeId<N> {
430 fn clone(&self) -> Self {
431 *self
432 }
433}
434
435impl<N: ItemTreeNode> PartialEq for ItemTreeId<N> {
436 fn eq(&self, other: &Self) -> bool {
437 self.file == other.file && self.value == other.value
438 }
439}
440
441impl<N: ItemTreeNode> Eq for ItemTreeId<N> {}
442
443impl<N: ItemTreeNode> Hash for ItemTreeId<N> {
444 fn hash<H: Hasher>(&self, state: &mut H) {
445 self.file.hash(state);
446 self.value.hash(state);
447 }
448}
405 449
406macro_rules! mod_items { 450macro_rules! mod_items {
407 ( $( $typ:ident in $fld:ident -> $ast:ty ),+ $(,)? ) => { 451 ( $( $typ:ident in $fld:ident -> $ast:ty ),+ $(,)? ) => {
@@ -488,7 +532,7 @@ macro_rules! impl_index {
488 }; 532 };
489} 533}
490 534
491impl_index!(fields: Field, variants: Variant); 535impl_index!(fields: Field, variants: Variant, params: Param);
492 536
493impl Index<RawVisibilityId> for ItemTree { 537impl Index<RawVisibilityId> for ItemTree {
494 type Output = RawVisibility; 538 type Output = RawVisibility;
@@ -564,12 +608,17 @@ pub struct Function {
564 /// Whether the function is located in an `extern` block (*not* whether it is an 608 /// Whether the function is located in an `extern` block (*not* whether it is an
565 /// `extern "abi" fn`). 609 /// `extern "abi" fn`).
566 pub is_in_extern_block: bool, 610 pub is_in_extern_block: bool,
567 pub params: Box<[Idx<TypeRef>]>, 611 pub params: IdRange<Param>,
568 pub is_varargs: bool,
569 pub ret_type: Idx<TypeRef>, 612 pub ret_type: Idx<TypeRef>,
570 pub ast_id: FileAstId<ast::Fn>, 613 pub ast_id: FileAstId<ast::Fn>,
571} 614}
572 615
616#[derive(Debug, Clone, Eq, PartialEq)]
617pub enum Param {
618 Normal(Idx<TypeRef>),
619 Varargs,
620}
621
573#[derive(Debug, Clone, PartialEq, Eq)] 622#[derive(Debug, Clone, PartialEq, Eq)]
574pub struct FunctionQualifier { 623pub struct FunctionQualifier {
575 pub is_default: bool, 624 pub is_default: bool,
@@ -800,6 +849,7 @@ pub struct Variant {
800 pub fields: Fields, 849 pub fields: Fields,
801} 850}
802 851
852/// A range of densely allocated ItemTree IDs.
803pub struct IdRange<T> { 853pub struct IdRange<T> {
804 range: Range<u32>, 854 range: Range<u32>,
805 _p: PhantomData<T>, 855 _p: PhantomData<T>,
@@ -818,6 +868,12 @@ impl<T> Iterator for IdRange<T> {
818 } 868 }
819} 869}
820 870
871impl<T> DoubleEndedIterator for IdRange<T> {
872 fn next_back(&mut self) -> Option<Self::Item> {
873 self.range.next_back().map(|raw| Idx::from_raw(raw.into()))
874 }
875}
876
821impl<T> fmt::Debug for IdRange<T> { 877impl<T> fmt::Debug for IdRange<T> {
822 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 878 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
823 f.debug_tuple(&format!("IdRange::<{}>", type_name::<T>())).field(&self.range).finish() 879 f.debug_tuple(&format!("IdRange::<{}>", type_name::<T>())).field(&self.range).finish()
diff --git a/crates/hir_def/src/item_tree/lower.rs b/crates/hir_def/src/item_tree/lower.rs
index d684b89d0..d3fe1ce1e 100644
--- a/crates/hir_def/src/item_tree/lower.rs
+++ b/crates/hir_def/src/item_tree/lower.rs
@@ -341,8 +341,8 @@ impl Ctx {
341 let visibility = self.lower_visibility(func); 341 let visibility = self.lower_visibility(func);
342 let name = func.name()?.as_name(); 342 let name = func.name()?.as_name();
343 343
344 let mut params = Vec::new();
345 let mut has_self_param = false; 344 let mut has_self_param = false;
345 let start_param = self.next_param_idx();
346 if let Some(param_list) = func.param_list() { 346 if let Some(param_list) = func.param_list() {
347 if let Some(self_param) = param_list.self_param() { 347 if let Some(self_param) = param_list.self_param() {
348 let self_type = match self_param.ty() { 348 let self_type = match self_param.ty() {
@@ -364,22 +364,25 @@ impl Ctx {
364 } 364 }
365 } 365 }
366 }; 366 };
367 params.push(self_type); 367 let ty = self.data().type_refs.intern(self_type);
368 let idx = self.data().params.alloc(Param::Normal(ty));
369 self.add_attrs(idx.into(), RawAttrs::new(&self_param, &self.hygiene));
368 has_self_param = true; 370 has_self_param = true;
369 } 371 }
370 for param in param_list.params() { 372 for param in param_list.params() {
371 let type_ref = TypeRef::from_ast_opt(&self.body_ctx, param.ty()); 373 let idx = match param.dotdotdot_token() {
372 params.push(type_ref); 374 Some(_) => self.data().params.alloc(Param::Varargs),
373 } 375 None => {
374 } 376 let type_ref = TypeRef::from_ast_opt(&self.body_ctx, param.ty());
375 let params = params.into_iter().map(|param| self.data().type_refs.intern(param)).collect(); 377 let ty = self.data().type_refs.intern(type_ref);
376 378 self.data().params.alloc(Param::Normal(ty))
377 let mut is_varargs = false; 379 }
378 if let Some(params) = func.param_list() { 380 };
379 if let Some(last) = params.params().last() { 381 self.add_attrs(idx.into(), RawAttrs::new(&param, &self.hygiene));
380 is_varargs = last.dotdotdot_token().is_some();
381 } 382 }
382 } 383 }
384 let end_param = self.next_param_idx();
385 let params = IdRange::new(start_param..end_param);
383 386
384 let ret_type = match func.ret_type().and_then(|rt| rt.ty()) { 387 let ret_type = match func.ret_type().and_then(|rt| rt.ty()) {
385 Some(type_ref) => TypeRef::from_ast(&self.body_ctx, type_ref), 388 Some(type_ref) => TypeRef::from_ast(&self.body_ctx, type_ref),
@@ -427,7 +430,6 @@ impl Ctx {
427 qualifier, 430 qualifier,
428 is_in_extern_block: false, 431 is_in_extern_block: false,
429 params, 432 params,
430 is_varargs,
431 ret_type, 433 ret_type,
432 ast_id, 434 ast_id,
433 }; 435 };
@@ -690,9 +692,11 @@ impl Ctx {
690 GenericsOwner::Function(func) => { 692 GenericsOwner::Function(func) => {
691 generics.fill(&self.body_ctx, sm, node); 693 generics.fill(&self.body_ctx, sm, node);
692 // lower `impl Trait` in arguments 694 // lower `impl Trait` in arguments
693 for param in &*func.params { 695 for id in func.params.clone() {
694 let param = self.data().type_refs.lookup(*param); 696 if let Param::Normal(ty) = self.data().params[id] {
695 generics.fill_implicit_impl_trait_args(param); 697 let ty = self.data().type_refs.lookup(ty);
698 generics.fill_implicit_impl_trait_args(ty);
699 }
696 } 700 }
697 } 701 }
698 GenericsOwner::Struct 702 GenericsOwner::Struct
@@ -777,6 +781,11 @@ impl Ctx {
777 self.tree.data.as_ref().map_or(0, |data| data.variants.len() as u32), 781 self.tree.data.as_ref().map_or(0, |data| data.variants.len() as u32),
778 )) 782 ))
779 } 783 }
784 fn next_param_idx(&self) -> Idx<Param> {
785 Idx::from_raw(RawIdx::from(
786 self.tree.data.as_ref().map_or(0, |data| data.params.len() as u32),
787 ))
788 }
780} 789}
781 790
782fn desugar_future_path(orig: TypeRef) -> Path { 791fn desugar_future_path(orig: TypeRef) -> Path {
diff --git a/crates/hir_def/src/nameres.rs b/crates/hir_def/src/nameres.rs
index 003d668ca..c97be584e 100644
--- a/crates/hir_def/src/nameres.rs
+++ b/crates/hir_def/src/nameres.rs
@@ -213,7 +213,7 @@ impl DefMap {
213 ) -> Option<Arc<DefMap>> { 213 ) -> Option<Arc<DefMap>> {
214 let block: BlockLoc = db.lookup_intern_block(block_id); 214 let block: BlockLoc = db.lookup_intern_block(block_id);
215 215
216 let item_tree = db.item_tree(block.ast_id.file_id); 216 let item_tree = db.file_item_tree(block.ast_id.file_id);
217 if item_tree.inner_items_of_block(block.ast_id.value).is_empty() { 217 if item_tree.inner_items_of_block(block.ast_id.value).is_empty() {
218 return None; 218 return None;
219 } 219 }
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs
index 81cf652b0..d0fefb5af 100644
--- a/crates/hir_def/src/nameres/collector.rs
+++ b/crates/hir_def/src/nameres/collector.rs
@@ -242,7 +242,7 @@ struct DefCollector<'a> {
242impl DefCollector<'_> { 242impl DefCollector<'_> {
243 fn seed_with_top_level(&mut self) { 243 fn seed_with_top_level(&mut self) {
244 let file_id = self.db.crate_graph()[self.def_map.krate].root_file_id; 244 let file_id = self.db.crate_graph()[self.def_map.krate].root_file_id;
245 let item_tree = self.db.item_tree(file_id.into()); 245 let item_tree = self.db.file_item_tree(file_id.into());
246 let module_id = self.def_map.root; 246 let module_id = self.def_map.root;
247 self.def_map.modules[module_id].origin = ModuleOrigin::CrateRoot { definition: file_id }; 247 self.def_map.modules[module_id].origin = ModuleOrigin::CrateRoot { definition: file_id };
248 if item_tree 248 if item_tree
@@ -263,7 +263,7 @@ impl DefCollector<'_> {
263 } 263 }
264 264
265 fn seed_with_inner(&mut self, block: AstId<ast::BlockExpr>) { 265 fn seed_with_inner(&mut self, block: AstId<ast::BlockExpr>) {
266 let item_tree = self.db.item_tree(block.file_id); 266 let item_tree = self.db.file_item_tree(block.file_id);
267 let module_id = self.def_map.root; 267 let module_id = self.def_map.root;
268 self.def_map.modules[module_id].origin = ModuleOrigin::BlockExpr { block }; 268 self.def_map.modules[module_id].origin = ModuleOrigin::BlockExpr { block };
269 if item_tree 269 if item_tree
@@ -656,26 +656,28 @@ impl DefCollector<'_> {
656 } 656 }
657 } 657 }
658 } else { 658 } else {
659 match import.path.segments().last() { 659 let name = match &import.alias {
660 Some(last_segment) => { 660 Some(ImportAlias::Alias(name)) => Some(name.clone()),
661 let name = match &import.alias { 661 Some(ImportAlias::Underscore) => None,
662 Some(ImportAlias::Alias(name)) => Some(name.clone()), 662 None => match import.path.segments().last() {
663 Some(ImportAlias::Underscore) => None, 663 Some(last_segment) => Some(last_segment.clone()),
664 None => Some(last_segment.clone()), 664 None => {
665 }; 665 cov_mark::hit!(bogus_paths);
666 log::debug!("resolved import {:?} ({:?}) to {:?}", name, import, def); 666 return;
667
668 // extern crates in the crate root are special-cased to insert entries into the extern prelude: rust-lang/rust#54658
669 if import.is_extern_crate && module_id == self.def_map.root {
670 if let (Some(def), Some(name)) = (def.take_types(), name.as_ref()) {
671 self.def_map.extern_prelude.insert(name.clone(), def);
672 }
673 } 667 }
668 },
669 };
670
671 log::debug!("resolved import {:?} ({:?}) to {:?}", name, import, def);
674 672
675 self.update(module_id, &[(name, def)], vis, ImportType::Named); 673 // extern crates in the crate root are special-cased to insert entries into the extern prelude: rust-lang/rust#54658
674 if import.is_extern_crate && module_id == self.def_map.root {
675 if let (Some(def), Some(name)) = (def.take_types(), name.as_ref()) {
676 self.def_map.extern_prelude.insert(name.clone(), def);
676 } 677 }
677 None => cov_mark::hit!(bogus_paths),
678 } 678 }
679
680 self.update(module_id, &[(name, def)], vis, ImportType::Named);
679 } 681 }
680 } 682 }
681 683
@@ -893,7 +895,7 @@ impl DefCollector<'_> {
893 } 895 }
894 896
895 // Then, fetch and process the item tree. This will reuse the expansion result from above. 897 // Then, fetch and process the item tree. This will reuse the expansion result from above.
896 let item_tree = self.db.item_tree(file_id); 898 let item_tree = self.db.file_item_tree(file_id);
897 let mod_dir = self.mod_dirs[&module_id].clone(); 899 let mod_dir = self.mod_dirs[&module_id].clone();
898 ModCollector { 900 ModCollector {
899 def_collector: &mut *self, 901 def_collector: &mut *self,
@@ -949,21 +951,21 @@ impl DefCollector<'_> {
949 let mut diagnosed_extern_crates = FxHashSet::default(); 951 let mut diagnosed_extern_crates = FxHashSet::default();
950 for directive in &self.unresolved_imports { 952 for directive in &self.unresolved_imports {
951 if let ImportSource::ExternCrate(krate) = directive.import.source { 953 if let ImportSource::ExternCrate(krate) = directive.import.source {
952 let item_tree = self.db.item_tree(krate.file_id); 954 let item_tree = krate.item_tree(self.db);
953 let extern_crate = &item_tree[krate.value]; 955 let extern_crate = &item_tree[krate.value];
954 956
955 diagnosed_extern_crates.insert(extern_crate.name.clone()); 957 diagnosed_extern_crates.insert(extern_crate.name.clone());
956 958
957 self.def_map.diagnostics.push(DefDiagnostic::unresolved_extern_crate( 959 self.def_map.diagnostics.push(DefDiagnostic::unresolved_extern_crate(
958 directive.module_id, 960 directive.module_id,
959 InFile::new(krate.file_id, extern_crate.ast_id), 961 InFile::new(krate.file_id(), extern_crate.ast_id),
960 )); 962 ));
961 } 963 }
962 } 964 }
963 965
964 for directive in &self.unresolved_imports { 966 for directive in &self.unresolved_imports {
965 if let ImportSource::Import(import) = &directive.import.source { 967 if let ImportSource::Import(import) = &directive.import.source {
966 let item_tree = self.db.item_tree(import.file_id); 968 let item_tree = import.item_tree(self.db);
967 let import_data = &item_tree[import.value]; 969 let import_data = &item_tree[import.value];
968 970
969 match (import_data.path.segments().first(), &import_data.path.kind) { 971 match (import_data.path.segments().first(), &import_data.path.kind) {
@@ -977,7 +979,7 @@ impl DefCollector<'_> {
977 979
978 self.def_map.diagnostics.push(DefDiagnostic::unresolved_import( 980 self.def_map.diagnostics.push(DefDiagnostic::unresolved_import(
979 directive.module_id, 981 directive.module_id,
980 InFile::new(import.file_id, import_data.ast_id), 982 InFile::new(import.file_id(), import_data.ast_id),
981 import_data.index, 983 import_data.index,
982 )); 984 ));
983 } 985 }
@@ -1053,7 +1055,7 @@ impl ModCollector<'_, '_> {
1053 self.def_collector.db, 1055 self.def_collector.db,
1054 krate, 1056 krate,
1055 &self.item_tree, 1057 &self.item_tree,
1056 InFile::new(self.file_id, import_id), 1058 ItemTreeId::new(self.file_id, import_id),
1057 ), 1059 ),
1058 status: PartialResolvedImport::Unresolved, 1060 status: PartialResolvedImport::Unresolved,
1059 }) 1061 })
@@ -1065,7 +1067,7 @@ impl ModCollector<'_, '_> {
1065 self.def_collector.db, 1067 self.def_collector.db,
1066 krate, 1068 krate,
1067 &self.item_tree, 1069 &self.item_tree,
1068 InFile::new(self.file_id, import_id), 1070 ItemTreeId::new(self.file_id, import_id),
1069 ), 1071 ),
1070 status: PartialResolvedImport::Unresolved, 1072 status: PartialResolvedImport::Unresolved,
1071 }) 1073 })
@@ -1297,7 +1299,7 @@ impl ModCollector<'_, '_> {
1297 Some((file_id, is_mod_rs)), 1299 Some((file_id, is_mod_rs)),
1298 &self.item_tree[module.visibility], 1300 &self.item_tree[module.visibility],
1299 ); 1301 );
1300 let item_tree = db.item_tree(file_id.into()); 1302 let item_tree = db.file_item_tree(file_id.into());
1301 ModCollector { 1303 ModCollector {
1302 def_collector: &mut *self.def_collector, 1304 def_collector: &mut *self.def_collector,
1303 macro_depth: self.macro_depth, 1305 macro_depth: self.macro_depth,
@@ -1469,7 +1471,9 @@ impl ModCollector<'_, '_> {
1469 ) 1471 )
1470 }) 1472 })
1471 }, 1473 },
1472 &mut |err| error = Some(err), 1474 &mut |err| {
1475 error.get_or_insert(err);
1476 },
1473 ) { 1477 ) {
1474 Ok(Ok(macro_call_id)) => { 1478 Ok(Ok(macro_call_id)) => {
1475 self.def_collector.unexpanded_macros.push(MacroDirective { 1479 self.def_collector.unexpanded_macros.push(MacroDirective {
diff --git a/crates/hir_def/src/nameres/tests.rs b/crates/hir_def/src/nameres/tests.rs
index de3aa4f9a..4f2e7a2f9 100644
--- a/crates/hir_def/src/nameres/tests.rs
+++ b/crates/hir_def/src/nameres/tests.rs
@@ -713,3 +713,22 @@ pub fn f() {}
713 "#]], 713 "#]],
714 ); 714 );
715} 715}
716
717#[test]
718fn use_crate_as() {
719 check(
720 r#"
721use crate as foo;
722
723use foo::bar as baz;
724
725fn bar() {}
726 "#,
727 expect![[r#"
728 crate
729 bar: v
730 baz: v
731 foo: t
732 "#]],
733 );
734}
diff --git a/crates/hir_def/src/nameres/tests/diagnostics.rs b/crates/hir_def/src/nameres/tests/diagnostics.rs
index c22ef46fd..a89061c2e 100644
--- a/crates/hir_def/src/nameres/tests/diagnostics.rs
+++ b/crates/hir_def/src/nameres/tests/diagnostics.rs
@@ -196,7 +196,24 @@ fn builtin_macro_fails_expansion() {
196 macro_rules! include { () => {} } 196 macro_rules! include { () => {} }
197 197
198 include!("doesntexist"); 198 include!("doesntexist");
199 //^^^^^^^^^^^^^^^^^^^^^^^^ could not convert tokens 199 //^^^^^^^^^^^^^^^^^^^^^^^^ failed to load file `doesntexist`
200 "#,
201 );
202}
203
204#[test]
205fn good_out_dir_diagnostic() {
206 check_diagnostics(
207 r#"
208 #[rustc_builtin_macro]
209 macro_rules! include { () => {} }
210 #[rustc_builtin_macro]
211 macro_rules! env { () => {} }
212 #[rustc_builtin_macro]
213 macro_rules! concat { () => {} }
214
215 include!(concat!(env!("OUT_DIR"), "/out.rs"));
216 //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `OUT_DIR` not set, enable "load out dirs from check" to fix
200 "#, 217 "#,
201 ); 218 );
202} 219}
diff --git a/crates/hir_def/src/src.rs b/crates/hir_def/src/src.rs
index 751d4c052..24e57b469 100644
--- a/crates/hir_def/src/src.rs
+++ b/crates/hir_def/src/src.rs
@@ -14,12 +14,12 @@ impl<N: ItemTreeNode> HasSource for AssocItemLoc<N> {
14 type Value = N::Source; 14 type Value = N::Source;
15 15
16 fn source(&self, db: &dyn DefDatabase) -> InFile<N::Source> { 16 fn source(&self, db: &dyn DefDatabase) -> InFile<N::Source> {
17 let tree = db.item_tree(self.id.file_id); 17 let tree = self.id.item_tree(db);
18 let ast_id_map = db.ast_id_map(self.id.file_id); 18 let ast_id_map = db.ast_id_map(self.id.file_id());
19 let root = db.parse_or_expand(self.id.file_id).unwrap(); 19 let root = db.parse_or_expand(self.id.file_id()).unwrap();
20 let node = &tree[self.id.value]; 20 let node = &tree[self.id.value];
21 21
22 InFile::new(self.id.file_id, ast_id_map.get(node.ast_id()).to_node(&root)) 22 InFile::new(self.id.file_id(), ast_id_map.get(node.ast_id()).to_node(&root))
23 } 23 }
24} 24}
25 25
@@ -27,12 +27,12 @@ impl<N: ItemTreeNode> HasSource for ItemLoc<N> {
27 type Value = N::Source; 27 type Value = N::Source;
28 28
29 fn source(&self, db: &dyn DefDatabase) -> InFile<N::Source> { 29 fn source(&self, db: &dyn DefDatabase) -> InFile<N::Source> {
30 let tree = db.item_tree(self.id.file_id); 30 let tree = self.id.item_tree(db);
31 let ast_id_map = db.ast_id_map(self.id.file_id); 31 let ast_id_map = db.ast_id_map(self.id.file_id());
32 let root = db.parse_or_expand(self.id.file_id).unwrap(); 32 let root = db.parse_or_expand(self.id.file_id()).unwrap();
33 let node = &tree[self.id.value]; 33 let node = &tree[self.id.value];
34 34
35 InFile::new(self.id.file_id, ast_id_map.get(node.ast_id()).to_node(&root)) 35 InFile::new(self.id.file_id(), ast_id_map.get(node.ast_id()).to_node(&root))
36 } 36 }
37} 37}
38 38