Skip to content

Commit 8c5a68e

Browse files
authored
Merge pull request #21200 from ChayimFriedman2/fake-impls
perf: Do not really expand builtin derives, instead treat them specifically
2 parents 97ac158 + 6ed7084 commit 8c5a68e

45 files changed

Lines changed: 2728 additions & 796 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

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: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
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::{InFile, builtin::BuiltinDeriveExpander, name::Name};
7+
use intern::{Symbol, sym};
8+
use tt::TextRange;
9+
10+
use crate::{
11+
AdtId, BuiltinDeriveImplId, BuiltinDeriveImplLoc, FunctionId, HasModule, db::DefDatabase,
12+
};
13+
14+
macro_rules! declare_enum {
15+
( $( $trait:ident => [ $( $method:ident ),* ] ),* $(,)? ) => {
16+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
17+
pub enum BuiltinDeriveImplTrait {
18+
$( $trait, )*
19+
}
20+
21+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
22+
#[allow(non_camel_case_types)]
23+
pub enum BuiltinDeriveImplMethod {
24+
$( $( $method, )* )*
25+
}
26+
27+
impl BuiltinDeriveImplTrait {
28+
#[inline]
29+
pub fn name(self) -> Symbol {
30+
match self {
31+
$( Self::$trait => sym::$trait, )*
32+
}
33+
}
34+
35+
#[inline]
36+
pub fn get_id(self, lang_items: &crate::lang_item::LangItems) -> Option<crate::TraitId> {
37+
match self {
38+
$( Self::$trait => lang_items.$trait, )*
39+
}
40+
}
41+
42+
#[inline]
43+
pub fn get_method(self, method_name: &Symbol) -> Option<BuiltinDeriveImplMethod> {
44+
match self {
45+
$(
46+
Self::$trait => {
47+
match method_name {
48+
$( _ if *method_name == sym::$method => Some(BuiltinDeriveImplMethod::$method), )*
49+
_ => None,
50+
}
51+
}
52+
)*
53+
}
54+
}
55+
56+
#[inline]
57+
pub fn all_methods(self) -> &'static [BuiltinDeriveImplMethod] {
58+
match self {
59+
$( Self::$trait => &[ $(BuiltinDeriveImplMethod::$method),* ], )*
60+
}
61+
}
62+
}
63+
64+
impl BuiltinDeriveImplMethod {
65+
#[inline]
66+
pub fn name(self) -> Symbol {
67+
match self {
68+
$( $( BuiltinDeriveImplMethod::$method => sym::$method, )* )*
69+
}
70+
}
71+
}
72+
};
73+
}
74+
75+
declare_enum!(
76+
Copy => [],
77+
Clone => [clone],
78+
Default => [default],
79+
Debug => [fmt],
80+
Hash => [hash],
81+
Ord => [cmp],
82+
PartialOrd => [partial_cmp],
83+
Eq => [],
84+
PartialEq => [eq],
85+
CoerceUnsized => [],
86+
DispatchFromDyn => [],
87+
);
88+
89+
impl BuiltinDeriveImplMethod {
90+
pub fn trait_method(
91+
self,
92+
db: &dyn DefDatabase,
93+
impl_: BuiltinDeriveImplId,
94+
) -> Option<FunctionId> {
95+
let loc = impl_.loc(db);
96+
let lang_items = crate::lang_item::lang_items(db, loc.krate(db));
97+
let trait_ = impl_.loc(db).trait_.get_id(lang_items)?;
98+
trait_.trait_items(db).method_by_name(&Name::new_symbol_root(self.name()))
99+
}
100+
}
101+
102+
pub(crate) fn with_derive_traits(
103+
derive: BuiltinDeriveExpander,
104+
mut f: impl FnMut(BuiltinDeriveImplTrait),
105+
) {
106+
let trait_ = match derive {
107+
BuiltinDeriveExpander::Copy => BuiltinDeriveImplTrait::Copy,
108+
BuiltinDeriveExpander::Clone => BuiltinDeriveImplTrait::Clone,
109+
BuiltinDeriveExpander::Default => BuiltinDeriveImplTrait::Default,
110+
BuiltinDeriveExpander::Debug => BuiltinDeriveImplTrait::Debug,
111+
BuiltinDeriveExpander::Hash => BuiltinDeriveImplTrait::Hash,
112+
BuiltinDeriveExpander::Ord => BuiltinDeriveImplTrait::Ord,
113+
BuiltinDeriveExpander::PartialOrd => BuiltinDeriveImplTrait::PartialOrd,
114+
BuiltinDeriveExpander::Eq => BuiltinDeriveImplTrait::Eq,
115+
BuiltinDeriveExpander::PartialEq => BuiltinDeriveImplTrait::PartialEq,
116+
BuiltinDeriveExpander::CoercePointee => {
117+
f(BuiltinDeriveImplTrait::CoerceUnsized);
118+
f(BuiltinDeriveImplTrait::DispatchFromDyn);
119+
return;
120+
}
121+
};
122+
f(trait_);
123+
}
124+
125+
impl BuiltinDeriveImplLoc {
126+
pub fn source(&self, db: &dyn DefDatabase) -> InFile<TextRange> {
127+
let (adt_ast_id, module) = match self.adt {
128+
AdtId::StructId(adt) => {
129+
let adt_loc = adt.loc(db);
130+
(adt_loc.id.upcast(), adt_loc.container)
131+
}
132+
AdtId::UnionId(adt) => {
133+
let adt_loc = adt.loc(db);
134+
(adt_loc.id.upcast(), adt_loc.container)
135+
}
136+
AdtId::EnumId(adt) => {
137+
let adt_loc = adt.loc(db);
138+
(adt_loc.id.upcast(), adt_loc.container)
139+
}
140+
};
141+
let derive_range = self.derive_attr_id.find_derive_range(
142+
db,
143+
module.krate(db),
144+
adt_ast_id,
145+
self.derive_index,
146+
);
147+
adt_ast_id.with_value(derive_range)
148+
}
149+
}

