Skip to content

Commit bcbea3b

Browse files
Make builtin derives cheaper, by not really expanding them, instead store them unexpanded
1 parent 3429867 commit bcbea3b

File tree

21 files changed

+1135
-152
lines changed

21 files changed

+1135
-152
lines changed

crates/hir-def/src/attrs.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,7 @@ fn match_attr_flags(attr_flags: &mut AttrFlags, attr: Meta) -> ControlFlow<Infal
185185
"deprecated" => attr_flags.insert(AttrFlags::IS_DEPRECATED),
186186
"macro_export" => attr_flags.insert(AttrFlags::IS_MACRO_EXPORT),
187187
"no_mangle" => attr_flags.insert(AttrFlags::NO_MANGLE),
188+
"pointee" => attr_flags.insert(AttrFlags::IS_POINTEE),
188189
"non_exhaustive" => attr_flags.insert(AttrFlags::NON_EXHAUSTIVE),
189190
"ignore" => attr_flags.insert(AttrFlags::IS_IGNORE),
190191
"bench" => attr_flags.insert(AttrFlags::IS_BENCH),
@@ -286,6 +287,7 @@ bitflags::bitflags! {
286287
const RUSTC_PAREN_SUGAR = 1 << 42;
287288
const RUSTC_COINDUCTIVE = 1 << 43;
288289
const RUSTC_FORCE_INLINE = 1 << 44;
290+
const IS_POINTEE = 1 << 45;
289291
}
290292
}
291293

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: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,9 @@ use syntax::ast;
1616
use thin_vec::ThinVec;
1717

