diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2021-03-24 22:37:48 +0000 |
---|---|---|
committer | GitHub <[email protected]> | 2021-03-24 22:37:48 +0000 |
commit | d7db38fff9c251c36d0796309b43678bdf9e5bd8 (patch) | |
tree | 83b422d45c28e3ae9a2eac550ce8a6048bf5fd71 | |
parent | 9d81618f11eb403cc0644a22f30648393ec77cf6 (diff) | |
parent | d1156bb52e900c015afd490f509d744c7a5adf10 (diff) |
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: https://github.com/rust-lang/rust/blob/66ec64ccf31883cd2c28d045912a76179c0c6ed2/compiler/rustc_typeck/src/check/expr.rs#L1610
r? @flodiebold
Co-authored-by: cynecx <[email protected]>
-rw-r--r-- | crates/hir/src/lib.rs | 2 | ||||
-rw-r--r-- | crates/hir_def/src/db.rs | 7 | ||||
-rw-r--r-- | crates/hir_def/src/visibility.rs | 32 | ||||
-rw-r--r-- | crates/hir_ty/src/infer/expr.rs | 45 | ||||
-rw-r--r-- | crates/hir_ty/src/infer/path.rs | 1 | ||||
-rw-r--r-- | crates/hir_ty/src/method_resolution.rs | 41 | ||||
-rw-r--r-- | crates/hir_ty/src/tests/macros.rs | 4 | ||||
-rw-r--r-- | crates/hir_ty/src/tests/method_resolution.rs | 119 | ||||
-rw-r--r-- | crates/hir_ty/src/tests/simple.rs | 32 | ||||
-rw-r--r-- | crates/hir_ty/src/tests/traits.rs | 4 |
10 files changed, 250 insertions, 37 deletions
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index eb7865c84..6fa676c4d 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs | |||
@@ -1999,6 +1999,7 @@ impl Type { | |||
1999 | env, | 1999 | env, |
2000 | krate, | 2000 | krate, |
2001 | traits_in_scope, | 2001 | traits_in_scope, |
2002 | None, | ||
2002 | name, | 2003 | name, |
2003 | method_resolution::LookupMode::MethodCall, | 2004 | method_resolution::LookupMode::MethodCall, |
2004 | |ty, it| match it { | 2005 | |ty, it| match it { |
@@ -2031,6 +2032,7 @@ impl Type { | |||
2031 | env, | 2032 | env, |
2032 | krate, | 2033 | krate, |
2033 | traits_in_scope, | 2034 | traits_in_scope, |
2035 | None, | ||
2034 | name, | 2036 | name, |
2035 | method_resolution::LookupMode::Path, | 2037 | method_resolution::LookupMode::Path, |
2036 | |ty, it| callback(ty, it.into()), | 2038 | |ty, it| callback(ty, it.into()), |
diff --git a/crates/hir_def/src/db.rs b/crates/hir_def/src/db.rs index 53df85089..068b2ee38 100644 --- a/crates/hir_def/src/db.rs +++ b/crates/hir_def/src/db.rs | |||
@@ -16,6 +16,7 @@ use crate::{ | |||
16 | item_tree::ItemTree, | 16 | item_tree::ItemTree, |
17 | lang_item::{LangItemTarget, LangItems}, | 17 | lang_item::{LangItemTarget, LangItems}, |
18 | nameres::DefMap, | 18 | nameres::DefMap, |
19 | visibility::{self, Visibility}, | ||
19 | AttrDefId, BlockId, BlockLoc, ConstId, ConstLoc, DefWithBodyId, EnumId, EnumLoc, FunctionId, | 20 | AttrDefId, BlockId, BlockLoc, ConstId, ConstLoc, DefWithBodyId, EnumId, EnumLoc, FunctionId, |
20 | FunctionLoc, GenericDefId, ImplId, ImplLoc, LocalEnumVariantId, LocalFieldId, StaticId, | 21 | FunctionLoc, GenericDefId, ImplId, ImplLoc, LocalEnumVariantId, LocalFieldId, StaticId, |
21 | StaticLoc, StructId, StructLoc, TraitId, TraitLoc, TypeAliasId, TypeAliasLoc, UnionId, | 22 | StaticLoc, StructId, StructLoc, TraitId, TraitLoc, TypeAliasId, TypeAliasLoc, UnionId, |
@@ -131,6 +132,12 @@ pub trait DefDatabase: InternDatabase + AstDatabase + Upcast<dyn AstDatabase> { | |||
131 | 132 | ||
132 | #[salsa::invoke(ImportMap::import_map_query)] | 133 | #[salsa::invoke(ImportMap::import_map_query)] |
133 | fn import_map(&self, krate: CrateId) -> Arc<ImportMap>; | 134 | fn import_map(&self, krate: CrateId) -> Arc<ImportMap>; |
135 | |||
136 | #[salsa::invoke(visibility::field_visibilities_query)] | ||
137 | fn field_visibilities(&self, var: VariantId) -> Arc<ArenaMap<LocalFieldId, Visibility>>; | ||
138 | |||
139 | #[salsa::invoke(visibility::function_visibility_query)] | ||
140 | fn function_visibility(&self, def: FunctionId) -> Visibility; | ||
134 | } | 141 | } |
135 | 142 | ||
136 | fn crate_def_map_wait(db: &dyn DefDatabase, krate: CrateId) -> Arc<DefMap> { | 143 | fn crate_def_map_wait(db: &dyn DefDatabase, krate: CrateId) -> Arc<DefMap> { |
diff --git a/crates/hir_def/src/visibility.rs b/crates/hir_def/src/visibility.rs index 0e3951910..7d00a37c4 100644 --- a/crates/hir_def/src/visibility.rs +++ b/crates/hir_def/src/visibility.rs | |||
@@ -1,13 +1,17 @@ | |||
1 | //! Defines hir-level representation of visibility (e.g. `pub` and `pub(crate)`). | 1 | //! Defines hir-level representation of visibility (e.g. `pub` and `pub(crate)`). |
2 | 2 | ||
3 | use std::sync::Arc; | ||
4 | |||
3 | use hir_expand::{hygiene::Hygiene, InFile}; | 5 | use hir_expand::{hygiene::Hygiene, InFile}; |
6 | use la_arena::ArenaMap; | ||
4 | use syntax::ast; | 7 | use syntax::ast; |
5 | 8 | ||
6 | use crate::{ | 9 | use crate::{ |
7 | db::DefDatabase, | 10 | db::DefDatabase, |
8 | nameres::DefMap, | 11 | nameres::DefMap, |
9 | path::{ModPath, PathKind}, | 12 | path::{ModPath, PathKind}, |
10 | ModuleId, | 13 | resolver::HasResolver, |
14 | FunctionId, HasModule, LocalFieldId, ModuleDefId, ModuleId, VariantId, | ||
11 | }; | 15 | }; |
12 | 16 | ||
13 | /// Visibility of an item, not yet resolved. | 17 | /// Visibility of an item, not yet resolved. |
@@ -190,3 +194,29 @@ impl Visibility { | |||
190 | } | 194 | } |
191 | } | 195 | } |
192 | } | 196 | } |
197 | |||
198 | /// Resolve visibility of all specific fields of a struct or union variant. | ||
199 | pub(crate) fn field_visibilities_query( | ||
200 | db: &dyn DefDatabase, | ||
201 | variant_id: VariantId, | ||
202 | ) -> Arc<ArenaMap<LocalFieldId, Visibility>> { | ||
203 | let var_data = match variant_id { | ||
204 | VariantId::StructId(it) => db.struct_data(it).variant_data.clone(), | ||
205 | VariantId::UnionId(it) => db.union_data(it).variant_data.clone(), | ||
206 | VariantId::EnumVariantId(it) => { | ||
207 | db.enum_data(it.parent).variants[it.local_id].variant_data.clone() | ||
208 | } | ||
209 | }; | ||
210 | let resolver = variant_id.module(db).resolver(db); | ||
211 | let mut res = ArenaMap::default(); | ||
212 | for (field_id, field_data) in var_data.fields().iter() { | ||
213 | res.insert(field_id, field_data.visibility.resolve(db, &resolver)) | ||
214 | } | ||
215 | Arc::new(res) | ||
216 | } | ||
217 | |||
218 | /// Resolve visibility of a function. | ||
219 | pub(crate) fn function_visibility_query(db: &dyn DefDatabase, def: FunctionId) -> Visibility { | ||
220 | let resolver = ModuleDefId::from(def).module(db).unwrap().resolver(db); | ||
221 | db.function_data(def).visibility.resolve(db, &resolver) | ||
222 | } | ||
diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs index 19249973c..3f3187ea2 100644 --- a/crates/hir_ty/src/infer/expr.rs +++ b/crates/hir_ty/src/infer/expr.rs | |||
@@ -443,27 +443,47 @@ impl<'a> InferenceContext<'a> { | |||
443 | }, | 443 | }, |
444 | ) | 444 | ) |
445 | .find_map(|derefed_ty| { | 445 | .find_map(|derefed_ty| { |
446 | let def_db = self.db.upcast(); | ||
447 | let module = self.resolver.module(); | ||
448 | let is_visible = |field_id: &FieldId| { | ||
449 | module | ||
450 | .map(|mod_id| { | ||
451 | self.db.field_visibilities(field_id.parent)[field_id.local_id] | ||
452 | .is_visible_from(def_db, mod_id) | ||
453 | }) | ||
454 | .unwrap_or(true) | ||
455 | }; | ||
446 | match canonicalized.decanonicalize_ty(derefed_ty.value).interned(&Interner) { | 456 | match canonicalized.decanonicalize_ty(derefed_ty.value).interned(&Interner) { |
447 | TyKind::Tuple(_, substs) => { | 457 | TyKind::Tuple(_, substs) => { |
448 | name.as_tuple_index().and_then(|idx| substs.0.get(idx).cloned()) | 458 | name.as_tuple_index().and_then(|idx| substs.0.get(idx).cloned()) |
449 | } | 459 | } |
450 | TyKind::Adt(AdtId(hir_def::AdtId::StructId(s)), parameters) => { | 460 | TyKind::Adt(AdtId(hir_def::AdtId::StructId(s)), parameters) => { |
451 | self.db.struct_data(*s).variant_data.field(name).map(|local_id| { | 461 | let local_id = self.db.struct_data(*s).variant_data.field(name)?; |
452 | let field = FieldId { parent: (*s).into(), local_id }; | 462 | let field = FieldId { parent: (*s).into(), local_id }; |
463 | if is_visible(&field) { | ||
453 | self.write_field_resolution(tgt_expr, field); | 464 | self.write_field_resolution(tgt_expr, field); |
454 | self.db.field_types((*s).into())[field.local_id] | 465 | Some( |
455 | .clone() | 466 | self.db.field_types((*s).into())[field.local_id] |
456 | .subst(¶meters) | 467 | .clone() |
457 | }) | 468 | .subst(¶meters), |
469 | ) | ||
470 | } else { | ||
471 | None | ||
472 | } | ||
458 | } | 473 | } |
459 | TyKind::Adt(AdtId(hir_def::AdtId::UnionId(u)), parameters) => { | 474 | TyKind::Adt(AdtId(hir_def::AdtId::UnionId(u)), parameters) => { |
460 | self.db.union_data(*u).variant_data.field(name).map(|local_id| { | 475 | let local_id = self.db.union_data(*u).variant_data.field(name)?; |
461 | let field = FieldId { parent: (*u).into(), local_id }; | 476 | let field = FieldId { parent: (*u).into(), local_id }; |
477 | if is_visible(&field) { | ||
462 | self.write_field_resolution(tgt_expr, field); | 478 | self.write_field_resolution(tgt_expr, field); |
463 | self.db.field_types((*u).into())[field.local_id] | 479 | Some( |
464 | .clone() | 480 | self.db.field_types((*u).into())[field.local_id] |
465 | .subst(¶meters) | 481 | .clone() |
466 | }) | 482 | .subst(¶meters), |
483 | ) | ||
484 | } else { | ||
485 | None | ||
486 | } | ||
467 | } | 487 | } |
468 | _ => None, | 488 | _ => None, |
469 | } | 489 | } |
@@ -828,6 +848,7 @@ impl<'a> InferenceContext<'a> { | |||
828 | self.trait_env.clone(), | 848 | self.trait_env.clone(), |
829 | krate, | 849 | krate, |
830 | &traits_in_scope, | 850 | &traits_in_scope, |
851 | self.resolver.module(), | ||
831 | method_name, | 852 | method_name, |
832 | ) | 853 | ) |
833 | }); | 854 | }); |
diff --git a/crates/hir_ty/src/infer/path.rs b/crates/hir_ty/src/infer/path.rs index 58cce56ab..cefa38509 100644 --- a/crates/hir_ty/src/infer/path.rs +++ b/crates/hir_ty/src/infer/path.rs | |||
@@ -230,6 +230,7 @@ impl<'a> InferenceContext<'a> { | |||
230 | self.trait_env.clone(), | 230 | self.trait_env.clone(), |
231 | krate, | 231 | krate, |
232 | &traits_in_scope, | 232 | &traits_in_scope, |
233 | None, | ||
233 | Some(name), | 234 | Some(name), |
234 | method_resolution::LookupMode::Path, | 235 | method_resolution::LookupMode::Path, |
235 | move |_ty, item| { | 236 | move |_ty, item| { |
diff --git a/crates/hir_ty/src/method_resolution.rs b/crates/hir_ty/src/method_resolution.rs index 8e986ddde..84d9a1e18 100644 --- a/crates/hir_ty/src/method_resolution.rs +++ b/crates/hir_ty/src/method_resolution.rs | |||
@@ -296,6 +296,7 @@ pub(crate) fn lookup_method( | |||
296 | env: Arc<TraitEnvironment>, | 296 | env: Arc<TraitEnvironment>, |
297 | krate: CrateId, | 297 | krate: CrateId, |
298 | traits_in_scope: &FxHashSet<TraitId>, | 298 | traits_in_scope: &FxHashSet<TraitId>, |
299 | visible_from_module: Option<ModuleId>, | ||
299 | name: &Name, | 300 | name: &Name, |
300 | ) -> Option<(Ty, FunctionId)> { | 301 | ) -> Option<(Ty, FunctionId)> { |
301 | iterate_method_candidates( | 302 | iterate_method_candidates( |
@@ -304,6 +305,7 @@ pub(crate) fn lookup_method( | |||
304 | env, | 305 | env, |
305 | krate, | 306 | krate, |
306 | &traits_in_scope, | 307 | &traits_in_scope, |
308 | visible_from_module, | ||
307 | Some(name), | 309 | Some(name), |
308 | LookupMode::MethodCall, | 310 | LookupMode::MethodCall, |
309 | |ty, f| match f { | 311 | |ty, f| match f { |
@@ -334,6 +336,7 @@ pub fn iterate_method_candidates<T>( | |||
334 | env: Arc<TraitEnvironment>, | 336 | env: Arc<TraitEnvironment>, |
335 | krate: CrateId, | 337 | krate: CrateId, |
336 | traits_in_scope: &FxHashSet<TraitId>, | 338 | traits_in_scope: &FxHashSet<TraitId>, |
339 | visible_from_module: Option<ModuleId>, | ||
337 | name: Option<&Name>, | 340 | name: Option<&Name>, |
338 | mode: LookupMode, | 341 | mode: LookupMode, |
339 | mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>, | 342 | mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>, |
@@ -345,6 +348,7 @@ pub fn iterate_method_candidates<T>( | |||
345 | env, | 348 | env, |
346 | krate, | 349 | krate, |
347 | traits_in_scope, | 350 | traits_in_scope, |
351 | visible_from_module, | ||
348 | name, | 352 | name, |
349 | mode, | 353 | mode, |
350 | &mut |ty, item| { | 354 | &mut |ty, item| { |
@@ -362,6 +366,7 @@ fn iterate_method_candidates_impl( | |||
362 | env: Arc<TraitEnvironment>, | 366 | env: Arc<TraitEnvironment>, |
363 | krate: CrateId, | 367 | krate: CrateId, |
364 | traits_in_scope: &FxHashSet<TraitId>, | 368 | traits_in_scope: &FxHashSet<TraitId>, |
369 | visible_from_module: Option<ModuleId>, | ||
365 | name: Option<&Name>, | 370 | name: Option<&Name>, |
366 | mode: LookupMode, | 371 | mode: LookupMode, |
367 | callback: &mut dyn FnMut(&Ty, AssocItemId) -> bool, | 372 | callback: &mut dyn FnMut(&Ty, AssocItemId) -> bool, |
@@ -399,6 +404,7 @@ fn iterate_method_candidates_impl( | |||
399 | env.clone(), | 404 | env.clone(), |
400 | krate, | 405 | krate, |
401 | traits_in_scope, | 406 | traits_in_scope, |
407 | visible_from_module, | ||
402 | name, | 408 | name, |
403 | callback, | 409 | callback, |
404 | ) { | 410 | ) { |
@@ -415,6 +421,7 @@ fn iterate_method_candidates_impl( | |||
415 | env, | 421 | env, |
416 | krate, | 422 | krate, |
417 | traits_in_scope, | 423 | traits_in_scope, |
424 | visible_from_module, | ||
418 | name, | 425 | name, |
419 | callback, | 426 | callback, |
420 | ) | 427 | ) |
@@ -428,6 +435,7 @@ fn iterate_method_candidates_with_autoref( | |||
428 | env: Arc<TraitEnvironment>, | 435 | env: Arc<TraitEnvironment>, |
429 | krate: CrateId, | 436 | krate: CrateId, |
430 | traits_in_scope: &FxHashSet<TraitId>, | 437 | traits_in_scope: &FxHashSet<TraitId>, |
438 | visible_from_module: Option<ModuleId>, | ||
431 | name: Option<&Name>, | 439 | name: Option<&Name>, |
432 | mut callback: &mut dyn FnMut(&Ty, AssocItemId) -> bool, | 440 | mut callback: &mut dyn FnMut(&Ty, AssocItemId) -> bool, |
433 | ) -> bool { | 441 | ) -> bool { |
@@ -438,6 +446,7 @@ fn iterate_method_candidates_with_autoref( | |||
438 | env.clone(), | 446 | env.clone(), |
439 | krate, | 447 | krate, |
440 | &traits_in_scope, | 448 | &traits_in_scope, |
449 | visible_from_module, | ||
441 | name, | 450 | name, |
442 | &mut callback, | 451 | &mut callback, |
443 | ) { | 452 | ) { |
@@ -454,6 +463,7 @@ fn iterate_method_candidates_with_autoref( | |||
454 | env.clone(), | 463 | env.clone(), |
455 | krate, | 464 | krate, |
456 | &traits_in_scope, | 465 | &traits_in_scope, |
466 | visible_from_module, | ||
457 | name, | 467 | name, |
458 | &mut callback, | 468 | &mut callback, |
459 | ) { | 469 | ) { |
@@ -470,6 +480,7 @@ fn iterate_method_candidates_with_autoref( | |||
470 | env, | 480 | env, |
471 | krate, | 481 | krate, |
472 | &traits_in_scope, | 482 | &traits_in_scope, |
483 | visible_from_module, | ||
473 | name, | 484 | name, |
474 | &mut callback, | 485 | &mut callback, |
475 | ) { | 486 | ) { |
@@ -485,6 +496,7 @@ fn iterate_method_candidates_by_receiver( | |||
485 | env: Arc<TraitEnvironment>, | 496 | env: Arc<TraitEnvironment>, |
486 | krate: CrateId, | 497 | krate: CrateId, |
487 | traits_in_scope: &FxHashSet<TraitId>, | 498 | traits_in_scope: &FxHashSet<TraitId>, |
499 | visible_from_module: Option<ModuleId>, | ||
488 | name: Option<&Name>, | 500 | name: Option<&Name>, |
489 | mut callback: &mut dyn FnMut(&Ty, AssocItemId) -> bool, | 501 | mut callback: &mut dyn FnMut(&Ty, AssocItemId) -> bool, |
490 | ) -> bool { | 502 | ) -> bool { |
@@ -492,7 +504,15 @@ fn iterate_method_candidates_by_receiver( | |||
492 | // be found in any of the derefs of receiver_ty, so we have to go through | 504 | // be found in any of the derefs of receiver_ty, so we have to go through |
493 | // that. | 505 | // that. |
494 | for self_ty in std::iter::once(receiver_ty).chain(rest_of_deref_chain) { | 506 | for self_ty in std::iter::once(receiver_ty).chain(rest_of_deref_chain) { |
495 | if iterate_inherent_methods(self_ty, db, name, Some(receiver_ty), krate, &mut callback) { | 507 | if iterate_inherent_methods( |
508 | self_ty, | ||
509 | db, | ||
510 | name, | ||
511 | Some(receiver_ty), | ||
512 | krate, | ||
513 | visible_from_module, | ||
514 | &mut callback, | ||
515 | ) { | ||
496 | return true; | 516 | return true; |
497 | } | 517 | } |
498 | } | 518 | } |
@@ -519,10 +539,12 @@ fn iterate_method_candidates_for_self_ty( | |||
519 | env: Arc<TraitEnvironment>, | 539 | env: Arc<TraitEnvironment>, |
520 | krate: CrateId, | 540 | krate: CrateId, |
521 | traits_in_scope: &FxHashSet<TraitId>, | 541 | traits_in_scope: &FxHashSet<TraitId>, |
542 | visible_from_module: Option<ModuleId>, | ||
522 | name: Option<&Name>, | 543 | name: Option<&Name>, |
523 | mut callback: &mut dyn FnMut(&Ty, AssocItemId) -> bool, | 544 | mut callback: &mut dyn FnMut(&Ty, AssocItemId) -> bool, |
524 | ) -> bool { | 545 | ) -> bool { |
525 | if iterate_inherent_methods(self_ty, db, name, None, krate, &mut callback) { | 546 | if iterate_inherent_methods(self_ty, db, name, None, krate, visible_from_module, &mut callback) |
547 | { | ||
526 | return true; | 548 | return true; |
527 | } | 549 | } |
528 | iterate_trait_method_candidates(self_ty, db, env, krate, traits_in_scope, name, None, callback) | 550 | iterate_trait_method_candidates(self_ty, db, env, krate, traits_in_scope, name, None, callback) |
@@ -559,7 +581,9 @@ fn iterate_trait_method_candidates( | |||
559 | // iteration | 581 | // iteration |
560 | let mut known_implemented = false; | 582 | let mut known_implemented = false; |
561 | for (_name, item) in data.items.iter() { | 583 | for (_name, item) in data.items.iter() { |
562 | if !is_valid_candidate(db, name, receiver_ty, *item, self_ty) { | 584 | // Don't pass a `visible_from_module` down to `is_valid_candidate`, |
585 | // since only inherent methods should be included into visibility checking. | ||
586 | if !is_valid_candidate(db, name, receiver_ty, *item, self_ty, None) { | ||
563 | continue; | 587 | continue; |
564 | } | 588 | } |
565 | if !known_implemented { | 589 | if !known_implemented { |
@@ -583,6 +607,7 @@ fn iterate_inherent_methods( | |||
583 | name: Option<&Name>, | 607 | name: Option<&Name>, |
584 | receiver_ty: Option<&Canonical<Ty>>, | 608 | receiver_ty: Option<&Canonical<Ty>>, |
585 | krate: CrateId, | 609 | krate: CrateId, |
610 | visible_from_module: Option<ModuleId>, | ||
586 | callback: &mut dyn FnMut(&Ty, AssocItemId) -> bool, | 611 | callback: &mut dyn FnMut(&Ty, AssocItemId) -> bool, |
587 | ) -> bool { | 612 | ) -> bool { |
588 | let def_crates = match self_ty.value.def_crates(db, krate) { | 613 | let def_crates = match self_ty.value.def_crates(db, krate) { |
@@ -594,7 +619,7 @@ fn iterate_inherent_methods( | |||
594 | 619 | ||
595 | for &impl_def in impls.for_self_ty(&self_ty.value) { | 620 | for &impl_def in impls.for_self_ty(&self_ty.value) { |
596 | for &item in db.impl_data(impl_def).items.iter() { | 621 | for &item in db.impl_data(impl_def).items.iter() { |
597 | if !is_valid_candidate(db, name, receiver_ty, item, self_ty) { | 622 | if !is_valid_candidate(db, name, receiver_ty, item, self_ty, visible_from_module) { |
598 | continue; | 623 | continue; |
599 | } | 624 | } |
600 | // we have to check whether the self type unifies with the type | 625 | // we have to check whether the self type unifies with the type |
@@ -639,6 +664,7 @@ fn is_valid_candidate( | |||
639 | receiver_ty: Option<&Canonical<Ty>>, | 664 | receiver_ty: Option<&Canonical<Ty>>, |
640 | item: AssocItemId, | 665 | item: AssocItemId, |
641 | self_ty: &Canonical<Ty>, | 666 | self_ty: &Canonical<Ty>, |
667 | visible_from_module: Option<ModuleId>, | ||
642 | ) -> bool { | 668 | ) -> bool { |
643 | match item { | 669 | match item { |
644 | AssocItemId::FunctionId(m) => { | 670 | AssocItemId::FunctionId(m) => { |
@@ -660,6 +686,13 @@ fn is_valid_candidate( | |||
660 | return false; | 686 | return false; |
661 | } | 687 | } |
662 | } | 688 | } |
689 | if let Some(from_module) = visible_from_module { | ||
690 | if !db.function_visibility(m).is_visible_from(db.upcast(), from_module) { | ||
691 | cov_mark::hit!(autoderef_candidate_not_visible); | ||
692 | return false; | ||
693 | } | ||
694 | } | ||
695 | |||
663 | true | 696 | true |
664 | } | 697 | } |
665 | AssocItemId::ConstId(c) => { | 698 | AssocItemId::ConstId(c) => { |
diff --git a/crates/hir_ty/src/tests/macros.rs b/crates/hir_ty/src/tests/macros.rs index 12951fb16..7eda51866 100644 --- a/crates/hir_ty/src/tests/macros.rs +++ b/crates/hir_ty/src/tests/macros.rs | |||
@@ -31,12 +31,12 @@ struct S; | |||
31 | 31 | ||
32 | #[cfg(not(test))] | 32 | #[cfg(not(test))] |
33 | impl S { | 33 | impl S { |
34 | fn foo3(&self) -> i32 { 0 } | 34 | pub fn foo3(&self) -> i32 { 0 } |
35 | } | 35 | } |
36 | 36 | ||
37 | #[cfg(test)] | 37 | #[cfg(test)] |
38 | impl S { | 38 | impl S { |
39 | fn foo4(&self) -> i32 { 0 } | 39 | pub fn foo4(&self) -> i32 { 0 } |
40 | } | 40 | } |
41 | "#, | 41 | "#, |
42 | ); | 42 | ); |
diff --git a/crates/hir_ty/src/tests/method_resolution.rs b/crates/hir_ty/src/tests/method_resolution.rs index 4e3f9a9b6..61f18b0d2 100644 --- a/crates/hir_ty/src/tests/method_resolution.rs +++ b/crates/hir_ty/src/tests/method_resolution.rs | |||
@@ -1173,3 +1173,122 @@ fn main() { | |||
1173 | "#, | 1173 | "#, |
1174 | ); | 1174 | ); |
1175 | } | 1175 | } |
1176 | |||
1177 | #[test] | ||
1178 | fn autoderef_visibility_field() { | ||
1179 | check_infer( | ||
1180 | r#" | ||
1181 | #[lang = "deref"] | ||
1182 | pub trait Deref { | ||
1183 | type Target; | ||
1184 | fn deref(&self) -> &Self::Target; | ||
1185 | } | ||
1186 | mod a { | ||
1187 | pub struct Foo(pub char); | ||
1188 | pub struct Bar(i32); | ||
1189 | impl Bar { | ||
1190 | pub fn new() -> Self { | ||
1191 | Self(0) | ||
1192 | } | ||
1193 | } | ||
1194 | impl super::Deref for Bar { | ||
1195 | type Target = Foo; | ||
1196 | fn deref(&self) -> &Foo { | ||
1197 | &Foo('z') | ||
1198 | } | ||
1199 | } | ||
1200 | } | ||
1201 | mod b { | ||
1202 | fn foo() { | ||
1203 | let x = super::a::Bar::new().0; | ||
1204 | } | ||
1205 | } | ||
1206 | "#, | ||
1207 | expect![[r#" | ||
1208 | 67..71 'self': &Self | ||
1209 | 200..231 '{ ... }': Bar | ||
1210 | 214..218 'Self': Bar(i32) -> Bar | ||
1211 | 214..221 'Self(0)': Bar | ||
1212 | 219..220 '0': i32 | ||
1213 | 315..319 'self': &Bar | ||
1214 | 329..362 '{ ... }': &Foo | ||
1215 | 343..352 '&Foo('z')': &Foo | ||
1216 | 344..347 'Foo': Foo(char) -> Foo | ||
1217 | 344..352 'Foo('z')': Foo | ||
1218 | 348..351 ''z'': char | ||
1219 | 392..439 '{ ... }': () | ||
1220 | 406..407 'x': char | ||
1221 | 410..428 'super:...r::new': fn new() -> Bar | ||
1222 | 410..430 'super:...:new()': Bar | ||
1223 | 410..432 'super:...ew().0': char | ||
1224 | "#]], | ||
1225 | ) | ||
1226 | } | ||
1227 | |||
1228 | #[test] | ||
1229 | fn autoderef_visibility_method() { | ||
1230 | cov_mark::check!(autoderef_candidate_not_visible); | ||
1231 | check_infer( | ||
1232 | r#" | ||
1233 | #[lang = "deref"] | ||
1234 | pub trait Deref { | ||
1235 | type Target; | ||
1236 | fn deref(&self) -> &Self::Target; | ||
1237 | } | ||
1238 | mod a { | ||
1239 | pub struct Foo(pub char); | ||
1240 | impl Foo { | ||
1241 | pub fn mango(&self) -> char { | ||
1242 | self.0 | ||
1243 | } | ||
1244 | } | ||
1245 | pub struct Bar(i32); | ||
1246 | impl Bar { | ||
1247 | pub fn new() -> Self { | ||
1248 | Self(0) | ||
1249 | } | ||
1250 | fn mango(&self) -> i32 { | ||
1251 | self.0 | ||
1252 | } | ||
1253 | } | ||
1254 | impl super::Deref for Bar { | ||
1255 | type Target = Foo; | ||
1256 | fn deref(&self) -> &Foo { | ||
1257 | &Foo('z') | ||
1258 | } | ||
1259 | } | ||
1260 | } | ||
1261 | mod b { | ||
1262 | fn foo() { | ||
1263 | let x = super::a::Bar::new().mango(); | ||
1264 | } | ||
1265 | } | ||
1266 | "#, | ||
1267 | expect![[r#" | ||
1268 | 67..71 'self': &Self | ||
1269 | 168..172 'self': &Foo | ||
1270 | 182..212 '{ ... }': char | ||
1271 | 196..200 'self': &Foo | ||
1272 | 196..202 'self.0': char | ||
1273 | 288..319 '{ ... }': Bar | ||
1274 | 302..306 'Self': Bar(i32) -> Bar | ||
1275 | 302..309 'Self(0)': Bar | ||
1276 | 307..308 '0': i32 | ||
1277 | 338..342 'self': &Bar | ||
1278 | 351..381 '{ ... }': i32 | ||
1279 | 365..369 'self': &Bar | ||
1280 | 365..371 'self.0': i32 | ||
1281 | 465..469 'self': &Bar | ||
1282 | 479..512 '{ ... }': &Foo | ||
1283 | 493..502 '&Foo('z')': &Foo | ||
1284 | 494..497 'Foo': Foo(char) -> Foo | ||
1285 | 494..502 'Foo('z')': Foo | ||
1286 | 498..501 ''z'': char | ||
1287 | 542..595 '{ ... }': () | ||
1288 | 556..557 'x': char | ||
1289 | 560..578 'super:...r::new': fn new() -> Bar | ||
1290 | 560..580 'super:...:new()': Bar | ||
1291 | 560..588 'super:...ango()': char | ||
1292 | "#]], | ||
1293 | ) | ||
1294 | } | ||
diff --git a/crates/hir_ty/src/tests/simple.rs b/crates/hir_ty/src/tests/simple.rs index bcc43ed70..361cd6302 100644 --- a/crates/hir_ty/src/tests/simple.rs +++ b/crates/hir_ty/src/tests/simple.rs | |||
@@ -1103,7 +1103,7 @@ fn infer_inherent_method() { | |||
1103 | 1103 | ||
1104 | mod b { | 1104 | mod b { |
1105 | impl super::A { | 1105 | impl super::A { |
1106 | fn bar(&self, x: u64) -> i64 {} | 1106 | pub fn bar(&self, x: u64) -> i64 {} |
1107 | } | 1107 | } |
1108 | } | 1108 | } |
1109 | 1109 | ||
@@ -1117,21 +1117,21 @@ fn infer_inherent_method() { | |||
1117 | 31..35 'self': A | 1117 | 31..35 'self': A |
1118 | 37..38 'x': u32 | 1118 | 37..38 'x': u32 |
1119 | 52..54 '{}': () | 1119 | 52..54 '{}': () |
1120 | 102..106 'self': &A | 1120 | 106..110 'self': &A |
1121 | 108..109 'x': u64 | 1121 | 112..113 'x': u64 |
1122 | 123..125 '{}': () | 1122 | 127..129 '{}': () |
1123 | 143..144 'a': A | 1123 | 147..148 'a': A |
1124 | 149..197 '{ ...(1); }': () | 1124 | 153..201 '{ ...(1); }': () |
1125 | 155..156 'a': A | 1125 | 159..160 'a': A |
1126 | 155..163 'a.foo(1)': i32 | 1126 | 159..167 'a.foo(1)': i32 |
1127 | 161..162 '1': u32 | 1127 | 165..166 '1': u32 |
1128 | 169..180 '(&a).bar(1)': i64 | 1128 | 173..184 '(&a).bar(1)': i64 |
1129 | 170..172 '&a': &A | 1129 | 174..176 '&a': &A |
1130 | 171..172 'a': A | 1130 | 175..176 'a': A |
1131 | 178..179 '1': u64 | 1131 | 182..183 '1': u64 |
1132 | 186..187 'a': A | 1132 | 190..191 'a': A |
1133 | 186..194 'a.bar(1)': i64 | 1133 | 190..198 'a.bar(1)': i64 |
1134 | 192..193 '1': u64 | 1134 | 196..197 '1': u64 |
1135 | "#]], | 1135 | "#]], |
1136 | ); | 1136 | ); |
1137 | } | 1137 | } |
diff --git a/crates/hir_ty/src/tests/traits.rs b/crates/hir_ty/src/tests/traits.rs index 45a1958e3..2ba97f814 100644 --- a/crates/hir_ty/src/tests/traits.rs +++ b/crates/hir_ty/src/tests/traits.rs | |||
@@ -187,8 +187,8 @@ mod iter { | |||
187 | mod collections { | 187 | mod collections { |
188 | struct Vec<T> {} | 188 | struct Vec<T> {} |
189 | impl<T> Vec<T> { | 189 | impl<T> Vec<T> { |
190 | fn new() -> Self { Vec {} } | 190 | pub fn new() -> Self { Vec {} } |
191 | fn push(&mut self, t: T) { } | 191 | pub fn push(&mut self, t: T) { } |
192 | } | 192 | } |
193 | 193 | ||
194 | impl<T> IntoIterator for Vec<T> { | 194 | impl<T> IntoIterator for Vec<T> { |