crates/hir-def/src/item_scope.rs

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,15 @@ use indexmap::map::Entry;
99
use itertools::Itertools;
1010
use la_arena::Idx;
1111
use rustc_hash::{FxHashMap, FxHashSet};
12-
use smallvec::{SmallVec, smallvec};
12+
use smallvec::SmallVec;
1313
use span::Edition;
1414
use stdx::format_to;
1515
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
}
@@ -522,12 +531,13 @@ impl ItemScope {
522531
adt: AstId<ast::Adt>,
523532
attr_id: AttrId,
524533
attr_call_id: MacroCallId,
525-
len: usize,
534+
mut derive_call_ids: SmallVec<[Option<MacroCallId>; 4]>,
526535
) {
536+
derive_call_ids.shrink_to_fit();
527537
self.derive_macros.entry(adt).or_default().push(DeriveMacroInvocation {
528538
attr_id,
529539
attr_call_id,
530-
derive_call_ids: smallvec![None; len],
540+
derive_call_ids,
531541
});
532542
}
533543

@@ -811,6 +821,7 @@ impl ItemScope {
811821
unresolved,
812822
declarations,
813823
impls,
824+
builtin_derive_impls,
814825
unnamed_consts,
815826
unnamed_trait_imports,
816827
legacy_macros,
@@ -834,6 +845,7 @@ impl ItemScope {
834845
unresolved.shrink_to_fit();
835846
declarations.shrink_to_fit();
836847
impls.shrink_to_fit();
848+
builtin_derive_impls.shrink_to_fit();
837849
unnamed_consts.shrink_to_fit();
838850
unnamed_trait_imports.shrink_to_fit();
839851
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();
@@ -158,6 +188,10 @@ macro_rules! language_item_table {
158188
(
159189
$LangItems:ident =>
160190
$( $(#[$attr:meta])* $lang_item:ident, $module:ident :: $name:ident, $target:ident; )*
191+
192+
@non_lang_core_traits:
193+
194+
$( core::$($non_lang_module:ident)::*, $non_lang_trait:ident; )*
161195
) => {
162196
#[allow(non_snake_case)] // FIXME: Should we remove this?
163197
#[derive(Debug, Default, Clone, PartialEq, Eq, Hash)]
@@ -166,6 +200,9 @@ macro_rules! language_item_table {
166200
$(#[$attr])*
167201
pub $lang_item: Option<$target>,
168202
)*
203+
$(
204+
pub $non_lang_trait: Option<TraitId>,
205+
)*
169206
}
170207

171208
impl LangItems {
@@ -176,6 +213,7 @@ macro_rules! language_item_table {
176213
/// Merges `self` with `other`, with preference to `self` items.
177214
fn merge_prefer_self(&mut self, other: &Self) {
178215
$( self.$lang_item = self.$lang_item.or(other.$lang_item); )*
216+
$( self.$non_lang_trait = self.$non_lang_trait.or(other.$non_lang_trait); )*
179217
}
180218

181219
fn assign_lang_item(&mut self, name: Symbol, target: LangItemTarget) {
@@ -190,6 +228,10 @@ macro_rules! language_item_table {
190228
_ => {}
191229
}
192230
}
231+
232+
fn fill_non_lang_core_traits(&mut self, db: &dyn DefDatabase, core_def_map: &DefMap) {
233+
$( self.$non_lang_trait = resolve_core_trait(db, core_def_map, &[ $(sym::$non_lang_module),* ], sym::$non_lang_trait); )*
234+
}
193235
}
194236

195237
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -426,4 +468,11 @@ language_item_table! { LangItems =>
426468
String, sym::String, StructId;
427469
CStr, sym::CStr, StructId;
428470
Ordering, sym::Ordering, EnumId;
471+
472+
@non_lang_core_traits:
473+
core::default, Default;
474+
core::fmt, Debug;
475+
core::hash, Hash;
476+
core::cmp, Ord;
477+
core::cmp, Eq;
429478
}

0 commit comments

Comments
 (0)