diff options
author | Jonas Schievink <[email protected]> | 2021-04-03 19:58:42 +0100 |
---|---|---|
committer | Jonas Schievink <[email protected]> | 2021-04-03 19:58:42 +0100 |
commit | ee4b5a34d8aa789ebc521926123fba79eebe5981 (patch) | |
tree | 9e5444bdd56ad6725525764d9f35a20f927b2209 /crates/hir_def | |
parent | f7e6b186e1d2f3a31b8e21d0885e13f12f12d71b (diff) |
Use bitflags to compress function properties
Very minor savings, only 1 MB or so
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 | 31 | ||||
-rw-r--r-- | crates/hir_def/src/item_tree/lower.rs | 66 |
4 files changed, 102 insertions, 53 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 dd80cef23..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}, |
@@ -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 ead7cd7a4..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 | ||
@@ -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) => { |