aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_def/src/item_tree/lower.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_def/src/item_tree/lower.rs')
-rw-r--r--crates/hir_def/src/item_tree/lower.rs123
1 files changed, 75 insertions, 48 deletions
diff --git a/crates/hir_def/src/item_tree/lower.rs b/crates/hir_def/src/item_tree/lower.rs
index 3f558edd8..45b099cf3 100644
--- a/crates/hir_def/src/item_tree/lower.rs
+++ b/crates/hir_def/src/item_tree/lower.rs
@@ -11,7 +11,7 @@ use syntax::{
11 11
12use crate::{ 12use crate::{
13 generics::{GenericParams, TypeParamData, TypeParamProvenance}, 13 generics::{GenericParams, TypeParamData, TypeParamProvenance},
14 type_ref::LifetimeRef, 14 type_ref::{LifetimeRef, TraitRef},
15}; 15};
16 16
17use super::*; 17use super::*;
@@ -174,6 +174,12 @@ impl Ctx {
174 let forced_vis = self.forced_visibility.take(); 174 let forced_vis = self.forced_visibility.take();
175 175
176 let mut block_stack = Vec::new(); 176 let mut block_stack = Vec::new();
177
178 // if container itself is block, add it to the stack
179 if let Some(block) = ast::BlockExpr::cast(container.clone()) {
180 block_stack.push(self.source_ast_id_map.ast_id(&block));
181 }
182
177 for event in container.preorder().skip(1) { 183 for event in container.preorder().skip(1) {
178 match event { 184 match event {
179 WalkEvent::Enter(node) => { 185 WalkEvent::Enter(node) => {
@@ -183,7 +189,7 @@ impl Ctx {
183 block_stack.push(self.source_ast_id_map.ast_id(&block)); 189 block_stack.push(self.source_ast_id_map.ast_id(&block));
184 }, 190 },
185 ast::Item(item) => { 191 ast::Item(item) => {
186 // FIXME: This triggers for macro calls in expression position 192 // FIXME: This triggers for macro calls in expression/pattern/type position
187 let mod_items = self.lower_mod_item(&item, true); 193 let mod_items = self.lower_mod_item(&item, true);
188 let current_block = block_stack.last(); 194 let current_block = block_stack.last();
189 if let (Some(mod_items), Some(block)) = (mod_items, current_block) { 195 if let (Some(mod_items), Some(block)) = (mod_items, current_block) {
@@ -356,7 +362,7 @@ impl Ctx {
356 } 362 }
357 } 363 }
358 }; 364 };
359 let ty = self.data().type_refs.intern(self_type); 365 let ty = Interned::new(self_type);
360 let idx = self.data().params.alloc(Param::Normal(ty)); 366 let idx = self.data().params.alloc(Param::Normal(ty));
361 self.add_attrs(idx.into(), RawAttrs::new(&self_param, &self.hygiene)); 367 self.add_attrs(idx.into(), RawAttrs::new(&self_param, &self.hygiene));
362 has_self_param = true; 368 has_self_param = true;
@@ -366,7 +372,7 @@ impl Ctx {
366 Some(_) => self.data().params.alloc(Param::Varargs), 372 Some(_) => self.data().params.alloc(Param::Varargs),
367 None => { 373 None => {
368 let type_ref = TypeRef::from_ast_opt(&self.body_ctx, param.ty()); 374 let type_ref = TypeRef::from_ast_opt(&self.body_ctx, param.ty());
369 let ty = self.data().type_refs.intern(type_ref); 375 let ty = Interned::new(type_ref);
370 self.data().params.alloc(Param::Normal(ty)) 376 self.data().params.alloc(Param::Normal(ty))
371 } 377 }
372 }; 378 };
@@ -389,41 +395,51 @@ impl Ctx {
389 ret_type 395 ret_type
390 }; 396 };
391 397
392 let ret_type = self.data().type_refs.intern(ret_type); 398 let abi = func.abi().map(|abi| {
393 399 // FIXME: Abi::abi() -> Option<SyntaxToken>?
394 let has_body = func.body().is_some(); 400 match abi.syntax().last_token() {
401 Some(tok) if tok.kind() == SyntaxKind::STRING => {
402 // FIXME: Better way to unescape?
403 Interned::new_str(tok.text().trim_matches('"'))
404 }
405 _ => {
406 // `extern` default to be `extern "C"`.
407 Interned::new_str("C")
408 }
409 }
410 });
395 411
396 let ast_id = self.source_ast_id_map.ast_id(func); 412 let ast_id = self.source_ast_id_map.ast_id(func);
397 let qualifier = FunctionQualifier { 413
398 is_default: func.default_token().is_some(), 414 let mut flags = FnFlags::default();
399 is_const: func.const_token().is_some(), 415 if func.body().is_some() {
400 is_async: func.async_token().is_some(), 416 flags.bits |= FnFlags::HAS_BODY;
401 is_unsafe: func.unsafe_token().is_some(), 417 }
402 abi: func.abi().map(|abi| { 418 if has_self_param {
403 // FIXME: Abi::abi() -> Option<SyntaxToken>? 419 flags.bits |= FnFlags::HAS_SELF_PARAM;
404 match abi.syntax().last_token() { 420 }
405 Some(tok) if tok.kind() == SyntaxKind::STRING => { 421 if func.default_token().is_some() {
406 // FIXME: Better way to unescape? 422 flags.bits |= FnFlags::IS_DEFAULT;
407 tok.text().trim_matches('"').into() 423 }
408 } 424 if func.const_token().is_some() {
409 _ => { 425 flags.bits |= FnFlags::IS_CONST;
410 // `extern` default to be `extern "C"`. 426 }
411 "C".into() 427 if func.async_token().is_some() {
412 } 428 flags.bits |= FnFlags::IS_ASYNC;
413 } 429 }
414 }), 430 if func.unsafe_token().is_some() {
415 }; 431 flags.bits |= FnFlags::IS_UNSAFE;
432 }
433
416 let mut res = Function { 434 let mut res = Function {
417 name, 435 name,
418 visibility, 436 visibility,
419 generic_params: GenericParamsId::EMPTY, 437 generic_params: Interned::new(GenericParams::default()),
420 has_self_param, 438 abi,
421 has_body,
422 qualifier,
423 is_in_extern_block: false,
424 params, 439 params,
425 ret_type, 440 ret_type: Interned::new(ret_type),
426 ast_id, 441 ast_id,
442 flags,
427 }; 443 };
428 res.generic_params = self.lower_generic_params(GenericsOwner::Function(&res), func); 444 res.generic_params = self.lower_generic_params(GenericsOwner::Function(&res), func);
429 445
@@ -536,8 +552,11 @@ impl Ctx {
536 fn lower_impl(&mut self, impl_def: &ast::Impl) -> Option<FileItemTreeId<Impl>> { 552 fn lower_impl(&mut self, impl_def: &ast::Impl) -> Option<FileItemTreeId<Impl>> {
537 let generic_params = 553 let generic_params =
538 self.lower_generic_params_and_inner_items(GenericsOwner::Impl, impl_def); 554 self.lower_generic_params_and_inner_items(GenericsOwner::Impl, impl_def);
539 let target_trait = impl_def.trait_().map(|tr| self.lower_type_ref(&tr)); 555 // FIXME: If trait lowering fails, due to a non PathType for example, we treat this impl
540 let target_type = self.lower_type_ref(&impl_def.self_ty()?); 556 // as if it was an non-trait impl. Ideally we want to create a unique missing ref that only
557 // equals itself.
558 let target_trait = impl_def.trait_().and_then(|tr| self.lower_trait_ref(&tr));
559 let self_ty = self.lower_type_ref(&impl_def.self_ty()?);
541 let is_negative = impl_def.excl_token().is_some(); 560 let is_negative = impl_def.excl_token().is_some();
542 561
543 // We cannot use `assoc_items()` here as that does not include macro calls. 562 // We cannot use `assoc_items()` here as that does not include macro calls.
@@ -554,7 +573,7 @@ impl Ctx {
554 }) 573 })
555 .collect(); 574 .collect();
556 let ast_id = self.source_ast_id_map.ast_id(impl_def); 575 let ast_id = self.source_ast_id_map.ast_id(impl_def);
557 let res = Impl { generic_params, target_trait, target_type, is_negative, items, ast_id }; 576 let res = Impl { generic_params, target_trait, self_ty, is_negative, items, ast_id };
558 Some(id(self.data().impls.alloc(res))) 577 Some(id(self.data().impls.alloc(res)))
559 } 578 }
560 579
@@ -570,7 +589,7 @@ impl Ctx {
570 &self.hygiene, 589 &self.hygiene,
571 |path, _use_tree, is_glob, alias| { 590 |path, _use_tree, is_glob, alias| {
572 imports.push(id(tree.imports.alloc(Import { 591 imports.push(id(tree.imports.alloc(Import {
573 path, 592 path: Interned::new(path),
574 alias, 593 alias,
575 visibility, 594 visibility,
576 is_glob, 595 is_glob,
@@ -599,7 +618,7 @@ impl Ctx {
599 } 618 }
600 619
601 fn lower_macro_call(&mut self, m: &ast::MacroCall) -> Option<FileItemTreeId<MacroCall>> { 620 fn lower_macro_call(&mut self, m: &ast::MacroCall) -> Option<FileItemTreeId<MacroCall>> {
602 let path = ModPath::from_src(m.path()?, &self.hygiene)?; 621 let path = Interned::new(ModPath::from_src(m.path()?, &self.hygiene)?);
603 let ast_id = self.source_ast_id_map.ast_id(m); 622 let ast_id = self.source_ast_id_map.ast_id(m);
604 let res = MacroCall { path, ast_id }; 623 let res = MacroCall { path, ast_id };
605 Some(id(self.data().macro_calls.alloc(res))) 624 Some(id(self.data().macro_calls.alloc(res)))
@@ -633,8 +652,10 @@ impl Ctx {
633 ast::ExternItem::Fn(ast) => { 652 ast::ExternItem::Fn(ast) => {
634 let func_id = self.lower_function(&ast)?; 653 let func_id = self.lower_function(&ast)?;
635 let func = &mut self.data().functions[func_id.index]; 654 let func = &mut self.data().functions[func_id.index];
636 func.qualifier.is_unsafe = is_intrinsic_fn_unsafe(&func.name); 655 if is_intrinsic_fn_unsafe(&func.name) {
637 func.is_in_extern_block = true; 656 func.flags.bits |= FnFlags::IS_UNSAFE;
657 }
658 func.flags.bits |= FnFlags::IS_IN_EXTERN_BLOCK;
638 func_id.into() 659 func_id.into()
639 } 660 }
640 ast::ExternItem::Static(ast) => { 661 ast::ExternItem::Static(ast) => {
@@ -661,7 +682,7 @@ impl Ctx {
661 &mut self, 682 &mut self,
662 owner: GenericsOwner<'_>, 683 owner: GenericsOwner<'_>,
663 node: &impl ast::GenericParamsOwner, 684 node: &impl ast::GenericParamsOwner,
664 ) -> GenericParamsId { 685 ) -> Interned<GenericParams> {
665 // Generics are part of item headers and may contain inner items we need to collect. 686 // Generics are part of item headers and may contain inner items we need to collect.
666 if let Some(params) = node.generic_param_list() { 687 if let Some(params) = node.generic_param_list() {
667 self.collect_inner_items(params.syntax()); 688 self.collect_inner_items(params.syntax());
@@ -677,7 +698,7 @@ impl Ctx {
677 &mut self, 698 &mut self,
678 owner: GenericsOwner<'_>, 699 owner: GenericsOwner<'_>,
679 node: &impl ast::GenericParamsOwner, 700 node: &impl ast::GenericParamsOwner,
680 ) -> GenericParamsId { 701 ) -> Interned<GenericParams> {
681 let mut sm = &mut Default::default(); 702 let mut sm = &mut Default::default();
682 let mut generics = GenericParams::default(); 703 let mut generics = GenericParams::default();
683 match owner { 704 match owner {
@@ -685,8 +706,7 @@ impl Ctx {
685 generics.fill(&self.body_ctx, sm, node); 706 generics.fill(&self.body_ctx, sm, node);
686 // lower `impl Trait` in arguments 707 // lower `impl Trait` in arguments
687 for id in func.params.clone() { 708 for id in func.params.clone() {
688 if let Param::Normal(ty) = self.data().params[id] { 709 if let Param::Normal(ty) = &self.data().params[id] {
689 let ty = self.data().type_refs.lookup(ty);
690 generics.fill_implicit_impl_trait_args(ty); 710 generics.fill_implicit_impl_trait_args(ty);
691 } 711 }
692 } 712 }
@@ -719,7 +739,8 @@ impl Ctx {
719 } 739 }
720 } 740 }
721 741
722 self.data().generics.alloc(generics) 742 generics.shrink_to_fit();
743 Interned::new(generics)
723 } 744 }
724 745
725 fn lower_type_bounds(&mut self, node: &impl ast::TypeBoundsOwner) -> Vec<TypeBound> { 746 fn lower_type_bounds(&mut self, node: &impl ast::TypeBoundsOwner) -> Vec<TypeBound> {
@@ -740,14 +761,20 @@ impl Ctx {
740 self.data().vis.alloc(vis) 761 self.data().vis.alloc(vis)
741 } 762 }
742 763
743 fn lower_type_ref(&mut self, type_ref: &ast::Type) -> Idx<TypeRef> { 764 fn lower_trait_ref(&mut self, trait_ref: &ast::Type) -> Option<Interned<TraitRef>> {
765 let trait_ref = TraitRef::from_ast(&self.body_ctx, trait_ref.clone())?;
766 Some(Interned::new(trait_ref))
767 }
768
769 fn lower_type_ref(&mut self, type_ref: &ast::Type) -> Interned<TypeRef> {
744 let tyref = TypeRef::from_ast(&self.body_ctx, type_ref.clone()); 770 let tyref = TypeRef::from_ast(&self.body_ctx, type_ref.clone());
745 self.data().type_refs.intern(tyref) 771 Interned::new(tyref)
746 } 772 }
747 fn lower_type_ref_opt(&mut self, type_ref: Option<ast::Type>) -> Idx<TypeRef> { 773
774 fn lower_type_ref_opt(&mut self, type_ref: Option<ast::Type>) -> Interned<TypeRef> {
748 match type_ref.map(|ty| self.lower_type_ref(&ty)) { 775 match type_ref.map(|ty| self.lower_type_ref(&ty)) {
749 Some(it) => it, 776 Some(it) => it,
750 None => self.data().type_refs.intern(TypeRef::Error), 777 None => Interned::new(TypeRef::Error),
751 } 778 }
752 } 779 }
753 780