Skip to content

Commit ba97a5f

Browse files
bors[bot]sinkuu
andcommitted
Merge #1436
1436: Method resolution for slices r=sinkuu a=sinkuu `impl<T> [T]` is separately defined in `core` and `alloc`, so I changed `def_crate` function in `method_resolution.rs` to return multiple crates. Co-authored-by: Shotaro Yamada <[email protected]>
2 parents 364ac9b + 9668737 commit ba97a5f

File tree

1 file changed

+38
-25
lines changed

1 file changed

+38
-25
lines changed

crates/ra_hir/src/ty/method_resolution.rs

Lines changed: 38 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
//! and the corresponding code mostly in librustc_typeck/check/method/probe.rs.
55
use std::sync::Arc;
66

7+
use arrayvec::ArrayVec;
78
use rustc_hash::FxHashMap;
89

910
use crate::{
@@ -113,19 +114,32 @@ impl CrateImplBlocks {
113114
}
114115
}
115116

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+
117130
match ty {
118131
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"),
122135
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())
124137
}
125138
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())
127140
}
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"),
129143
_ => None,
130144
},
131145
_ => None,
@@ -218,19 +232,17 @@ fn iterate_inherent_methods<T>(
218232
krate: Crate,
219233
mut callback: impl FnMut(&Ty, Function) -> Option<T>,
220234
) -> 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);
226237

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+
}
234246
}
235247
}
236248
}
@@ -248,13 +260,14 @@ impl Ty {
248260
krate: Crate,
249261
mut callback: impl FnMut(ImplItem) -> Option<T>,
250262
) -> 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);
253265

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+
}
258271
}
259272
}
260273
}

0 commit comments

Comments
 (0)