Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir/src/lib.rs')
-rw-r--r--crates/hir/src/lib.rs238
1 files changed, 116 insertions, 122 deletions
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 85f33a10fc..777be711a5 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -35,7 +35,7 @@ pub mod term_search;
mod display;
-use std::{iter, mem::discriminant, ops::ControlFlow};
+use std::{mem::discriminant, ops::ControlFlow};
use arrayvec::ArrayVec;
use base_db::{CrateDisplayName, CrateId, CrateOrigin, FileId};
@@ -52,7 +52,6 @@ use hir_def::{
path::ImportAlias,
per_ns::PerNs,
resolver::{HasResolver, Resolver},
- src::HasSource as _,
AssocItemId, AssocItemLoc, AttrDefId, ConstId, ConstParamId, CrateRootModuleId, DefWithBodyId,
EnumId, EnumVariantId, ExternCrateId, FunctionId, GenericDefId, GenericParamId, HasModule,
ImplId, InTypeConstId, ItemContainerId, LifetimeParamId, LocalFieldId, Lookup, MacroExpander,
@@ -69,7 +68,7 @@ use hir_ty::{
diagnostics::BodyValidationDiagnostic,
error_lifetime, known_const_to_ast,
layout::{Layout as TyLayout, RustcEnumVariantIdx, RustcFieldIdx, TagEncoding},
- method_resolution::{self, TyFingerprint},
+ method_resolution::{self},
mir::{interpret_mir, MutBorrowKind},
primitive::UintTy,
traits::FnTrait,
@@ -100,6 +99,7 @@ pub use crate::{
VisibleTraits,
},
};
+pub use hir_ty::method_resolution::TyFingerprint;
// Be careful with these re-exports.
//
@@ -123,6 +123,7 @@ pub use {
per_ns::Namespace,
type_ref::{Mutability, TypeRef},
visibility::Visibility,
+ ImportPathConfig,
// FIXME: This is here since some queries take it as input that are used
// outside of hir.
{AdtId, MacroId, ModuleDefId},
@@ -141,7 +142,7 @@ pub use {
display::{ClosureStyle, HirDisplay, HirDisplayError, HirWrite},
layout::LayoutError,
mir::{MirEvalError, MirLowerError},
- PointerCast, Safety,
+ FnAbi, PointerCast, Safety,
},
// FIXME: Properly encapsulate mir
hir_ty::{mir, Interner as ChalkTyInterner},
@@ -789,40 +790,32 @@ impl Module {
/// Finds a path that can be used to refer to the given item from within
/// this module, if possible.
- pub fn find_use_path(
+ pub fn find_path(
self,
db: &dyn DefDatabase,
item: impl Into<ItemInNs>,
- prefer_no_std: bool,
- prefer_prelude: bool,
+ cfg: ImportPathConfig,
) -> Option<ModPath> {
hir_def::find_path::find_path(
db,
item.into().into(),
self.into(),
- prefer_no_std,
- prefer_prelude,
+ PrefixKind::Plain,
+ false,
+ cfg,
)
}
/// Finds a path that can be used to refer to the given item from within
/// this module, if possible. This is used for returning import paths for use-statements.
- pub fn find_use_path_prefixed(
+ pub fn find_use_path(
self,
db: &dyn DefDatabase,
item: impl Into<ItemInNs>,
prefix_kind: PrefixKind,
- prefer_no_std: bool,
- prefer_prelude: bool,
+ cfg: ImportPathConfig,
) -> Option<ModPath> {
- hir_def::find_path::find_path_prefixed(
- db,
- item.into().into(),
- self.into(),
- prefix_kind,
- prefer_no_std,
- prefer_prelude,
- )
+ hir_def::find_path::find_path(db, item.into().into(), self.into(), prefix_kind, true, cfg)
}
}
@@ -1965,7 +1958,7 @@ impl Function {
.enumerate()
.map(|(idx, ty)| {
let ty = Type { env: environment.clone(), ty: ty.clone() };
- Param { func: self, ty, idx }
+ Param { func: Callee::Def(CallableDefId::FunctionId(self.id)), ty, idx }
})
.collect()
}
@@ -1991,7 +1984,7 @@ impl Function {
.skip(skip)
.map(|(idx, ty)| {
let ty = Type { env: environment.clone(), ty: ty.clone() };
- Param { func: self, ty, idx }
+ Param { func: Callee::Def(CallableDefId::FunctionId(self.id)), ty, idx }
})
.collect()
}
@@ -2037,7 +2030,7 @@ impl Function {
.skip(skip)
.map(|(idx, ty)| {
let ty = Type { env: environment.clone(), ty: ty.clone() };
- Param { func: self, ty, idx }
+ Param { func: Callee::Def(CallableDefId::FunctionId(self.id)), ty, idx }
})
.collect()
}
@@ -2167,17 +2160,24 @@ impl From<hir_ty::Mutability> for Access {
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
pub struct Param {
- func: Function,
+ func: Callee,
/// The index in parameter list, including self parameter.
idx: usize,
ty: Type,
}
impl Param {
- pub fn parent_fn(&self) -> Function {
- self.func
+ pub fn parent_fn(&self) -> Option<Function> {
+ match self.func {
+ Callee::Def(CallableDefId::FunctionId(f)) => Some(f.into()),
+ _ => None,
+ }
}
+ // pub fn parent_closure(&self) -> Option<Closure> {
+ // self.func.as_ref().right().cloned()
+ // }
+
pub fn index(&self) -> usize {
self.idx
}
@@ -2191,7 +2191,11 @@ impl Param {
}
pub fn as_local(&self, db: &dyn HirDatabase) -> Option<Local> {
- let parent = DefWithBodyId::FunctionId(self.func.into());
+ let parent = match self.func {
+ Callee::Def(CallableDefId::FunctionId(it)) => DefWithBodyId::FunctionId(it),
+ Callee::Closure(closure, _) => db.lookup_intern_closure(closure.into()).0,
+ _ => return None,
+ };
let body = db.body(parent);
if let Some(self_param) = body.self_param.filter(|_| self.idx == 0) {
Some(Local { parent, binding_id: self_param })
@@ -2205,18 +2209,45 @@ impl Param {
}
pub fn pattern_source(&self, db: &dyn HirDatabase) -> Option<ast::Pat> {
- self.source(db).and_then(|p| p.value.pat())
+ self.source(db).and_then(|p| p.value.right()?.pat())
}
- pub fn source(&self, db: &dyn HirDatabase) -> Option<InFile<ast::Param>> {
- let InFile { file_id, value } = self.func.source(db)?;
- let params = value.param_list()?;
- if params.self_param().is_some() {
- params.params().nth(self.idx.checked_sub(params.self_param().is_some() as usize)?)
- } else {
- params.params().nth(self.idx)
+ pub fn source(
+ &self,
+ db: &dyn HirDatabase,
+ ) -> Option<InFile<Either<ast::SelfParam, ast::Param>>> {
+ match self.func {
+ Callee::Def(CallableDefId::FunctionId(func)) => {
+ let InFile { file_id, value } = Function { id: func }.source(db)?;
+ let params = value.param_list()?;
+ if let Some(self_param) = params.self_param() {
+ if let Some(idx) = self.idx.checked_sub(1) {
+ params.params().nth(idx).map(Either::Right)
+ } else {
+ Some(Either::Left(self_param))
+ }
+ } else {
+ params.params().nth(self.idx).map(Either::Right)
+ }
+ .map(|value| InFile { file_id, value })
+ }
+ Callee::Closure(closure, _) => {
+ let InternedClosure(owner, expr_id) = db.lookup_intern_closure(closure.into());
+ let (_, source_map) = db.body_with_source_map(owner);
+ let ast @ InFile { file_id, value } = source_map.expr_syntax(expr_id).ok()?;
+ let root = db.parse_or_expand(file_id);
+ match value.to_node(&root) {
+ ast::Expr::ClosureExpr(it) => it
+ .param_list()?
+ .params()
+ .nth(self.idx)
+ .map(Either::Right)
+ .map(|value| InFile { file_id: ast.file_id, value }),
+ _ => None,
+ }
+ }
+ _ => None,
}
- .map(|value| InFile { file_id, value })
}
}
@@ -3372,34 +3403,21 @@ impl BuiltinAttr {
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct ToolModule {
- krate: Option<CrateId>,
+ krate: CrateId,
idx: u32,
}
impl ToolModule {
- // FIXME: consider crates\hir_def\src\nameres\attr_resolution.rs?
pub(crate) fn by_name(db: &dyn HirDatabase, krate: Crate, name: &str) -> Option<Self> {
- if let builtin @ Some(_) = Self::builtin(name) {
- return builtin;
- }
+ let krate = krate.id;
let idx =
- db.crate_def_map(krate.id).registered_tools().iter().position(|it| it == name)? as u32;
- Some(ToolModule { krate: Some(krate.id), idx })
- }
-
- fn builtin(name: &str) -> Option<Self> {
- hir_def::attr::builtin::TOOL_MODULES
- .iter()
- .position(|&tool| tool == name)
- .map(|idx| ToolModule { krate: None, idx: idx as u32 })
+ db.crate_def_map(krate).registered_tools().iter().position(|it| it == name)? as u32;
+ Some(ToolModule { krate, idx })
}
pub fn name(&self, db: &dyn HirDatabase) -> SmolStr {
// FIXME: Return a `Name` here
- match self.krate {
- Some(krate) => db.crate_def_map(krate).registered_tools()[self.idx as usize].clone(),
- None => SmolStr::new(hir_def::attr::builtin::TOOL_MODULES[self.idx as usize]),
- }
+ db.crate_def_map(self.krate).registered_tools()[self.idx as usize].clone()
}
}
@@ -4292,27 +4310,37 @@ impl Type {
}
pub fn as_callable(&self, db: &dyn HirDatabase) -> Option<Callable> {
- let mut the_ty = &self.ty;
let callee = match self.ty.kind(Interner) {
- TyKind::Ref(_, _, ty) if ty.as_closure().is_some() => {
- the_ty = ty;
- Callee::Closure(ty.as_closure().unwrap())
- }
- TyKind::Closure(id, _) => Callee::Closure(*id),
+ TyKind::Closure(id, subst) => Callee::Closure(*id, subst.clone()),
TyKind::Function(_) => Callee::FnPtr,
TyKind::FnDef(..) => Callee::Def(self.ty.callable_def(db)?),
- _ => {
- let sig = hir_ty::callable_sig_from_fnonce(&self.ty, self.env.clone(), db)?;
+ kind => {
+ // This will happen when it implements fn or fn mut, since we add an autoborrow adjustment
+ let (ty, kind) = if let TyKind::Ref(_, _, ty) = kind {
+ (ty, ty.kind(Interner))
+ } else {
+ (&self.ty, kind)
+ };
+ if let TyKind::Closure(closure, subst) = kind {
+ let sig = ty.callable_sig(db)?;
+ return Some(Callable {
+ ty: self.clone(),
+ sig,
+ callee: Callee::Closure(*closure, subst.clone()),
+ is_bound_method: false,
+ });
+ }
+ let (fn_trait, sig) = hir_ty::callable_sig_from_fn_trait(ty, self.env.clone(), db)?;
return Some(Callable {
ty: self.clone(),
sig,
- callee: Callee::Other,
+ callee: Callee::FnImpl(fn_trait),
is_bound_method: false,
});
}
};
- let sig = the_ty.callable_sig(db)?;
+ let sig = self.ty.callable_sig(db)?;
Some(Callable { ty: self.clone(), sig, callee, is_bound_method: false })
}
@@ -4929,37 +4957,39 @@ pub struct Callable {
sig: CallableSig,
callee: Callee,
/// Whether this is a method that was called with method call syntax.
- pub(crate) is_bound_method: bool,
+ is_bound_method: bool,
}
-#[derive(Debug)]
+#[derive(Clone, PartialEq, Eq, Hash, Debug)]
enum Callee {
Def(CallableDefId),
- Closure(ClosureId),
+ Closure(ClosureId, Substitution),
FnPtr,
- Other,
+ FnImpl(FnTrait),
}
pub enum CallableKind {
Function(Function),
TupleStruct(Struct),
TupleEnumVariant(Variant),
- Closure,
+ Closure(Closure),
FnPtr,
- /// Some other type that implements `FnOnce`.
- Other,
+ FnImpl(FnTrait),
}
impl Callable {
pub fn kind(&self) -> CallableKind {
- use Callee::*;
match self.callee {
- Def(CallableDefId::FunctionId(it)) => CallableKind::Function(it.into()),
- Def(CallableDefId::StructId(it)) => CallableKind::TupleStruct(it.into()),
- Def(CallableDefId::EnumVariantId(it)) => CallableKind::TupleEnumVariant(it.into()),
- Closure(_) => CallableKind::Closure,
- FnPtr => CallableKind::FnPtr,
- Other => CallableKind::Other,
+ Callee::Def(CallableDefId::FunctionId(it)) => CallableKind::Function(it.into()),
+ Callee::Def(CallableDefId::StructId(it)) => CallableKind::TupleStruct(it.into()),
+ Callee::Def(CallableDefId::EnumVariantId(it)) => {
+ CallableKind::TupleEnumVariant(it.into())
+ }
+ Callee::Closure(id, ref subst) => {
+ CallableKind::Closure(Closure { id, subst: subst.clone() })
+ }
+ Callee::FnPtr => CallableKind::FnPtr,
+ Callee::FnImpl(fn_) => CallableKind::FnImpl(fn_),
}
}
pub fn receiver_param(&self, db: &dyn HirDatabase) -> Option<(SelfParam, Type)> {
@@ -4973,43 +5003,15 @@ impl Callable {
pub fn n_params(&self) -> usize {
self.sig.params().len() - if self.is_bound_method { 1 } else { 0 }
}
- pub fn params(
- &self,
- db: &dyn HirDatabase,
- ) -> Vec<(Option<Either<ast::SelfParam, ast::Pat>>, Type)> {
- let types = self
- .sig
+ pub fn params(&self) -> Vec<Param> {
+ self.sig
.params()
.iter()
+ .enumerate()
.skip(if self.is_bound_method { 1 } else { 0 })
- .map(|ty| self.ty.derived(ty.clone()));
- let map_param = |it: ast::Param| it.pat().map(Either::Right);
- let patterns = match self.callee {
- Callee::Def(CallableDefId::FunctionId(func)) => {
- let src = func.lookup(db.upcast()).source(db.upcast());
- src.value.param_list().map(|param_list| {
- param_list
- .self_param()
- .map(|it| Some(Either::Left(it)))
- .filter(|_| !self.is_bound_method)
- .into_iter()
- .chain(param_list.params().map(map_param))
- })
- }
- Callee::Closure(closure_id) => match closure_source(db, closure_id) {
- Some(src) => src.param_list().map(|param_list| {
- param_list
- .self_param()
- .map(|it| Some(Either::Left(it)))
- .filter(|_| !self.is_bound_method)
- .into_iter()
- .chain(param_list.params().map(map_param))
- }),
- None => None,
- },
- _ => None,
- };
- patterns.into_iter().flatten().chain(iter::repeat(None)).zip(types).collect()
+ .map(|(idx, ty)| (idx, self.ty.derived(ty.clone())))
+ .map(|(idx, ty)| Param { func: self.callee.clone(), idx, ty })
+ .collect()
}
pub fn return_type(&self) -> Type {
self.ty.derived(self.sig.ret().clone())
@@ -5017,17 +5019,9 @@ impl Callable {
pub fn sig(&self) -> &CallableSig {
&self.sig
}
-}
-fn closure_source(db: &dyn HirDatabase, closure: ClosureId) -> Option<ast::ClosureExpr> {
- let InternedClosure(owner, expr_id) = db.lookup_intern_closure(closure.into());
- let (_, source_map) = db.body_with_source_map(owner);
- let ast = source_map.expr_syntax(expr_id).ok()?;
- let root = ast.file_syntax(db.upcast());
- let expr = ast.value.to_node(&root);
- match expr {
- ast::Expr::ClosureExpr(it) => Some(it),
- _ => None,
+ pub fn ty(&self) -> &Type {
+ &self.ty
}
}