Skip to content

Commit ee4b5a3

Browse files
Use bitflags to compress function properties
Very minor savings, only 1 MB or so
1 parent f7e6b18 commit ee4b5a3

File tree

11 files changed

+120
-71
lines changed

11 files changed

+120
-71
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/hir/src/display.rs

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,22 +20,21 @@ impl HirDisplay for Function {
2020
fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
2121
let data = f.db.function_data(self.id);
2222
write_visibility(self.module(f.db).id, self.visibility(f.db), f)?;
23-
let qual = &data.qualifier;
24-
if qual.is_default {
23+
if data.is_default() {
2524
write!(f, "default ")?;
2625
}
27-
if qual.is_const {
26+
if data.is_const() {
2827
write!(f, "const ")?;
2928
}
30-
if qual.is_async {
29+
if data.is_async() {
3130
write!(f, "async ")?;
3231
}
33-
if qual.is_unsafe {
32+
if data.is_unsafe() {
3433
write!(f, "unsafe ")?;
3534
}
36-
if let Some(abi) = &qual.abi {
35+
if let Some(abi) = &data.abi {
3736
// FIXME: String escape?
38-
write!(f, "extern \"{}\" ", abi)?;
37+
write!(f, "extern \"{}\" ", &**abi)?;
3938
}
4039
write!(f, "fn {}", data.name)?;
4140

@@ -68,7 +67,7 @@ impl HirDisplay for Function {
6867
write!(f, ", ")?;
6968
} else {
7069
first = false;
71-
if data.has_self_param {
70+
if data.has_self_param() {
7271
write_self_param(type_ref, f)?;
7372
continue;
7473
}
@@ -88,7 +87,7 @@ impl HirDisplay for Function {
8887
// `FunctionData::ret_type` will be `::core::future::Future<Output = ...>` for async fns.
8988
// Use ugly pattern match to strip the Future trait.
9089
// Better way?
91-
let ret_type = if !qual.is_async {
90+
let ret_type = if !data.is_async() {
9291
&data.ret_type
9392
} else {
9493
match &*data.ret_type {

crates/hir/src/lib.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -832,7 +832,7 @@ impl Function {
832832
}
833833

834834
pub fn self_param(self, db: &dyn HirDatabase) -> Option<SelfParam> {
835-
if !db.function_data(self.id).has_self_param {
835+
if !db.function_data(self.id).has_self_param() {
836836
return None;
837837
}
838838
Some(SelfParam { func: self.id })
@@ -864,7 +864,7 @@ impl Function {
864864
}
865865

866866
pub fn is_unsafe(self, db: &dyn HirDatabase) -> bool {
867-
db.function_data(self.id).qualifier.is_unsafe
867+
db.function_data(self.id).is_unsafe()
868868
}
869869

870870
pub fn diagnostics(self, db: &dyn HirDatabase, sink: &mut DiagnosticSink) {
@@ -878,7 +878,7 @@ impl Function {
878878
///
879879
/// This is false in the case of required (not provided) trait methods.
880880
pub fn has_body(self, db: &dyn HirDatabase) -> bool {
881-
db.function_data(self.id).has_body
881+
db.function_data(self.id).has_body()
882882
}
883883

884884
/// A textual representation of the HIR of this function for debugging purposes.

crates/hir_def/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ edition = "2018"
1010
doctest = false
1111

1212
[dependencies]
13+
bitflags = "1.2.1"
1314
cov-mark = { version = "1.1", features = ["thread-local"] }
1415
dashmap = { version = "4.0.2", features = ["raw-api"] }
1516
log = "0.4.8"

crates/hir_def/src/data.rs

Lines changed: 44 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use crate::{
1010
body::Expander,
1111
db::DefDatabase,
1212
intern::Interned,
13-
item_tree::{AssocItem, FunctionQualifier, ItemTreeId, ModItem, Param},
13+
item_tree::{AssocItem, FnFlags, ItemTreeId, ModItem, Param},
1414
type_ref::{TraitRef, TypeBound, TypeRef},
1515
visibility::RawVisibility,
1616
AssocContainerId, AssocItemId, ConstId, ConstLoc, FunctionId, FunctionLoc, HasModule, ImplId,
@@ -23,14 +23,9 @@ pub struct FunctionData {
2323
pub params: Vec<Interned<TypeRef>>,
2424
pub ret_type: Interned<TypeRef>,
2525
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,
3326
pub visibility: RawVisibility,
27+
pub abi: Option<Interned<str>>,
28+
flags: FnFlags,
3429
}
3530

3631
impl FunctionData {
@@ -53,6 +48,11 @@ impl FunctionData {
5348
.next_back()
5449
.map_or(false, |param| matches!(item_tree[param], Param::Varargs));
5550

51+
let mut flags = func.flags;
52+
if is_varargs {
53+
flags |= FnFlags::IS_VARARGS;
54+
}
55+
5656
Arc::new(FunctionData {
5757
name: func.name.clone(),
5858
params: enabled_params
@@ -64,14 +64,45 @@ impl FunctionData {
6464
.collect(),
6565
ret_type: func.ret_type.clone(),
6666
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,
7267
visibility: item_tree[func.visibility].clone(),
68+
abi: func.abi.clone(),
69+
flags,
7370
})
7471
}
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+
}
75106
}
76107

77108
#[derive(Debug, Clone, PartialEq, Eq)]

crates/hir_def/src/item_tree.rs

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ use la_arena::{Arena, Idx, RawIdx};
2424
use profile::Count;
2525
use rustc_hash::FxHashMap;
2626
use smallvec::SmallVec;
27-
use syntax::{ast, match_ast, SmolStr, SyntaxKind};
27+
use syntax::{ast, match_ast, SyntaxKind};
2828

2929
use crate::{
3030
attr::{Attrs, RawAttrs},
@@ -556,15 +556,11 @@ pub struct Function {
556556
pub name: Name,
557557
pub visibility: RawVisibilityId,
558558
pub generic_params: GenericParamsId,
559-
pub has_self_param: bool,
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,
559+
pub abi: Option<Interned<str>>,
565560
pub params: IdRange<Param>,
566561
pub ret_type: Interned<TypeRef>,
567562
pub ast_id: FileAstId<ast::Fn>,
563+
pub(crate) flags: FnFlags,
568564
}
569565

570566
#[derive(Debug, Clone, Eq, PartialEq)]
@@ -573,13 +569,20 @@ pub enum Param {
573569
Varargs,
574570
}
575571

576-
#[derive(Debug, Clone, PartialEq, Eq)]
577-
pub struct FunctionQualifier {
578-
pub is_default: bool,
579-
pub is_const: bool,
580-
pub is_async: bool,
581-
pub is_unsafe: bool,
582-
pub abi: Option<SmolStr>,
572+
bitflags::bitflags! {
573+
/// NOTE: Shared with `FunctionData`
574+
pub(crate) struct FnFlags: u8 {
575+
const HAS_SELF_PARAM = 1 << 0;
576+
const HAS_BODY = 1 << 1;
577+
const IS_DEFAULT = 1 << 2;
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+
}
583586
}
584587

585588
#[derive(Debug, Clone, Eq, PartialEq)]

crates/hir_def/src/item_tree/lower.rs

Lines changed: 40 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -395,39 +395,51 @@ impl Ctx {
395395
ret_type
396396
};
397397

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+
});
399411

400412
let ast_id = self.source_ast_id_map.ast_id(func);
401-
let qualifier = FunctionQualifier {
402-
is_default: func.default_token().is_some(),
403-
is_const: func.const_token().is_some(),
404-
is_async: func.async_token().is_some(),
405-
is_unsafe: func.unsafe_token().is_some(),
406-
abi: func.abi().map(|abi| {
407-
// FIXME: Abi::abi() -> Option<SyntaxToken>?
408-
match abi.syntax().last_token() {
409-
Some(tok) if tok.kind() == SyntaxKind::STRING => {
410-
// FIXME: Better way to unescape?
411-
tok.text().trim_matches('"').into()
412-
}
413-
_ => {
414-
// `extern` default to be `extern "C"`.
415-
"C".into()
416-
}
417-
}
418-
}),
419-
};
413+
414+
let mut flags = FnFlags::empty();
415+
if func.body().is_some() {
416+
flags |= FnFlags::HAS_BODY;
417+
}
418+
if has_self_param {
419+
flags |= FnFlags::HAS_SELF_PARAM;
420+
}
421+
if func.default_token().is_some() {
422+
flags |= FnFlags::IS_DEFAULT;
423+
}
424+
if func.const_token().is_some() {
425+
flags |= FnFlags::IS_CONST;
426+
}
427+
if func.async_token().is_some() {
428+
flags |= FnFlags::IS_ASYNC;
429+
}
430+
if func.unsafe_token().is_some() {
431+
flags |= FnFlags::IS_UNSAFE;
432+
}
433+
420434
let mut res = Function {
421435
name,
422436
visibility,
423437
generic_params: GenericParamsId::EMPTY,
424-
has_self_param,
425-
has_body,
426-
qualifier,
427-
is_in_extern_block: false,
438+
abi,
428439
params,
429440
ret_type: Interned::new(ret_type),
430441
ast_id,
442+
flags,
431443
};
432444
res.generic_params = self.lower_generic_params(GenericsOwner::Function(&res), func);
433445

@@ -640,8 +652,10 @@ impl Ctx {
640652
ast::ExternItem::Fn(ast) => {
641653
let func_id = self.lower_function(&ast)?;
642654
let func = &mut self.data().functions[func_id.index];
643-
func.qualifier.is_unsafe = is_intrinsic_fn_unsafe(&func.name);
644-
func.is_in_extern_block = true;
655+
if is_intrinsic_fn_unsafe(&func.name) {
656+
func.flags |= FnFlags::IS_UNSAFE;
657+
}
658+
func.flags |= FnFlags::IS_IN_EXTERN_BLOCK;
645659
func_id.into()
646660
}
647661
ast::ExternItem::Static(ast) => {

crates/hir_ty/src/diagnostics/decl_check.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ impl<'a, 'b> DeclValidator<'a, 'b> {
9191

9292
fn validate_func(&mut self, func: FunctionId) {
9393
let data = self.db.function_data(func);
94-
if data.is_in_extern_block {
94+
if data.is_in_extern_block() {
9595
cov_mark::hit!(extern_func_incorrect_case_ignored);
9696
return;
9797
}

crates/hir_ty/src/diagnostics/unsafe_check.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ impl<'a, 'b> UnsafeValidator<'a, 'b> {
3232
let def = self.owner;
3333
let unsafe_expressions = unsafe_expressions(db, self.infer.as_ref(), def);
3434
let is_unsafe = match self.owner {
35-
DefWithBodyId::FunctionId(it) => db.function_data(it).qualifier.is_unsafe,
35+
DefWithBodyId::FunctionId(it) => db.function_data(it).is_unsafe(),
3636
DefWithBodyId::StaticId(_) | DefWithBodyId::ConstId(_) => false,
3737
};
3838
if is_unsafe
@@ -86,7 +86,7 @@ fn walk_unsafe(
8686
match expr {
8787
&Expr::Call { callee, .. } => {
8888
if let Some(func) = infer[callee].as_fn_def(db) {
89-
if db.function_data(func).qualifier.is_unsafe {
89+
if db.function_data(func).is_unsafe() {
9090
unsafe_exprs.push(UnsafeExpr { expr: current, inside_unsafe_block });
9191
}
9292
}
@@ -103,7 +103,7 @@ fn walk_unsafe(
103103
Expr::MethodCall { .. } => {
104104
if infer
105105
.method_resolution(current)
106-
.map(|func| db.function_data(func).qualifier.is_unsafe)
106+
.map(|func| db.function_data(func).is_unsafe())
107107
.unwrap_or(false)
108108
{
109109
unsafe_exprs.push(UnsafeExpr { expr: current, inside_unsafe_block });

crates/hir_ty/src/lower.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1054,7 +1054,7 @@ fn fn_sig_for_fn(db: &dyn HirDatabase, def: FunctionId) -> PolyFnSig {
10541054
let ret = (&ctx_ret).lower_ty(&data.ret_type);
10551055
let generics = generics(db.upcast(), def.into());
10561056
let num_binders = generics.len();
1057-
Binders::new(num_binders, CallableSig::from_params_and_return(params, ret, data.is_varargs))
1057+
Binders::new(num_binders, CallableSig::from_params_and_return(params, ret, data.is_varargs()))
10581058
}
10591059

10601060
/// Build the declared type of a function. This should not need to look at the

0 commit comments

Comments
 (0)