From 63e1e63a9160d28597a8d77fd83c43a2c90d3f6b Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 12 Sep 2019 20:39:10 +0300 Subject: start cleaning up the resolution Nameres related types, like `PerNs`, can represent unreasonable situations, like a local in a type namespace. We should clean this up, by requiring that call-site specifies the kind of resolution it expects. --- crates/ra_hir/src/expr/validation.rs | 11 ++++----- crates/ra_hir/src/resolve.rs | 38 ++++++++++++++++++++++++++++- crates/ra_hir/src/source_binder.rs | 11 ++++----- crates/ra_hir/src/ty/infer.rs | 46 +++++++++--------------------------- crates/ra_hir/src/ty/lower.rs | 2 +- 5 files changed, 59 insertions(+), 49 deletions(-) (limited to 'crates/ra_hir/src') diff --git a/crates/ra_hir/src/expr/validation.rs b/crates/ra_hir/src/expr/validation.rs index 6a22e1318..c985dbdad 100644 --- a/crates/ra_hir/src/expr/validation.rs +++ b/crates/ra_hir/src/expr/validation.rs @@ -11,7 +11,7 @@ use crate::{ name, path::{PathKind, PathSegment}, ty::{ApplicationTy, InferenceResult, Ty, TypeCtor}, - Function, ModuleDef, Name, Path, PerNs, Resolution, + Function, Name, Path, }; use super::{Expr, ExprId, RecordLitField}; @@ -119,11 +119,10 @@ impl<'a, 'b> ExprValidator<'a, 'b> { }; let resolver = self.func.resolver(db); - let std_result_enum = - match resolver.resolve_path_segments(db, &std_result_path).into_fully_resolved() { - PerNs { types: Some(Resolution::Def(ModuleDef::Enum(e))), .. } => e, - _ => return, - }; + let std_result_enum = match resolver.resolve_known_enum(db, &std_result_path) { + Some(it) => it, + _ => return, + }; let std_result_ctor = TypeCtor::Adt(AdtDef::Enum(std_result_enum)); let params = match &mismatch.expected { diff --git a/crates/ra_hir/src/resolve.rs b/crates/ra_hir/src/resolve.rs index d9bdd0e22..1ed150f5a 100644 --- a/crates/ra_hir/src/resolve.rs +++ b/crates/ra_hir/src/resolve.rs @@ -15,7 +15,7 @@ use crate::{ name::{Name, SELF_PARAM, SELF_TYPE}, nameres::{CrateDefMap, CrateModuleId, PerNs}, path::Path, - MacroDef, ModuleDef, Trait, + Enum, MacroDef, ModuleDef, Struct, Trait, }; #[derive(Debug, Clone, Default)] @@ -39,6 +39,8 @@ pub(crate) struct ExprScope { #[derive(Debug, Clone)] pub(crate) struct PathResult { /// The actual path resolution + // FIXME: `PerNs` type doesn't make sense, as not every + // Resolution variant can appear in every namespace resolution: PerNs, /// The first index in the path that we /// were unable to resolve. @@ -113,6 +115,9 @@ pub(crate) enum Scope { pub enum Resolution { /// An item Def(ModuleDef), + + // FIXME: there's no way we can syntactically confuse a local with generic + // param, so these two should not be members of the single enum /// A local binding (only value namespace) LocalBinding(PatId), /// A generic parameter @@ -121,6 +126,37 @@ pub enum Resolution { } impl Resolver { + /// Resolve known trait from std, like `std::futures::Future` + pub(crate) fn resolve_known_trait(&self, db: &impl HirDatabase, path: &Path) -> Option { + let res = self.resolve_path_segments(db, path).into_fully_resolved().take_types()?; + match res { + Resolution::Def(ModuleDef::Trait(it)) => Some(it), + _ => None, + } + } + + /// Resolve known struct from std, like `std::boxed::Box` + pub(crate) fn resolve_known_struct( + &self, + db: &impl HirDatabase, + path: &Path, + ) -> Option { + let res = self.resolve_path_segments(db, path).into_fully_resolved().take_types()?; + match res { + Resolution::Def(ModuleDef::Struct(it)) => Some(it), + _ => None, + } + } + + /// Resolve known enum from std, like `std::result::Result` + pub(crate) fn resolve_known_enum(&self, db: &impl HirDatabase, path: &Path) -> Option { + let res = self.resolve_path_segments(db, path).into_fully_resolved().take_types()?; + match res { + Resolution::Def(ModuleDef::Enum(it)) => Some(it), + _ => None, + } + } + pub(crate) fn resolve_name(&self, db: &impl HirDatabase, name: &Name) -> PerNs { let mut resolution = PerNs::none(); for scope in self.scopes.iter().rev() { diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index afdcd5415..65b304b43 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs @@ -29,7 +29,7 @@ use crate::{ path::{PathKind, PathSegment}, ty::method_resolution::implements_trait, AsName, AstId, Const, Crate, DefWithBody, Either, Enum, Function, HasBody, HirFileId, MacroDef, - Module, ModuleDef, Name, Path, PerNs, Resolution, Resolver, Static, Struct, Trait, Ty, + Module, Name, Path, PerNs, Resolver, Static, Struct, Trait, Ty, }; /// Locates the module by `FileId`. Picks topmost module in the file. @@ -426,11 +426,10 @@ impl SourceAnalyzer { ], }; - let std_future_trait = - match self.resolver.resolve_path_segments(db, &std_future_path).into_fully_resolved() { - PerNs { types: Some(Resolution::Def(ModuleDef::Trait(trait_))), .. } => trait_, - _ => return false, - }; + let std_future_trait = match self.resolver.resolve_known_trait(db, &std_future_path) { + Some(it) => it, + _ => return false, + }; let krate = match self.resolver.krate() { Some(krate) => krate, diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs index 1057bbbec..3970c49e3 100644 --- a/crates/ra_hir/src/ty/infer.rs +++ b/crates/ra_hir/src/ty/infer.rs @@ -34,7 +34,7 @@ use super::{ }; use crate::{ adt::VariantDef, - code_model::{ModuleDef::Trait, TypeAlias}, + code_model::TypeAlias, db::HirDatabase, diagnostics::DiagnosticSink, expr::{ @@ -43,12 +43,9 @@ use crate::{ }, generics::{GenericParams, HasGenericParams}, name, - nameres::{Namespace, PerNs}, + nameres::Namespace, path::{GenericArg, GenericArgs, PathKind, PathSegment}, - resolve::{ - Resolution::{self, Def}, - Resolver, - }, + resolve::{Resolution, Resolver}, ty::infer::diagnostics::InferenceDiagnostic, type_ref::{Mutability, TypeRef}, AdtDef, ConstData, DefWithBody, FnData, Function, HasBody, ImplItem, ModuleDef, Name, Path, @@ -1460,12 +1457,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { ], }; - match self.resolver.resolve_path_segments(self.db, &into_iter_path).into_fully_resolved() { - PerNs { types: Some(Def(Trait(trait_))), .. } => { - Some(trait_.associated_type_by_name(self.db, &name::ITEM)?) - } - _ => None, - } + let trait_ = self.resolver.resolve_known_trait(self.db, &into_iter_path)?; + trait_.associated_type_by_name(self.db, &name::ITEM) } fn resolve_ops_try_ok(&self) -> Option { @@ -1478,12 +1471,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { ], }; - match self.resolver.resolve_path_segments(self.db, &ops_try_path).into_fully_resolved() { - PerNs { types: Some(Def(Trait(trait_))), .. } => { - Some(trait_.associated_type_by_name(self.db, &name::OK)?) - } - _ => None, - } + let trait_ = self.resolver.resolve_known_trait(self.db, &ops_try_path)?; + trait_.associated_type_by_name(self.db, &name::OK) } fn resolve_future_future_output(&self) -> Option { @@ -1496,16 +1485,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { ], }; - match self - .resolver - .resolve_path_segments(self.db, &future_future_path) - .into_fully_resolved() - { - PerNs { types: Some(Def(Trait(trait_))), .. } => { - Some(trait_.associated_type_by_name(self.db, &name::OUTPUT)?) - } - _ => None, - } + let trait_ = self.resolver.resolve_known_trait(self.db, &future_future_path)?; + trait_.associated_type_by_name(self.db, &name::OUTPUT) } fn resolve_boxed_box(&self) -> Option { @@ -1517,13 +1498,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { PathSegment { name: name::BOX_TYPE, args_and_bindings: None }, ], }; - - match self.resolver.resolve_path_segments(self.db, &boxed_box_path).into_fully_resolved() { - PerNs { types: Some(Def(ModuleDef::Struct(struct_))), .. } => { - Some(AdtDef::Struct(struct_)) - } - _ => None, - } + let struct_ = self.resolver.resolve_known_struct(self.db, &boxed_box_path)?; + Some(AdtDef::Struct(struct_)) } } diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs index 061229842..e67525a74 100644 --- a/crates/ra_hir/src/ty/lower.rs +++ b/crates/ra_hir/src/ty/lower.rs @@ -86,7 +86,7 @@ impl Ty { } } - pub(crate) fn from_hir_path(db: &impl HirDatabase, resolver: &Resolver, path: &Path) -> Self { + pub(crate) fn from_hir_path(db: &impl HirDatabase, resolver: &Resolver, path: &Path) -> Ty { // Resolve the path (in type namespace) let (resolution, remaining_index) = resolver.resolve_path_segments(db, path).into_inner(); let resolution = resolution.take_types(); -- cgit v1.2.3