Skip to content

Commit d8434df

Browse files
Make builtin derives cheaper, by not really expanding them, instead store them unexpanded
1 parent 0023f19 commit d8434df

File tree

21 files changed

+1140
-151
lines changed

21 files changed

+1140
-151
lines changed

crates/hir-def/src/attrs.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,7 @@ fn match_attr_flags(attr_flags: &mut AttrFlags, attr: Meta) -> ControlFlow<Infal
188188
"deprecated" => attr_flags.insert(AttrFlags::IS_DEPRECATED),
189189
"macro_export" => attr_flags.insert(AttrFlags::IS_MACRO_EXPORT),
190190
"no_mangle" => attr_flags.insert(AttrFlags::NO_MANGLE),
191+
"pointee" => attr_flags.insert(AttrFlags::IS_POINTEE),
191192
"non_exhaustive" => attr_flags.insert(AttrFlags::NON_EXHAUSTIVE),
192193
"ignore" => attr_flags.insert(AttrFlags::IS_IGNORE),
193194
"bench" => attr_flags.insert(AttrFlags::IS_BENCH),
@@ -289,6 +290,7 @@ bitflags::bitflags! {
289290
const RUSTC_PAREN_SUGAR = 1 << 42;
290291
const RUSTC_COINDUCTIVE = 1 << 43;
291292
const RUSTC_FORCE_INLINE = 1 << 44;
293+
const IS_POINTEE = 1 << 45;
292294
}
293295
}
294296

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
//! Definition of builtin derive impls.
2+
//!
3+
//! To save time and memory, builtin derives are not really expanded. Instead, we record them
4+
//! and create their impls based on lowered data, see crates/hir-ty/src/builtin_derive.rs.
5+
6+
use hir_expand::builtin::BuiltinDeriveExpander;
7+
8+
macro_rules! declare_enum {
9+
( $( $trait:ident ),* $(,)? ) => {
10+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
11+
pub enum BuiltinDeriveImplTrait {
12+
$( $trait, )*
13+
}
14+
15+
impl BuiltinDeriveImplTrait {
16+
#[inline]
17+
pub fn get_id(self, lang_items: &crate::lang_item::LangItems) -> Option<crate::TraitId> {
18+
match self {
19+
$( Self::$trait => lang_items.$trait, )*
20+
}
21+
}
22+
}
23+
};
24+
}
25+
26+
declare_enum!(
27+
Copy,
28+
Clone,
29+
Default,
30+
Debug,
31+
Hash,
32+
Ord,
33+
PartialOrd,
34+
Eq,
35+
PartialEq,
36+
CoerceUnsized,
37+
DispatchFromDyn,
38+
);
39+
40+
pub(crate) fn with_derive_traits(
41+
derive: BuiltinDeriveExpander,
42+
mut f: impl FnMut(BuiltinDeriveImplTrait),
43+
) {
44+
let trait_ = match derive {
45+
BuiltinDeriveExpander::Copy => BuiltinDeriveImplTrait::Copy,
46+
BuiltinDeriveExpander::Clone => BuiltinDeriveImplTrait::Clone,
47+
BuiltinDeriveExpander::Default => BuiltinDeriveImplTrait::Default,
48+
BuiltinDeriveExpander::Debug => BuiltinDeriveImplTrait::Debug,
49+
BuiltinDeriveExpander::Hash => BuiltinDeriveImplTrait::Hash,
50+
BuiltinDeriveExpander::Ord => BuiltinDeriveImplTrait::Ord,
51+
BuiltinDeriveExpander::PartialOrd => BuiltinDeriveImplTrait::PartialOrd,
52+
BuiltinDeriveExpander::Eq => BuiltinDeriveImplTrait::Eq,
53+
BuiltinDeriveExpander::PartialEq => BuiltinDeriveImplTrait::PartialEq,
54+
BuiltinDeriveExpander::CoercePointee => {
55+
f(BuiltinDeriveImplTrait::CoerceUnsized);
56+
f(BuiltinDeriveImplTrait::DispatchFromDyn);
57+
return;
58+
}
59+
};
60+
f(trait_);
61+
}

crates/hir-def/src/item_scope.rs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ use syntax::ast;
1616
use thin_vec::ThinVec;
1717

