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.rs | 88 |
1 files changed, 62 insertions, 26 deletions
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 739fbfe068..f18853030a 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(), + } } } |