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:
bors 2024-03-11 12:45:46 +00:00
commit 2320e12541
18 changed files with 256 additions and 144 deletions

View file

@ -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(),
}
}
}