diff options
author | Jonas Schievink <[email protected]> | 2021-06-01 20:33:14 +0100 |
---|---|---|
committer | Jonas Schievink <[email protected]> | 2021-06-01 20:34:08 +0100 |
commit | 955064b6aaa5c24e980328f9d9fbe731cc29636c (patch) | |
tree | 533c9942faa54bb7859c0fb986c5699847c7cea2 /crates/hir_ty/src/method_resolution.rs | |
parent | dbdfeeeff91b5e42d8687df09dda1d29f99b34f8 (diff) |
Implement `#[rustc_skip_array_during_method_dispatch]`
Diffstat (limited to 'crates/hir_ty/src/method_resolution.rs')
-rw-r--r-- | crates/hir_ty/src/method_resolution.rs | 16 |
1 files changed, 15 insertions, 1 deletions
diff --git a/crates/hir_ty/src/method_resolution.rs b/crates/hir_ty/src/method_resolution.rs index af6b6cda7..a23527f7d 100644 --- a/crates/hir_ty/src/method_resolution.rs +++ b/crates/hir_ty/src/method_resolution.rs | |||
@@ -5,7 +5,7 @@ | |||
5 | use std::{iter, sync::Arc}; | 5 | use std::{iter, sync::Arc}; |
6 | 6 | ||
7 | use arrayvec::ArrayVec; | 7 | use arrayvec::ArrayVec; |
8 | use base_db::CrateId; | 8 | use base_db::{CrateId, Edition}; |
9 | use chalk_ir::{cast::Cast, Mutability, UniverseIndex}; | 9 | use chalk_ir::{cast::Cast, Mutability, UniverseIndex}; |
10 | use hir_def::{ | 10 | use hir_def::{ |
11 | lang_item::LangItemTarget, nameres::DefMap, AssocContainerId, AssocItemId, FunctionId, | 11 | lang_item::LangItemTarget, nameres::DefMap, AssocContainerId, AssocItemId, FunctionId, |
@@ -639,6 +639,7 @@ fn iterate_trait_method_candidates( | |||
639 | receiver_ty: Option<&Canonical<Ty>>, | 639 | receiver_ty: Option<&Canonical<Ty>>, |
640 | callback: &mut dyn FnMut(&Ty, AssocItemId) -> bool, | 640 | callback: &mut dyn FnMut(&Ty, AssocItemId) -> bool, |
641 | ) -> bool { | 641 | ) -> bool { |
642 | let receiver_is_array = matches!(self_ty.value.kind(&Interner), chalk_ir::TyKind::Array(..)); | ||
642 | // if ty is `dyn Trait`, the trait doesn't need to be in scope | 643 | // if ty is `dyn Trait`, the trait doesn't need to be in scope |
643 | let inherent_trait = | 644 | let inherent_trait = |
644 | self_ty.value.dyn_trait().into_iter().flat_map(|t| all_super_traits(db.upcast(), t)); | 645 | self_ty.value.dyn_trait().into_iter().flat_map(|t| all_super_traits(db.upcast(), t)); |
@@ -655,6 +656,19 @@ fn iterate_trait_method_candidates( | |||
655 | 'traits: for t in traits { | 656 | 'traits: for t in traits { |
656 | let data = db.trait_data(t); | 657 | let data = db.trait_data(t); |
657 | 658 | ||
659 | // Traits annotated with `#[rustc_skip_array_during_method_dispatch]` are skipped during | ||
660 | // method resolution, if the receiver is an array, and we're compiling for editions before | ||
661 | // 2021. | ||
662 | // This is to make `[a].into_iter()` not break code with the new `IntoIterator` impl for | ||
663 | // arrays. | ||
664 | if data.skip_array_during_method_dispatch && receiver_is_array { | ||
665 | // FIXME: this should really be using the edition of the method name's span, in case it | ||
666 | // comes from a macro | ||
667 | if db.crate_graph()[krate].edition < Edition::Edition2021 { | ||
668 | continue; | ||
669 | } | ||
670 | } | ||
671 | |||
658 | // we'll be lazy about checking whether the type implements the | 672 | // we'll be lazy about checking whether the type implements the |
659 | // trait, but if we find out it doesn't, we'll skip the rest of the | 673 | // trait, but if we find out it doesn't, we'll skip the rest of the |
660 | // iteration | 674 | // iteration |