minor: make code clearer with ControlFlow

This commit is contained in:
Aleksey Kladov 2021-09-11 20:49:10 +03:00
parent abdb75912c
commit 9b2bac621e
3 changed files with 71 additions and 73 deletions

View file

@ -31,7 +31,7 @@ pub mod db;
mod display; mod display;
use std::{iter, sync::Arc}; use std::{iter, ops::ControlFlow, sync::Arc};
use arrayvec::ArrayVec; use arrayvec::ArrayVec;
use base_db::{CrateDisplayName, CrateId, Edition, FileId}; use base_db::{CrateDisplayName, CrateId, Edition, FileId};
@ -2573,12 +2573,14 @@ impl Type {
krate, krate,
traits_in_scope, traits_in_scope,
name, name,
&mut |ty, assoc_item_id| match assoc_item_id { &mut |ty, assoc_item_id| {
AssocItemId::FunctionId(it) => { if let AssocItemId::FunctionId(func) = assoc_item_id {
slot = callback(self.derived(ty.clone()), it.into()); if let Some(res) = callback(self.derived(ty.clone()), func.into()) {
slot.is_some() slot = Some(res);
return ControlFlow::Break(());
}
} }
AssocItemId::ConstId(_) | AssocItemId::TypeAliasId(_) => false, ControlFlow::Continue(())
}, },
); );
slot slot
@ -2590,7 +2592,7 @@ impl Type {
krate: Crate, krate: Crate,
traits_in_scope: &FxHashSet<TraitId>, traits_in_scope: &FxHashSet<TraitId>,
name: Option<&Name>, 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 // There should be no inference vars in types passed here
// FIXME check that? // FIXME check that?
@ -2630,8 +2632,11 @@ impl Type {
traits_in_scope, traits_in_scope,
name, name,
&mut |ty, assoc_item_id| { &mut |ty, assoc_item_id| {
slot = callback(self.derived(ty.clone()), assoc_item_id.into()); if let Some(res) = callback(self.derived(ty.clone()), assoc_item_id.into()) {
slot.is_some() slot = Some(res);
return ControlFlow::Break(());
}
ControlFlow::Continue(())
}, },
); );
slot slot
@ -2643,7 +2648,7 @@ impl Type {
krate: Crate, krate: Crate,
traits_in_scope: &FxHashSet<TraitId>, traits_in_scope: &FxHashSet<TraitId>,
name: Option<&Name>, 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); let canonical = hir_ty::replace_errors_with_variables(&self.ty);

View file

