mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-16 23:24:03 +00:00
commit
c867cbf9b6
7 changed files with 62 additions and 71 deletions
|
@ -821,9 +821,9 @@ pub fn iterate_method_candidates_dyn(
|
||||||
|
|
||||||
let mut table = InferenceTable::new(db, env.clone());
|
let mut table = InferenceTable::new(db, env.clone());
|
||||||
let ty = table.instantiate_canonical(ty.clone());
|
let ty = table.instantiate_canonical(ty.clone());
|
||||||
let (deref_chain, adj) = autoderef_method_receiver(&mut table, ty);
|
let deref_chain = autoderef_method_receiver(&mut table, ty);
|
||||||
|
|
||||||
let result = deref_chain.into_iter().zip(adj).try_for_each(|(receiver_ty, adj)| {
|
let result = deref_chain.into_iter().try_for_each(|(receiver_ty, adj)| {
|
||||||
iterate_method_candidates_with_autoref(
|
iterate_method_candidates_with_autoref(
|
||||||
&receiver_ty,
|
&receiver_ty,
|
||||||
adj,
|
adj,
|
||||||
|
@ -867,16 +867,20 @@ fn iterate_method_candidates_with_autoref(
|
||||||
return ControlFlow::Continue(());
|
return ControlFlow::Continue(());
|
||||||
}
|
}
|
||||||
|
|
||||||
iterate_method_candidates_by_receiver(
|
let mut iterate_method_candidates_by_receiver = move |receiver_ty, first_adjustment| {
|
||||||
receiver_ty,
|
iterate_method_candidates_by_receiver(
|
||||||
first_adjustment.clone(),
|
receiver_ty,
|
||||||
db,
|
first_adjustment,
|
||||||
env.clone(),
|
db,
|
||||||
traits_in_scope,
|
env.clone(),
|
||||||
visible_from_module,
|
traits_in_scope,
|
||||||
name,
|
visible_from_module,
|
||||||
&mut callback,
|
name,
|
||||||
)?;
|
&mut callback,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
iterate_method_candidates_by_receiver(receiver_ty, first_adjustment.clone())?;
|
||||||
|
|
||||||
let refed = Canonical {
|
let refed = Canonical {
|
||||||
value: TyKind::Ref(Mutability::Not, static_lifetime(), receiver_ty.value.clone())
|
value: TyKind::Ref(Mutability::Not, static_lifetime(), receiver_ty.value.clone())
|
||||||
|
@ -884,16 +888,7 @@ fn iterate_method_candidates_with_autoref(
|
||||||
binders: receiver_ty.binders.clone(),
|
binders: receiver_ty.binders.clone(),
|
||||||
};
|
};
|
||||||
|
|
||||||
iterate_method_candidates_by_receiver(
|
iterate_method_candidates_by_receiver(&refed, first_adjustment.with_autoref(Mutability::Not))?;
|
||||||
&refed,
|
|
||||||
first_adjustment.with_autoref(Mutability::Not),
|
|
||||||
db,
|
|
||||||
env.clone(),
|
|
||||||
traits_in_scope,
|
|
||||||
visible_from_module,
|
|
||||||
name,
|
|
||||||
&mut callback,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
let ref_muted = Canonical {
|
let ref_muted = Canonical {
|
||||||
value: TyKind::Ref(Mutability::Mut, static_lifetime(), receiver_ty.value.clone())
|
value: TyKind::Ref(Mutability::Mut, static_lifetime(), receiver_ty.value.clone())
|
||||||
|
@ -904,12 +899,6 @@ fn iterate_method_candidates_with_autoref(
|
||||||
iterate_method_candidates_by_receiver(
|
iterate_method_candidates_by_receiver(
|
||||||
&ref_muted,
|
&ref_muted,
|
||||||
first_adjustment.with_autoref(Mutability::Mut),
|
first_adjustment.with_autoref(Mutability::Mut),
|
||||||
db,
|
|
||||||
env,
|
|
||||||
traits_in_scope,
|
|
||||||
visible_from_module,
|
|
||||||
name,
|
|
||||||
&mut callback,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1210,8 +1199,8 @@ pub fn resolve_indexing_op(
|
||||||
) -> Option<ReceiverAdjustments> {
|
) -> Option<ReceiverAdjustments> {
|
||||||
let mut table = InferenceTable::new(db, env.clone());
|
let mut table = InferenceTable::new(db, env.clone());
|
||||||
let ty = table.instantiate_canonical(ty);
|
let ty = table.instantiate_canonical(ty);
|
||||||
let (deref_chain, adj) = autoderef_method_receiver(&mut table, ty);
|
let deref_chain = autoderef_method_receiver(&mut table, ty);
|
||||||
for (ty, adj) in deref_chain.into_iter().zip(adj) {
|
for (ty, adj) in deref_chain {
|
||||||
let goal = generic_implements_goal(db, env.clone(), index_trait, &ty);
|
let goal = generic_implements_goal(db, env.clone(), index_trait, &ty);
|
||||||
if db.trait_solve(env.krate, goal.cast(Interner)).is_some() {
|
if db.trait_solve(env.krate, goal.cast(Interner)).is_some() {
|
||||||
return Some(adj);
|
return Some(adj);
|
||||||
|
@ -1421,25 +1410,24 @@ fn generic_implements_goal(
|
||||||
fn autoderef_method_receiver(
|
fn autoderef_method_receiver(
|
||||||
table: &mut InferenceTable<'_>,
|
table: &mut InferenceTable<'_>,
|
||||||
ty: Ty,
|
ty: Ty,
|
||||||
) -> (Vec<Canonical<Ty>>, Vec<ReceiverAdjustments>) {
|
) -> Vec<(Canonical<Ty>, ReceiverAdjustments)> {
|
||||||
let (mut deref_chain, mut adjustments): (Vec<_>, Vec<_>) = (Vec::new(), Vec::new());
|
let mut deref_chain: Vec<_> = Vec::new();
|
||||||
let mut autoderef = autoderef::Autoderef::new(table, ty);
|
let mut autoderef = autoderef::Autoderef::new(table, ty);
|
||||||
while let Some((ty, derefs)) = autoderef.next() {
|
while let Some((ty, derefs)) = autoderef.next() {
|
||||||
deref_chain.push(autoderef.table.canonicalize(ty).value);
|
deref_chain.push((
|
||||||
adjustments.push(ReceiverAdjustments {
|
autoderef.table.canonicalize(ty).value,
|
||||||
autoref: None,
|
ReceiverAdjustments { autoref: None, autoderefs: derefs, unsize_array: false },
|
||||||
autoderefs: derefs,
|
));
|
||||||
unsize_array: false,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
// As a last step, we can do array unsizing (that's the only unsizing that rustc does for method receivers!)
|
// As a last step, we can do array unsizing (that's the only unsizing that rustc does for method receivers!)
|
||||||
if let (Some((TyKind::Array(parameters, _), binders)), Some(adj)) = (
|
if let Some((TyKind::Array(parameters, _), binders, adj)) =
|
||||||
deref_chain.last().map(|ty| (ty.value.kind(Interner), ty.binders.clone())),
|
deref_chain.last().map(|(ty, adj)| (ty.value.kind(Interner), ty.binders.clone(), adj))
|
||||||
adjustments.last().cloned(),
|
{
|
||||||
) {
|
|
||||||
let unsized_ty = TyKind::Slice(parameters.clone()).intern(Interner);
|
let unsized_ty = TyKind::Slice(parameters.clone()).intern(Interner);
|
||||||
deref_chain.push(Canonical { value: unsized_ty, binders });
|
deref_chain.push((
|
||||||
adjustments.push(ReceiverAdjustments { unsize_array: true, ..adj });
|
Canonical { value: unsized_ty, binders },
|
||||||
|
ReceiverAdjustments { unsize_array: true, ..adj.clone() },
|
||||||
|
));
|
||||||
}
|
}
|
||||||
(deref_chain, adjustments)
|
deref_chain
|
||||||
}
|
}
|
||||||
|
|
|
@ -3339,12 +3339,10 @@ impl Type {
|
||||||
.map(move |ty| self.derived(ty))
|
.map(move |ty| self.derived(ty))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn iterate_method_candidates<T>(
|
pub fn iterate_method_candidates_with_traits<T>(
|
||||||
&self,
|
&self,
|
||||||
db: &dyn HirDatabase,
|
db: &dyn HirDatabase,
|
||||||
scope: &SemanticsScope<'_>,
|
scope: &SemanticsScope<'_>,
|
||||||
// FIXME this can be retrieved from `scope`, except autoimport uses this
|
|
||||||
// to specify a different set, so the method needs to be split
|
|
||||||
traits_in_scope: &FxHashSet<TraitId>,
|
traits_in_scope: &FxHashSet<TraitId>,
|
||||||
with_local_impls: Option<Module>,
|
with_local_impls: Option<Module>,
|
||||||
name: Option<&Name>,
|
name: Option<&Name>,
|
||||||
|
@ -3372,6 +3370,24 @@ impl Type {
|
||||||
slot
|
slot
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn iterate_method_candidates<T>(
|
||||||
|
&self,
|
||||||
|
db: &dyn HirDatabase,
|
||||||
|
scope: &SemanticsScope<'_>,
|
||||||
|
with_local_impls: Option<Module>,
|
||||||
|
name: Option<&Name>,
|
||||||
|
callback: impl FnMut(Function) -> Option<T>,
|
||||||
|
) -> Option<T> {
|
||||||
|
self.iterate_method_candidates_with_traits(
|
||||||
|
db,
|
||||||
|
scope,
|
||||||
|
&scope.visible_traits().0,
|
||||||
|
with_local_impls,
|
||||||
|
name,
|
||||||
|
callback,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
fn iterate_method_candidates_dyn(
|
fn iterate_method_candidates_dyn(
|
||||||
&self,
|
&self,
|
||||||
db: &dyn HirDatabase,
|
db: &dyn HirDatabase,
|
||||||
|
|
|
@ -1673,6 +1673,7 @@ impl<'a> SemanticsScope<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct VisibleTraits(pub FxHashSet<TraitId>);
|
pub struct VisibleTraits(pub FxHashSet<TraitId>);
|
||||||
|
|
||||||
impl ops::Deref for VisibleTraits {
|
impl ops::Deref for VisibleTraits {
|
||||||
|
|
|
@ -157,19 +157,12 @@ fn is_ref_and_impls_iter_method(
|
||||||
let iter_trait = FamousDefs(sema, krate).core_iter_Iterator()?;
|
let iter_trait = FamousDefs(sema, krate).core_iter_Iterator()?;
|
||||||
|
|
||||||
let has_wanted_method = ty
|
let has_wanted_method = ty
|
||||||
.iterate_method_candidates(
|
.iterate_method_candidates(sema.db, &scope, None, Some(&wanted_method), |func| {
|
||||||
sema.db,
|
if func.ret_type(sema.db).impls_trait(sema.db, iter_trait, &[]) {
|
||||||
&scope,
|
return Some(());
|
||||||
&scope.visible_traits().0,
|
}
|
||||||
None,
|
None
|
||||||
Some(&wanted_method),
|
})
|
||||||
|func| {
|
|
||||||
if func.ret_type(sema.db).impls_trait(sema.db, iter_trait, &[]) {
|
|
||||||
return Some(());
|
|
||||||
}
|
|
||||||
None
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.is_some();
|
.is_some();
|
||||||
if !has_wanted_method {
|
if !has_wanted_method {
|
||||||
return None;
|
return None;
|
||||||
|
|
|
@ -95,14 +95,7 @@ fn get_impl_method(
|
||||||
|
|
||||||
let scope = ctx.sema.scope(impl_.syntax())?;
|
let scope = ctx.sema.scope(impl_.syntax())?;
|
||||||
let ty = impl_def.self_ty(db);
|
let ty = impl_def.self_ty(db);
|
||||||
ty.iterate_method_candidates(
|
ty.iterate_method_candidates(db, &scope, None, Some(fn_name), |func| Some(func))
|
||||||
db,
|
|
||||||
&scope,
|
|
||||||
&scope.visible_traits().0,
|
|
||||||
None,
|
|
||||||
Some(fn_name),
|
|
||||||
|func| Some(func),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
|
@ -122,7 +122,7 @@ fn complete_methods(
|
||||||
mut f: impl FnMut(hir::Function),
|
mut f: impl FnMut(hir::Function),
|
||||||
) {
|
) {
|
||||||
let mut seen_methods = FxHashSet::default();
|
let mut seen_methods = FxHashSet::default();
|
||||||
receiver.iterate_method_candidates(
|
receiver.iterate_method_candidates_with_traits(
|
||||||
ctx.db,
|
ctx.db,
|
||||||
&ctx.scope,
|
&ctx.scope,
|
||||||
&ctx.traits_in_scope(),
|
&ctx.traits_in_scope(),
|
||||||
|
|
|
@ -528,7 +528,7 @@ fn trait_applicable_items(
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
trait_candidate.receiver_ty.iterate_method_candidates(
|
trait_candidate.receiver_ty.iterate_method_candidates_with_traits(
|
||||||
db,
|
db,
|
||||||
scope,
|
scope,
|
||||||
&trait_candidates,
|
&trait_candidates,
|
||||||
|
|
Loading…
Reference in a new issue