1818
use crate::{
19-
AdtId, BuiltinType, ConstId, ExternBlockId, ExternCrateId, FxIndexMap, HasModule, ImplId,
20-
Lookup, MacroCallStyles, MacroId, ModuleDefId, ModuleId, TraitId, UseId,
19+
AdtId, BuiltinDeriveImplId, BuiltinType, ConstId, ExternBlockId, ExternCrateId, FxIndexMap,
20+
HasModule, ImplId, Lookup, MacroCallStyles, MacroId, ModuleDefId, ModuleId, TraitId, UseId,
2121
db::DefDatabase,
2222
per_ns::{Item, MacrosItem, PerNs, TypesItem, ValuesItem},
2323
visibility::Visibility,
@@ -159,6 +159,7 @@ pub struct ItemScope {
159159
declarations: ThinVec<ModuleDefId>,
160160

161161
impls: ThinVec<ImplId>,
162+
builtin_derive_impls: ThinVec<BuiltinDeriveImplId>,
162163
extern_blocks: ThinVec<ExternBlockId>,
163164
unnamed_consts: ThinVec<ConstId>,
164165
/// Traits imported via `use Trait as _;`.
@@ -329,6 +330,10 @@ impl ItemScope {
329330
self.impls.iter().copied()
330331
}
331332

333+
pub fn builtin_derive_impls(&self) -> impl ExactSizeIterator<Item = BuiltinDeriveImplId> + '_ {
334+
self.builtin_derive_impls.iter().copied()
335+
}
336+
332337
pub fn all_macro_calls(&self) -> impl Iterator<Item = MacroCallId> + '_ {
333338
self.macro_invocations.values().copied().chain(self.attr_macros.values().copied()).chain(
334339
self.derive_macros.values().flat_map(|it| {
@@ -471,6 +476,10 @@ impl ItemScope {
471476
self.impls.push(imp);
472477
}
473478

479+
pub(crate) fn define_builtin_derive_impl(&mut self, imp: BuiltinDeriveImplId) {
480+
self.builtin_derive_impls.push(imp);
481+
}
482+
474483
pub(crate) fn define_extern_block(&mut self, extern_block: ExternBlockId) {
475484
self.extern_blocks.push(extern_block);
476485
}
@@ -811,6 +820,7 @@ impl ItemScope {
811820
unresolved,
812821
declarations,
813822
impls,
823+
builtin_derive_impls,
814824
unnamed_consts,
815825
unnamed_trait_imports,
816826
legacy_macros,
@@ -834,6 +844,7 @@ impl ItemScope {
834844
unresolved.shrink_to_fit();
835845
declarations.shrink_to_fit();
836846
impls.shrink_to_fit();
847+
builtin_derive_impls.shrink_to_fit();
837848
unnamed_consts.shrink_to_fit();
838849
unnamed_trait_imports.shrink_to_fit();
839850
legacy_macros.shrink_to_fit();

crates/hir-def/src/lang_item.rs

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
//!
33
//! This attribute to tell the compiler about semi built-in std library
44
//! features, such as Fn family of traits.
5+
use hir_expand::name::Name;
56
use intern::{Symbol, sym};
67
use stdx::impl_from;
78

@@ -10,7 +11,7 @@ use crate::{
1011
StaticId, StructId, TraitId, TypeAliasId, UnionId,
1112
attrs::AttrFlags,
1213
db::DefDatabase,
13-
nameres::{assoc::TraitItems, crate_def_map, crate_local_def_map},
14+
nameres::{DefMap, assoc::TraitItems, crate_def_map, crate_local_def_map},
1415
};
1516

1617
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -93,6 +94,10 @@ pub fn crate_lang_items(db: &dyn DefDatabase, krate: Crate) -> Option<Box<LangIt
9394
}
9495
}
9596

97+
if matches!(krate.data(db).origin, base_db::CrateOrigin::Lang(base_db::LangCrateOrigin::Core)) {
98+
lang_items.fill_non_lang_core_traits(db, crate_def_map);
99+
}
100+
96101
if lang_items.is_empty() { None } else { Some(Box::new(lang_items)) }
97102
}
98103

@@ -135,6 +140,31 @@ impl LangItems {
135140
}
136141
}
137142

143+
fn resolve_core_trait(
144+
db: &dyn DefDatabase,
145+
core_def_map: &DefMap,
146+
modules: &[Symbol],
147+
name: Symbol,
148+
) -> Option<TraitId> {
149+
let mut current = &core_def_map[core_def_map.root];
150+
for module in modules {
151+
let Some((ModuleDefId::ModuleId(cur), _)) =
152+
current.scope.type_(&Name::new_symbol_root(module.clone()))
153+
else {
154+
return None;
155+
};
156+
if cur.krate(db) != core_def_map.krate() || cur.block(db) != core_def_map.block_id() {
157+
return None;
158+
}
159+
current = &core_def_map[cur];
160+
}
161+
let Some((ModuleDefId::TraitId(trait_), _)) = current.scope.type_(&Name::new_symbol_root(name))
162+
else {
163+
return None;
164+
};
165+
Some(trait_)
166+
}
167+
138168
#[salsa::tracked(returns(as_deref))]
139169
pub(crate) fn crate_notable_traits(db: &dyn DefDatabase, krate: Crate) -> Option<Box<[TraitId]>> {
140170
let mut traits = Vec::new();
@@ -164,6 +194,10 @@ macro_rules! language_item_table {
164194
(
165195
$LangItems:ident =>
166196
$( $(#[$attr:meta])* $lang_item:ident, $module:ident :: $name:ident, $method:ident, $target:ident, $generics:expr; )*
197+
198+
@non_lang_core_traits:
199+
200+
$( core::$($non_lang_module:ident)::*, $non_lang_trait:ident; )*
167201
) => {
168202
#[allow(non_snake_case)] // FIXME: Should we remove this?
169203
#[derive(Debug, Default, Clone, PartialEq, Eq, Hash)]
@@ -172,6 +206,9 @@ macro_rules! language_item_table {
172206
$(#[$attr])*
173207
pub $lang_item: Option<$target>,
174208
)*
209+
$(
210+
pub $non_lang_trait: Option<TraitId>,
211+
)*
175212
}
176213

177214
impl LangItems {
@@ -182,6 +219,7 @@ macro_rules! language_item_table {
182219
/// Merges `self` with `other`, with preference to `self` items.
183220
fn merge_prefer_self(&mut self, other: &Self) {
184221
$( self.$lang_item = self.$lang_item.or(other.$lang_item); )*
222+
$( self.$non_lang_trait = self.$non_lang_trait.or(other.$non_lang_trait); )*
185223
}
186224

187225
fn assign_lang_item(&mut self, name: Symbol, target: LangItemTarget) {
@@ -196,6 +234,10 @@ macro_rules! language_item_table {
196234
_ => {}
197235
}
198236
}
237+
238+
fn fill_non_lang_core_traits(&mut self, db: &dyn DefDatabase, core_def_map: &DefMap) {
239+
$( self.$non_lang_trait = resolve_core_trait(db, core_def_map, &[ $(sym::$non_lang_module),* ], sym::$non_lang_trait); )*
240+
}
199241
}
200242

201243
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -431,4 +473,11 @@ language_item_table! { LangItems =>
431473
String, sym::String, string, StructId, GenericRequirement::None;
432474
CStr, sym::CStr, c_str, StructId, GenericRequirement::None;
433475
Ordering, sym::Ordering, ordering, EnumId, GenericRequirement::None;
476+
477+
@non_lang_core_traits:
478+
core::default, Default;
479+
core::fmt, Debug;
480+
core::hash, Hash;
481+
core::cmp, Ord;
482+
core::cmp, Eq;
434483
}

crates/hir-def/src/lib.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ pub mod dyn_map;
3030

3131
pub mod item_tree;
3232

33+
pub mod builtin_derive;
3334
pub mod lang_item;
3435

3536
pub mod hir;
@@ -80,6 +81,7 @@ pub use hir_expand::{Intern, Lookup, tt};
8081

8182
use crate::{
8283
attrs::AttrFlags,
84+
builtin_derive::BuiltinDeriveImplTrait,
8385
builtin_type::BuiltinType,
8486
db::DefDatabase,
8587
expr_store::ExpressionStoreSourceMap,
@@ -331,6 +333,19 @@ impl ImplId {
331333
}
332334
}
333335

336+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
337+
pub struct BuiltinDeriveImplLoc {
338+
pub adt: AdtId,
339+
pub trait_: BuiltinDeriveImplTrait,
340+
}
341+
342+
#[salsa::interned(debug, no_lifetime)]
343+
#[derive(PartialOrd, Ord)]
344+
pub struct BuiltinDeriveImplId {
345+
#[returns(ref)]
346+
pub loc: BuiltinDeriveImplLoc,
347+
}
348+
334349
type UseLoc = ItemLoc<ast::Use>;
335350
impl_intern!(UseId, UseLoc, intern_use, lookup_intern_use);
336351

@@ -1009,6 +1024,20 @@ fn module_for_assoc_item_loc<'db>(
10091024
id.lookup(db).container.module(db)
10101025
}
10111026

1027+
impl HasModule for BuiltinDeriveImplLoc {
1028+
#[inline]
1029+
fn module(&self, db: &dyn DefDatabase) -> ModuleId {
1030+
self.adt.module(db)
1031+
}
1032+
}
1033+
1034+
impl HasModule for BuiltinDeriveImplId {
1035+
#[inline]
1036+
fn module(&self, db: &dyn DefDatabase) -> ModuleId {
1037+
self.loc(db).module(db)
1038+
}
1039+
}
1040+
10121041
impl HasModule for FunctionId {
10131042
#[inline]
10141043
fn module(&self, db: &dyn DefDatabase) -> ModuleId {

0 commit comments

Comments
 (0)