@ -2,7 +2,7 @@
//! For details about how this works in rustc, see the method lookup page in the //! 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) //! [rustc guide](https://rust-lang.github.io/rustc-guide/method-lookup.html)
//! and the corresponding code mostly in librustc_typeck/check/method/probe.rs. //! 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 arrayvec::ArrayVec;
use base_db::{CrateId, Edition}; use base_db::{CrateId, Edition};
@ -435,8 +435,11 @@ pub fn iterate_method_candidates<T>(
mode, mode,
&mut |ty, item| { &mut |ty, item| {
assert!(slot.is_none()); assert!(slot.is_none());
slot = callback(ty, item); if let Some(it) = callback(ty, item) {
slot.is_some() slot = Some(it);
return ControlFlow::Break(());
}
ControlFlow::Continue(())
}, },
); );
slot slot
@ -451,8 +454,8 @@ pub fn iterate_method_candidates_dyn(
visible_from_module: Option<ModuleId>, visible_from_module: Option<ModuleId>,
name: Option<&Name>, name: Option<&Name>,
mode: LookupMode, mode: LookupMode,
callback: &mut dyn FnMut(&Ty, AssocItemId) -> bool, callback: &mut dyn FnMut(&Ty, AssocItemId) -> ControlFlow<()>,
) -> bool { ) -> ControlFlow<()> {
match mode { match mode {
LookupMode::MethodCall => { LookupMode::MethodCall => {
// For method calls, rust first does any number of autoderef, and then one // 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); let deref_chain = autoderef_method_receiver(db, krate, ty);
for i in 0..deref_chain.len() { for i in 0..deref_chain.len() {
if iterate_method_candidates_with_autoref( iterate_method_candidates_with_autoref(
&deref_chain[i..], &deref_chain[i..],
db, db,
env.clone(), env.clone(),
@ -489,11 +492,9 @@ pub fn iterate_method_candidates_dyn(
visible_from_module, visible_from_module,
name, name,
callback, callback,
) { )?;
return true;
}
} }
false ControlFlow::Continue(())
} }
LookupMode::Path => { LookupMode::Path => {
// No autoderef for path lookups // No autoderef for path lookups
@ -519,9 +520,9 @@ fn iterate_method_candidates_with_autoref(
traits_in_scope: &FxHashSet<TraitId>, traits_in_scope: &FxHashSet<TraitId>,
visible_from_module: Option<ModuleId>, visible_from_module: Option<ModuleId>,
name: Option<&Name>, name: Option<&Name>,
mut callback: &mut dyn FnMut(&Ty, AssocItemId) -> bool, mut callback: &mut dyn FnMut(&Ty, AssocItemId) -> ControlFlow<()>,
) -> bool { ) -> ControlFlow<()> {
if iterate_method_candidates_by_receiver( iterate_method_candidates_by_receiver(
&deref_chain[0], &deref_chain[0],
&deref_chain[1..], &deref_chain[1..],
db, db,
@ -531,15 +532,15 @@ fn iterate_method_candidates_with_autoref(
visible_from_module, visible_from_module,
name, name,
&mut callback, &mut callback,
) { )?;
return true;
}
let refed = Canonical { let refed = Canonical {
binders: deref_chain[0].binders.clone(), binders: deref_chain[0].binders.clone(),
value: TyKind::Ref(Mutability::Not, static_lifetime(), deref_chain[0].value.clone()) value: TyKind::Ref(Mutability::Not, static_lifetime(), deref_chain[0].value.clone())
.intern(&Interner), .intern(&Interner),
}; };
if iterate_method_candidates_by_receiver(
iterate_method_candidates_by_receiver(
&refed, &refed,
deref_chain, deref_chain,
db, db,
@ -549,15 +550,15 @@ fn iterate_method_candidates_with_autoref(
visible_from_module, visible_from_module,
name, name,
&mut callback, &mut callback,
) { )?;
return true;
}
let ref_muted = Canonical { let ref_muted = Canonical {
binders: deref_chain[0].binders.clone(), binders: deref_chain[0].binders.clone(),
value: TyKind::Ref(Mutability::Mut, static_lifetime(), deref_chain[0].value.clone()) value: TyKind::Ref(Mutability::Mut, static_lifetime(), deref_chain[0].value.clone())
.intern(&Interner), .intern(&Interner),
}; };
if iterate_method_candidates_by_receiver(
iterate_method_candidates_by_receiver(
&ref_muted, &ref_muted,
deref_chain, deref_chain,
db, db,
@ -567,10 +568,7 @@ fn iterate_method_candidates_with_autoref(
visible_from_module, visible_from_module,
name, name,
&mut callback, &mut callback,
) { )
return true;
}
false
} }
fn iterate_method_candidates_by_receiver( fn iterate_method_candidates_by_receiver(
@ -582,13 +580,13 @@ fn iterate_method_candidates_by_receiver(
traits_in_scope: &FxHashSet<TraitId>, traits_in_scope: &FxHashSet<TraitId>,
visible_from_module: Option<ModuleId>, visible_from_module: Option<ModuleId>,
name: Option<&Name>, name: Option<&Name>,
mut callback: &mut dyn FnMut(&Ty, AssocItemId) -> bool, mut callback: &mut dyn FnMut(&Ty, AssocItemId) -> ControlFlow<()>,
) -> bool { ) -> ControlFlow<()> {
// We're looking for methods with *receiver* type receiver_ty. These could // 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 // be found in any of the derefs of receiver_ty, so we have to go through
// that. // that.
for self_ty in std::iter::once(receiver_ty).chain(rest_of_deref_chain) { for self_ty in std::iter::once(receiver_ty).chain(rest_of_deref_chain) {
if iterate_inherent_methods( iterate_inherent_methods(
self_ty, self_ty,
db, db,
env.clone(), env.clone(),
@ -597,12 +595,11 @@ fn iterate_method_candidates_by_receiver(
krate, krate,
visible_from_module, visible_from_module,
&mut callback, &mut callback,
) { )?
return true;
}
} }
for self_ty in std::iter::once(receiver_ty).chain(rest_of_deref_chain) { 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, self_ty,
db, db,
env.clone(), env.clone(),
@ -611,11 +608,10 @@ fn iterate_method_candidates_by_receiver(
name, name,
Some(receiver_ty), Some(receiver_ty),
&mut callback, &mut callback,
) { )?
return true;
}
} }
false
ControlFlow::Continue(())
} }
fn iterate_method_candidates_for_self_ty( fn iterate_method_candidates_for_self_ty(
@ -626,9 +622,9 @@ fn iterate_method_candidates_for_self_ty(
traits_in_scope: &FxHashSet<TraitId>, traits_in_scope: &FxHashSet<TraitId>,
visible_from_module: Option<ModuleId>, visible_from_module: Option<ModuleId>,
name: Option<&Name>, name: Option<&Name>,
mut callback: &mut dyn FnMut(&Ty, AssocItemId) -> bool, mut callback: &mut dyn FnMut(&Ty, AssocItemId) -> ControlFlow<()>,
) -> bool { ) -> ControlFlow<()> {
if iterate_inherent_methods( iterate_inherent_methods(
self_ty, self_ty,
db, db,
env.clone(), env.clone(),
@ -637,9 +633,7 @@ fn iterate_method_candidates_for_self_ty(
krate, krate,
visible_from_module, visible_from_module,
&mut callback, &mut callback,
) { )?;
return true;
}
iterate_trait_method_candidates(self_ty, db, env, krate, traits_in_scope, name, None, callback) 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<TraitId>, traits_in_scope: &FxHashSet<TraitId>,
name: Option<&Name>, name: Option<&Name>,
receiver_ty: Option<&Canonical<Ty>>, receiver_ty: Option<&Canonical<Ty>>,
callback: &mut dyn FnMut(&Ty, AssocItemId) -> bool, callback: &mut dyn FnMut(&Ty, AssocItemId) -> ControlFlow<()>,
) -> bool { ) -> ControlFlow<()> {
let receiver_is_array = matches!(self_ty.value.kind(&Interner), chalk_ir::TyKind::Array(..)); 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 // if ty is `dyn Trait`, the trait doesn't need to be in scope
let inherent_trait = let inherent_trait =
self_ty.value.dyn_trait().into_iter().flat_map(|t| all_super_traits(db.upcast(), t)); 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) { let env_traits = match self_ty.value.kind(&Interner) {
// if we have `T: Trait` in the param env, the trait doesn't need to be in scope TyKind::Placeholder(_) => {
env.traits_in_scope_from_clauses(&self_ty.value) // if we have `T: Trait` in the param env, the trait doesn't need to be in scope
.flat_map(|t| all_super_traits(db.upcast(), t)) env.traits_in_scope_from_clauses(&self_ty.value)
.collect() .flat_map(|t| all_super_traits(db.upcast(), t))
} else { .collect()
Vec::new() }
_ => Vec::new(),
}; };
let traits = let traits =
inherent_trait.chain(env_traits.into_iter()).chain(traits_in_scope.iter().copied()); inherent_trait.chain(env_traits.into_iter()).chain(traits_in_scope.iter().copied());
'traits: for t in traits { 'traits: for t in traits {
let data = db.trait_data(t); let data = db.trait_data(t);
@ -701,12 +697,10 @@ fn iterate_trait_method_candidates(
} }
known_implemented = true; known_implemented = true;
// FIXME: we shouldn't be ignoring the binders here // FIXME: we shouldn't be ignoring the binders here
if callback(&self_ty.value, *item) { callback(&self_ty.value, *item)?
return true;
}
} }
} }
false ControlFlow::Continue(())
} }
fn filter_inherent_impls_for_self_ty<'i>( fn filter_inherent_impls_for_self_ty<'i>(
@ -744,12 +738,13 @@ fn iterate_inherent_methods(
receiver_ty: Option<&Canonical<Ty>>, receiver_ty: Option<&Canonical<Ty>>,
krate: CrateId, krate: CrateId,
visible_from_module: Option<ModuleId>, visible_from_module: Option<ModuleId>,
callback: &mut dyn FnMut(&Ty, AssocItemId) -> bool, callback: &mut dyn FnMut(&Ty, AssocItemId) -> ControlFlow<()>,
) -> bool { ) -> ControlFlow<()> {
let def_crates = match def_crates(db, &self_ty.value, krate) { let def_crates = match def_crates(db, &self_ty.value, krate) {
Some(k) => k, Some(k) => k,
None => return false, None => return ControlFlow::Continue(()),
}; };
for krate in def_crates { for krate in def_crates {
let impls = db.inherent_impls_in_crate(krate); let impls = db.inherent_impls_in_crate(krate);
@ -779,13 +774,11 @@ fn iterate_inherent_methods(
continue; continue;
} }
let receiver_ty = receiver_ty.map(|x| &x.value).unwrap_or(&self_ty.value); let receiver_ty = receiver_ty.map(|x| &x.value).unwrap_or(&self_ty.value);
if callback(receiver_ty, item) { callback(receiver_ty, item)?;
return true;
}
} }
} }
} }
false ControlFlow::Continue(())
} }
/// Returns the self type for the index trait call. /// Returns the self type for the index trait call.

View file

@ -8,7 +8,7 @@ use xshell::{cmd, pushd};
use crate::flags; use crate::flags;
// Latest stable, feel free to send a PR if this lags behind. // 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 { impl flags::Install {
pub(crate) fn run(self) -> Result<()> { pub(crate) fn run(self) -> Result<()> {