diff options
Diffstat (limited to 'crates/hir_def/src/item_tree')
-rw-r--r-- | crates/hir_def/src/item_tree/lower.rs | 123 |
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 | ||
12 | use crate::{ | 12 | use crate::{ |
13 | generics::{GenericParams, TypeParamData, TypeParamProvenance}, | 13 | generics::{GenericParams, TypeParamData, TypeParamProvenance}, |
14 | type_ref::LifetimeRef, | 14 | type_ref::{LifetimeRef, TraitRef}, |
15 | }; | 15 | }; |
16 | 16 | ||
17 | use super::*; | 17 | use 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 | ||