Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir/src/source_analyzer.rs')
| -rw-r--r-- | crates/hir/src/source_analyzer.rs | 156 |
1 files changed, 102 insertions, 54 deletions
diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs index fb27f9dec4..e80567641b 100644 --- a/crates/hir/src/source_analyzer.rs +++ b/crates/hir/src/source_analyzer.rs @@ -24,8 +24,9 @@ use hir_def::{ hir::{BindingId, Expr, ExprId, ExprOrPatId, Pat, PatId, generics::GenericParams}, lang_item::LangItems, nameres::MacroSubNs, - resolver::{Resolver, TypeNs, ValueNs, resolver_for_scope}, + resolver::{ResolveValueResult, Resolver, TypeNs, ValueNs, resolver_for_scope}, type_ref::{Mutability, TypeRefId}, + visibility::Visibility, }; use hir_expand::{ HirFileId, InFile, @@ -1060,7 +1061,7 @@ impl<'db> SourceAnalyzer<'db> { }; let store_owner = self.resolver.expression_store_owner(); - let res = resolve_hir_value_path( + let (res, _) = resolve_hir_value_path( db, &self.resolver, store_owner, @@ -1643,7 +1644,8 @@ impl<'db> SourceAnalyzer<'db> { Some(name.clone()), )), hygiene, - ), + ) + .map(|(it, _)| it), ) }) } @@ -1683,7 +1685,8 @@ impl<'db> SourceAnalyzer<'db> { Some(name.clone()), )), hygiene, - ), + ) + .map(|(it, _)| it), ) })) } @@ -1865,7 +1868,7 @@ pub(crate) fn resolve_hir_path_as_attr_macro( ) -> Option<Macro> { resolver .resolve_path_as_macro(db, path.mod_path()?, Some(MacroSubNs::Attr)) - .map(|(it, _)| it) + .map(|it| it.def) .map(Into::into) } @@ -1880,7 +1883,7 @@ fn resolve_hir_path_<'db>( resolve_per_ns: bool, ) -> PathResolutionPerNs<'db> { let types = || { - let (ty, unresolved) = match path.type_anchor() { + let (ty, unresolved, ty_is_visible) = match path.type_anchor() { Some(type_ref) => resolver.generic_def().and_then(|def| { let generics = OnceCell::new(); let (_, res) = TyLoweringContext::new( @@ -1894,19 +1897,20 @@ fn resolve_hir_path_<'db>( LifetimeLoweringMode::LateParam, ) .lower_ty_ext(type_ref); - res.map(|ty_ns| (ty_ns, path.segments().first())) + res.map(|ty_ns| (ty_ns, path.segments().first(), Visibility::Public)) }), None => { - let (ty, remaining_idx, _) = resolver.resolve_path_in_type_ns(db, path)?; + let (ty, remaining_idx, _, _, vis) = + resolver.resolve_path_in_type_ns_with_prefix_info(db, path)?; match remaining_idx { Some(remaining_idx) => { if remaining_idx + 1 == path.segments().len() { - Some((ty, path.segments().last())) + Some((ty, path.segments().last(), vis)) } else { None } } - None => Some((ty, None)), + None => Some((ty, None, vis)), } } }?; @@ -1917,7 +1921,10 @@ fn resolve_hir_path_<'db>( && let Some(type_alias_id) = trait_id.trait_items(db).associated_type_by_name(unresolved.name) { - return Some(PathResolution::Def(ModuleDefId::from(type_alias_id).into())); + return Some(( + PathResolution::Def(ModuleDefId::from(type_alias_id).into()), + ty_is_visible, + )); } let res = match ty { @@ -1945,8 +1952,8 @@ fn resolve_hir_path_<'db>( }) .map(TypeAlias::from) .map(Into::into) - .map(PathResolution::Def), - None => Some(res), + .map(|def| (PathResolution::Def(def), ty_is_visible)), + None => Some((res, ty_is_visible)), } }; @@ -1956,41 +1963,79 @@ fn resolve_hir_path_<'db>( let items = || { resolver .resolve_module_path_in_items(db, path.mod_path()?) - .take_types() - .map(|it| PathResolution::Def(it.into())) + .take_types_full() + .map(|it| (PathResolution::Def(it.def.into()), it.vis)) }; let macros = || { resolver .resolve_path_as_macro(db, path.mod_path()?, None) - .map(|(def, _)| PathResolution::Def(ModuleDef::Macro(def.into()))) + .map(|res| (PathResolution::Def(ModuleDef::Macro(res.def.into())), res.vis)) }; - if resolve_per_ns { - PathResolutionPerNs { - type_ns: types().or_else(items), - value_ns: values(), - macro_ns: macros(), - } - } else { - let res = if prefer_value_ns { - values() - .map(|value_ns| PathResolutionPerNs::new(None, Some(value_ns), None)) - .unwrap_or_else(|| PathResolutionPerNs::new(types(), None, None)) - } else { - types() - .map(|type_ns| PathResolutionPerNs::new(Some(type_ns), None, None)) - .unwrap_or_else(|| PathResolutionPerNs::new(None, values(), None)) - }; + let mut types_ns: Option<Option<_>> = None; + let mut values_ns: Option<Option<_>> = None; + + let mut types_is_visible: Option<bool> = None; + let mut values_is_visible: Option<bool> = None; - if res.any().is_some() { - res - } else if let Some(type_ns) = items() { - PathResolutionPerNs::new(Some(type_ns), None, None) + if !resolve_per_ns { + if prefer_value_ns { + values_ns = Some(values().inspect(|(_, vis)| { + values_is_visible = Some(resolver.is_visible(db, *vis)); + })); + + if let Some(Some((res, _))) = values_ns + && values_is_visible.unwrap_or_default() + { + return PathResolutionPerNs::new(None, Some(res), None); + } } else { - PathResolutionPerNs::new(None, None, macros()) + types_ns = Some(types().or_else(items).inspect(|(_, vis)| { + types_is_visible = Some(resolver.is_visible(db, *vis)); + })); + + if let Some(Some((res, _))) = types_ns + && types_is_visible.unwrap_or_default() + { + return PathResolutionPerNs::new(Some(res), None, None); + } + } + } + + let mut macros_is_visible = false; + + let mut types = types_ns.unwrap_or_else(|| types().or_else(items)).map(|(res, vis)| { + types_is_visible = Some(types_is_visible.unwrap_or_else(|| resolver.is_visible(db, vis))); + res + }); + let mut values = values_ns.unwrap_or_else(values).map(|(res, vis)| { + values_is_visible = Some(values_is_visible.unwrap_or_else(|| resolver.is_visible(db, vis))); + res + }); + let mut macros = macros().map(|(res, vis)| { + macros_is_visible = resolver.is_visible(db, vis); + res + }); + + let types_is_visible = types_is_visible.unwrap_or_default(); + let values_is_visible = values_is_visible.unwrap_or_default(); + + // If there is a visible resolution and an invisible one, we only want to include the visible one. But if all are + // invisible, we want to include them all. + if types_is_visible || values_is_visible || macros_is_visible { + if !types_is_visible { + types = None; + } + if !values_is_visible { + values = None; + } + if !macros_is_visible { + macros = None; } } + + PathResolutionPerNs { type_ns: types, value_ns: values, macro_ns: macros } } fn resolve_hir_value_path<'db>( @@ -2000,23 +2045,26 @@ fn resolve_hir_value_path<'db>( infer_body: Option<InferBodyId<'db>>, path: &Path, hygiene: HygieneId, -) -> Option<PathResolution<'db>> { - resolver.resolve_path_in_value_ns_fully(db, path, hygiene).and_then(|val| { - let res = match val { - ValueNs::LocalBinding(binding_id) => { - let var = Local { parent: store_owner?, parent_infer: infer_body?, binding_id }; - PathResolution::Local(var) - } - ValueNs::FunctionId(it) => PathResolution::Def(Function::from(it).into()), - ValueNs::ConstId(it) => PathResolution::Def(Const::from(it).into()), - ValueNs::StaticId(it) => PathResolution::Def(Static::from(it).into()), - ValueNs::StructId(it) => PathResolution::Def(Struct::from(it).into()), - ValueNs::EnumVariantId(it) => PathResolution::Def(EnumVariant::from(it).into()), - ValueNs::ImplSelf(impl_id) => PathResolution::SelfType(impl_id.into()), - ValueNs::GenericParam(id) => PathResolution::ConstParam(id.into()), - }; - Some(res) - }) +) -> Option<(PathResolution<'db>, Visibility)> { + resolver.resolve_path_in_value_ns_with_prefix_info(db, path, hygiene).and_then( + |(val, _, vis)| { + let ResolveValueResult::ValueNs(val) = val else { return None }; + let res = match val { + ValueNs::LocalBinding(binding_id) => { + let var = Local { parent: store_owner?, parent_infer: infer_body?, binding_id }; + PathResolution::Local(var) + } + ValueNs::FunctionId(it) => PathResolution::Def(Function::from(it).into()), + ValueNs::ConstId(it) => PathResolution::Def(Const::from(it).into()), + ValueNs::StaticId(it) => PathResolution::Def(Static::from(it).into()), + ValueNs::StructId(it) => PathResolution::Def(Struct::from(it).into()), + ValueNs::EnumVariantId(it) => PathResolution::Def(EnumVariant::from(it).into()), + ValueNs::ImplSelf(impl_id) => PathResolution::SelfType(impl_id.into()), + ValueNs::GenericParam(id) => PathResolution::ConstParam(id.into()), + }; + Some((res, vis)) + }, + ) } /// Resolves a path where we know it is a qualifier of another path. |