diff options
Diffstat (limited to 'crates/hir_def/src')
-rw-r--r-- | crates/hir_def/src/adt.rs | 6 | ||||
-rw-r--r-- | crates/hir_def/src/attr.rs | 146 | ||||
-rw-r--r-- | crates/hir_def/src/body/lower.rs | 27 | ||||
-rw-r--r-- | crates/hir_def/src/body/tests.rs | 2 | ||||
-rw-r--r-- | crates/hir_def/src/data.rs | 62 | ||||
-rw-r--r-- | crates/hir_def/src/db.rs | 4 | ||||
-rw-r--r-- | crates/hir_def/src/generics.rs | 14 | ||||
-rw-r--r-- | crates/hir_def/src/item_tree.rs | 68 | ||||
-rw-r--r-- | crates/hir_def/src/item_tree/lower.rs | 41 | ||||
-rw-r--r-- | crates/hir_def/src/nameres.rs | 2 | ||||
-rw-r--r-- | crates/hir_def/src/nameres/collector.rs | 58 | ||||
-rw-r--r-- | crates/hir_def/src/nameres/tests.rs | 19 | ||||
-rw-r--r-- | crates/hir_def/src/nameres/tests/diagnostics.rs | 19 | ||||
-rw-r--r-- | crates/hir_def/src/src.rs | 16 |
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 { | |||
76 | impl RawAttrs { | 76 | impl 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 | ||
381 | pub struct AttrSourceMap { | ||
382 | attrs: Vec<Either<ast::Attr, ast::Comment>>, | ||
383 | } | ||
384 | |||
385 | impl 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)] |
369 | pub struct Attr { | 400 | pub struct Attr { |
370 | index: u32, | 401 | index: u32, |
@@ -381,7 +412,7 @@ pub enum AttrInput { | |||
381 | } | 412 | } |
382 | 413 | ||
383 | impl Attr { | 414 | impl 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 | ||
494 | fn attrs_from_item_tree<N: ItemTreeNode>(id: ItemTreeId<N>, db: &dyn DefDatabase) -> RawAttrs { | 532 | fn 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 | ||
500 | fn collect_attrs(owner: &dyn AttrsOwner) -> impl Iterator<Item = Either<ast::Attr, ast::Comment>> { | 538 | fn 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(|¶m| 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 { | |||
96 | impl TraitData { | 115 | impl 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 { | |||
183 | impl ConstData { | 202 | impl 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 { | |||
206 | impl StaticData { | 225 | impl 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)] |
50 | pub trait DefDatabase: InternDatabase + AstDatabase + Upcast<dyn AstDatabase> { | 50 | pub 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 | ||
78 | impl ItemTree { | 78 | impl 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 | ||
343 | macro_rules! from_attrs { | 347 | macro_rules! from_attrs { |
@@ -352,7 +356,7 @@ macro_rules! from_attrs { | |||
352 | }; | 356 | }; |
353 | } | 357 | } |
354 | 358 | ||
355 | from_attrs!(ModItem(ModItem), Variant(Idx<Variant>), Field(Idx<Field>)); | 359 | from_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. |
358 | pub trait ItemTreeNode: Clone { | 362 | pub trait ItemTreeNode: Clone { |
@@ -401,7 +405,47 @@ impl<N: ItemTreeNode> fmt::Debug for FileItemTreeId<N> { | |||
401 | } | 405 | } |
402 | } | 406 | } |
403 | 407 | ||
404 | pub type ItemTreeId<N> = InFile<FileItemTreeId<N>>; | 408 | #[derive(Debug)] |
409 | pub struct ItemTreeId<N: ItemTreeNode> { | ||
410 | file: HirFileId, | ||
411 | pub value: FileItemTreeId<N>, | ||
412 | } | ||
413 | |||
414 | impl<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 | |||
428 | impl<N: ItemTreeNode> Copy for ItemTreeId<N> {} | ||
429 | impl<N: ItemTreeNode> Clone for ItemTreeId<N> { | ||
430 | fn clone(&self) -> Self { | ||
431 | *self | ||
432 | } | ||
433 | } | ||
434 | |||
435 | impl<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 | |||
441 | impl<N: ItemTreeNode> Eq for ItemTreeId<N> {} | ||
442 | |||
443 | impl<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 | ||
406 | macro_rules! mod_items { | 450 | macro_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 | ||
491 | impl_index!(fields: Field, variants: Variant); | 535 | impl_index!(fields: Field, variants: Variant, params: Param); |
492 | 536 | ||
493 | impl Index<RawVisibilityId> for ItemTree { | 537 | impl 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)] | ||
617 | pub enum Param { | ||
618 | Normal(Idx<TypeRef>), | ||
619 | Varargs, | ||
620 | } | ||
621 | |||
573 | #[derive(Debug, Clone, PartialEq, Eq)] | 622 | #[derive(Debug, Clone, PartialEq, Eq)] |
574 | pub struct FunctionQualifier { | 623 | pub 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. | ||
803 | pub struct IdRange<T> { | 853 | pub 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 | ||
871 | impl<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 | |||
821 | impl<T> fmt::Debug for IdRange<T> { | 877 | impl<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(¶m, &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 | ||
782 | fn desugar_future_path(orig: TypeRef) -> Path { | 791 | fn 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> { | |||
242 | impl DefCollector<'_> { | 242 | impl 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] | ||
718 | fn use_crate_as() { | ||
719 | check( | ||
720 | r#" | ||
721 | use crate as foo; | ||
722 | |||
723 | use foo::bar as baz; | ||
724 | |||
725 | fn 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] | ||
205 | fn 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 | ||