mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-28 12:54:58 +00:00
Auto merge of #16771 - Veykril:self-param-split, r=Veykril
internal: Don't desugar self param into a pattern Small experiment to see if this simplifies things
This commit is contained in:
commit
2320e12541
18 changed files with 256 additions and 144 deletions
|
@ -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(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue