@@ -13,6 +13,7 @@ use hir_def::{
13
13
} ;
14
14
use hir_expand:: name:: Name ;
15
15
use rustc_hash:: { FxHashMap , FxHashSet } ;
16
+ use stdx:: always;
16
17
17
18
use crate :: {
18
19
autoderef,
@@ -21,50 +22,89 @@ use crate::{
21
22
primitive:: { self , FloatTy , IntTy , UintTy } ,
22
23
static_lifetime,
23
24
utils:: all_super_traits,
24
- AdtId , Canonical , CanonicalVarKinds , DebruijnIndex , FnPointer , FnSig , ForeignDefId ,
25
- InEnvironment , Interner , Scalar , Substitution , TraitEnvironment , TraitRefExt , Ty , TyBuilder ,
26
- TyExt , TyKind ,
25
+ AdtId , Canonical , CanonicalVarKinds , DebruijnIndex , ForeignDefId , InEnvironment , Interner ,
26
+ Scalar , Substitution , TraitEnvironment , TraitRefExt , Ty , TyBuilder , TyExt , TyKind ,
27
27
} ;
28
28
29
29
/// This is used as a key for indexing impls.
30
30
#[ derive( Debug , Copy , Clone , PartialEq , Eq , Hash ) ]
31
31
pub enum TyFingerprint {
32
+ // These are lang item impls:
32
33
Str ,
33
34
Slice ,
34
35
Array ,
35
36
Never ,
36
37
RawPtr ( Mutability ) ,
37
38
Scalar ( Scalar ) ,
39
+ // These can have user-defined impls:
38
40
Adt ( hir_def:: AdtId ) ,
39
41
Dyn ( TraitId ) ,
40
- Tuple ( usize ) ,
41
42
ForeignType ( ForeignDefId ) ,
42
- FnPtr ( usize , FnSig ) ,
43
+ // These only exist for trait impls
44
+ Unit ,
45
+ Unnameable ,
46
+ Function ( u32 ) ,
43
47
}
44
48
45
49
impl TyFingerprint {
46
- /// Creates a TyFingerprint for looking up an impl. Only certain types can
47
- /// have impls: if we have some `struct S`, we can have an `impl S`, but not
48
- /// `impl &S`. Hence, this will return `None` for reference types and such.
49
- pub fn for_impl ( ty : & Ty ) -> Option < TyFingerprint > {
50
+ /// Creates a TyFingerprint for looking up an inherent impl. Only certain
51
+ /// types can have inherent impls: if we have some `struct S`, we can have
52
+ /// an `impl S`, but not `impl &S`. Hence, this will return `None` for
53
+ /// reference types and such.
54
+ pub fn for_inherent_impl ( ty : & Ty ) -> Option < TyFingerprint > {
50
55
let fp = match ty. kind ( & Interner ) {
51
56
TyKind :: Str => TyFingerprint :: Str ,
52
57
TyKind :: Never => TyFingerprint :: Never ,
53
58
TyKind :: Slice ( ..) => TyFingerprint :: Slice ,
54
59
TyKind :: Array ( ..) => TyFingerprint :: Array ,
55
60
TyKind :: Scalar ( scalar) => TyFingerprint :: Scalar ( * scalar) ,
56
61
TyKind :: Adt ( AdtId ( adt) , _) => TyFingerprint :: Adt ( * adt) ,
57
- TyKind :: Tuple ( cardinality, _) => TyFingerprint :: Tuple ( * cardinality) ,
58
62
TyKind :: Raw ( mutability, ..) => TyFingerprint :: RawPtr ( * mutability) ,
59
63
TyKind :: Foreign ( alias_id, ..) => TyFingerprint :: ForeignType ( * alias_id) ,
60
- TyKind :: Function ( FnPointer { sig, substitution : substs, .. } ) => {
61
- TyFingerprint :: FnPtr ( substs. 0 . len ( & Interner ) - 1 , * sig)
62
- }
63
64
TyKind :: Dyn ( _) => ty. dyn_trait ( ) . map ( |trait_| TyFingerprint :: Dyn ( trait_) ) ?,
64
65
_ => return None ,
65
66
} ;
66
67
Some ( fp)
67
68
}
69
+
70
+ /// Creates a TyFingerprint for looking up a trait impl.
71
+ pub fn for_trait_impl ( ty : & Ty ) -> Option < TyFingerprint > {
72
+ let fp = match ty. kind ( & Interner ) {
73
+ TyKind :: Str => TyFingerprint :: Str ,
74
+ TyKind :: Never => TyFingerprint :: Never ,
75
+ TyKind :: Slice ( ..) => TyFingerprint :: Slice ,
76
+ TyKind :: Array ( ..) => TyFingerprint :: Array ,
77
+ TyKind :: Scalar ( scalar) => TyFingerprint :: Scalar ( * scalar) ,
78
+ TyKind :: Adt ( AdtId ( adt) , _) => TyFingerprint :: Adt ( * adt) ,
79
+ TyKind :: Raw ( mutability, ..) => TyFingerprint :: RawPtr ( * mutability) ,
80
+ TyKind :: Foreign ( alias_id, ..) => TyFingerprint :: ForeignType ( * alias_id) ,
81
+ TyKind :: Dyn ( _) => ty. dyn_trait ( ) . map ( |trait_| TyFingerprint :: Dyn ( trait_) ) ?,
82
+ TyKind :: Ref ( _, _, ty) => return TyFingerprint :: for_trait_impl ( ty) ,
83
+ TyKind :: Tuple ( _, subst) => {
84
+ let first_ty = subst. interned ( ) . get ( 0 ) . map ( |arg| arg. assert_ty_ref ( & Interner ) ) ;
85
+ if let Some ( ty) = first_ty {
86
+ return TyFingerprint :: for_trait_impl ( ty) ;
87
+ } else {
88
+ TyFingerprint :: Unit
89
+ }
90
+ }
91
+ TyKind :: AssociatedType ( _, _)
92
+ | TyKind :: OpaqueType ( _, _)
93
+ | TyKind :: FnDef ( _, _)
94
+ | TyKind :: Closure ( _, _)
95
+ | TyKind :: Generator ( ..)
96
+ | TyKind :: GeneratorWitness ( ..) => TyFingerprint :: Unnameable ,
97
+ TyKind :: Function ( fn_ptr) => {
98
+ TyFingerprint :: Function ( fn_ptr. substitution . 0 . len ( & Interner ) as u32 )
99
+ }
100
+ TyKind :: Alias ( _)
101
+ | TyKind :: Placeholder ( _)
102
+ | TyKind :: BoundVar ( _)
103
+ | TyKind :: InferenceVar ( _, _)
104
+ | TyKind :: Error => return None ,
105
+ } ;
106
+ Some ( fp)
107
+ }
68
108
}
69
109
70
110
pub ( crate ) const ALL_INT_FPS : [ TyFingerprint ; 12 ] = [
@@ -112,7 +152,7 @@ impl TraitImpls {
112
152
None => continue ,
113
153
} ;
114
154
let self_ty = db. impl_self_ty ( impl_id) ;
115
- let self_ty_fp = TyFingerprint :: for_impl ( self_ty. skip_binders ( ) ) ;
155
+ let self_ty_fp = TyFingerprint :: for_trait_impl ( self_ty. skip_binders ( ) ) ;
116
156
impls
117
157
. map
118
158
. entry ( target_trait)
@@ -157,10 +197,13 @@ impl TraitImpls {
157
197
}
158
198
159
199
/// Queries all trait impls for the given type.
160
- pub fn for_self_ty ( & self , fp : TyFingerprint ) -> impl Iterator < Item = ImplId > + ' _ {
200
+ pub fn for_self_ty_without_blanket_impls (
201
+ & self ,
202
+ fp : TyFingerprint ,
203
+ ) -> impl Iterator < Item = ImplId > + ' _ {
161
204
self . map
162
205
. values ( )
163
- . flat_map ( move |impls| impls. get ( & None ) . into_iter ( ) . chain ( impls . get ( & Some ( fp) ) ) )
206
+ . flat_map ( move |impls| impls. get ( & Some ( fp) ) . into_iter ( ) )
164
207
. flat_map ( |it| it. iter ( ) . copied ( ) )
165
208
}
166
209
@@ -215,7 +258,9 @@ impl InherentImpls {
215
258
}
216
259
217
260
let self_ty = db. impl_self_ty ( impl_id) ;
218
- if let Some ( fp) = TyFingerprint :: for_impl ( self_ty. skip_binders ( ) ) {
261
+ let fp = TyFingerprint :: for_inherent_impl ( self_ty. skip_binders ( ) ) ;
262
+ always ! ( fp. is_some( ) ) ;
263
+ if let Some ( fp) = fp {
219
264
map. entry ( fp) . or_default ( ) . push ( impl_id) ;
220
265
}
221
266
}
@@ -228,7 +273,7 @@ impl InherentImpls {
228
273
}
229
274
230
275
pub fn for_self_ty ( & self , self_ty : & Ty ) -> & [ ImplId ] {
231
- match TyFingerprint :: for_impl ( self_ty) {
276
+ match TyFingerprint :: for_inherent_impl ( self_ty) {
232
277
Some ( fp) => self . map . get ( & fp) . map ( |vec| vec. as_ref ( ) ) . unwrap_or ( & [ ] ) ,
233
278
None => & [ ] ,
234
279
}
0 commit comments