mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-28 12:54:58 +00:00
Allow hir::Param to refer to other entity params aside from functions
This commit is contained in:
parent
cd9e90cc71
commit
7c6f31a45b
9 changed files with 114 additions and 118 deletions
|
@ -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>);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue