mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-01 06:11:35 +00:00
Merge #7907
7907: Autoderef with visibility r=cynecx a=cynecx
Fixes https://github.com/rust-analyzer/rust-analyzer/issues/7841.
I am not sure about the general approach here. Right now this simply tries to check whether the autoderef candidate is reachable from the current module. ~~However this doesn't exactly work with traits (see the `tests::macros::infer_derive_clone_in_core` test, which fails right now).~~ see comment below
Refs:
- `rustc_typeck` checking fields: 66ec64ccf3/compiler/rustc_typeck/src/check/expr.rs (L1610)
r? @flodiebold
Co-authored-by: cynecx <me@cynecx.net>
This commit is contained in:
commit
d7db38fff9
10 changed files with 250 additions and 37 deletions
|
@ -296,6 +296,7 @@ pub(crate) fn lookup_method(
|
|||
env: Arc<TraitEnvironment>,
|
||||
krate: CrateId,
|
||||
traits_in_scope: &FxHashSet<TraitId>,
|
||||
visible_from_module: Option<ModuleId>,
|
||||
name: &Name,
|
||||
) -> Option<(Ty, FunctionId)> {
|
||||
iterate_method_candidates(
|
||||
|
@ -304,6 +305,7 @@ pub(crate) fn lookup_method(
|
|||
env,
|
||||
krate,
|
||||
&traits_in_scope,
|
||||
visible_from_module,
|
||||
Some(name),
|
||||
LookupMode::MethodCall,
|
||||
|ty, f| match f {
|
||||
|
@ -334,6 +336,7 @@ pub fn iterate_method_candidates<T>(
|
|||
env: Arc<TraitEnvironment>,
|
||||
krate: CrateId,
|
||||
traits_in_scope: &FxHashSet<TraitId>,
|
||||
visible_from_module: Option<ModuleId>,
|
||||
name: Option<&Name>,
|
||||
mode: LookupMode,
|
||||
mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>,
|
||||
|
@ -345,6 +348,7 @@ pub fn iterate_method_candidates<T>(
|
|||
env,
|
||||
krate,
|
||||
traits_in_scope,
|
||||
visible_from_module,
|
||||
name,
|
||||
mode,
|
||||
&mut |ty, item| {
|
||||
|
@ -362,6 +366,7 @@ fn iterate_method_candidates_impl(
|
|||
env: Arc<TraitEnvironment>,
|
||||
krate: CrateId,
|
||||
traits_in_scope: &FxHashSet<TraitId>,
|
||||
visible_from_module: Option<ModuleId>,
|
||||
name: Option<&Name>,
|
||||
mode: LookupMode,
|
||||
callback: &mut dyn FnMut(&Ty, AssocItemId) -> bool,
|
||||
|
@ -399,6 +404,7 @@ fn iterate_method_candidates_impl(
|
|||
env.clone(),
|
||||
krate,
|
||||
traits_in_scope,
|
||||
visible_from_module,
|
||||
name,
|
||||
callback,
|
||||
) {
|
||||
|
@ -415,6 +421,7 @@ fn iterate_method_candidates_impl(
|
|||
env,
|
||||
krate,
|
||||
traits_in_scope,
|
||||
visible_from_module,
|
||||
name,
|
||||
callback,
|
||||
)
|
||||
|
@ -428,6 +435,7 @@ fn iterate_method_candidates_with_autoref(
|
|||
env: Arc<TraitEnvironment>,
|
||||
krate: CrateId,
|
||||
traits_in_scope: &FxHashSet<TraitId>,
|
||||
visible_from_module: Option<ModuleId>,
|
||||
name: Option<&Name>,
|
||||
mut callback: &mut dyn FnMut(&Ty, AssocItemId) -> bool,
|
||||
) -> bool {
|
||||
|
@ -438,6 +446,7 @@ fn iterate_method_candidates_with_autoref(
|
|||
env.clone(),
|
||||
krate,
|
||||
&traits_in_scope,
|
||||
visible_from_module,
|
||||
name,
|
||||
&mut callback,
|
||||
) {
|
||||
|
@ -454,6 +463,7 @@ fn iterate_method_candidates_with_autoref(
|
|||
env.clone(),
|
||||
krate,
|
||||
&traits_in_scope,
|
||||
visible_from_module,
|
||||
name,
|
||||
&mut callback,
|
||||
) {
|
||||
|
@ -470,6 +480,7 @@ fn iterate_method_candidates_with_autoref(
|
|||
env,
|
||||
krate,
|
||||
&traits_in_scope,
|
||||
visible_from_module,
|
||||
name,
|
||||
&mut callback,
|
||||
) {
|
||||
|
@ -485,6 +496,7 @@ fn iterate_method_candidates_by_receiver(
|
|||
env: Arc<TraitEnvironment>,
|
||||
krate: CrateId,
|
||||
traits_in_scope: &FxHashSet<TraitId>,
|
||||
visible_from_module: Option<ModuleId>,
|
||||
name: Option<&Name>,
|
||||
mut callback: &mut dyn FnMut(&Ty, AssocItemId) -> bool,
|
||||
) -> bool {
|
||||
|
@ -492,7 +504,15 @@ fn iterate_method_candidates_by_receiver(
|
|||
// 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(self_ty, db, name, Some(receiver_ty), krate, &mut callback) {
|
||||
if iterate_inherent_methods(
|
||||
self_ty,
|
||||
db,
|
||||
name,
|
||||
Some(receiver_ty),
|
||||
krate,
|
||||
visible_from_module,
|
||||
&mut callback,
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -519,10 +539,12 @@ fn iterate_method_candidates_for_self_ty(
|
|||
env: Arc<TraitEnvironment>,
|
||||
krate: CrateId,
|
||||
traits_in_scope: &FxHashSet<TraitId>,
|
||||
visible_from_module: Option<ModuleId>,
|
||||
name: Option<&Name>,
|
||||
mut callback: &mut dyn FnMut(&Ty, AssocItemId) -> bool,
|
||||
) -> bool {
|
||||
if iterate_inherent_methods(self_ty, db, name, None, krate, &mut callback) {
|
||||
if iterate_inherent_methods(self_ty, db, name, None, krate, visible_from_module, &mut callback)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
iterate_trait_method_candidates(self_ty, db, env, krate, traits_in_scope, name, None, callback)
|
||||
|
@ -559,7 +581,9 @@ fn iterate_trait_method_candidates(
|
|||
// iteration
|
||||
let mut known_implemented = false;
|
||||
for (_name, item) in data.items.iter() {
|
||||
if !is_valid_candidate(db, name, receiver_ty, *item, self_ty) {
|
||||
// Don't pass a `visible_from_module` down to `is_valid_candidate`,
|
||||
// since only inherent methods should be included into visibility checking.
|
||||
if !is_valid_candidate(db, name, receiver_ty, *item, self_ty, None) {
|
||||
continue;
|
||||
}
|
||||
if !known_implemented {
|
||||
|
@ -583,6 +607,7 @@ fn iterate_inherent_methods(
|
|||
name: Option<&Name>,
|
||||
receiver_ty: Option<&Canonical<Ty>>,
|
||||
krate: CrateId,
|
||||
visible_from_module: Option<ModuleId>,
|
||||
callback: &mut dyn FnMut(&Ty, AssocItemId) -> bool,
|
||||
) -> bool {
|
||||
let def_crates = match self_ty.value.def_crates(db, krate) {
|
||||
|
@ -594,7 +619,7 @@ fn iterate_inherent_methods(
|
|||
|
||||
for &impl_def in impls.for_self_ty(&self_ty.value) {
|
||||
for &item in db.impl_data(impl_def).items.iter() {
|
||||
if !is_valid_candidate(db, name, receiver_ty, item, self_ty) {
|
||||
if !is_valid_candidate(db, name, receiver_ty, item, self_ty, visible_from_module) {
|
||||
continue;
|
||||
}
|
||||
// we have to check whether the self type unifies with the type
|
||||
|
@ -639,6 +664,7 @@ fn is_valid_candidate(
|
|||
receiver_ty: Option<&Canonical<Ty>>,
|
||||
item: AssocItemId,
|
||||
self_ty: &Canonical<Ty>,
|
||||
visible_from_module: Option<ModuleId>,
|
||||
) -> bool {
|
||||
match item {
|
||||
AssocItemId::FunctionId(m) => {
|
||||
|
@ -660,6 +686,13 @@ fn is_valid_candidate(
|
|||
return false;
|
||||
}
|
||||
}
|
||||
if let Some(from_module) = visible_from_module {
|
||||
if !db.function_visibility(m).is_visible_from(db.upcast(), from_module) {
|
||||
cov_mark::hit!(autoderef_candidate_not_visible);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
AssocItemId::ConstId(c) => {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue