4
4
//! and the corresponding code mostly in librustc_typeck/check/method/probe.rs.
5
5
use std:: sync:: Arc ;
6
6
7
+ use arrayvec:: ArrayVec ;
7
8
use rustc_hash:: FxHashMap ;
8
9
9
10
use crate :: {
@@ -113,19 +114,32 @@ impl CrateImplBlocks {
113
114
}
114
115
}
115
116
116
- fn def_crate ( db : & impl HirDatabase , cur_crate : Crate , ty : & Ty ) -> Option < Crate > {
117
+ fn def_crates ( db : & impl HirDatabase , cur_crate : Crate , ty : & Ty ) -> Option < ArrayVec < [ Crate ; 2 ] > > {
118
+ // Types like slice can have inherent impls in several crates, (core and alloc).
119
+ // The correspoinding impls are marked with lang items, so we can use them to find the required crates.
120
+ macro_rules! lang_item_crate {
121
+ ( $db: expr, $cur_crate: expr, $( $name: expr) ,+ $( , ) ?) => { {
122
+ let mut v = ArrayVec :: <[ Crate ; 2 ] >:: new( ) ;
123
+ $(
124
+ v. push( $db. lang_item( $cur_crate, $name. into( ) ) ?. krate( $db) ?) ;
125
+ ) +
126
+ Some ( v)
127
+ } } ;
128
+ }
129
+
117
130
match ty {
118
131
Ty :: Apply ( a_ty) => match a_ty. ctor {
119
- TypeCtor :: Adt ( def_id) => def_id. krate ( db) ,
120
- TypeCtor :: Bool => db . lang_item ( cur_crate, "bool" . into ( ) ) ? . krate ( db ) ,
121
- TypeCtor :: Char => db . lang_item ( cur_crate, "char" . into ( ) ) ? . krate ( db ) ,
132
+ TypeCtor :: Adt ( def_id) => Some ( std :: iter :: once ( def_id. krate ( db) ? ) . collect ( ) ) ,
133
+ TypeCtor :: Bool => lang_item_crate ! ( db , cur_crate, "bool" ) ,
134
+ TypeCtor :: Char => lang_item_crate ! ( db , cur_crate, "char" ) ,
122
135
TypeCtor :: Float ( UncertainFloatTy :: Known ( f) ) => {
123
- db . lang_item ( cur_crate, f. ty_to_string ( ) . into ( ) ) ? . krate ( db )
136
+ lang_item_crate ! ( db , cur_crate, f. ty_to_string( ) )
124
137
}
125
138
TypeCtor :: Int ( UncertainIntTy :: Known ( i) ) => {
126
- db . lang_item ( cur_crate, i. ty_to_string ( ) . into ( ) ) ? . krate ( db )
139
+ lang_item_crate ! ( db , cur_crate, i. ty_to_string( ) )
127
140
}
128
- TypeCtor :: Str => db. lang_item ( cur_crate, "str" . into ( ) ) ?. krate ( db) ,
141
+ TypeCtor :: Str => lang_item_crate ! ( db, cur_crate, "str" ) ,
142
+ TypeCtor :: Slice => lang_item_crate ! ( db, cur_crate, "slice_alloc" , "slice" ) ,
129
143
_ => None ,
130
144
} ,
131
145
_ => None ,
@@ -218,19 +232,17 @@ fn iterate_inherent_methods<T>(
218
232
krate : Crate ,
219
233
mut callback : impl FnMut ( & Ty , Function ) -> Option < T > ,
220
234
) -> Option < T > {
221
- let krate = match def_crate ( db, krate, & ty. value ) {
222
- Some ( krate) => krate,
223
- None => return None ,
224
- } ;
225
- let impls = db. impls_in_crate ( krate) ;
235
+ for krate in def_crates ( db, krate, & ty. value ) ? {
236
+ let impls = db. impls_in_crate ( krate) ;
226
237
227
- for impl_block in impls. lookup_impl_blocks ( & ty. value ) {
228
- for item in impl_block. items ( db) {
229
- if let ImplItem :: Method ( f) = item {
230
- let data = f. data ( db) ;
231
- if name. map_or ( true , |name| data. name ( ) == name) && data. has_self_param ( ) {
232
- if let Some ( result) = callback ( & ty. value , f) {
233
- return Some ( result) ;
238
+ for impl_block in impls. lookup_impl_blocks ( & ty. value ) {
239
+ for item in impl_block. items ( db) {
240
+ if let ImplItem :: Method ( f) = item {
241
+ let data = f. data ( db) ;
242
+ if name. map_or ( true , |name| data. name ( ) == name) && data. has_self_param ( ) {
243
+ if let Some ( result) = callback ( & ty. value , f) {
244
+ return Some ( result) ;
245
+ }
234
246
}
235
247
}
236
248
}
@@ -248,13 +260,14 @@ impl Ty {
248
260
krate : Crate ,
249
261
mut callback : impl FnMut ( ImplItem ) -> Option < T > ,
250
262
) -> Option < T > {
251
- let krate = def_crate ( db, krate, & self ) ?;
252
- let impls = db. impls_in_crate ( krate) ;
263
+ for krate in def_crates ( db, krate, & self ) ? {
264
+ let impls = db. impls_in_crate ( krate) ;
253
265
254
- for impl_block in impls. lookup_impl_blocks ( & self ) {
255
- for item in impl_block. items ( db) {
256
- if let Some ( result) = callback ( item) {
257
- return Some ( result) ;
266
+ for impl_block in impls. lookup_impl_blocks ( & self ) {
267
+ for item in impl_block. items ( db) {
268
+ if let Some ( result) = callback ( item) {
269
+ return Some ( result) ;
270
+ }
258
271
}
259
272
}
260
273
}
0 commit comments