Skip to content

Commit ebb8912

Browse files
committed
Split and document array method resolution logic.
1 parent 9593fe6 commit ebb8912

File tree

1 file changed

+53
-34
lines changed

1 file changed

+53
-34
lines changed

crates/hir_ty/src/method_resolution.rs

+53-34
Original file line numberDiff line numberDiff line change
@@ -709,6 +709,33 @@ fn iterate_trait_method_candidates(
709709
false
710710
}
711711

712+
fn filter_inherent_impls_for_self_ty<'i>(
713+
impls: &'i InherentImpls,
714+
self_ty: &Ty,
715+
) -> impl Iterator<Item = &'i ImplId> {
716+
// inherent methods on arrays are fingerprinted as [T; {unknown}], so we must also consider them when
717+
// resolving a method call on an array with a known len
718+
let array_impls = {
719+
if let TyKind::Array(parameters, array_len) = self_ty.kind(&Interner) {
720+
if !array_len.is_unknown() {
721+
let unknown_array_len_ty =
722+
TyKind::Array(parameters.clone(), consteval::usize_const(None))
723+
.intern(&Interner);
724+
725+
Some(impls.for_self_ty(&unknown_array_len_ty))
726+
} else {
727+
None
728+
}
729+
} else {
730+
None
731+
}
732+
}
733+
.into_iter()
734+
.flatten();
735+
736+
impls.for_self_ty(self_ty).iter().chain(array_impls)
737+
}
738+
712739
fn iterate_inherent_methods(
713740
self_ty: &Canonical<Ty>,
714741
db: &dyn HirDatabase,
@@ -726,25 +753,7 @@ fn iterate_inherent_methods(
726753
for krate in def_crates {
727754
let impls = db.inherent_impls_in_crate(krate);
728755

729-
let impls_for_self_ty = impls.for_self_ty(&self_ty.value).iter().chain(
730-
{
731-
if let TyKind::Array(parameters, array_len) = self_ty.value.kind(&Interner) {
732-
if !array_len.is_unknown() {
733-
let unknown_array_len_ty =
734-
TyKind::Array(parameters.clone(), consteval::usize_const(None))
735-
.intern(&Interner);
736-
737-
Some(impls.for_self_ty(&unknown_array_len_ty))
738-
} else {
739-
None
740-
}
741-
} else {
742-
None
743-
}
744-
}
745-
.into_iter()
746-
.flatten(),
747-
);
756+
let impls_for_self_ty = filter_inherent_impls_for_self_ty(&impls, &self_ty.value);
748757

749758
for &impl_def in impls_for_self_ty {
750759
for &item in db.impl_data(impl_def).items.iter() {
@@ -798,6 +807,28 @@ pub fn resolve_indexing_op(
798807
None
799808
}
800809

810+
fn is_transformed_receiver_ty_equal(transformed_receiver_ty: &Ty, receiver_ty: &Ty) -> bool {
811+
if transformed_receiver_ty == receiver_ty {
812+
return true;
813+
}
814+
815+
// a transformed receiver may be considered equal (and a valid method call candidate) if it is an array
816+
// with an unknown (i.e. generic) length, and the receiver is an array with the same item type but a known len,
817+
// this allows inherent methods on arrays to be considered valid resolution candidates
818+
match (transformed_receiver_ty.kind(&Interner), receiver_ty.kind(&Interner)) {
819+
(
820+
TyKind::Array(transformed_array_ty, transformed_array_len),
821+
TyKind::Array(receiver_array_ty, receiver_array_len),
822+
) if transformed_array_ty == receiver_array_ty
823+
&& transformed_array_len.is_unknown()
824+
&& !receiver_array_len.is_unknown() =>
825+
{
826+
true
827+
}
828+
_ => false,
829+
}
830+
}
831+
801832
fn is_valid_candidate(
802833
db: &dyn HirDatabase,
803834
env: Arc<TraitEnvironment>,
@@ -823,21 +854,9 @@ fn is_valid_candidate(
823854
Some(ty) => ty,
824855
None => return false,
825856
};
826-
if transformed_receiver_ty != receiver_ty.value {
827-
match (
828-
transformed_receiver_ty.kind(&Interner),
829-
receiver_ty.value.kind(&Interner),
830-
) {
831-
(
832-
TyKind::Array(transformed_array_ty, transformed_array_len),
833-
TyKind::Array(receiver_array_ty, receiver_array_len),
834-
) if transformed_array_ty == receiver_array_ty
835-
&& transformed_array_len.is_unknown()
836-
&& !receiver_array_len.is_unknown() => {}
837-
_ => {
838-
return false;
839-
}
840-
}
857+
858+
if !is_transformed_receiver_ty_equal(&transformed_receiver_ty, &receiver_ty.value) {
859+
return false;
841860
}
842861
}
843862
if let Some(from_module) = visible_from_module {

0 commit comments

Comments
 (0)