Skip to content

Commit b78f1a0

Browse files
Merge #8315
8315: Try to reduce ItemTree size further r=jonas-schievink a=jonas-schievink This was mostly a failed experiment, but still seems like the right thing to do. Memory reduction is mostly negligible. bors r+ Co-authored-by: Jonas Schievink <[email protected]>
2 parents e2213a5 + ee4b5a3 commit b78f1a0

File tree

12 files changed

+128
-75
lines changed

12 files changed

+128
-75
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: 18 additions & 15 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},
@@ -529,7 +529,7 @@ impl<N: ItemTreeNode> Index<FileItemTreeId<N>> for ItemTree {
529529
/// A desugared `use` import.
530530
#[derive(Debug, Clone, Eq, PartialEq)]
531531
pub struct Import {
532-
pub path: ModPath,
532+
pub path: Interned<ModPath>,
533533
pub alias: Option<ImportAlias>,
534534
pub visibility: RawVisibilityId,
535535
pub is_glob: bool,
@@ -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: 41 additions & 27 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

@@ -577,7 +589,7 @@ impl Ctx {
577589
&self.hygiene,
578590
|path, _use_tree, is_glob, alias| {
579591
imports.push(id(tree.imports.alloc(Import {
580-
path,
592+
path: Interned::new(path),
581593
alias,
582594
visibility,
583595
is_glob,
@@ -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_def/src/nameres/collector.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ use crate::{
2323
attr::Attrs,
2424
db::DefDatabase,
2525
derive_macro_as_call_id,
26+
intern::Interned,
2627
item_scope::{ImportType, PerNsGlobImports},
2728
item_tree::{
2829
self, FileItemTreeId, ItemTree, ItemTreeId, MacroCall, MacroDef, MacroRules, Mod, ModItem,
@@ -139,7 +140,7 @@ enum ImportSource {
139140

140141
#[derive(Clone, Debug, Eq, PartialEq)]
141142
struct Import {
142-
path: ModPath,
143+
path: Interned<ModPath>,
143144
alias: Option<ImportAlias>,
144145
visibility: RawVisibility,
145146
is_glob: bool,
@@ -181,7 +182,10 @@ impl Import {
181182
let attrs = &tree.attrs(db, krate, ModItem::from(id.value).into());
182183
let visibility = &tree[it.visibility];
183184
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+
)),
185189
alias: it.alias.clone(),
186190
visibility: visibility.clone(),
187191
is_glob: false,

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
}

0 commit comments

Comments
 (0)