Auto merge of #13678 - Veykril:hir-file-encode, r=Veykril

Encode the variants of `HirFileId` in a u32 with MSB as the tag

This saves 10mb on `self` analysis, while this does limit us to 2billion real files and 2 billion macro expansions, I doubt we will ever hit that limit :) `HirFileId` is used a lot, so going from 8 bytes to 4 is a decent win.
This commit is contained in:
bors 2022-11-25 22:33:32 +00:00
commit d2281f0367
4 changed files with 145 additions and 226 deletions

View File

@ -240,7 +240,7 @@ fn ast_id_map(db: &dyn AstDatabase, file_id: HirFileId) -> Arc<AstIdMap> {
}
fn parse_or_expand(db: &dyn AstDatabase, file_id: HirFileId) -> Option<SyntaxNode> {
match file_id.0 {
match file_id.repr() {
HirFileIdRepr::FileId(file_id) => Some(db.parse(file_id).tree().syntax().clone()),
HirFileIdRepr::MacroFile(macro_file) => {
// FIXME: Note how we convert from `Parse` to `SyntaxNode` here,

View File

@ -17,7 +17,7 @@ use crate::{
db::{self, AstDatabase},
fixup,
name::{AsName, Name},
HirFileId, HirFileIdRepr, InFile, MacroCallKind, MacroCallLoc, MacroDefKind, MacroFile,
HirFileId, InFile, MacroCallKind, MacroCallLoc, MacroDefKind, MacroFile,
};
#[derive(Clone, Debug)]
@ -216,9 +216,9 @@ fn make_hygiene_info(
impl HygieneFrame {
pub(crate) fn new(db: &dyn AstDatabase, file_id: HirFileId) -> HygieneFrame {
let (info, krate, local_inner) = match file_id.0 {
HirFileIdRepr::FileId(_) => (None, None, false),
HirFileIdRepr::MacroFile(macro_file) => {
let (info, krate, local_inner) = match file_id.macro_file() {
None => (None, None, false),
Some(macro_file) => {
let loc = db.lookup_intern_macro_call(macro_file.macro_call_id);
let info =
make_hygiene_info(db, macro_file, &loc).map(|info| (loc.kind.file_id(), info));

View File

@ -23,7 +23,11 @@ pub use mbe::{Origin, ValueResult};
use std::{fmt, hash::Hash, iter, sync::Arc};
use base_db::{impl_intern_key, salsa, CrateId, FileId, FileRange, ProcMacroKind};
use base_db::{
impl_intern_key,
salsa::{self, InternId},
CrateId, FileId, FileRange, ProcMacroKind,
};
use either::Either;
use syntax::{
algo::{self, skip_trivia_token},
@ -79,26 +83,12 @@ impl fmt::Display for ExpandError {
/// finite (because everything bottoms out at the real `FileId`) and small
/// (`MacroCallId` uses the location interning. You can check details here:
/// <https://en.wikipedia.org/wiki/String_interning>).
///
/// The two variants are encoded in a single u32 which are differentiated by the MSB.
/// If the MSB is 0, the value represents a `FileId`, otherwise the remaining 31 bits represent a
/// `MacroCallId`.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct HirFileId(HirFileIdRepr);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
enum HirFileIdRepr {
FileId(FileId),
MacroFile(MacroFile),
}
impl From<FileId> for HirFileId {
fn from(id: FileId) -> Self {
HirFileId(HirFileIdRepr::FileId(id))
}
}
impl From<MacroFile> for HirFileId {
fn from(id: MacroFile) -> Self {
HirFileId(HirFileIdRepr::MacroFile(id))
}
}
pub struct HirFileId(u32);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct MacroFile {
@ -172,13 +162,37 @@ pub enum MacroCallKind {
},
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
enum HirFileIdRepr {
FileId(FileId),
MacroFile(MacroFile),
}
impl From<FileId> for HirFileId {
fn from(FileId(id): FileId) -> Self {
assert!(id < Self::MAX_FILE_ID);
HirFileId(id)
}
}
impl From<MacroFile> for HirFileId {
fn from(MacroFile { macro_call_id: MacroCallId(id) }: MacroFile) -> Self {
let id = id.as_u32();
assert!(id < Self::MAX_FILE_ID);
HirFileId(id | Self::MACRO_FILE_TAG_MASK)
}
}
impl HirFileId {
const MAX_FILE_ID: u32 = u32::MAX ^ Self::MACRO_FILE_TAG_MASK;
const MACRO_FILE_TAG_MASK: u32 = 1 << 31;
/// For macro-expansion files, returns the file original source file the
/// expansion originated from.
pub fn original_file(self, db: &dyn db::AstDatabase) -> FileId {
let mut file_id = self;
loop {
match file_id.0 {
match file_id.repr() {
HirFileIdRepr::FileId(id) => break id,
HirFileIdRepr::MacroFile(MacroFile { macro_call_id }) => {
let loc: MacroCallLoc = db.lookup_intern_macro_call(macro_call_id);
@ -194,7 +208,7 @@ impl HirFileId {
pub fn expansion_level(self, db: &dyn db::AstDatabase) -> u32 {
let mut level = 0;
let mut curr = self;
while let HirFileIdRepr::MacroFile(macro_file) = curr.0 {
while let Some(macro_file) = curr.macro_file() {
let loc: MacroCallLoc = db.lookup_intern_macro_call(macro_file.macro_call_id);
level += 1;
@ -205,25 +219,17 @@ impl HirFileId {
/// If this is a macro call, returns the syntax node of the call.
pub fn call_node(self, db: &dyn db::AstDatabase) -> Option<InFile<SyntaxNode>> {
match self.0 {
HirFileIdRepr::FileId(_) => None,
HirFileIdRepr::MacroFile(macro_file) => {
let macro_file = self.macro_file()?;
let loc: MacroCallLoc = db.lookup_intern_macro_call(macro_file.macro_call_id);
Some(loc.kind.to_node(db))
}
}
}
/// If this is a macro call, returns the syntax node of the very first macro call this file resides in.
pub fn original_call_node(self, db: &dyn db::AstDatabase) -> Option<(FileId, SyntaxNode)> {
let mut call = match self.0 {
HirFileIdRepr::FileId(_) => return None,
HirFileIdRepr::MacroFile(MacroFile { macro_call_id }) => {
db.lookup_intern_macro_call(macro_call_id).kind.to_node(db)
}
};
let mut call =
db.lookup_intern_macro_call(self.macro_file()?.macro_call_id).kind.to_node(db);
loop {
match call.file_id.0 {
match call.file_id.repr() {
HirFileIdRepr::FileId(file_id) => break Some((file_id, call.value)),
HirFileIdRepr::MacroFile(MacroFile { macro_call_id }) => {
call = db.lookup_intern_macro_call(macro_call_id).kind.to_node(db);
@ -234,9 +240,7 @@ impl HirFileId {
/// Return expansion information if it is a macro-expansion file
pub fn expansion_info(self, db: &dyn db::AstDatabase) -> Option<ExpansionInfo> {
match self.0 {
HirFileIdRepr::FileId(_) => None,
HirFileIdRepr::MacroFile(macro_file) => {
let macro_file = self.macro_file()?;
let loc: MacroCallLoc = db.lookup_intern_macro_call(macro_file.macro_call_id);
let arg_tt = loc.kind.arg(db)?;
@ -248,9 +252,7 @@ impl HirFileId {
let def = loc.def.ast_id().left().and_then(|id| {
let def_tt = match id.to_node(db) {
ast::Macro::MacroRules(mac) => mac.token_tree()?,
ast::Macro::MacroDef(_)
if matches!(*macro_def, TokenExpander::BuiltinAttr(_)) =>
{
ast::Macro::MacroDef(_) if matches!(*macro_def, TokenExpander::BuiltinAttr(_)) => {
return None
}
ast::Macro::MacroDef(mac) => mac.body()?,
@ -280,14 +282,10 @@ impl HirFileId {
exp_map,
})
}
}
}
/// Indicate it is macro file generated for builtin derive
pub fn is_builtin_derive(&self, db: &dyn db::AstDatabase) -> Option<InFile<ast::Attr>> {
match self.0 {
HirFileIdRepr::FileId(_) => None,
HirFileIdRepr::MacroFile(macro_file) => {
let macro_file = self.macro_file()?;
let loc: MacroCallLoc = db.lookup_intern_macro_call(macro_file.macro_call_id);
let attr = match loc.def.kind {
MacroDefKind::BuiltInDerive(..) => loc.kind.to_node(db),
@ -295,23 +293,21 @@ impl HirFileId {
};
Some(attr.with_value(ast::Attr::cast(attr.value.clone())?))
}
}
}
pub fn is_custom_derive(&self, db: &dyn db::AstDatabase) -> bool {
match self.0 {
HirFileIdRepr::FileId(_) => false,
HirFileIdRepr::MacroFile(macro_file) => {
match self.macro_file() {
Some(macro_file) => {
let loc: MacroCallLoc = db.lookup_intern_macro_call(macro_file.macro_call_id);
matches!(loc.def.kind, MacroDefKind::ProcMacro(_, ProcMacroKind::CustomDerive, _))
}
None => false,
}
}
/// Return whether this file is an include macro
pub fn is_include_macro(&self, db: &dyn db::AstDatabase) -> bool {
match self.0 {
HirFileIdRepr::MacroFile(macro_file) => {
match self.macro_file() {
Some(macro_file) => {
let loc: MacroCallLoc = db.lookup_intern_macro_call(macro_file.macro_call_id);
matches!(loc.eager, Some(EagerCallInfo { included_file: Some(_), .. }))
}
@ -321,8 +317,8 @@ impl HirFileId {
/// Return whether this file is an attr macro
pub fn is_attr_macro(&self, db: &dyn db::AstDatabase) -> bool {
match self.0 {
HirFileIdRepr::MacroFile(macro_file) => {
match self.macro_file() {
Some(macro_file) => {
let loc: MacroCallLoc = db.lookup_intern_macro_call(macro_file.macro_call_id);
matches!(loc.kind, MacroCallKind::Attr { .. })
}
@ -333,23 +329,36 @@ impl HirFileId {
/// Return whether this file is the pseudo expansion of the derive attribute.
/// See [`crate::builtin_attr_macro::derive_attr_expand`].
pub fn is_derive_attr_pseudo_expansion(&self, db: &dyn db::AstDatabase) -> bool {
match self.0 {
HirFileIdRepr::MacroFile(macro_file) => {
match self.macro_file() {
Some(macro_file) => {
let loc: MacroCallLoc = db.lookup_intern_macro_call(macro_file.macro_call_id);
matches!(loc.kind, MacroCallKind::Attr { is_derive: true, .. })
}
_ => false,
None => false,
}
}
#[inline]
pub fn is_macro(self) -> bool {
matches!(self.0, HirFileIdRepr::MacroFile(_))
self.0 & Self::MACRO_FILE_TAG_MASK != 0
}
#[inline]
pub fn macro_file(self) -> Option<MacroFile> {
match self.0 {
HirFileIdRepr::FileId(_) => None,
HirFileIdRepr::MacroFile(m) => Some(m),
match self.0 & Self::MACRO_FILE_TAG_MASK {
0 => None,
_ => Some(MacroFile {
macro_call_id: MacroCallId(InternId::from(self.0 ^ Self::MACRO_FILE_TAG_MASK)),
}),
}
}
fn repr(self) -> HirFileIdRepr {
match self.0 & Self::MACRO_FILE_TAG_MASK {
0 => HirFileIdRepr::FileId(FileId(self.0)),
_ => HirFileIdRepr::MacroFile(MacroFile {
macro_call_id: MacroCallId(InternId::from(self.0 ^ Self::MACRO_FILE_TAG_MASK)),
}),
}
}
}
@ -442,7 +451,7 @@ impl MacroCallKind {
pub fn original_call_range_with_body(self, db: &dyn db::AstDatabase) -> FileRange {
let mut kind = self;
let file_id = loop {
match kind.file_id().0 {
match kind.file_id().repr() {
HirFileIdRepr::MacroFile(file) => {
kind = db.lookup_intern_macro_call(file.macro_call_id).kind;
}
@ -467,7 +476,7 @@ impl MacroCallKind {
pub fn original_call_range(self, db: &dyn db::AstDatabase) -> FileRange {
let mut kind = self;
let file_id = loop {
match kind.file_id().0 {
match kind.file_id().repr() {
HirFileIdRepr::MacroFile(file) => {
kind = db.lookup_intern_macro_call(file.macro_call_id).kind;
}
@ -779,7 +788,7 @@ impl<'a> InFile<&'a SyntaxNode> {
/// For attributes and derives, this will point back to the attribute only.
/// For the entire item `InFile::use original_file_range_full`.
pub fn original_file_range(self, db: &dyn db::AstDatabase) -> FileRange {
match self.file_id.0 {
match self.file_id.repr() {
HirFileIdRepr::FileId(file_id) => FileRange { file_id, range: self.value.text_range() },
HirFileIdRepr::MacroFile(mac_file) => {
if let Some(res) = self.original_file_range_opt(db) {
@ -846,7 +855,7 @@ impl InFile<SyntaxToken> {
/// Falls back to the macro call range if the node cannot be mapped up fully.
pub fn original_file_range(self, db: &dyn db::AstDatabase) -> FileRange {
match self.file_id.0 {
match self.file_id.repr() {
HirFileIdRepr::FileId(file_id) => FileRange { file_id, range: self.value.text_range() },
HirFileIdRepr::MacroFile(mac_file) => {
if let Some(res) = self.original_file_range_opt(db) {
@ -861,7 +870,7 @@ impl InFile<SyntaxToken> {
/// Attempts to map the syntax node back up its macro calls.
pub fn original_file_range_opt(self, db: &dyn db::AstDatabase) -> Option<FileRange> {
match self.file_id.0 {
match self.file_id.repr() {
HirFileIdRepr::FileId(file_id) => {
Some(FileRange { file_id, range: self.value.text_range() })
}

View File

@ -14,12 +14,8 @@
name: "Alias",
loc: DeclarationLocation {
hir_file_id: HirFileId(
FileId(
FileId(
0,
),
),
),
ptr: SyntaxNodePtr {
kind: TYPE_ALIAS,
range: 397..417,
@ -36,12 +32,8 @@
name: "CONST",
loc: DeclarationLocation {
hir_file_id: HirFileId(
FileId(
FileId(
0,
),
),
),
ptr: SyntaxNodePtr {
kind: CONST,
range: 340..361,
@ -58,12 +50,8 @@
name: "CONST_WITH_INNER",
loc: DeclarationLocation {
hir_file_id: HirFileId(
FileId(
FileId(
0,
),
),
),
ptr: SyntaxNodePtr {
kind: CONST,
range: 520..592,
@ -80,12 +68,8 @@
name: "Enum",
loc: DeclarationLocation {
hir_file_id: HirFileId(
FileId(
FileId(
0,
),
),
),
ptr: SyntaxNodePtr {
kind: ENUM,
range: 185..207,
@ -102,12 +86,8 @@
name: "Macro",
loc: DeclarationLocation {
hir_file_id: HirFileId(
FileId(
FileId(
0,
),
),
),
ptr: SyntaxNodePtr {
kind: MACRO_DEF,
range: 153..168,
@ -124,12 +104,8 @@
name: "STATIC",
loc: DeclarationLocation {
hir_file_id: HirFileId(
FileId(
FileId(
0,
),
),
),
ptr: SyntaxNodePtr {
kind: STATIC,
range: 362..396,
@ -146,12 +122,8 @@
name: "Struct",
loc: DeclarationLocation {
hir_file_id: HirFileId(
FileId(
FileId(
0,
),
),
),
ptr: SyntaxNodePtr {
kind: STRUCT,
range: 170..184,
@ -168,13 +140,7 @@
name: "StructFromMacro",
loc: DeclarationLocation {
hir_file_id: HirFileId(
MacroFile(
MacroFile {
macro_call_id: MacroCallId(
0,
),
},
),
2147483648,
),
ptr: SyntaxNodePtr {
kind: STRUCT,
@ -192,12 +158,8 @@
name: "StructInFn",
loc: DeclarationLocation {
hir_file_id: HirFileId(
FileId(
FileId(
0,
),
),
),
ptr: SyntaxNodePtr {
kind: STRUCT,
range: 318..336,
@ -216,12 +178,8 @@
name: "StructInNamedConst",
loc: DeclarationLocation {
hir_file_id: HirFileId(
FileId(
FileId(
0,
),
),
),
ptr: SyntaxNodePtr {
kind: STRUCT,
range: 555..581,
@ -240,12 +198,8 @@
name: "StructInUnnamedConst",
loc: DeclarationLocation {
hir_file_id: HirFileId(
FileId(
FileId(
0,
),
),
),
ptr: SyntaxNodePtr {
kind: STRUCT,
range: 479..507,
@ -262,12 +216,8 @@
name: "Trait",
loc: DeclarationLocation {
hir_file_id: HirFileId(
FileId(
FileId(
0,
),
),
),
ptr: SyntaxNodePtr {
kind: TRAIT,
range: 261..300,
@ -284,12 +234,8 @@
name: "Union",
loc: DeclarationLocation {
hir_file_id: HirFileId(
FileId(
FileId(
0,
),
),
),
ptr: SyntaxNodePtr {
kind: UNION,
range: 208..222,
@ -306,12 +252,8 @@
name: "a_mod",
loc: DeclarationLocation {
hir_file_id: HirFileId(
FileId(
FileId(
0,
),
),
),
ptr: SyntaxNodePtr {
kind: MODULE,
range: 419..457,
@ -328,12 +270,8 @@
name: "b_mod",
loc: DeclarationLocation {
hir_file_id: HirFileId(
FileId(
FileId(
0,
),
),
),
ptr: SyntaxNodePtr {
kind: MODULE,
range: 594..604,
@ -350,12 +288,8 @@
name: "define_struct",
loc: DeclarationLocation {
hir_file_id: HirFileId(
FileId(
FileId(
0,
),
),
),
ptr: SyntaxNodePtr {
kind: MACRO_RULES,
range: 51..131,
@ -372,12 +306,8 @@
name: "impl_fn",
loc: DeclarationLocation {
hir_file_id: HirFileId(
FileId(
FileId(
0,
),
),
),
ptr: SyntaxNodePtr {
kind: FN,
range: 242..257,
@ -394,12 +324,8 @@
name: "macro_rules_macro",
loc: DeclarationLocation {
hir_file_id: HirFileId(
FileId(
FileId(
0,
),
),
),
ptr: SyntaxNodePtr {
kind: MACRO_RULES,
range: 1..48,
@ -416,12 +342,8 @@
name: "main",
loc: DeclarationLocation {
hir_file_id: HirFileId(
FileId(
FileId(
0,
),
),
),
ptr: SyntaxNodePtr {
kind: FN,
range: 302..338,
@ -438,12 +360,8 @@
name: "trait_fn",
loc: DeclarationLocation {
hir_file_id: HirFileId(
FileId(
FileId(
0,
),
),
),
ptr: SyntaxNodePtr {
kind: FN,
range: 279..298,
@ -475,12 +393,8 @@
name: "StructInModA",
loc: DeclarationLocation {
hir_file_id: HirFileId(
FileId(
FileId(
0,
),
),
),
ptr: SyntaxNodePtr {
kind: STRUCT,
range: 435..455,
@ -510,12 +424,8 @@
name: "StructInModB",
loc: DeclarationLocation {
hir_file_id: HirFileId(
FileId(
FileId(
1,
),
),
),
ptr: SyntaxNodePtr {
kind: STRUCT,
range: 0..20,