diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 62c634b549f..b028e76c17a 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -31,7 +31,7 @@ mod display; -use std::{iter, sync::Arc}; +use std::{iter, ops::ControlFlow, sync::Arc}; use arrayvec::ArrayVec; use base_db::{CrateDisplayName, CrateId, Edition, FileId}; @@ -2573,12 +2573,14 @@ pub fn iterate_method_candidates( krate, traits_in_scope, name, - &mut |ty, assoc_item_id| match assoc_item_id { - AssocItemId::FunctionId(it) => { - slot = callback(self.derived(ty.clone()), it.into()); - slot.is_some() + &mut |ty, assoc_item_id| { + if let AssocItemId::FunctionId(func) = assoc_item_id { + if let Some(res) = callback(self.derived(ty.clone()), func.into()) { + slot = Some(res); + return ControlFlow::Break(()); + } } - AssocItemId::ConstId(_) | AssocItemId::TypeAliasId(_) => false, + ControlFlow::Continue(()) }, ); slot @@ -2590,7 +2592,7 @@ fn iterate_method_candidates_dyn( krate: Crate, traits_in_scope: &FxHashSet, name: Option<&Name>, - callback: &mut dyn FnMut(&Ty, AssocItemId) -> bool, + callback: &mut dyn FnMut(&Ty, AssocItemId) -> ControlFlow<()>, ) { // There should be no inference vars in types passed here // FIXME check that? @@ -2630,8 +2632,11 @@ pub fn iterate_path_candidates( traits_in_scope, name, &mut |ty, assoc_item_id| { - slot = callback(self.derived(ty.clone()), assoc_item_id.into()); - slot.is_some() + if let Some(res) = callback(self.derived(ty.clone()), assoc_item_id.into()) { + slot = Some(res); + return ControlFlow::Break(()); + } + ControlFlow::Continue(()) }, ); slot @@ -2643,7 +2648,7 @@ fn iterate_path_candidates_dyn( krate: Crate, traits_in_scope: &FxHashSet, name: Option<&Name>, - callback: &mut dyn FnMut(&Ty, AssocItemId) -> bool, + callback: &mut dyn FnMut(&Ty, AssocItemId) -> ControlFlow<()>, ) { let canonical = hir_ty::replace_errors_with_variables(&self.ty); diff --git a/crates/hir_ty/src/method_resolution.rs b/crates/hir_ty/src/method_resolution.rs index f12ced24cc4..3921c365517 100644 --- a/crates/hir_ty/src/method_resolution.rs +++ b/crates/hir_ty/src/method_resolution.rs @@ -2,7 +2,7 @@ //! For details about how this works in rustc, see the method lookup page in the //! [rustc guide](https://rust-lang.github.io/rustc-guide/method-lookup.html) //! and the corresponding code mostly in librustc_typeck/check/method/probe.rs. -use std::{iter, sync::Arc}; +use std::{iter, ops::ControlFlow, sync::Arc}; use arrayvec::ArrayVec; use base_db::{CrateId, Edition}; @@ -435,8 +435,11 @@ pub fn iterate_method_candidates( mode, &mut |ty, item| { assert!(slot.is_none()); - slot = callback(ty, item); - slot.is_some() + if let Some(it) = callback(ty, item) { + slot = Some(it); + return ControlFlow::Break(()); + } + ControlFlow::Continue(()) }, ); slot @@ -451,8 +454,8 @@ pub fn iterate_method_candidates_dyn( visible_from_module: Option, name: Option<&Name>, mode: LookupMode, - callback: &mut dyn FnMut(&Ty, AssocItemId) -> bool, -) -> bool { + callback: &mut dyn FnMut(&Ty, AssocItemId) -> ControlFlow<()>, +) -> ControlFlow<()> { match mode { LookupMode::MethodCall => { // For method calls, rust first does any number of autoderef, and then one @@ -480,7 +483,7 @@ pub fn iterate_method_candidates_dyn( let deref_chain = autoderef_method_receiver(db, krate, ty); for i in 0..deref_chain.len() { - if iterate_method_candidates_with_autoref( + iterate_method_candidates_with_autoref( &deref_chain[i..], db, env.clone(), @@ -489,11 +492,9 @@ pub fn iterate_method_candidates_dyn( visible_from_module, name, callback, - ) { - return true; - } + )?; } - false + ControlFlow::Continue(()) } LookupMode::Path => { // No autoderef for path lookups @@ -519,9 +520,9 @@ fn iterate_method_candidates_with_autoref( traits_in_scope: &FxHashSet, visible_from_module: Option, name: Option<&Name>, - mut callback: &mut dyn FnMut(&Ty, AssocItemId) -> bool, -) -> bool { - if iterate_method_candidates_by_receiver( + mut callback: &mut dyn FnMut(&Ty, AssocItemId) -> ControlFlow<()>, +) -> ControlFlow<()> { + iterate_method_candidates_by_receiver( &deref_chain[0], &deref_chain[1..], db, @@ -531,15 +532,15 @@ fn iterate_method_candidates_with_autoref( visible_from_module, name, &mut callback, - ) { - return true; - } + )?; + let refed = Canonical { binders: deref_chain[0].binders.clone(), value: TyKind::Ref(Mutability::Not, static_lifetime(), deref_chain[0].value.clone()) .intern(&Interner), }; - if iterate_method_candidates_by_receiver( + + iterate_method_candidates_by_receiver( &refed, deref_chain, db, @@ -549,15 +550,15 @@ fn iterate_method_candidates_with_autoref( visible_from_module, name, &mut callback, - ) { - return true; - } + )?; + let ref_muted = Canonical { binders: deref_chain[0].binders.clone(), value: TyKind::Ref(Mutability::Mut, static_lifetime(), deref_chain[0].value.clone()) .intern(&Interner), }; - if iterate_method_candidates_by_receiver( + + iterate_method_candidates_by_receiver( &ref_muted, deref_chain, db, @@ -567,10 +568,7 @@ fn iterate_method_candidates_with_autoref( visible_from_module, name, &mut callback, - ) { - return true; - } - false + ) } fn iterate_method_candidates_by_receiver( @@ -582,13 +580,13 @@ fn iterate_method_candidates_by_receiver( traits_in_scope: &FxHashSet, visible_from_module: Option, name: Option<&Name>, - mut callback: &mut dyn FnMut(&Ty, AssocItemId) -> bool, -) -> bool { + mut callback: &mut dyn FnMut(&Ty, AssocItemId) -> ControlFlow<()>, +) -> ControlFlow<()> { // We're looking for methods with *receiver* type receiver_ty. These could // be found in any of the derefs of receiver_ty, so we have to go through // that. for self_ty in std::iter::once(receiver_ty).chain(rest_of_deref_chain) { - if iterate_inherent_methods( + iterate_inherent_methods( self_ty, db, env.clone(), @@ -597,12 +595,11 @@ fn iterate_method_candidates_by_receiver( krate, visible_from_module, &mut callback, - ) { - return true; - } + )? } + for self_ty in std::iter::once(receiver_ty).chain(rest_of_deref_chain) { - if iterate_trait_method_candidates( + iterate_trait_method_candidates( self_ty, db, env.clone(), @@ -611,11 +608,10 @@ fn iterate_method_candidates_by_receiver( name, Some(receiver_ty), &mut callback, - ) { - return true; - } + )? } - false + + ControlFlow::Continue(()) } fn iterate_method_candidates_for_self_ty( @@ -626,9 +622,9 @@ fn iterate_method_candidates_for_self_ty( traits_in_scope: &FxHashSet, visible_from_module: Option, name: Option<&Name>, - mut callback: &mut dyn FnMut(&Ty, AssocItemId) -> bool, -) -> bool { - if iterate_inherent_methods( + mut callback: &mut dyn FnMut(&Ty, AssocItemId) -> ControlFlow<()>, +) -> ControlFlow<()> { + iterate_inherent_methods( self_ty, db, env.clone(), @@ -637,9 +633,7 @@ fn iterate_method_candidates_for_self_ty( krate, visible_from_module, &mut callback, - ) { - return true; - } + )?; iterate_trait_method_candidates(self_ty, db, env, krate, traits_in_scope, name, None, callback) } @@ -651,22 +645,24 @@ fn iterate_trait_method_candidates( traits_in_scope: &FxHashSet, name: Option<&Name>, receiver_ty: Option<&Canonical>, - callback: &mut dyn FnMut(&Ty, AssocItemId) -> bool, -) -> bool { + callback: &mut dyn FnMut(&Ty, AssocItemId) -> ControlFlow<()>, +) -> ControlFlow<()> { let receiver_is_array = matches!(self_ty.value.kind(&Interner), chalk_ir::TyKind::Array(..)); // if ty is `dyn Trait`, the trait doesn't need to be in scope let inherent_trait = self_ty.value.dyn_trait().into_iter().flat_map(|t| all_super_traits(db.upcast(), t)); - let env_traits = if let TyKind::Placeholder(_) = self_ty.value.kind(&Interner) { - // if we have `T: Trait` in the param env, the trait doesn't need to be in scope - env.traits_in_scope_from_clauses(&self_ty.value) - .flat_map(|t| all_super_traits(db.upcast(), t)) - .collect() - } else { - Vec::new() + let env_traits = match self_ty.value.kind(&Interner) { + TyKind::Placeholder(_) => { + // if we have `T: Trait` in the param env, the trait doesn't need to be in scope + env.traits_in_scope_from_clauses(&self_ty.value) + .flat_map(|t| all_super_traits(db.upcast(), t)) + .collect() + } + _ => Vec::new(), }; let traits = inherent_trait.chain(env_traits.into_iter()).chain(traits_in_scope.iter().copied()); + 'traits: for t in traits { let data = db.trait_data(t); @@ -701,12 +697,10 @@ fn iterate_trait_method_candidates( } known_implemented = true; // FIXME: we shouldn't be ignoring the binders here - if callback(&self_ty.value, *item) { - return true; - } + callback(&self_ty.value, *item)? } } - false + ControlFlow::Continue(()) } fn filter_inherent_impls_for_self_ty<'i>( @@ -744,12 +738,13 @@ fn iterate_inherent_methods( receiver_ty: Option<&Canonical>, krate: CrateId, visible_from_module: Option, - callback: &mut dyn FnMut(&Ty, AssocItemId) -> bool, -) -> bool { + callback: &mut dyn FnMut(&Ty, AssocItemId) -> ControlFlow<()>, +) -> ControlFlow<()> { let def_crates = match def_crates(db, &self_ty.value, krate) { Some(k) => k, - None => return false, + None => return ControlFlow::Continue(()), }; + for krate in def_crates { let impls = db.inherent_impls_in_crate(krate); @@ -779,13 +774,11 @@ fn iterate_inherent_methods( continue; } let receiver_ty = receiver_ty.map(|x| &x.value).unwrap_or(&self_ty.value); - if callback(receiver_ty, item) { - return true; - } + callback(receiver_ty, item)?; } } } - false + ControlFlow::Continue(()) } /// Returns the self type for the index trait call. diff --git a/xtask/src/install.rs b/xtask/src/install.rs index 64ab12b42a9..922957f57d1 100644 --- a/xtask/src/install.rs +++ b/xtask/src/install.rs @@ -8,7 +8,7 @@ use crate::flags; // Latest stable, feel free to send a PR if this lags behind. -const REQUIRED_RUST_VERSION: u32 = 53; +const REQUIRED_RUST_VERSION: u32 = 55; impl flags::Install { pub(crate) fn run(self) -> Result<()> {