1818
use crate::{
19-
AdtId, BuiltinType, ConstId, ExternBlockId, ExternCrateId, FxIndexMap, HasModule, ImplId,
20-
LocalModuleId, Lookup, MacroCallStyles, MacroId, ModuleDefId, ModuleId, TraitId, UseId,
19+
AdtId, BuiltinDeriveImplId, BuiltinType, ConstId, ExternBlockId, ExternCrateId, FxIndexMap,
20+
HasModule, ImplId, LocalModuleId, Lookup, MacroCallStyles, MacroId, ModuleDefId, ModuleId,
21+
TraitId, UseId,
2122
db::DefDatabase,
2223
per_ns::{Item, MacrosItem, PerNs, TypesItem, ValuesItem},
2324
visibility::Visibility,
@@ -159,6 +160,7 @@ pub struct ItemScope {
159160
declarations: ThinVec<ModuleDefId>,
160161

161162
impls: ThinVec<ImplId>,
163+
builtin_derive_impls: ThinVec<BuiltinDeriveImplId>,
162164
extern_blocks: ThinVec<ExternBlockId>,
163165
unnamed_consts: ThinVec<ConstId>,
164166
/// Traits imported via `use Trait as _;`.
@@ -333,6 +335,10 @@ impl ItemScope {
333335
self.impls.iter().copied()
334336
}
335337

338+
pub fn builtin_derive_impls(&self) -> impl ExactSizeIterator<Item = BuiltinDeriveImplId> + '_ {
339+
self.builtin_derive_impls.iter().copied()
340+
}
341+
336342
pub fn all_macro_calls(&self) -> impl Iterator<Item = MacroCallId> + '_ {
337343
self.macro_invocations.values().copied().chain(self.attr_macros.values().copied()).chain(
338344
self.derive_macros.values().flat_map(|it| {
@@ -475,6 +481,10 @@ impl ItemScope {
475481
self.impls.push(imp);
476482
}
477483

484+
pub(crate) fn define_builtin_derive_impl(&mut self, imp: BuiltinDeriveImplId) {
485+
self.builtin_derive_impls.push(imp);
486+
}
487+
478488
pub(crate) fn define_extern_block(&mut self, extern_block: ExternBlockId) {
479489
self.extern_blocks.push(extern_block);
480490
}
@@ -815,6 +825,7 @@ impl ItemScope {
815825
unresolved,
816826
declarations,
817827
impls,
828+
builtin_derive_impls,
818829
unnamed_consts,
819830
unnamed_trait_imports,
820831
legacy_macros,
@@ -838,6 +849,7 @@ impl ItemScope {
838849
unresolved.shrink_to_fit();
839850
declarations.shrink_to_fit();
840851
impls.shrink_to_fit();
852+
builtin_derive_impls.shrink_to_fit();
841853
unnamed_consts.shrink_to_fit();
842854
unnamed_trait_imports.shrink_to_fit();
843855
legacy_macros.shrink_to_fit();

crates/hir-def/src/lang_item.rs

Lines changed: 45 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(crate_def_map);
99+
}
100+
96101
if lang_items.is_empty() { None } else { Some(Box::new(lang_items)) }
97102
}
98103

@@ -134,6 +139,26 @@ impl LangItems {
134139
}
135140
}
136141

142+
fn resolve_core_trait(core_def_map: &DefMap, modules: &[Symbol], name: Symbol) -> Option<TraitId> {
143+
let mut current = &core_def_map[DefMap::ROOT];
144+
for module in modules {
145+
let Some((ModuleDefId::ModuleId(cur), _)) =
146+
current.scope.type_(&Name::new_symbol_root(module.clone()))
147+
else {
148+
return None;
149+
};
150+
if cur.krate != core_def_map.krate() || cur.block != core_def_map.block_id() {
151+
return None;
152+
}
153+
current = &core_def_map[cur.local_id];
154+
}
155+
let Some((ModuleDefId::TraitId(trait_), _)) = current.scope.type_(&Name::new_symbol_root(name))
156+
else {
157+
return None;
158+
};
159+
Some(trait_)
160+
}
161+
137162
#[salsa::tracked(returns(as_deref))]
138163
pub(crate) fn crate_notable_traits(db: &dyn DefDatabase, krate: Crate) -> Option<Box<[TraitId]>> {
139164
let mut traits = Vec::new();
@@ -163,6 +188,10 @@ macro_rules! language_item_table {
163188
(
164189
$LangItems:ident =>
165190
$( $(#[$attr:meta])* $lang_item:ident, $module:ident :: $name:ident, $method:ident, $target:ident, $generics:expr; )*
191+
192+
@non_lang_core_traits:
193+
194+
$( core::$($non_lang_module:ident)::*, $non_lang_trait:ident; )*
166195
) => {
167196
#[allow(non_snake_case)] // FIXME: Should we remove this?
168197
#[derive(Debug, Default, Clone, PartialEq, Eq, Hash)]
@@ -171,6 +200,9 @@ macro_rules! language_item_table {
171200
$(#[$attr])*
172201
pub $lang_item: Option<$target>,
173202
)*
203+
$(
204+
pub $non_lang_trait: Option<TraitId>,
205+
)*
174206
}
175207

176208
impl LangItems {
@@ -181,6 +213,7 @@ macro_rules! language_item_table {
181213
/// Merges `self` with `other`, with preference to `self` items.
182214
fn merge_prefer_self(&mut self, other: &Self) {
183215
$( self.$lang_item = self.$lang_item.or(other.$lang_item); )*
216+
$( self.$non_lang_trait = self.$non_lang_trait.or(other.$non_lang_trait); )*
184217
}
185218

186219
fn assign_lang_item(&mut self, name: Symbol, target: LangItemTarget) {
@@ -195,6 +228,10 @@ macro_rules! language_item_table {
195228
_ => {}
196229
}
197230
}
231+
232+
fn fill_non_lang_core_traits(&mut self, core_def_map: &DefMap) {
233+
$( self.$non_lang_trait = resolve_core_trait(core_def_map, &[ $(sym::$non_lang_module),* ], sym::$non_lang_trait); )*
234+
}
198235
}
199236

200237
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -430,4 +467,11 @@ language_item_table! { LangItems =>
430467
String, sym::String, string, StructId, GenericRequirement::None;
431468
CStr, sym::CStr, c_str, StructId, GenericRequirement::None;
432469
Ordering, sym::Ordering, ordering, EnumId, GenericRequirement::None;
470+
471+
@non_lang_core_traits:
472+
core::default, Default;
473+
core::fmt, Debug;
474+
core::hash, Hash;
475+
core::cmp, Ord;
476+
core::cmp, Eq;
433477
}

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;
@@ -81,6 +82,7 @@ pub use hir_expand::{Intern, Lookup, tt};
8182

8283
use crate::{
8384
attrs::AttrFlags,
85+
builtin_derive::BuiltinDeriveImplTrait,
8486
builtin_type::BuiltinType,
8587
db::DefDatabase,
8688
expr_store::ExpressionStoreSourceMap,
@@ -332,6 +334,19 @@ impl ImplId {
332334
}
333335
}
334336

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

@@ -1109,6 +1124,20 @@ fn module_for_assoc_item_loc<'db>(
11091124
id.lookup(db).container.module(db)
11101125
}
11111126

1127+
impl HasModule for BuiltinDeriveImplLoc {
1128+
#[inline]
1129+
fn module(&self, db: &dyn DefDatabase) -> ModuleId {
1130+
self.adt.module(db)
1131+
}
1132+
}
1133+
1134+
impl HasModule for BuiltinDeriveImplId {
1135+
#[inline]
1136+
fn module(&self, db: &dyn DefDatabase) -> ModuleId {
1137+
self.loc(db).module(db)
1138+
}
1139+
}
1140+
11121141
impl HasModule for FunctionId {
11131142
#[inline]
11141143
fn module(&self, db: &dyn DefDatabase) -> ModuleId {

0 commit comments

Comments
 (0)