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.rs10
-rw-r--r--crates/hir_def/src/body/lower.rs105
-rw-r--r--crates/hir_def/src/data.rs22
-rw-r--r--crates/hir_def/src/item_tree.rs24
-rw-r--r--crates/hir_def/src/item_tree/lower.rs35
-rw-r--r--crates/hir_def/src/path.rs11
6 files changed, 140 insertions, 67 deletions
diff --git a/crates/hir_def/src/adt.rs b/crates/hir_def/src/adt.rs
index efbde17d8..1b9bb8235 100644
--- a/crates/hir_def/src/adt.rs
+++ b/crates/hir_def/src/adt.rs
@@ -31,12 +31,14 @@ pub struct StructData {
31 pub name: Name, 31 pub name: Name,
32 pub variant_data: Arc<VariantData>, 32 pub variant_data: Arc<VariantData>,
33 pub repr: Option<ReprKind>, 33 pub repr: Option<ReprKind>,
34 pub visibility: RawVisibility,
34} 35}
35 36
36#[derive(Debug, Clone, PartialEq, Eq)] 37#[derive(Debug, Clone, PartialEq, Eq)]
37pub struct EnumData { 38pub struct EnumData {
38 pub name: Name, 39 pub name: Name,
39 pub variants: Arena<EnumVariantData>, 40 pub variants: Arena<EnumVariantData>,
41 pub visibility: RawVisibility,
40} 42}
41 43
42#[derive(Debug, Clone, PartialEq, Eq)] 44#[derive(Debug, Clone, PartialEq, Eq)]
@@ -102,6 +104,7 @@ impl StructData {
102 name: strukt.name.clone(), 104 name: strukt.name.clone(),
103 variant_data: Arc::new(variant_data), 105 variant_data: Arc::new(variant_data),
104 repr, 106 repr,
107 visibility: item_tree[strukt.visibility].clone(),
105 }) 108 })
106 } 109 }
107 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> {
@@ -118,6 +121,7 @@ impl StructData {
118 name: union.name.clone(), 121 name: union.name.clone(),
119 variant_data: Arc::new(variant_data), 122 variant_data: Arc::new(variant_data),
120 repr, 123 repr,
124 visibility: item_tree[union.visibility].clone(),
121 }) 125 })
122 } 126 }
123} 127}
@@ -150,7 +154,11 @@ impl EnumData {
150 } 154 }
151 } 155 }
152 156
153 Arc::new(EnumData { name: enum_.name.clone(), variants }) 157 Arc::new(EnumData {
158 name: enum_.name.clone(),
159 variants,
160 visibility: item_tree[enum_.visibility].clone(),
161 })
154 } 162 }
155 163
156 pub fn variant(&self, name: &Name) -> Option<LocalEnumVariantId> { 164 pub fn variant(&self, name: &Name) -> Option<LocalEnumVariantId> {
diff --git a/crates/hir_def/src/body/lower.rs b/crates/hir_def/src/body/lower.rs
index 08f0c32f4..60b25db56 100644
--- a/crates/hir_def/src/body/lower.rs
+++ b/crates/hir_def/src/body/lower.rs
@@ -519,7 +519,7 @@ impl ExprCollector<'_> {
519 } 519 }
520 ast::Expr::MacroCall(e) => { 520 ast::Expr::MacroCall(e) => {
521 let mut ids = vec![]; 521 let mut ids = vec![];
522 self.collect_macro_call(e, syntax_ptr.clone(), |this, expansion| { 522 self.collect_macro_call(e, syntax_ptr.clone(), true, |this, expansion| {
523 ids.push(match expansion { 523 ids.push(match expansion {
524 Some(it) => this.collect_expr(it), 524 Some(it) => this.collect_expr(it),
525 None => this.alloc_expr(Expr::Missing, syntax_ptr.clone()), 525 None => this.alloc_expr(Expr::Missing, syntax_ptr.clone()),
@@ -527,6 +527,17 @@ impl ExprCollector<'_> {
527 }); 527 });
528 ids[0] 528 ids[0]
529 } 529 }
530 ast::Expr::MacroStmts(e) => {
531 // FIXME: these statements should be held by some hir containter
532 for stmt in e.statements() {
533 self.collect_stmt(stmt);
534 }
535 if let Some(expr) = e.expr() {
536 self.collect_expr(expr)
537 } else {
538 self.alloc_expr(Expr::Missing, syntax_ptr)
539 }
540 }
530 } 541 }
531 } 542 }
532 543
@@ -534,6 +545,7 @@ impl ExprCollector<'_> {
534 &mut self, 545 &mut self,
535 e: ast::MacroCall, 546 e: ast::MacroCall,
536 syntax_ptr: AstPtr<ast::Expr>, 547 syntax_ptr: AstPtr<ast::Expr>,
548 is_error_recoverable: bool,
537 mut collector: F, 549 mut collector: F,
538 ) { 550 ) {
539 // File containing the macro call. Expansion errors will be attached here. 551 // File containing the macro call. Expansion errors will be attached here.
@@ -578,7 +590,7 @@ impl ExprCollector<'_> {
578 Some((mark, expansion)) => { 590 Some((mark, expansion)) => {
579 // FIXME: Statements are too complicated to recover from error for now. 591 // FIXME: Statements are too complicated to recover from error for now.
580 // It is because we don't have any hygiene for local variable expansion right now. 592 // It is because we don't have any hygiene for local variable expansion right now.
581 if T::can_cast(syntax::SyntaxKind::MACRO_STMTS) && res.err.is_some() { 593 if !is_error_recoverable && res.err.is_some() {
582 self.expander.exit(self.db, mark); 594 self.expander.exit(self.db, mark);
583 collector(self, None); 595 collector(self, None);
584 } else { 596 } else {
@@ -602,56 +614,55 @@ impl ExprCollector<'_> {
602 } 614 }
603 615
604 fn collect_stmt(&mut self, s: ast::Stmt) -> Option<Vec<Statement>> { 616 fn collect_stmt(&mut self, s: ast::Stmt) -> Option<Vec<Statement>> {
605 let stmt = 617 let stmt = match s {
606 match s { 618 ast::Stmt::LetStmt(stmt) => {
607 ast::Stmt::LetStmt(stmt) => { 619 self.check_cfg(&stmt)?;
608 self.check_cfg(&stmt)?; 620
609 621 let pat = self.collect_pat_opt(stmt.pat());
610 let pat = self.collect_pat_opt(stmt.pat()); 622 let type_ref = stmt.ty().map(|it| TypeRef::from_ast(&self.ctx(), it));
611 let type_ref = stmt.ty().map(|it| TypeRef::from_ast(&self.ctx(), it)); 623 let initializer = stmt.initializer().map(|e| self.collect_expr(e));
612 let initializer = stmt.initializer().map(|e| self.collect_expr(e)); 624 vec![Statement::Let { pat, type_ref, initializer }]
613 vec![Statement::Let { pat, type_ref, initializer }] 625 }
614 } 626 ast::Stmt::ExprStmt(stmt) => {
615 ast::Stmt::ExprStmt(stmt) => { 627 self.check_cfg(&stmt)?;
616 self.check_cfg(&stmt)?; 628
617 629 // Note that macro could be expended to multiple statements
618 // Note that macro could be expended to multiple statements 630 if let Some(ast::Expr::MacroCall(m)) = stmt.expr() {
619 if let Some(ast::Expr::MacroCall(m)) = stmt.expr() { 631 let syntax_ptr = AstPtr::new(&stmt.expr().unwrap());
620 let syntax_ptr = AstPtr::new(&stmt.expr().unwrap()); 632 let mut stmts = vec![];
621 let mut stmts = vec![]; 633
622 634 self.collect_macro_call(m, syntax_ptr.clone(), false, |this, expansion| {
623 self.collect_macro_call(m, syntax_ptr.clone(), |this, expansion| { 635 match expansion {
624 match expansion { 636 Some(expansion) => {
625 Some(expansion) => { 637 let statements: ast::MacroStmts = expansion;
626 let statements: ast::MacroStmts = expansion; 638
627 639 statements.statements().for_each(|stmt| {
628 statements.statements().for_each(|stmt| { 640 if let Some(mut r) = this.collect_stmt(stmt) {
629 if let Some(mut r) = this.collect_stmt(stmt) { 641 stmts.append(&mut r);
630 stmts.append(&mut r);
631 }
632 });
633 if let Some(expr) = statements.expr() {
634 stmts.push(Statement::Expr(this.collect_expr(expr)));
635 } 642 }
636 } 643 });
637 None => { 644 if let Some(expr) = statements.expr() {
638 stmts.push(Statement::Expr( 645 stmts.push(Statement::Expr(this.collect_expr(expr)));
639 this.alloc_expr(Expr::Missing, syntax_ptr.clone()),
640 ));
641 } 646 }
642 } 647 }
643 }); 648 None => {
644 stmts 649 stmts.push(Statement::Expr(
645 } else { 650 this.alloc_expr(Expr::Missing, syntax_ptr.clone()),
646 vec![Statement::Expr(self.collect_expr_opt(stmt.expr()))] 651 ));
647 } 652 }
653 }
654 });
655 stmts
656 } else {
657 vec![Statement::Expr(self.collect_expr_opt(stmt.expr()))]
648 } 658 }
649 ast::Stmt::Item(item) => { 659 }
650 self.check_cfg(&item)?; 660 ast::Stmt::Item(item) => {
661 self.check_cfg(&item)?;
651 662
652 return None; 663 return None;
653 } 664 }
654 }; 665 };
655 666
656 Some(stmt) 667 Some(stmt)
657 } 668 }
diff --git a/crates/hir_def/src/data.rs b/crates/hir_def/src/data.rs
index e3bb9de08..1a27f7bf2 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, ItemTreeId, ModItem}, 12 item_tree::{AssocItem, FunctionQualifier, ItemTreeId, ModItem},
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,
@@ -26,9 +26,9 @@ pub struct FunctionData {
26 /// can be called as a method. 26 /// can be called as a method.
27 pub has_self_param: bool, 27 pub has_self_param: bool,
28 pub has_body: bool, 28 pub has_body: bool,
29 pub is_unsafe: bool, 29 pub qualifier: FunctionQualifier,
30 pub is_in_extern_block: bool,
30 pub is_varargs: bool, 31 pub is_varargs: bool,
31 pub is_extern: bool,
32 pub visibility: RawVisibility, 32 pub visibility: RawVisibility,
33} 33}
34 34
@@ -46,9 +46,9 @@ impl FunctionData {
46 attrs: item_tree.attrs(db, krate, ModItem::from(loc.id.value).into()), 46 attrs: item_tree.attrs(db, krate, ModItem::from(loc.id.value).into()),
47 has_self_param: func.has_self_param, 47 has_self_param: func.has_self_param,
48 has_body: func.has_body, 48 has_body: func.has_body,
49 is_unsafe: func.is_unsafe, 49 qualifier: func.qualifier.clone(),
50 is_in_extern_block: func.is_in_extern_block,
50 is_varargs: func.is_varargs, 51 is_varargs: func.is_varargs,
51 is_extern: func.is_extern,
52 visibility: item_tree[func.visibility].clone(), 52 visibility: item_tree[func.visibility].clone(),
53 }) 53 })
54 } 54 }
@@ -87,7 +87,10 @@ impl TypeAliasData {
87pub struct TraitData { 87pub struct TraitData {
88 pub name: Name, 88 pub name: Name,
89 pub items: Vec<(Name, AssocItemId)>, 89 pub items: Vec<(Name, AssocItemId)>,
90 pub auto: bool, 90 pub is_auto: bool,
91 pub is_unsafe: bool,
92 pub visibility: RawVisibility,
93 pub bounds: Box<[TypeBound]>,
91} 94}
92 95
93impl TraitData { 96impl TraitData {
@@ -96,10 +99,13 @@ impl TraitData {
96 let item_tree = db.item_tree(tr_loc.id.file_id); 99 let item_tree = db.item_tree(tr_loc.id.file_id);
97 let tr_def = &item_tree[tr_loc.id.value]; 100 let tr_def = &item_tree[tr_loc.id.value];
98 let name = tr_def.name.clone(); 101 let name = tr_def.name.clone();
99 let auto = tr_def.auto; 102 let is_auto = tr_def.is_auto;
103 let is_unsafe = tr_def.is_unsafe;
100 let module_id = tr_loc.container; 104 let module_id = tr_loc.container;
101 let container = AssocContainerId::TraitId(tr); 105 let container = AssocContainerId::TraitId(tr);
102 let mut expander = Expander::new(db, tr_loc.id.file_id, module_id); 106 let mut expander = Expander::new(db, tr_loc.id.file_id, module_id);
107 let visibility = item_tree[tr_def.visibility].clone();
108 let bounds = tr_def.bounds.clone();
103 109
104 let items = collect_items( 110 let items = collect_items(
105 db, 111 db,
@@ -111,7 +117,7 @@ impl TraitData {
111 100, 117 100,
112 ); 118 );
113 119
114 Arc::new(TraitData { name, items, auto }) 120 Arc::new(TraitData { name, items, is_auto, is_unsafe, visibility, bounds })
115 } 121 }
116 122
117 pub fn associated_types(&self) -> impl Iterator<Item = TypeAliasId> + '_ { 123 pub fn associated_types(&self) -> impl Iterator<Item = TypeAliasId> + '_ {
diff --git a/crates/hir_def/src/item_tree.rs b/crates/hir_def/src/item_tree.rs
index 09bcb10dc..7bb22c4c4 100644
--- a/crates/hir_def/src/item_tree.rs
+++ b/crates/hir_def/src/item_tree.rs
@@ -24,7 +24,7 @@ use la_arena::{Arena, Idx, RawIdx};
24use profile::Count; 24use profile::Count;
25use rustc_hash::FxHashMap; 25use rustc_hash::FxHashMap;
26use smallvec::SmallVec; 26use smallvec::SmallVec;
27use syntax::{ast, match_ast, SyntaxKind}; 27use syntax::{ast, match_ast, SmolStr, SyntaxKind};
28 28
29use crate::{ 29use crate::{
30 attr::{Attrs, RawAttrs}, 30 attr::{Attrs, RawAttrs},
@@ -110,6 +110,11 @@ impl ItemTree {
110 // still need to collect inner items. 110 // still need to collect inner items.
111 ctx.lower_inner_items(e.syntax()) 111 ctx.lower_inner_items(e.syntax())
112 }, 112 },
113 ast::ExprStmt(stmt) => {
114 // Macros can expand to stmt. We return an empty item tree in this case, but
115 // still need to collect inner items.
116 ctx.lower_inner_items(stmt.syntax())
117 },
113 _ => { 118 _ => {
114 panic!("cannot create item tree from {:?} {}", syntax, syntax); 119 panic!("cannot create item tree from {:?} {}", syntax, syntax);
115 }, 120 },
@@ -551,16 +556,25 @@ pub struct Function {
551 pub generic_params: GenericParamsId, 556 pub generic_params: GenericParamsId,
552 pub has_self_param: bool, 557 pub has_self_param: bool,
553 pub has_body: bool, 558 pub has_body: bool,
554 pub is_unsafe: bool, 559 pub qualifier: FunctionQualifier,
555 /// Whether the function is located in an `extern` block (*not* whether it is an 560 /// Whether the function is located in an `extern` block (*not* whether it is an
556 /// `extern "abi" fn`). 561 /// `extern "abi" fn`).
557 pub is_extern: bool, 562 pub is_in_extern_block: bool,
558 pub params: Box<[Idx<TypeRef>]>, 563 pub params: Box<[Idx<TypeRef>]>,
559 pub is_varargs: bool, 564 pub is_varargs: bool,
560 pub ret_type: Idx<TypeRef>, 565 pub ret_type: Idx<TypeRef>,
561 pub ast_id: FileAstId<ast::Fn>, 566 pub ast_id: FileAstId<ast::Fn>,
562} 567}
563 568
569#[derive(Debug, Clone, PartialEq, Eq)]
570pub struct FunctionQualifier {
571 pub is_default: bool,
572 pub is_const: bool,
573 pub is_async: bool,
574 pub is_unsafe: bool,
575 pub abi: Option<SmolStr>,
576}
577
564#[derive(Debug, Clone, Eq, PartialEq)] 578#[derive(Debug, Clone, Eq, PartialEq)]
565pub struct Struct { 579pub struct Struct {
566 pub name: Name, 580 pub name: Name,
@@ -624,7 +638,9 @@ pub struct Trait {
624 pub name: Name, 638 pub name: Name,
625 pub visibility: RawVisibilityId, 639 pub visibility: RawVisibilityId,
626 pub generic_params: GenericParamsId, 640 pub generic_params: GenericParamsId,
627 pub auto: bool, 641 pub is_auto: bool,
642 pub is_unsafe: bool,
643 pub bounds: Box<[TypeBound]>,
628 pub items: Box<[AssocItem]>, 644 pub items: Box<[AssocItem]>,
629 pub ast_id: FileAstId<ast::Trait>, 645 pub ast_id: FileAstId<ast::Trait>,
630} 646}
diff --git a/crates/hir_def/src/item_tree/lower.rs b/crates/hir_def/src/item_tree/lower.rs
index 240fdacf9..7e91b991d 100644
--- a/crates/hir_def/src/item_tree/lower.rs
+++ b/crates/hir_def/src/item_tree/lower.rs
@@ -391,14 +391,33 @@ impl Ctx {
391 let has_body = func.body().is_some(); 391 let has_body = func.body().is_some();
392 392
393 let ast_id = self.source_ast_id_map.ast_id(func); 393 let ast_id = self.source_ast_id_map.ast_id(func);
394 let qualifier = FunctionQualifier {
395 is_default: func.default_token().is_some(),
396 is_const: func.const_token().is_some(),
397 is_async: func.async_token().is_some(),
398 is_unsafe: func.unsafe_token().is_some(),
399 abi: func.abi().map(|abi| {
400 // FIXME: Abi::abi() -> Option<SyntaxToken>?
401 match abi.syntax().last_token() {
402 Some(tok) if tok.kind() == SyntaxKind::STRING => {
403 // FIXME: Better way to unescape?
404 tok.text().trim_matches('"').into()
405 }
406 _ => {
407 // `extern` default to be `extern "C"`.
408 "C".into()
409 }
410 }
411 }),
412 };
394 let mut res = Function { 413 let mut res = Function {
395 name, 414 name,
396 visibility, 415 visibility,
397 generic_params: GenericParamsId::EMPTY, 416 generic_params: GenericParamsId::EMPTY,
398 has_self_param, 417 has_self_param,
399 has_body, 418 has_body,
400 is_unsafe: func.unsafe_token().is_some(), 419 qualifier,
401 is_extern: false, 420 is_in_extern_block: false,
402 params, 421 params,
403 is_varargs, 422 is_varargs,
404 ret_type, 423 ret_type,
@@ -481,7 +500,9 @@ impl Ctx {
481 let visibility = self.lower_visibility(trait_def); 500 let visibility = self.lower_visibility(trait_def);
482 let generic_params = 501 let generic_params =
483 self.lower_generic_params_and_inner_items(GenericsOwner::Trait(trait_def), trait_def); 502 self.lower_generic_params_and_inner_items(GenericsOwner::Trait(trait_def), trait_def);
484 let auto = trait_def.auto_token().is_some(); 503 let is_auto = trait_def.auto_token().is_some();
504 let is_unsafe = trait_def.unsafe_token().is_some();
505 let bounds = self.lower_type_bounds(trait_def);
485 let items = trait_def.assoc_item_list().map(|list| { 506 let items = trait_def.assoc_item_list().map(|list| {
486 self.with_inherited_visibility(visibility, |this| { 507 self.with_inherited_visibility(visibility, |this| {
487 list.assoc_items() 508 list.assoc_items()
@@ -501,7 +522,9 @@ impl Ctx {
501 name, 522 name,
502 visibility, 523 visibility,
503 generic_params, 524 generic_params,
504 auto, 525 is_auto,
526 is_unsafe,
527 bounds: bounds.into(),
505 items: items.unwrap_or_default(), 528 items: items.unwrap_or_default(),
506 ast_id, 529 ast_id,
507 }; 530 };
@@ -608,8 +631,8 @@ impl Ctx {
608 ast::ExternItem::Fn(ast) => { 631 ast::ExternItem::Fn(ast) => {
609 let func_id = self.lower_function(&ast)?; 632 let func_id = self.lower_function(&ast)?;
610 let func = &mut self.data().functions[func_id.index]; 633 let func = &mut self.data().functions[func_id.index];
611 func.is_unsafe = is_intrinsic_fn_unsafe(&func.name); 634 func.qualifier.is_unsafe = is_intrinsic_fn_unsafe(&func.name);
612 func.is_extern = true; 635 func.is_in_extern_block = true;
613 func_id.into() 636 func_id.into()
614 } 637 }
615 ast::ExternItem::Static(ast) => { 638 ast::ExternItem::Static(ast) => {
diff --git a/crates/hir_def/src/path.rs b/crates/hir_def/src/path.rs
index 0e60dc2b6..8c923bb7b 100644
--- a/crates/hir_def/src/path.rs
+++ b/crates/hir_def/src/path.rs
@@ -9,7 +9,10 @@ use std::{
9 9
10use crate::{body::LowerCtx, type_ref::LifetimeRef}; 10use crate::{body::LowerCtx, type_ref::LifetimeRef};
11use base_db::CrateId; 11use base_db::CrateId;
12use hir_expand::{hygiene::Hygiene, name::Name}; 12use hir_expand::{
13 hygiene::Hygiene,
14 name::{name, Name},
15};
13use syntax::ast; 16use syntax::ast;
14 17
15use crate::{ 18use crate::{
@@ -209,6 +212,12 @@ impl Path {
209 }; 212 };
210 Some(res) 213 Some(res)
211 } 214 }
215
216 pub fn is_self_type(&self) -> bool {
217 self.type_anchor.is_none()
218 && self.generic_args == &[None]
219 && self.mod_path.as_ident() == Some(&name!(Self))
220 }
212} 221}
213 222
214#[derive(Debug, Clone, PartialEq, Eq, Hash)] 223#[derive(Debug, Clone, PartialEq, Eq, Hash)]