mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-29 14:33:29 +00:00
start cleaning up the resolution
Nameres related types, like `PerNs<Resolution>`, 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.
This commit is contained in:
parent
5c09c5949a
commit
63e1e63a91
5 changed files with 59 additions and 49 deletions
|
@ -11,7 +11,7 @@ use crate::{
|
||||||
name,
|
name,
|
||||||
path::{PathKind, PathSegment},
|
path::{PathKind, PathSegment},
|
||||||
ty::{ApplicationTy, InferenceResult, Ty, TypeCtor},
|
ty::{ApplicationTy, InferenceResult, Ty, TypeCtor},
|
||||||
Function, ModuleDef, Name, Path, PerNs, Resolution,
|
Function, Name, Path,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{Expr, ExprId, RecordLitField};
|
use super::{Expr, ExprId, RecordLitField};
|
||||||
|
@ -119,9 +119,8 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
|
||||||
};
|
};
|
||||||
|
|
||||||
let resolver = self.func.resolver(db);
|
let resolver = self.func.resolver(db);
|
||||||
let std_result_enum =
|
let std_result_enum = match resolver.resolve_known_enum(db, &std_result_path) {
|
||||||
match resolver.resolve_path_segments(db, &std_result_path).into_fully_resolved() {
|
Some(it) => it,
|
||||||
PerNs { types: Some(Resolution::Def(ModuleDef::Enum(e))), .. } => e,
|
|
||||||
_ => return,
|
_ => return,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@ use crate::{
|
||||||
name::{Name, SELF_PARAM, SELF_TYPE},
|
name::{Name, SELF_PARAM, SELF_TYPE},
|
||||||
nameres::{CrateDefMap, CrateModuleId, PerNs},
|
nameres::{CrateDefMap, CrateModuleId, PerNs},
|
||||||
path::Path,
|
path::Path,
|
||||||
MacroDef, ModuleDef, Trait,
|
Enum, MacroDef, ModuleDef, Struct, Trait,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default)]
|
#[derive(Debug, Clone, Default)]
|
||||||
|
@ -39,6 +39,8 @@ pub(crate) struct ExprScope {
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub(crate) struct PathResult {
|
pub(crate) struct PathResult {
|
||||||
/// The actual path resolution
|
/// The actual path resolution
|
||||||
|
// FIXME: `PerNs<Resolution>` type doesn't make sense, as not every
|
||||||
|
// Resolution variant can appear in every namespace
|
||||||
resolution: PerNs<Resolution>,
|
resolution: PerNs<Resolution>,
|
||||||
/// The first index in the path that we
|
/// The first index in the path that we
|
||||||
/// were unable to resolve.
|
/// were unable to resolve.
|
||||||
|
@ -113,6 +115,9 @@ pub(crate) enum Scope {
|
||||||
pub enum Resolution {
|
pub enum Resolution {
|
||||||
/// An item
|
/// An item
|
||||||
Def(ModuleDef),
|
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)
|
/// A local binding (only value namespace)
|
||||||
LocalBinding(PatId),
|
LocalBinding(PatId),
|
||||||
/// A generic parameter
|
/// A generic parameter
|
||||||
|
@ -121,6 +126,37 @@ pub enum Resolution {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Resolver {
|
impl Resolver {
|
||||||
|
/// Resolve known trait from std, like `std::futures::Future`
|
||||||
|
pub(crate) fn resolve_known_trait(&self, db: &impl HirDatabase, path: &Path) -> Option<Trait> {
|
||||||
|
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<Struct> {
|
||||||
|
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<Enum> {
|
||||||
|
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<Resolution> {
|
pub(crate) fn resolve_name(&self, db: &impl HirDatabase, name: &Name) -> PerNs<Resolution> {
|
||||||
let mut resolution = PerNs::none();
|
let mut resolution = PerNs::none();
|
||||||
for scope in self.scopes.iter().rev() {
|
for scope in self.scopes.iter().rev() {
|
||||||
|
|
|
@ -29,7 +29,7 @@ use crate::{
|
||||||
path::{PathKind, PathSegment},
|
path::{PathKind, PathSegment},
|
||||||
ty::method_resolution::implements_trait,
|
ty::method_resolution::implements_trait,
|
||||||
AsName, AstId, Const, Crate, DefWithBody, Either, Enum, Function, HasBody, HirFileId, MacroDef,
|
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.
|
/// Locates the module by `FileId`. Picks topmost module in the file.
|
||||||
|
@ -426,9 +426,8 @@ impl SourceAnalyzer {
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
let std_future_trait =
|
let std_future_trait = match self.resolver.resolve_known_trait(db, &std_future_path) {
|
||||||
match self.resolver.resolve_path_segments(db, &std_future_path).into_fully_resolved() {
|
Some(it) => it,
|
||||||
PerNs { types: Some(Resolution::Def(ModuleDef::Trait(trait_))), .. } => trait_,
|
|
||||||
_ => return false,
|
_ => return false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,7 @@ use super::{
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
adt::VariantDef,
|
adt::VariantDef,
|
||||||
code_model::{ModuleDef::Trait, TypeAlias},
|
code_model::TypeAlias,
|
||||||
db::HirDatabase,
|
db::HirDatabase,
|
||||||
diagnostics::DiagnosticSink,
|
diagnostics::DiagnosticSink,
|
||||||
expr::{
|
expr::{
|
||||||
|
@ -43,12 +43,9 @@ use crate::{
|
||||||
},
|
},
|
||||||
generics::{GenericParams, HasGenericParams},
|
generics::{GenericParams, HasGenericParams},
|
||||||
name,
|
name,
|
||||||
nameres::{Namespace, PerNs},
|
nameres::Namespace,
|
||||||
path::{GenericArg, GenericArgs, PathKind, PathSegment},
|
path::{GenericArg, GenericArgs, PathKind, PathSegment},
|
||||||
resolve::{
|
resolve::{Resolution, Resolver},
|
||||||
Resolution::{self, Def},
|
|
||||||
Resolver,
|
|
||||||
},
|
|
||||||
ty::infer::diagnostics::InferenceDiagnostic,
|
ty::infer::diagnostics::InferenceDiagnostic,
|
||||||
type_ref::{Mutability, TypeRef},
|
type_ref::{Mutability, TypeRef},
|
||||||
AdtDef, ConstData, DefWithBody, FnData, Function, HasBody, ImplItem, ModuleDef, Name, Path,
|
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() {
|
let trait_ = self.resolver.resolve_known_trait(self.db, &into_iter_path)?;
|
||||||
PerNs { types: Some(Def(Trait(trait_))), .. } => {
|
trait_.associated_type_by_name(self.db, &name::ITEM)
|
||||||
Some(trait_.associated_type_by_name(self.db, &name::ITEM)?)
|
|
||||||
}
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_ops_try_ok(&self) -> Option<TypeAlias> {
|
fn resolve_ops_try_ok(&self) -> Option<TypeAlias> {
|
||||||
|
@ -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() {
|
let trait_ = self.resolver.resolve_known_trait(self.db, &ops_try_path)?;
|
||||||
PerNs { types: Some(Def(Trait(trait_))), .. } => {
|
trait_.associated_type_by_name(self.db, &name::OK)
|
||||||
Some(trait_.associated_type_by_name(self.db, &name::OK)?)
|
|
||||||
}
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_future_future_output(&self) -> Option<TypeAlias> {
|
fn resolve_future_future_output(&self) -> Option<TypeAlias> {
|
||||||
|
@ -1496,16 +1485,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
match self
|
let trait_ = self.resolver.resolve_known_trait(self.db, &future_future_path)?;
|
||||||
.resolver
|
trait_.associated_type_by_name(self.db, &name::OUTPUT)
|
||||||
.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,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_boxed_box(&self) -> Option<AdtDef> {
|
fn resolve_boxed_box(&self) -> Option<AdtDef> {
|
||||||
|
@ -1517,14 +1498,9 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
||||||
PathSegment { name: name::BOX_TYPE, args_and_bindings: None },
|
PathSegment { name: name::BOX_TYPE, args_and_bindings: None },
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
let struct_ = self.resolver.resolve_known_struct(self.db, &boxed_box_path)?;
|
||||||
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_))
|
Some(AdtDef::Struct(struct_))
|
||||||
}
|
}
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The ID of a type variable.
|
/// The ID of a type variable.
|
||||||
|
|
|
@ -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)
|
// Resolve the path (in type namespace)
|
||||||
let (resolution, remaining_index) = resolver.resolve_path_segments(db, path).into_inner();
|
let (resolution, remaining_index) = resolver.resolve_path_segments(db, path).into_inner();
|
||||||
let resolution = resolution.take_types();
|
let resolution = resolution.take_types();
|
||||||
|
|
Loading…
Reference in a new issue