diff options
Diffstat (limited to 'crates/hir_def')
-rw-r--r-- | crates/hir_def/Cargo.toml | 1 | ||||
-rw-r--r-- | crates/hir_def/src/data.rs | 57 | ||||
-rw-r--r-- | crates/hir_def/src/item_tree.rs | 33 | ||||
-rw-r--r-- | crates/hir_def/src/item_tree/lower.rs | 68 | ||||
-rw-r--r-- | crates/hir_def/src/nameres/collector.rs | 8 |
5 files changed, 110 insertions, 57 deletions
diff --git a/crates/hir_def/Cargo.toml b/crates/hir_def/Cargo.toml index 43324d8d9..60adb655c 100644 --- a/crates/hir_def/Cargo.toml +++ b/crates/hir_def/Cargo.toml | |||
@@ -10,6 +10,7 @@ edition = "2018" | |||
10 | doctest = false | 10 | doctest = false |
11 | 11 | ||
12 | [dependencies] | 12 | [dependencies] |
13 | bitflags = "1.2.1" | ||
13 | cov-mark = { version = "1.1", features = ["thread-local"] } | 14 | cov-mark = { version = "1.1", features = ["thread-local"] } |
14 | dashmap = { version = "4.0.2", features = ["raw-api"] } | 15 | dashmap = { version = "4.0.2", features = ["raw-api"] } |
15 | log = "0.4.8" | 16 | log = "0.4.8" |
diff --git a/crates/hir_def/src/data.rs b/crates/hir_def/src/data.rs index 31f994681..b409fb45c 100644 --- a/crates/hir_def/src/data.rs +++ b/crates/hir_def/src/data.rs | |||
@@ -10,7 +10,7 @@ use crate::{ | |||
10 | body::Expander, | 10 | body::Expander, |
11 | db::DefDatabase, | 11 | db::DefDatabase, |
12 | intern::Interned, | 12 | intern::Interned, |
13 | item_tree::{AssocItem, FunctionQualifier, ItemTreeId, ModItem, Param}, | 13 | item_tree::{AssocItem, FnFlags, ItemTreeId, ModItem, Param}, |
14 | type_ref::{TraitRef, TypeBound, TypeRef}, | 14 | type_ref::{TraitRef, TypeBound, TypeRef}, |
15 | visibility::RawVisibility, | 15 | visibility::RawVisibility, |
16 | AssocContainerId, AssocItemId, ConstId, ConstLoc, FunctionId, FunctionLoc, HasModule, ImplId, | 16 | AssocContainerId, AssocItemId, ConstId, ConstLoc, FunctionId, FunctionLoc, HasModule, ImplId, |
@@ -23,14 +23,9 @@ pub struct FunctionData { | |||
23 | pub params: Vec<Interned<TypeRef>>, | 23 | pub params: Vec<Interned<TypeRef>>, |
24 | pub ret_type: Interned<TypeRef>, | 24 | pub ret_type: Interned<TypeRef>, |
25 | pub attrs: Attrs, | 25 | pub attrs: Attrs, |
26 | /// True if the first param is `self`. This is relevant to decide whether this | ||
27 | /// can be called as a method. | ||
28 | pub has_self_param: bool, | ||
29 | pub has_body: bool, | ||
30 | pub qualifier: FunctionQualifier, | ||
31 | pub is_in_extern_block: bool, | ||
32 | pub is_varargs: bool, | ||
33 | pub visibility: RawVisibility, | 26 | pub visibility: RawVisibility, |
27 | pub abi: Option<Interned<str>>, | ||
28 | flags: FnFlags, | ||
34 | } | 29 | } |
35 | 30 | ||
36 | impl FunctionData { | 31 | impl FunctionData { |
@@ -53,6 +48,11 @@ impl FunctionData { | |||
53 | .next_back() | 48 | .next_back() |
54 | .map_or(false, |param| matches!(item_tree[param], Param::Varargs)); | 49 | .map_or(false, |param| matches!(item_tree[param], Param::Varargs)); |
55 | 50 | ||
51 | let mut flags = func.flags; | ||
52 | if is_varargs { | ||
53 | flags |= FnFlags::IS_VARARGS; | ||
54 | } | ||
55 | |||
56 | Arc::new(FunctionData { | 56 | Arc::new(FunctionData { |
57 | name: func.name.clone(), | 57 | name: func.name.clone(), |
58 | params: enabled_params | 58 | params: enabled_params |
@@ -64,14 +64,45 @@ impl FunctionData { | |||
64 | .collect(), | 64 | .collect(), |
65 | ret_type: func.ret_type.clone(), | 65 | ret_type: func.ret_type.clone(), |
66 | attrs: item_tree.attrs(db, krate, ModItem::from(loc.id.value).into()), | 66 | attrs: item_tree.attrs(db, krate, ModItem::from(loc.id.value).into()), |
67 | has_self_param: func.has_self_param, | ||
68 | has_body: func.has_body, | ||
69 | qualifier: func.qualifier.clone(), | ||
70 | is_in_extern_block: func.is_in_extern_block, | ||
71 | is_varargs, | ||
72 | visibility: item_tree[func.visibility].clone(), | 67 | visibility: item_tree[func.visibility].clone(), |
68 | abi: func.abi.clone(), | ||
69 | flags, | ||
73 | }) | 70 | }) |
74 | } | 71 | } |
72 | |||
73 | pub fn has_body(&self) -> bool { | ||
74 | self.flags.contains(FnFlags::HAS_BODY) | ||
75 | } | ||
76 | |||
77 | /// True if the first param is `self`. This is relevant to decide whether this | ||
78 | /// can be called as a method. | ||
79 | pub fn has_self_param(&self) -> bool { | ||
80 | self.flags.contains(FnFlags::HAS_SELF_PARAM) | ||
81 | } | ||
82 | |||
83 | pub fn is_default(&self) -> bool { | ||
84 | self.flags.contains(FnFlags::IS_DEFAULT) | ||
85 | } | ||
86 | |||
87 | pub fn is_const(&self) -> bool { | ||
88 | self.flags.contains(FnFlags::IS_CONST) | ||
89 | } | ||
90 | |||
91 | pub fn is_async(&self) -> bool { | ||
92 | self.flags.contains(FnFlags::IS_ASYNC) | ||
93 | } | ||
94 | |||
95 | pub fn is_unsafe(&self) -> bool { | ||
96 | self.flags.contains(FnFlags::IS_UNSAFE) | ||
97 | } | ||
98 | |||
99 | pub fn is_in_extern_block(&self) -> bool { | ||
100 | self.flags.contains(FnFlags::IS_IN_EXTERN_BLOCK) | ||
101 | } | ||
102 | |||
103 | pub fn is_varargs(&self) -> bool { | ||
104 | self.flags.contains(FnFlags::IS_VARARGS) | ||
105 | } | ||
75 | } | 106 | } |
76 | 107 | ||
77 | #[derive(Debug, Clone, PartialEq, Eq)] | 108 | #[derive(Debug, Clone, PartialEq, Eq)] |
diff --git a/crates/hir_def/src/item_tree.rs b/crates/hir_def/src/item_tree.rs index 69a313c7e..c6d700977 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}; | |||
24 | use profile::Count; | 24 | use profile::Count; |
25 | use rustc_hash::FxHashMap; | 25 | use rustc_hash::FxHashMap; |
26 | use smallvec::SmallVec; | 26 | use smallvec::SmallVec; |
27 | use syntax::{ast, match_ast, SmolStr, SyntaxKind}; | 27 | use syntax::{ast, match_ast, SyntaxKind}; |
28 | 28 | ||
29 | use crate::{ | 29 | use crate::{ |
30 | attr::{Attrs, RawAttrs}, | 30 | attr::{Attrs, RawAttrs}, |
@@ -529,7 +529,7 @@ impl<N: ItemTreeNode> Index<FileItemTreeId<N>> for ItemTree { | |||
529 | /// A desugared `use` import. | 529 | /// A desugared `use` import. |
530 | #[derive(Debug, Clone, Eq, PartialEq)] | 530 | #[derive(Debug, Clone, Eq, PartialEq)] |
531 | pub struct Import { | 531 | pub struct Import { |
532 | pub path: ModPath, | 532 | pub path: Interned<ModPath>, |
533 | pub alias: Option<ImportAlias>, | 533 | pub alias: Option<ImportAlias>, |
534 | pub visibility: RawVisibilityId, | 534 | pub visibility: RawVisibilityId, |
535 | pub is_glob: bool, | 535 | pub is_glob: bool, |
@@ -556,15 +556,11 @@ pub struct Function { | |||
556 | pub name: Name, | 556 | pub name: Name, |
557 | pub visibility: RawVisibilityId, | 557 | pub visibility: RawVisibilityId, |
558 | pub generic_params: GenericParamsId, | 558 | pub generic_params: GenericParamsId, |
559 | pub has_self_param: bool, | 559 | pub abi: Option<Interned<str>>, |
560 | pub has_body: bool, | ||
561 | pub qualifier: FunctionQualifier, | ||
562 | /// Whether the function is located in an `extern` block (*not* whether it is an | ||
563 | /// `extern "abi" fn`). | ||
564 | pub is_in_extern_block: bool, | ||
565 | pub params: IdRange<Param>, | 560 | pub params: IdRange<Param>, |
566 | pub ret_type: Interned<TypeRef>, | 561 | pub ret_type: Interned<TypeRef>, |
567 | pub ast_id: FileAstId<ast::Fn>, | 562 | pub ast_id: FileAstId<ast::Fn>, |
563 | pub(crate) flags: FnFlags, | ||
568 | } | 564 | } |
569 | 565 | ||
570 | #[derive(Debug, Clone, Eq, PartialEq)] | 566 | #[derive(Debug, Clone, Eq, PartialEq)] |
@@ -573,13 +569,20 @@ pub enum Param { | |||
573 | Varargs, | 569 | Varargs, |
574 | } | 570 | } |
575 | 571 | ||
576 | #[derive(Debug, Clone, PartialEq, Eq)] | 572 | bitflags::bitflags! { |
577 | pub struct FunctionQualifier { | 573 | /// NOTE: Shared with `FunctionData` |
578 | pub is_default: bool, | 574 | pub(crate) struct FnFlags: u8 { |
579 | pub is_const: bool, | 575 | const HAS_SELF_PARAM = 1 << 0; |
580 | pub is_async: bool, | 576 | const HAS_BODY = 1 << 1; |
581 | pub is_unsafe: bool, | 577 | const IS_DEFAULT = 1 << 2; |
582 | pub abi: Option<SmolStr>, | 578 | const IS_CONST = 1 << 3; |
579 | const IS_ASYNC = 1 << 4; | ||
580 | const IS_UNSAFE = 1 << 5; | ||
581 | /// Whether the function is located in an `extern` block (*not* whether it is an | ||
582 | /// `extern "abi" fn`). | ||
583 | const IS_IN_EXTERN_BLOCK = 1 << 6; | ||
584 | const IS_VARARGS = 1 << 7; | ||
585 | } | ||
583 | } | 586 | } |
584 | 587 | ||
585 | #[derive(Debug, Clone, Eq, PartialEq)] | 588 | #[derive(Debug, Clone, Eq, PartialEq)] |
diff --git a/crates/hir_def/src/item_tree/lower.rs b/crates/hir_def/src/item_tree/lower.rs index 5247379c5..39e8403b0 100644 --- a/crates/hir_def/src/item_tree/lower.rs +++ b/crates/hir_def/src/item_tree/lower.rs | |||
@@ -395,39 +395,51 @@ impl Ctx { | |||
395 | ret_type | 395 | ret_type |
396 | }; | 396 | }; |
397 | 397 | ||
398 | let has_body = func.body().is_some(); | 398 | let abi = func.abi().map(|abi| { |
399 | // FIXME: Abi::abi() -> Option<SyntaxToken>? | ||
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 | }); | ||
399 | 411 | ||
400 | let ast_id = self.source_ast_id_map.ast_id(func); | 412 | let ast_id = self.source_ast_id_map.ast_id(func); |
401 | let qualifier = FunctionQualifier { | 413 | |
402 | is_default: func.default_token().is_some(), | 414 | let mut flags = FnFlags::empty(); |
403 | is_const: func.const_token().is_some(), | 415 | if func.body().is_some() { |
404 | is_async: func.async_token().is_some(), | 416 | flags |= FnFlags::HAS_BODY; |
405 | is_unsafe: func.unsafe_token().is_some(), | 417 | } |
406 | abi: func.abi().map(|abi| { | 418 | if has_self_param { |
407 | // FIXME: Abi::abi() -> Option<SyntaxToken>? | 419 | flags |= FnFlags::HAS_SELF_PARAM; |
408 | match abi.syntax().last_token() { | 420 | } |
409 | Some(tok) if tok.kind() == SyntaxKind::STRING => { | 421 | if func.default_token().is_some() { |
410 | // FIXME: Better way to unescape? | 422 | flags |= FnFlags::IS_DEFAULT; |
411 | tok.text().trim_matches('"').into() | 423 | } |
412 | } | 424 | if func.const_token().is_some() { |
413 | _ => { | 425 | flags |= FnFlags::IS_CONST; |
414 | // `extern` default to be `extern "C"`. | 426 | } |
415 | "C".into() | 427 | if func.async_token().is_some() { |
416 | } | 428 | flags |= FnFlags::IS_ASYNC; |
417 | } | 429 | } |
418 | }), | 430 | if func.unsafe_token().is_some() { |
419 | }; | 431 | flags |= FnFlags::IS_UNSAFE; |
432 | } | ||
433 | |||
420 | let mut res = Function { | 434 | let mut res = Function { |
421 | name, | 435 | name, |
422 | visibility, | 436 | visibility, |
423 | generic_params: GenericParamsId::EMPTY, | 437 | generic_params: GenericParamsId::EMPTY, |
424 | has_self_param, | 438 | abi, |
425 | has_body, | ||
426 | qualifier, | ||
427 | is_in_extern_block: false, | ||
428 | params, | 439 | params, |
429 | ret_type: Interned::new(ret_type), | 440 | ret_type: Interned::new(ret_type), |
430 | ast_id, | 441 | ast_id, |
442 | flags, | ||
431 | }; | 443 | }; |
432 | res.generic_params = self.lower_generic_params(GenericsOwner::Function(&res), func); | 444 | res.generic_params = self.lower_generic_params(GenericsOwner::Function(&res), func); |
433 | 445 | ||
@@ -577,7 +589,7 @@ impl Ctx { | |||
577 | &self.hygiene, | 589 | &self.hygiene, |
578 | |path, _use_tree, is_glob, alias| { | 590 | |path, _use_tree, is_glob, alias| { |
579 | imports.push(id(tree.imports.alloc(Import { | 591 | imports.push(id(tree.imports.alloc(Import { |
580 | path, | 592 | path: Interned::new(path), |
581 | alias, | 593 | alias, |
582 | visibility, | 594 | visibility, |
583 | is_glob, | 595 | is_glob, |
@@ -640,8 +652,10 @@ impl Ctx { | |||
640 | ast::ExternItem::Fn(ast) => { | 652 | ast::ExternItem::Fn(ast) => { |
641 | let func_id = self.lower_function(&ast)?; | 653 | let func_id = self.lower_function(&ast)?; |
642 | let func = &mut self.data().functions[func_id.index]; | 654 | let func = &mut self.data().functions[func_id.index]; |
643 | func.qualifier.is_unsafe = is_intrinsic_fn_unsafe(&func.name); | 655 | if is_intrinsic_fn_unsafe(&func.name) { |
644 | func.is_in_extern_block = true; | 656 | func.flags |= FnFlags::IS_UNSAFE; |
657 | } | ||
658 | func.flags |= FnFlags::IS_IN_EXTERN_BLOCK; | ||
645 | func_id.into() | 659 | func_id.into() |
646 | } | 660 | } |
647 | ast::ExternItem::Static(ast) => { | 661 | ast::ExternItem::Static(ast) => { |
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs index c8f494707..c2e445b68 100644 --- a/crates/hir_def/src/nameres/collector.rs +++ b/crates/hir_def/src/nameres/collector.rs | |||
@@ -23,6 +23,7 @@ use crate::{ | |||
23 | attr::Attrs, | 23 | attr::Attrs, |
24 | db::DefDatabase, | 24 | db::DefDatabase, |
25 | derive_macro_as_call_id, | 25 | derive_macro_as_call_id, |
26 | intern::Interned, | ||
26 | item_scope::{ImportType, PerNsGlobImports}, | 27 | item_scope::{ImportType, PerNsGlobImports}, |
27 | item_tree::{ | 28 | item_tree::{ |
28 | self, FileItemTreeId, ItemTree, ItemTreeId, MacroCall, MacroDef, MacroRules, Mod, ModItem, | 29 | self, FileItemTreeId, ItemTree, ItemTreeId, MacroCall, MacroDef, MacroRules, Mod, ModItem, |
@@ -139,7 +140,7 @@ enum ImportSource { | |||
139 | 140 | ||
140 | #[derive(Clone, Debug, Eq, PartialEq)] | 141 | #[derive(Clone, Debug, Eq, PartialEq)] |
141 | struct Import { | 142 | struct Import { |
142 | path: ModPath, | 143 | path: Interned<ModPath>, |
143 | alias: Option<ImportAlias>, | 144 | alias: Option<ImportAlias>, |
144 | visibility: RawVisibility, | 145 | visibility: RawVisibility, |
145 | is_glob: bool, | 146 | is_glob: bool, |
@@ -181,7 +182,10 @@ impl Import { | |||
181 | let attrs = &tree.attrs(db, krate, ModItem::from(id.value).into()); | 182 | let attrs = &tree.attrs(db, krate, ModItem::from(id.value).into()); |
182 | let visibility = &tree[it.visibility]; | 183 | let visibility = &tree[it.visibility]; |
183 | Self { | 184 | Self { |
184 | path: ModPath::from_segments(PathKind::Plain, iter::once(it.name.clone())), | 185 | path: Interned::new(ModPath::from_segments( |
186 | PathKind::Plain, | ||
187 | iter::once(it.name.clone()), | ||
188 | )), | ||
185 | alias: it.alias.clone(), | 189 | alias: it.alias.clone(), |
186 | visibility: visibility.clone(), | 190 | visibility: visibility.clone(), |
187 | is_glob: false, | 191 | is_glob: false, |