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.rs88
1 files changed, 62 insertions, 26 deletions
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 5eed7ecd5b..ea15535670 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -1725,6 +1725,10 @@ impl DefWithBody {
Ok(s) => s.map(|it| it.into()),
Err(_) => continue,
},
+ mir::MirSpan::SelfParam => match source_map.self_param_syntax() {
+ Some(s) => s.map(|it| it.into()),
+ None => continue,
+ },
mir::MirSpan::Unknown => continue,
};
acc.push(
@@ -1776,6 +1780,11 @@ impl DefWithBody {
Ok(s) => s.map(|it| it.into()),
Err(_) => continue,
},
+ mir::MirSpan::SelfParam => match source_map.self_param_syntax()
+ {
+ Some(s) => s.map(|it| it.into()),
+ None => continue,
+ },
mir::MirSpan::Unknown => continue,
};
acc.push(NeedMut { local, span }.into());
@@ -2127,8 +2136,11 @@ impl Param {
pub fn as_local(&self, db: &dyn HirDatabase) -> Option<Local> {
let parent = DefWithBodyId::FunctionId(self.func.into());
let body = db.body(parent);
- let pat_id = body.params[self.idx];
- if let Pat::Bind { id, .. } = &body[pat_id] {
+ if let Some(self_param) = body.self_param.filter(|_| self.idx == 0) {
+ Some(Local { parent, binding_id: self_param })
+ } else if let Pat::Bind { id, .. } =
+ &body[body.params[self.idx - body.self_param.is_some() as usize]]
+ {
Some(Local { parent, binding_id: *id })
} else {
None
@@ -2143,7 +2155,7 @@ impl 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(1)?)
+ params.params().nth(self.idx.checked_sub(params.self_param().is_some() as usize)?)
} else {
params.params().nth(self.idx)
}
@@ -3134,35 +3146,59 @@ impl Local {
/// All definitions for this local. Example: `let (a$0, _) | (_, a$0) = it;`
pub fn sources(self, db: &dyn HirDatabase) -> Vec<LocalSource> {
let (body, source_map) = db.body_with_source_map(self.parent);
- self.sources_(db, &body, &source_map).collect()
+ match body.self_param.zip(source_map.self_param_syntax()) {
+ Some((param, source)) if param == self.binding_id => {
+ let root = source.file_syntax(db.upcast());
+ vec![LocalSource {
+ local: self,
+ source: source.map(|ast| Either::Right(ast.to_node(&root))),
+ }]
+ }
+ _ => body[self.binding_id]
+ .definitions
+ .iter()
+ .map(|&definition| {
+ let src = source_map.pat_syntax(definition).unwrap(); // Hmm...
+ let root = src.file_syntax(db.upcast());
+ LocalSource {
+ local: self,
+ source: src.map(|ast| match ast.to_node(&root) {
+ ast::Pat::IdentPat(it) => Either::Left(it),
+ _ => unreachable!("local with non ident-pattern"),
+ }),
+ }
+ })
+ .collect(),
+ }
}
/// The leftmost definition for this local. Example: `let (a$0, _) | (_, a) = it;`
pub fn primary_source(self, db: &dyn HirDatabase) -> LocalSource {
let (body, source_map) = db.body_with_source_map(self.parent);
- let src = self.sources_(db, &body, &source_map).next().unwrap();
- src
- }
-
- fn sources_<'a>(
- self,
- db: &'a dyn HirDatabase,
- body: &'a hir_def::body::Body,
- source_map: &'a hir_def::body::BodySourceMap,
- ) -> impl Iterator<Item = LocalSource> + 'a {
- body[self.binding_id]
- .definitions
- .iter()
- .map(|&definition| {
- let src = source_map.pat_syntax(definition).unwrap(); // Hmm...
- let root = src.file_syntax(db.upcast());
- src.map(|ast| match ast.to_node(&root) {
- Either::Left(ast::Pat::IdentPat(it)) => Either::Left(it),
- Either::Left(_) => unreachable!("local with non ident-pattern"),
- Either::Right(it) => Either::Right(it),
+ match body.self_param.zip(source_map.self_param_syntax()) {
+ Some((param, source)) if param == self.binding_id => {
+ let root = source.file_syntax(db.upcast());
+ LocalSource {
+ local: self,
+ source: source.map(|ast| Either::Right(ast.to_node(&root))),
+ }
+ }
+ _ => body[self.binding_id]
+ .definitions
+ .first()
+ .map(|&definition| {
+ let src = source_map.pat_syntax(definition).unwrap(); // Hmm...
+ let root = src.file_syntax(db.upcast());
+ LocalSource {
+ local: self,
+ source: src.map(|ast| match ast.to_node(&root) {
+ ast::Pat::IdentPat(it) => Either::Left(it),
+ _ => unreachable!("local with non ident-pattern"),
+ }),
+ }
})
- })
- .map(move |source| LocalSource { local: self, source })
+ .unwrap(),
+ }
}
}