From 15e4aae82329e5c53e488c54fb0561bb289f5c21 Mon Sep 17 00:00:00 2001 From: cynecx Date: Sat, 20 Mar 2021 17:12:49 +0100 Subject: hir_ty: fix tests by making required methods public --- crates/hir_ty/src/tests/macros.rs | 4 ++-- crates/hir_ty/src/tests/traits.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/hir_ty/src/tests/macros.rs b/crates/hir_ty/src/tests/macros.rs index c1e605740..88ba9b118 100644 --- a/crates/hir_ty/src/tests/macros.rs +++ b/crates/hir_ty/src/tests/macros.rs @@ -31,12 +31,12 @@ struct S; #[cfg(not(test))] impl S { - fn foo3(&self) -> i32 { 0 } + pub fn foo3(&self) -> i32 { 0 } } #[cfg(test)] impl S { - fn foo4(&self) -> i32 { 0 } + pub fn foo4(&self) -> i32 { 0 } } "#, ); diff --git a/crates/hir_ty/src/tests/traits.rs b/crates/hir_ty/src/tests/traits.rs index 8f2bdffc0..f7ee6def6 100644 --- a/crates/hir_ty/src/tests/traits.rs +++ b/crates/hir_ty/src/tests/traits.rs @@ -187,8 +187,8 @@ mod iter { mod collections { struct Vec {} impl Vec { - fn new() -> Self { Vec {} } - fn push(&mut self, t: T) { } + pub fn new() -> Self { Vec {} } + pub fn push(&mut self, t: T) { } } impl IntoIterator for Vec { -- cgit v1.2.3 From edfd741c5bdd9bbc044e3e362f5b446db7d817ef Mon Sep 17 00:00:00 2001 From: cynecx Date: Sat, 20 Mar 2021 17:13:58 +0100 Subject: hir_ty: add tests around autoderef with visibility checking --- crates/hir_ty/src/tests/method_resolution.rs | 119 +++++++++++++++++++++++++++ 1 file changed, 119 insertions(+) diff --git a/crates/hir_ty/src/tests/method_resolution.rs b/crates/hir_ty/src/tests/method_resolution.rs index 4e3f9a9b6..751a7ce54 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() { "#, ); } + +#[test] +fn autoderef_visibility_field() { + check_infer( + r#" +#[lang = "deref"] +pub trait Deref { + type Target; + fn deref(&self) -> &Self::Target; +} +mod a { + pub struct Foo(pub char); + pub struct Bar(i32); + impl Bar { + pub fn new() -> Self { + Self(0) + } + } + impl super::Deref for Bar { + type Target = Foo; + fn deref(&self) -> &Foo { + &Foo('z') + } + } +} +mod b { + fn foo() { + let x = super::a::Bar::new().0; + } +} + "#, + expect![[r#" + 67..71 'self': &Self + 200..231 '{ ... }': Bar + 214..218 'Self': Bar(i32) -> Bar + 214..221 'Self(0)': Bar + 219..220 '0': i32 + 315..319 'self': &Bar + 329..362 '{ ... }': &Foo + 343..352 '&Foo('z')': &Foo + 344..347 'Foo': Foo(char) -> Foo + 344..352 'Foo('z')': Foo + 348..351 ''z'': char + 392..439 '{ ... }': () + 406..407 'x': char + 410..428 'super:...r::new': fn new() -> Bar + 410..430 'super:...:new()': Bar + 410..432 'super:...ew().0': char + "#]], + ) +} + +#[test] +fn autoderef_visibility_method() { + check_infer( + r#" +#[lang = "deref"] +pub trait Deref { + type Target; + fn deref(&self) -> &Self::Target; +} +mod a { + pub struct Foo(pub char); + + impl Foo { + pub fn mango(&self) -> char { + self.0 + } + } + pub struct Bar(i32); + impl Bar { + pub fn new() -> Self { + Self(0) + } + fn mango(&self) -> i32 { + self.0 + } + } + impl super::Deref for Bar { + type Target = Foo; + fn deref(&self) -> &Foo { + &Foo('z') + } + } +} +mod b { + fn foo() { + let x = super::a::Bar::new().mango(); + } +} + "#, + expect![[r#" + 67..71 'self': &Self + 173..177 'self': &Foo + 187..217 '{ ... }': char + 201..205 'self': &Foo + 201..207 'self.0': char + 293..324 '{ ... }': Bar + 307..311 'Self': Bar(i32) -> Bar + 307..314 'Self(0)': Bar + 312..313 '0': i32 + 343..347 'self': &Bar + 356..386 '{ ... }': i32 + 370..374 'self': &Bar + 370..376 'self.0': i32 + 470..474 'self': &Bar + 484..517 '{ ... }': &Foo + 498..507 '&Foo('z')': &Foo + 499..502 'Foo': Foo(char) -> Foo + 499..507 'Foo('z')': Foo + 503..506 ''z'': char + 547..600 '{ ... }': () + 561..562 'x': char + 565..583 'super:...r::new': fn new() -> Bar + 565..585 'super:...:new()': Bar + 565..593 'super:...ango()': char + "#]], + ) +} -- cgit v1.2.3 From 30980396afa713a7b877c7962c5b45329230cdc5 Mon Sep 17 00:00:00 2001 From: cynecx Date: Sat, 20 Mar 2021 18:29:30 +0100 Subject: hir_ty: add field_visibilities and fn_visibility queries --- crates/hir_ty/src/db.rs | 10 ++++++++-- crates/hir_ty/src/lower.rs | 27 +++++++++++++++++++++++++-- 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/crates/hir_ty/src/db.rs b/crates/hir_ty/src/db.rs index 91a2e0b5b..b1d22a9f9 100644 --- a/crates/hir_ty/src/db.rs +++ b/crates/hir_ty/src/db.rs @@ -4,8 +4,8 @@ use std::sync::Arc; use base_db::{impl_intern_key, salsa, CrateId, Upcast}; use hir_def::{ - db::DefDatabase, expr::ExprId, ConstParamId, DefWithBodyId, FunctionId, GenericDefId, ImplId, - LocalFieldId, TypeParamId, VariantId, + db::DefDatabase, expr::ExprId, visibility::Visibility, ConstParamId, DefWithBodyId, FunctionId, + GenericDefId, ImplId, LocalFieldId, TypeParamId, VariantId, }; use la_arena::ArenaMap; @@ -128,6 +128,12 @@ pub trait HirDatabase: DefDatabase + Upcast { krate: CrateId, env: chalk_ir::Environment, ) -> chalk_ir::ProgramClauses; + + #[salsa::invoke(crate::lower::field_visibilities_query)] + fn field_visibilities(&self, var: VariantId) -> Arc>; + + #[salsa::invoke(crate::lower::fn_visibility_query)] + fn fn_visibility(&self, def: FunctionId) -> Visibility; } fn infer_wait(db: &dyn HirDatabase, def: DefWithBodyId) -> Arc { diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs index cbbb535e5..c4062a41d 100644 --- a/crates/hir_ty/src/lower.rs +++ b/crates/hir_ty/src/lower.rs @@ -16,9 +16,10 @@ use hir_def::{ path::{GenericArg, Path, PathSegment, PathSegments}, resolver::{HasResolver, Resolver, TypeNs}, type_ref::{TypeBound, TypeRef}, + visibility::Visibility, AdtId, AssocContainerId, AssocItemId, ConstId, ConstParamId, EnumId, EnumVariantId, FunctionId, - GenericDefId, HasModule, ImplId, LocalFieldId, Lookup, StaticId, StructId, TraitId, - TypeAliasId, TypeParamId, UnionId, VariantId, + GenericDefId, HasModule, ImplId, LocalFieldId, Lookup, ModuleDefId, StaticId, StructId, + TraitId, TypeAliasId, TypeParamId, UnionId, VariantId, }; use hir_expand::name::Name; use la_arena::ArenaMap; @@ -867,6 +868,28 @@ pub(crate) fn field_types_query( Arc::new(res) } +/// Resolve visibility of all specific fields of a struct or union variant. +pub(crate) fn field_visibilities_query( + db: &dyn HirDatabase, + variant_id: VariantId, +) -> Arc> { + let def_db = db.upcast(); + let var_data = variant_data(def_db, variant_id); + let resolver = variant_id.module(def_db).resolver(def_db); + let mut res = ArenaMap::default(); + for (field_id, field_data) in var_data.fields().iter() { + res.insert(field_id, field_data.visibility.resolve(def_db, &resolver)) + } + Arc::new(res) +} + +/// Resolve visibility of a function. +pub(crate) fn fn_visibility_query(db: &dyn HirDatabase, def: FunctionId) -> Visibility { + let def_db = db.upcast(); + let resolver = ModuleDefId::from(def).module(def_db).unwrap().resolver(def_db); + db.function_data(def).visibility.resolve(def_db, &resolver) +} + /// This query exists only to be used when resolving short-hand associated types /// like `T::Item`. /// -- cgit v1.2.3 From b1b456c64254e82c4edf065c9cc526bf8e734d68 Mon Sep 17 00:00:00 2001 From: cynecx Date: Sat, 20 Mar 2021 19:07:23 +0100 Subject: hir_ty: check field visibility while iterating through autoderef candidates --- crates/hir_ty/src/infer/expr.rs | 50 +++++++++++++++++++++++++++++------------ 1 file changed, 36 insertions(+), 14 deletions(-) diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs index 79bbc5dab..9bf9f87e4 100644 --- a/crates/hir_ty/src/infer/expr.rs +++ b/crates/hir_ty/src/infer/expr.rs @@ -442,27 +442,49 @@ impl<'a> InferenceContext<'a> { }, ) .find_map(|derefed_ty| { + let def_db = self.db.upcast(); + let module = self.resolver.module(); + let is_visible = |field_id: &FieldId| { + module + .map(|mod_id| { + self.db.field_visibilities(field_id.parent)[field_id.local_id] + .is_visible_from(def_db, mod_id) + }) + .unwrap_or(true) + }; match canonicalized.decanonicalize_ty(derefed_ty.value).interned(&Interner) { TyKind::Tuple(_, substs) => { name.as_tuple_index().and_then(|idx| substs.0.get(idx).cloned()) } TyKind::Adt(AdtId(hir_def::AdtId::StructId(s)), parameters) => { - self.db.struct_data(*s).variant_data.field(name).map(|local_id| { - let field = FieldId { parent: (*s).into(), local_id }; - self.write_field_resolution(tgt_expr, field); - self.db.field_types((*s).into())[field.local_id] - .clone() - .subst(¶meters) - }) + let local_id = self.db.struct_data(*s).variant_data.field(name)?; + let field = FieldId { parent: (*s).into(), local_id }; + let is_visible_in_ctx = is_visible(&field); + self.write_field_resolution(tgt_expr, field); + if is_visible_in_ctx { + Some( + self.db.field_types((*s).into())[field.local_id] + .clone() + .subst(¶meters), + ) + } else { + None + } } TyKind::Adt(AdtId(hir_def::AdtId::UnionId(u)), parameters) => { - self.db.union_data(*u).variant_data.field(name).map(|local_id| { - let field = FieldId { parent: (*u).into(), local_id }; - self.write_field_resolution(tgt_expr, field); - self.db.field_types((*u).into())[field.local_id] - .clone() - .subst(¶meters) - }) + let local_id = self.db.union_data(*u).variant_data.field(name)?; + let field = FieldId { parent: (*u).into(), local_id }; + let is_visible_in_ctx = is_visible(&field); + self.write_field_resolution(tgt_expr, field); + if is_visible_in_ctx { + Some( + self.db.field_types((*u).into())[field.local_id] + .clone() + .subst(¶meters), + ) + } else { + None + } } _ => None, } -- cgit v1.2.3 From 34bb13e293e757bb7267eb76884caacb4b94b48b Mon Sep 17 00:00:00 2001 From: cynecx Date: Sat, 20 Mar 2021 19:28:26 +0100 Subject: hir_ty: introduce visible_from_module param into method resolution --- crates/hir/src/lib.rs | 7 +++++++ crates/hir_ty/src/infer/expr.rs | 1 + crates/hir_ty/src/infer/path.rs | 1 + crates/hir_ty/src/method_resolution.rs | 35 ++++++++++++++++++++++++++++++---- 4 files changed, 40 insertions(+), 4 deletions(-) diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 30e577671..1a65a5cad 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -1967,12 +1967,18 @@ impl Type { let env = self.ty.environment.clone(); let krate = krate.id; + let from_module = match self.as_adt() { + Some(adt) => Some(adt.module(db).id), + None => None, + }; + method_resolution::iterate_method_candidates( &canonical, db, env, krate, traits_in_scope, + from_module, name, method_resolution::LookupMode::MethodCall, |ty, it| match it { @@ -2004,6 +2010,7 @@ impl Type { env, krate, traits_in_scope, + None, name, method_resolution::LookupMode::Path, |ty, it| callback(ty, it.into()), diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs index 9bf9f87e4..b08880cdf 100644 --- a/crates/hir_ty/src/infer/expr.rs +++ b/crates/hir_ty/src/infer/expr.rs @@ -849,6 +849,7 @@ impl<'a> InferenceContext<'a> { self.trait_env.clone(), krate, &traits_in_scope, + self.resolver.module(), method_name, ) }); 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> { self.trait_env.clone(), krate, &traits_in_scope, + None, Some(name), method_resolution::LookupMode::Path, move |_ty, item| { diff --git a/crates/hir_ty/src/method_resolution.rs b/crates/hir_ty/src/method_resolution.rs index da6bc2a4a..6c34982a1 100644 --- a/crates/hir_ty/src/method_resolution.rs +++ b/crates/hir_ty/src/method_resolution.rs @@ -295,6 +295,7 @@ pub(crate) fn lookup_method( env: Arc, krate: CrateId, traits_in_scope: &FxHashSet, + visible_from_module: Option, name: &Name, ) -> Option<(Ty, FunctionId)> { iterate_method_candidates( @@ -303,6 +304,7 @@ pub(crate) fn lookup_method( env, krate, &traits_in_scope, + visible_from_module, Some(name), LookupMode::MethodCall, |ty, f| match f { @@ -333,6 +335,7 @@ pub fn iterate_method_candidates( env: Arc, krate: CrateId, traits_in_scope: &FxHashSet, + visible_from_module: Option, name: Option<&Name>, mode: LookupMode, mut callback: impl FnMut(&Ty, AssocItemId) -> Option, @@ -344,6 +347,7 @@ pub fn iterate_method_candidates( env, krate, traits_in_scope, + visible_from_module, name, mode, &mut |ty, item| { @@ -361,6 +365,7 @@ fn iterate_method_candidates_impl( env: Arc, krate: CrateId, traits_in_scope: &FxHashSet, + visible_from_module: Option, name: Option<&Name>, mode: LookupMode, callback: &mut dyn FnMut(&Ty, AssocItemId) -> bool, @@ -398,6 +403,7 @@ fn iterate_method_candidates_impl( env.clone(), krate, traits_in_scope, + visible_from_module, name, callback, ) { @@ -427,6 +433,7 @@ fn iterate_method_candidates_with_autoref( env: Arc, krate: CrateId, traits_in_scope: &FxHashSet, + visible_from_module: Option, name: Option<&Name>, mut callback: &mut dyn FnMut(&Ty, AssocItemId) -> bool, ) -> bool { @@ -437,6 +444,7 @@ fn iterate_method_candidates_with_autoref( env.clone(), krate, &traits_in_scope, + visible_from_module, name, &mut callback, ) { @@ -453,6 +461,7 @@ fn iterate_method_candidates_with_autoref( env.clone(), krate, &traits_in_scope, + visible_from_module, name, &mut callback, ) { @@ -469,6 +478,7 @@ fn iterate_method_candidates_with_autoref( env, krate, &traits_in_scope, + visible_from_module, name, &mut callback, ) { @@ -484,6 +494,7 @@ fn iterate_method_candidates_by_receiver( env: Arc, krate: CrateId, traits_in_scope: &FxHashSet, + visible_from_module: Option, name: Option<&Name>, mut callback: &mut dyn FnMut(&Ty, AssocItemId) -> bool, ) -> bool { @@ -491,7 +502,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; } } @@ -521,7 +540,7 @@ fn iterate_method_candidates_for_self_ty( 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, None, &mut callback) { return true; } iterate_trait_method_candidates(self_ty, db, env, krate, traits_in_scope, name, None, callback) @@ -558,7 +577,7 @@ 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) { + if !is_valid_candidate(db, name, receiver_ty, *item, self_ty, None) { continue; } if !known_implemented { @@ -582,6 +601,7 @@ fn iterate_inherent_methods( name: Option<&Name>, receiver_ty: Option<&Canonical>, krate: CrateId, + visible_from_module: Option, callback: &mut dyn FnMut(&Ty, AssocItemId) -> bool, ) -> bool { let def_crates = match self_ty.value.def_crates(db, krate) { @@ -593,7 +613,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 @@ -638,6 +658,7 @@ fn is_valid_candidate( receiver_ty: Option<&Canonical>, item: AssocItemId, self_ty: &Canonical, + visible_from_module: Option, ) -> bool { match item { AssocItemId::FunctionId(m) => { @@ -659,6 +680,12 @@ fn is_valid_candidate( return false; } } + if let Some(from_module) = visible_from_module { + if !db.fn_visibility(m).is_visible_from(db.upcast(), from_module) { + return false; + } + } + true } AssocItemId::ConstId(c) => { -- cgit v1.2.3 From 66d295d72df72640573522df527deb90abc94fcd Mon Sep 17 00:00:00 2001 From: cynecx Date: Sat, 20 Mar 2021 19:47:14 +0100 Subject: hir_ty: fix visibility in infer_inherent_method test --- crates/hir_ty/src/tests/simple.rs | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) 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() { mod b { impl super::A { - fn bar(&self, x: u64) -> i64 {} + pub fn bar(&self, x: u64) -> i64 {} } } @@ -1117,21 +1117,21 @@ fn infer_inherent_method() { 31..35 'self': A 37..38 'x': u32 52..54 '{}': () - 102..106 'self': &A - 108..109 'x': u64 - 123..125 '{}': () - 143..144 'a': A - 149..197 '{ ...(1); }': () - 155..156 'a': A - 155..163 'a.foo(1)': i32 - 161..162 '1': u32 - 169..180 '(&a).bar(1)': i64 - 170..172 '&a': &A - 171..172 'a': A - 178..179 '1': u64 - 186..187 'a': A - 186..194 'a.bar(1)': i64 - 192..193 '1': u64 + 106..110 'self': &A + 112..113 'x': u64 + 127..129 '{}': () + 147..148 'a': A + 153..201 '{ ...(1); }': () + 159..160 'a': A + 159..167 'a.foo(1)': i32 + 165..166 '1': u32 + 173..184 '(&a).bar(1)': i64 + 174..176 '&a': &A + 175..176 'a': A + 182..183 '1': u64 + 190..191 'a': A + 190..198 'a.bar(1)': i64 + 196..197 '1': u64 "#]], ); } -- cgit v1.2.3 From ac2a831b2e61a5a3ef5edd20791b4b2db48402b2 Mon Sep 17 00:00:00 2001 From: cynecx Date: Sat, 20 Mar 2021 19:48:35 +0100 Subject: hir_ty: iterate_method_candidates_for_self_ty pass `visible_from_module` down to `iterate_inherent_methods` --- crates/hir_ty/src/method_resolution.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/crates/hir_ty/src/method_resolution.rs b/crates/hir_ty/src/method_resolution.rs index 6c34982a1..80e7b7b79 100644 --- a/crates/hir_ty/src/method_resolution.rs +++ b/crates/hir_ty/src/method_resolution.rs @@ -420,6 +420,7 @@ fn iterate_method_candidates_impl( env, krate, traits_in_scope, + visible_from_module, name, callback, ) @@ -537,10 +538,12 @@ fn iterate_method_candidates_for_self_ty( env: Arc, krate: CrateId, traits_in_scope: &FxHashSet, + visible_from_module: Option, name: Option<&Name>, mut callback: &mut dyn FnMut(&Ty, AssocItemId) -> bool, ) -> bool { - if iterate_inherent_methods(self_ty, db, name, None, krate, None, &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) @@ -577,6 +580,8 @@ fn iterate_trait_method_candidates( // iteration let mut known_implemented = false; for (_name, item) in data.items.iter() { + // 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; } -- cgit v1.2.3 From 2dc85f739a678682d6b112d2d990802ffa4ffd90 Mon Sep 17 00:00:00 2001 From: cynecx Date: Sat, 20 Mar 2021 19:58:00 +0100 Subject: hir_ty: fix test by removing trailing whitespace --- crates/hir_ty/src/tests/method_resolution.rs | 47 ++++++++++++++-------------- 1 file changed, 23 insertions(+), 24 deletions(-) diff --git a/crates/hir_ty/src/tests/method_resolution.rs b/crates/hir_ty/src/tests/method_resolution.rs index 751a7ce54..6e74763ca 100644 --- a/crates/hir_ty/src/tests/method_resolution.rs +++ b/crates/hir_ty/src/tests/method_resolution.rs @@ -1236,7 +1236,6 @@ pub trait Deref { } mod a { pub struct Foo(pub char); - impl Foo { pub fn mango(&self) -> char { self.0 @@ -1266,29 +1265,29 @@ mod b { "#, expect![[r#" 67..71 'self': &Self - 173..177 'self': &Foo - 187..217 '{ ... }': char - 201..205 'self': &Foo - 201..207 'self.0': char - 293..324 '{ ... }': Bar - 307..311 'Self': Bar(i32) -> Bar - 307..314 'Self(0)': Bar - 312..313 '0': i32 - 343..347 'self': &Bar - 356..386 '{ ... }': i32 - 370..374 'self': &Bar - 370..376 'self.0': i32 - 470..474 'self': &Bar - 484..517 '{ ... }': &Foo - 498..507 '&Foo('z')': &Foo - 499..502 'Foo': Foo(char) -> Foo - 499..507 'Foo('z')': Foo - 503..506 ''z'': char - 547..600 '{ ... }': () - 561..562 'x': char - 565..583 'super:...r::new': fn new() -> Bar - 565..585 'super:...:new()': Bar - 565..593 'super:...ango()': char + 168..172 'self': &Foo + 182..212 '{ ... }': char + 196..200 'self': &Foo + 196..202 'self.0': char + 288..319 '{ ... }': Bar + 302..306 'Self': Bar(i32) -> Bar + 302..309 'Self(0)': Bar + 307..308 '0': i32 + 338..342 'self': &Bar + 351..381 '{ ... }': i32 + 365..369 'self': &Bar + 365..371 'self.0': i32 + 465..469 'self': &Bar + 479..512 '{ ... }': &Foo + 493..502 '&Foo('z')': &Foo + 494..497 'Foo': Foo(char) -> Foo + 494..502 'Foo('z')': Foo + 498..501 ''z'': char + 542..595 '{ ... }': () + 556..557 'x': char + 560..578 'super:...r::new': fn new() -> Bar + 560..580 'super:...:new()': Bar + 560..588 'super:...ango()': char "#]], ) } -- cgit v1.2.3 From 42abfa0f885834c3c2bf61a4d0fafaa3f570debd Mon Sep 17 00:00:00 2001 From: cynecx Date: Sat, 20 Mar 2021 20:35:57 +0100 Subject: hir_ty: add coverage testing for autoderef_visibility_method test --- crates/hir_ty/src/method_resolution.rs | 1 + crates/hir_ty/src/tests/method_resolution.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/crates/hir_ty/src/method_resolution.rs b/crates/hir_ty/src/method_resolution.rs index 80e7b7b79..f91208068 100644 --- a/crates/hir_ty/src/method_resolution.rs +++ b/crates/hir_ty/src/method_resolution.rs @@ -687,6 +687,7 @@ fn is_valid_candidate( } if let Some(from_module) = visible_from_module { if !db.fn_visibility(m).is_visible_from(db.upcast(), from_module) { + cov_mark::hit!(autoderef_candidate_not_visible); return false; } } diff --git a/crates/hir_ty/src/tests/method_resolution.rs b/crates/hir_ty/src/tests/method_resolution.rs index 6e74763ca..61f18b0d2 100644 --- a/crates/hir_ty/src/tests/method_resolution.rs +++ b/crates/hir_ty/src/tests/method_resolution.rs @@ -1227,6 +1227,7 @@ mod b { #[test] fn autoderef_visibility_method() { + cov_mark::check!(autoderef_candidate_not_visible); check_infer( r#" #[lang = "deref"] -- cgit v1.2.3 From 96c88680b2d680f42809f838e79213e087d1fa1c Mon Sep 17 00:00:00 2001 From: cynecx Date: Wed, 24 Mar 2021 22:59:59 +0100 Subject: hir_def: move visibility queries from hir_ty to hir_def --- crates/hir_def/src/db.rs | 7 +++++++ crates/hir_def/src/visibility.rs | 32 +++++++++++++++++++++++++++++++- crates/hir_ty/src/db.rs | 10 ++-------- crates/hir_ty/src/lower.rs | 27 ++------------------------- crates/hir_ty/src/method_resolution.rs | 2 +- 5 files changed, 43 insertions(+), 35 deletions(-) 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::{ item_tree::ItemTree, lang_item::{LangItemTarget, LangItems}, nameres::DefMap, + visibility::{self, Visibility}, AttrDefId, BlockId, BlockLoc, ConstId, ConstLoc, DefWithBodyId, EnumId, EnumLoc, FunctionId, FunctionLoc, GenericDefId, ImplId, ImplLoc, LocalEnumVariantId, LocalFieldId, StaticId, StaticLoc, StructId, StructLoc, TraitId, TraitLoc, TypeAliasId, TypeAliasLoc, UnionId, @@ -131,6 +132,12 @@ pub trait DefDatabase: InternDatabase + AstDatabase + Upcast { #[salsa::invoke(ImportMap::import_map_query)] fn import_map(&self, krate: CrateId) -> Arc; + + #[salsa::invoke(visibility::field_visibilities_query)] + fn field_visibilities(&self, var: VariantId) -> Arc>; + + #[salsa::invoke(visibility::function_visibility_query)] + fn function_visibility(&self, def: FunctionId) -> Visibility; } fn crate_def_map_wait(db: &dyn DefDatabase, krate: CrateId) -> Arc { 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 @@ //! Defines hir-level representation of visibility (e.g. `pub` and `pub(crate)`). +use std::sync::Arc; + use hir_expand::{hygiene::Hygiene, InFile}; +use la_arena::ArenaMap; use syntax::ast; use crate::{ db::DefDatabase, nameres::DefMap, path::{ModPath, PathKind}, - ModuleId, + resolver::HasResolver, + FunctionId, HasModule, LocalFieldId, ModuleDefId, ModuleId, VariantId, }; /// Visibility of an item, not yet resolved. @@ -190,3 +194,29 @@ impl Visibility { } } } + +/// Resolve visibility of all specific fields of a struct or union variant. +pub(crate) fn field_visibilities_query( + db: &dyn DefDatabase, + variant_id: VariantId, +) -> Arc> { + let var_data = match variant_id { + VariantId::StructId(it) => db.struct_data(it).variant_data.clone(), + VariantId::UnionId(it) => db.union_data(it).variant_data.clone(), + VariantId::EnumVariantId(it) => { + db.enum_data(it.parent).variants[it.local_id].variant_data.clone() + } + }; + let resolver = variant_id.module(db).resolver(db); + let mut res = ArenaMap::default(); + for (field_id, field_data) in var_data.fields().iter() { + res.insert(field_id, field_data.visibility.resolve(db, &resolver)) + } + Arc::new(res) +} + +/// Resolve visibility of a function. +pub(crate) fn function_visibility_query(db: &dyn DefDatabase, def: FunctionId) -> Visibility { + let resolver = ModuleDefId::from(def).module(db).unwrap().resolver(db); + db.function_data(def).visibility.resolve(db, &resolver) +} diff --git a/crates/hir_ty/src/db.rs b/crates/hir_ty/src/db.rs index b1d22a9f9..91a2e0b5b 100644 --- a/crates/hir_ty/src/db.rs +++ b/crates/hir_ty/src/db.rs @@ -4,8 +4,8 @@ use std::sync::Arc; use base_db::{impl_intern_key, salsa, CrateId, Upcast}; use hir_def::{ - db::DefDatabase, expr::ExprId, visibility::Visibility, ConstParamId, DefWithBodyId, FunctionId, - GenericDefId, ImplId, LocalFieldId, TypeParamId, VariantId, + db::DefDatabase, expr::ExprId, ConstParamId, DefWithBodyId, FunctionId, GenericDefId, ImplId, + LocalFieldId, TypeParamId, VariantId, }; use la_arena::ArenaMap; @@ -128,12 +128,6 @@ pub trait HirDatabase: DefDatabase + Upcast { krate: CrateId, env: chalk_ir::Environment, ) -> chalk_ir::ProgramClauses; - - #[salsa::invoke(crate::lower::field_visibilities_query)] - fn field_visibilities(&self, var: VariantId) -> Arc>; - - #[salsa::invoke(crate::lower::fn_visibility_query)] - fn fn_visibility(&self, def: FunctionId) -> Visibility; } fn infer_wait(db: &dyn HirDatabase, def: DefWithBodyId) -> Arc { diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs index c4062a41d..cbbb535e5 100644 --- a/crates/hir_ty/src/lower.rs +++ b/crates/hir_ty/src/lower.rs @@ -16,10 +16,9 @@ use hir_def::{ path::{GenericArg, Path, PathSegment, PathSegments}, resolver::{HasResolver, Resolver, TypeNs}, type_ref::{TypeBound, TypeRef}, - visibility::Visibility, AdtId, AssocContainerId, AssocItemId, ConstId, ConstParamId, EnumId, EnumVariantId, FunctionId, - GenericDefId, HasModule, ImplId, LocalFieldId, Lookup, ModuleDefId, StaticId, StructId, - TraitId, TypeAliasId, TypeParamId, UnionId, VariantId, + GenericDefId, HasModule, ImplId, LocalFieldId, Lookup, StaticId, StructId, TraitId, + TypeAliasId, TypeParamId, UnionId, VariantId, }; use hir_expand::name::Name; use la_arena::ArenaMap; @@ -868,28 +867,6 @@ pub(crate) fn field_types_query( Arc::new(res) } -/// Resolve visibility of all specific fields of a struct or union variant. -pub(crate) fn field_visibilities_query( - db: &dyn HirDatabase, - variant_id: VariantId, -) -> Arc> { - let def_db = db.upcast(); - let var_data = variant_data(def_db, variant_id); - let resolver = variant_id.module(def_db).resolver(def_db); - let mut res = ArenaMap::default(); - for (field_id, field_data) in var_data.fields().iter() { - res.insert(field_id, field_data.visibility.resolve(def_db, &resolver)) - } - Arc::new(res) -} - -/// Resolve visibility of a function. -pub(crate) fn fn_visibility_query(db: &dyn HirDatabase, def: FunctionId) -> Visibility { - let def_db = db.upcast(); - let resolver = ModuleDefId::from(def).module(def_db).unwrap().resolver(def_db); - db.function_data(def).visibility.resolve(def_db, &resolver) -} - /// This query exists only to be used when resolving short-hand associated types /// like `T::Item`. /// diff --git a/crates/hir_ty/src/method_resolution.rs b/crates/hir_ty/src/method_resolution.rs index f91208068..54192ec30 100644 --- a/crates/hir_ty/src/method_resolution.rs +++ b/crates/hir_ty/src/method_resolution.rs @@ -686,7 +686,7 @@ fn is_valid_candidate( } } if let Some(from_module) = visible_from_module { - if !db.fn_visibility(m).is_visible_from(db.upcast(), from_module) { + if !db.function_visibility(m).is_visible_from(db.upcast(), from_module) { cov_mark::hit!(autoderef_candidate_not_visible); return false; } -- cgit v1.2.3 From 7155f815b96fbc1de5816e3954c4c03c43e709c9 Mon Sep 17 00:00:00 2001 From: cynecx Date: Wed, 24 Mar 2021 23:03:30 +0100 Subject: hir_ty: don't call write_field_resolution when field candidate isn't visible --- crates/hir_ty/src/infer/expr.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs index b08880cdf..46d713a7b 100644 --- a/crates/hir_ty/src/infer/expr.rs +++ b/crates/hir_ty/src/infer/expr.rs @@ -459,9 +459,8 @@ impl<'a> InferenceContext<'a> { TyKind::Adt(AdtId(hir_def::AdtId::StructId(s)), parameters) => { let local_id = self.db.struct_data(*s).variant_data.field(name)?; let field = FieldId { parent: (*s).into(), local_id }; - let is_visible_in_ctx = is_visible(&field); - self.write_field_resolution(tgt_expr, field); - if is_visible_in_ctx { + if is_visible(&field) { + self.write_field_resolution(tgt_expr, field); Some( self.db.field_types((*s).into())[field.local_id] .clone() @@ -474,9 +473,8 @@ impl<'a> InferenceContext<'a> { TyKind::Adt(AdtId(hir_def::AdtId::UnionId(u)), parameters) => { let local_id = self.db.union_data(*u).variant_data.field(name)?; let field = FieldId { parent: (*u).into(), local_id }; - let is_visible_in_ctx = is_visible(&field); - self.write_field_resolution(tgt_expr, field); - if is_visible_in_ctx { + if is_visible(&field) { + self.write_field_resolution(tgt_expr, field); Some( self.db.field_types((*u).into())[field.local_id] .clone() -- cgit v1.2.3 From d1156bb52e900c015afd490f509d744c7a5adf10 Mon Sep 17 00:00:00 2001 From: cynecx Date: Wed, 24 Mar 2021 23:09:22 +0100 Subject: hir: don't use the self module as visible_from in iterate_method_candidates --- crates/hir/src/lib.rs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 1a65a5cad..746b4c942 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -1967,18 +1967,13 @@ impl Type { let env = self.ty.environment.clone(); let krate = krate.id; - let from_module = match self.as_adt() { - Some(adt) => Some(adt.module(db).id), - None => None, - }; - method_resolution::iterate_method_candidates( &canonical, db, env, krate, traits_in_scope, - from_module, + None, name, method_resolution::LookupMode::MethodCall, |ty, it| match it { -- cgit v1.2.3