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.rs127
1 files changed, 62 insertions, 65 deletions
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index a902ae2d33..49e6241f7a 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,
@@ -1965,7 +1964,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 +1990,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 +2036,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 +2166,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 +2197,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 +2215,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 as usize) {
+ 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 })
}
}
@@ -4919,7 +4956,7 @@ pub struct Callable {
pub(crate) is_bound_method: bool,
}
-#[derive(Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
enum Callee {
Def(CallableDefId),
Closure(ClosureId),
@@ -4960,43 +4997,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, idx, ty })
+ .collect()
}
pub fn return_type(&self) -> Type {
self.ty.derived(self.sig.ret().clone())
@@ -5006,18 +5015,6 @@ impl Callable {
}
}
-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,
- }
-}
-
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Layout(Arc<TyLayout>, Arc<TargetDataLayout>);