Auto merge of #17671 - Veykril:binding-size, r=Veykril

internal: Shrink size of `Binding`

This should save a bit of memory now that we LRU the source map
This commit is contained in:
bors 2024-07-22 15:16:05 +00:00
commit 329adb5ab1
15 changed files with 94 additions and 56 deletions

View file

@ -6,13 +6,14 @@ pub mod scope;
#[cfg(test)] #[cfg(test)]
mod tests; mod tests;
use std::ops::Index; use std::ops::{Deref, Index};
use base_db::CrateId; use base_db::CrateId;
use cfg::{CfgExpr, CfgOptions}; use cfg::{CfgExpr, CfgOptions};
use hir_expand::{name::Name, InFile}; use hir_expand::{name::Name, InFile};
use la_arena::{Arena, ArenaMap}; use la_arena::{Arena, ArenaMap};
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use smallvec::SmallVec;
use span::MacroFileId; use span::MacroFileId;
use syntax::{ast, AstPtr, SyntaxNodePtr}; use syntax::{ast, AstPtr, SyntaxNodePtr};
use triomphe::Arc; use triomphe::Arc;
@ -91,6 +92,7 @@ pub struct BodySourceMap {
label_map_back: ArenaMap<LabelId, LabelSource>, label_map_back: ArenaMap<LabelId, LabelSource>,
self_param: Option<InFile<AstPtr<ast::SelfParam>>>, self_param: Option<InFile<AstPtr<ast::SelfParam>>>,
binding_definitions: FxHashMap<BindingId, SmallVec<[PatId; 4]>>,
/// We don't create explicit nodes for record fields (`S { record_field: 92 }`). /// We don't create explicit nodes for record fields (`S { record_field: 92 }`).
/// Instead, we use id of expression (`92`) to identify the field. /// Instead, we use id of expression (`92`) to identify the field.
@ -377,6 +379,10 @@ impl BodySourceMap {
self.label_map_back[label] self.label_map_back[label]
} }
pub fn patterns_for_binding(&self, binding: BindingId) -> &[PatId] {
self.binding_definitions.get(&binding).map_or(&[], Deref::deref)
}
pub fn node_label(&self, node: InFile<&ast::Label>) -> Option<LabelId> { pub fn node_label(&self, node: InFile<&ast::Label>) -> Option<LabelId> {
let src = node.map(AstPtr::new); let src = node.map(AstPtr::new);
self.label_map.get(&src).cloned() self.label_map.get(&src).cloned()
@ -428,6 +434,7 @@ impl BodySourceMap {
expansions, expansions,
format_args_template_map, format_args_template_map,
diagnostics, diagnostics,
binding_definitions,
} = self; } = self;
format_args_template_map.shrink_to_fit(); format_args_template_map.shrink_to_fit();
expr_map.shrink_to_fit(); expr_map.shrink_to_fit();
@ -440,5 +447,6 @@ impl BodySourceMap {
pat_field_map_back.shrink_to_fit(); pat_field_map_back.shrink_to_fit();
expansions.shrink_to_fit(); expansions.shrink_to_fit();
diagnostics.shrink_to_fit(); diagnostics.shrink_to_fit();
binding_definitions.shrink_to_fit();
} }
} }

View file

@ -11,7 +11,6 @@ use hir_expand::{
}; };
use intern::{sym, Interned, Symbol}; use intern::{sym, Interned, Symbol};
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use smallvec::SmallVec;
use span::AstIdMap; use span::AstIdMap;
use stdx::never; use stdx::never;
use syntax::{ use syntax::{
@ -1437,11 +1436,12 @@ impl ExprCollector<'_> {
args: AstChildren<ast::Pat>, args: AstChildren<ast::Pat>,
has_leading_comma: bool, has_leading_comma: bool,
binding_list: &mut BindingList, binding_list: &mut BindingList,
) -> (Box<[PatId]>, Option<usize>) { ) -> (Box<[PatId]>, Option<u32>) {
let args: Vec<_> = args.map(|p| self.collect_pat_possibly_rest(p, binding_list)).collect(); let args: Vec<_> = args.map(|p| self.collect_pat_possibly_rest(p, binding_list)).collect();
// Find the location of the `..`, if there is one. Note that we do not // Find the location of the `..`, if there is one. Note that we do not
// consider the possibility of there being multiple `..` here. // consider the possibility of there being multiple `..` here.
let ellipsis = args.iter().position(|p| p.is_right()); let ellipsis = args.iter().position(|p| p.is_right()).map(|it| it as u32);
// We want to skip the `..` pattern here, since we account for it above. // We want to skip the `..` pattern here, since we account for it above.
let mut args: Vec<_> = args.into_iter().filter_map(Either::left).collect(); let mut args: Vec<_> = args.into_iter().filter_map(Either::left).collect();
// if there is a leading comma, the user is most likely to type out a leading pattern // if there is a leading comma, the user is most likely to type out a leading pattern
@ -1512,7 +1512,7 @@ impl ExprCollector<'_> {
} }
fn add_definition_to_binding(&mut self, binding_id: BindingId, pat_id: PatId) { fn add_definition_to_binding(&mut self, binding_id: BindingId, pat_id: PatId) {
self.body.bindings[binding_id].definitions.push(pat_id); self.source_map.binding_definitions.entry(binding_id).or_default().push(pat_id);
} }
// region: labels // region: labels
@ -2058,12 +2058,7 @@ impl ExprCollector<'_> {
} }
fn alloc_binding(&mut self, name: Name, mode: BindingAnnotation) -> BindingId { fn alloc_binding(&mut self, name: Name, mode: BindingAnnotation) -> BindingId {
let binding = self.body.bindings.alloc(Binding { let binding = self.body.bindings.alloc(Binding { name, mode, problems: None });
name,
mode,
definitions: SmallVec::new(),
problems: None,
});
if let Some(owner) = self.current_binding_owner { if let Some(owner) = self.current_binding_owner {
self.body.binding_owners.insert(binding, owner); self.body.binding_owners.insert(binding, owner);
} }

View file

@ -517,7 +517,7 @@ impl Printer<'_> {
if i != 0 { if i != 0 {
w!(self, ", "); w!(self, ", ");
} }
if *ellipsis == Some(i) { if *ellipsis == Some(i as u32) {
w!(self, ".., "); w!(self, ".., ");
} }
self.print_pat(*pat); self.print_pat(*pat);
@ -595,7 +595,7 @@ impl Printer<'_> {
if i != 0 { if i != 0 {
w!(self, ", "); w!(self, ", ");
} }
if *ellipsis == Some(i) { if *ellipsis == Some(i as u32) {
w!(self, ", .."); w!(self, ", ..");
} }
self.print_pat(*arg); self.print_pat(*arg);

View file

@ -484,7 +484,7 @@ fn foo() {
let function = find_function(&db, file_id.file_id()); let function = find_function(&db, file_id.file_id());
let scopes = db.expr_scopes(function.into()); let scopes = db.expr_scopes(function.into());
let (body, source_map) = db.body_with_source_map(function.into()); let (_, source_map) = db.body_with_source_map(function.into());
let expr_scope = { let expr_scope = {
let expr_ast = name_ref.syntax().ancestors().find_map(ast::Expr::cast).unwrap(); let expr_ast = name_ref.syntax().ancestors().find_map(ast::Expr::cast).unwrap();
@ -495,7 +495,7 @@ fn foo() {
let resolved = scopes.resolve_name_in_scope(expr_scope, &name_ref.as_name()).unwrap(); let resolved = scopes.resolve_name_in_scope(expr_scope, &name_ref.as_name()).unwrap();
let pat_src = source_map let pat_src = source_map
.pat_syntax(*body.bindings[resolved.binding()].definitions.first().unwrap()) .pat_syntax(*source_map.binding_definitions[&resolved.binding()].first().unwrap())
.unwrap(); .unwrap();
let local_name = pat_src.value.syntax_node_ptr().to_node(file.syntax()); let local_name = pat_src.value.syntax_node_ptr().to_node(file.syntax());

View file

@ -21,7 +21,6 @@ use hir_expand::name::Name;
use intern::{Interned, Symbol}; use intern::{Interned, Symbol};
use la_arena::{Idx, RawIdx}; use la_arena::{Idx, RawIdx};
use rustc_apfloat::ieee::{Half as f16, Quad as f128}; use rustc_apfloat::ieee::{Half as f16, Quad as f128};
use smallvec::SmallVec;
use syntax::ast; use syntax::ast;
use crate::{ use crate::{
@ -525,7 +524,6 @@ pub enum BindingProblems {
pub struct Binding { pub struct Binding {
pub name: Name, pub name: Name,
pub mode: BindingAnnotation, pub mode: BindingAnnotation,
pub definitions: SmallVec<[PatId; 1]>,
pub problems: Option<BindingProblems>, pub problems: Option<BindingProblems>,
} }
@ -540,7 +538,7 @@ pub struct RecordFieldPat {
pub enum Pat { pub enum Pat {
Missing, Missing,
Wild, Wild,
Tuple { args: Box<[PatId]>, ellipsis: Option<usize> }, Tuple { args: Box<[PatId]>, ellipsis: Option<u32> },
Or(Box<[PatId]>), Or(Box<[PatId]>),
Record { path: Option<Box<Path>>, args: Box<[RecordFieldPat]>, ellipsis: bool }, Record { path: Option<Box<Path>>, args: Box<[RecordFieldPat]>, ellipsis: bool },
Range { start: Option<Box<LiteralOrConst>>, end: Option<Box<LiteralOrConst>> }, Range { start: Option<Box<LiteralOrConst>>, end: Option<Box<LiteralOrConst>> },
@ -548,7 +546,7 @@ pub enum Pat {
Path(Box<Path>), Path(Box<Path>),
Lit(ExprId), Lit(ExprId),
Bind { id: BindingId, subpat: Option<PatId> }, Bind { id: BindingId, subpat: Option<PatId> },
TupleStruct { path: Option<Box<Path>>, args: Box<[PatId]>, ellipsis: Option<usize> }, TupleStruct { path: Option<Box<Path>>, args: Box<[PatId]>, ellipsis: Option<u32> },
Ref { pat: PatId, mutability: Mutability }, Ref { pat: PatId, mutability: Mutability },
Box { inner: PatId }, Box { inner: PatId },
ConstBlock(ExprId), ConstBlock(ExprId),

View file

@ -206,7 +206,7 @@ impl<'a> PatCtxt<'a> {
&mut self, &mut self,
pats: &[PatId], pats: &[PatId],
expected_len: usize, expected_len: usize,
ellipsis: Option<usize>, ellipsis: Option<u32>,
) -> Vec<FieldPat> { ) -> Vec<FieldPat> {
if pats.len() > expected_len { if pats.len() > expected_len {
self.errors.push(PatternError::ExtraFields); self.errors.push(PatternError::ExtraFields);
@ -214,7 +214,7 @@ impl<'a> PatCtxt<'a> {
} }
pats.iter() pats.iter()
.enumerate_and_adjust(expected_len, ellipsis) .enumerate_and_adjust(expected_len, ellipsis.map(|it| it as usize))
.map(|(i, &subpattern)| FieldPat { .map(|(i, &subpattern)| FieldPat {
field: LocalFieldId::from_raw((i as u32).into()), field: LocalFieldId::from_raw((i as u32).into()),
pattern: self.lower_pattern(subpattern), pattern: self.lower_pattern(subpattern),

View file

@ -889,7 +889,7 @@ impl InferenceContext<'_> {
match &self.body[pat] { match &self.body[pat] {
Pat::Missing | Pat::Wild => (), Pat::Missing | Pat::Wild => (),
Pat::Tuple { args, ellipsis } => { Pat::Tuple { args, ellipsis } => {
let (al, ar) = args.split_at(ellipsis.unwrap_or(args.len())); let (al, ar) = args.split_at(ellipsis.map_or(args.len(), |it| it as usize));
let field_count = match self.result[pat].kind(Interner) { let field_count = match self.result[pat].kind(Interner) {
TyKind::Tuple(_, s) => s.len(Interner), TyKind::Tuple(_, s) => s.len(Interner),
_ => return, _ => return,
@ -964,7 +964,7 @@ impl InferenceContext<'_> {
} }
VariantId::StructId(s) => { VariantId::StructId(s) => {
let vd = &*self.db.struct_data(s).variant_data; let vd = &*self.db.struct_data(s).variant_data;
let (al, ar) = args.split_at(ellipsis.unwrap_or(args.len())); let (al, ar) = args.split_at(ellipsis.map_or(args.len(), |it| it as usize));
let fields = vd.fields().iter(); let fields = vd.fields().iter();
let it = let it =
al.iter().zip(fields.clone()).chain(ar.iter().rev().zip(fields.rev())); al.iter().zip(fields.clone()).chain(ar.iter().rev().zip(fields.rev()));

View file

@ -1170,7 +1170,7 @@ impl InferenceContext<'_> {
Expr::Tuple { exprs, .. } => { Expr::Tuple { exprs, .. } => {
// We don't consider multiple ellipses. This is analogous to // We don't consider multiple ellipses. This is analogous to
// `hir_def::body::lower::ExprCollector::collect_tuple_pat()`. // `hir_def::body::lower::ExprCollector::collect_tuple_pat()`.
let ellipsis = exprs.iter().position(|e| is_rest_expr(*e)); let ellipsis = exprs.iter().position(|e| is_rest_expr(*e)).map(|it| it as u32);
let exprs: Vec<_> = exprs.iter().filter(|e| !is_rest_expr(**e)).copied().collect(); let exprs: Vec<_> = exprs.iter().filter(|e| !is_rest_expr(**e)).copied().collect();
self.infer_tuple_pat_like(&rhs_ty, (), ellipsis, &exprs) self.infer_tuple_pat_like(&rhs_ty, (), ellipsis, &exprs)
@ -1184,7 +1184,7 @@ impl InferenceContext<'_> {
// We don't consider multiple ellipses. This is analogous to // We don't consider multiple ellipses. This is analogous to
// `hir_def::body::lower::ExprCollector::collect_tuple_pat()`. // `hir_def::body::lower::ExprCollector::collect_tuple_pat()`.
let ellipsis = args.iter().position(|e| is_rest_expr(*e)); let ellipsis = args.iter().position(|e| is_rest_expr(*e)).map(|it| it as u32);
let args: Vec<_> = args.iter().filter(|e| !is_rest_expr(**e)).copied().collect(); let args: Vec<_> = args.iter().filter(|e| !is_rest_expr(**e)).copied().collect();
self.infer_tuple_struct_pat_like(path, &rhs_ty, (), lhs, ellipsis, &args) self.infer_tuple_struct_pat_like(path, &rhs_ty, (), lhs, ellipsis, &args)

View file

@ -68,7 +68,7 @@ impl InferenceContext<'_> {
expected: &Ty, expected: &Ty,
default_bm: T::BindingMode, default_bm: T::BindingMode,
id: T, id: T,
ellipsis: Option<usize>, ellipsis: Option<u32>,
subs: &[T], subs: &[T],
) -> Ty { ) -> Ty {
let (ty, def) = self.resolve_variant(path, true); let (ty, def) = self.resolve_variant(path, true);
@ -98,7 +98,7 @@ impl InferenceContext<'_> {
let visibilities = self.db.field_visibilities(def); let visibilities = self.db.field_visibilities(def);
let (pre, post) = match ellipsis { let (pre, post) = match ellipsis {
Some(idx) => subs.split_at(idx), Some(idx) => subs.split_at(idx as usize),
None => (subs, &[][..]), None => (subs, &[][..]),
}; };
let post_idx_offset = field_types.iter().count().saturating_sub(post.len()); let post_idx_offset = field_types.iter().count().saturating_sub(post.len());
@ -219,7 +219,7 @@ impl InferenceContext<'_> {
&mut self, &mut self,
expected: &Ty, expected: &Ty,
default_bm: T::BindingMode, default_bm: T::BindingMode,
ellipsis: Option<usize>, ellipsis: Option<u32>,
subs: &[T], subs: &[T],
) -> Ty { ) -> Ty {
let expected = self.resolve_ty_shallow(expected); let expected = self.resolve_ty_shallow(expected);
@ -229,7 +229,9 @@ impl InferenceContext<'_> {
}; };
let ((pre, post), n_uncovered_patterns) = match ellipsis { let ((pre, post), n_uncovered_patterns) = match ellipsis {
Some(idx) => (subs.split_at(idx), expectations.len().saturating_sub(subs.len())), Some(idx) => {
(subs.split_at(idx as usize), expectations.len().saturating_sub(subs.len()))
}
None => ((subs, &[][..]), 0), None => ((subs, &[][..]), 0),
}; };
let mut expectations_iter = expectations let mut expectations_iter = expectations

View file

@ -1164,6 +1164,7 @@ impl MirBody {
pub enum MirSpan { pub enum MirSpan {
ExprId(ExprId), ExprId(ExprId),
PatId(PatId), PatId(PatId),
BindingId(BindingId),
SelfParam, SelfParam,
Unknown, Unknown,
} }

View file

@ -388,6 +388,16 @@ impl MirEvalError {
Ok(s) => s.map(|it| it.syntax_node_ptr()), Ok(s) => s.map(|it| it.syntax_node_ptr()),
Err(_) => continue, Err(_) => continue,
}, },
MirSpan::BindingId(b) => {
match source_map
.patterns_for_binding(*b)
.iter()
.find_map(|p| source_map.pat_syntax(*p).ok())
{
Some(s) => s.map(|it| it.syntax_node_ptr()),
None => continue,
}
}
MirSpan::SelfParam => match source_map.self_param_syntax() { MirSpan::SelfParam => match source_map.self_param_syntax() {
Some(s) => s.map(|it| it.syntax_node_ptr()), Some(s) => s.map(|it| it.syntax_node_ptr()),
None => continue, None => continue,

View file

@ -1720,14 +1720,8 @@ impl<'ctx> MirLowerCtx<'ctx> {
/// This function push `StorageLive` statement for the binding, and applies changes to add `StorageDead` and /// This function push `StorageLive` statement for the binding, and applies changes to add `StorageDead` and
/// `Drop` in the appropriated places. /// `Drop` in the appropriated places.
fn push_storage_live(&mut self, b: BindingId, current: BasicBlockId) -> Result<()> { fn push_storage_live(&mut self, b: BindingId, current: BasicBlockId) -> Result<()> {
let span = self.body.bindings[b]
.definitions
.first()
.copied()
.map(MirSpan::PatId)
.unwrap_or(MirSpan::Unknown);
let l = self.binding_local(b)?; let l = self.binding_local(b)?;
self.push_storage_live_for_local(l, current, span) self.push_storage_live_for_local(l, current, MirSpan::BindingId(b))
} }
fn push_storage_live_for_local( fn push_storage_live_for_local(

View file

@ -23,7 +23,7 @@ macro_rules! not_supported {
} }
pub(super) enum AdtPatternShape<'a> { pub(super) enum AdtPatternShape<'a> {
Tuple { args: &'a [PatId], ellipsis: Option<usize> }, Tuple { args: &'a [PatId], ellipsis: Option<u32> },
Record { args: &'a [RecordFieldPat] }, Record { args: &'a [RecordFieldPat] },
Unit, Unit,
} }
@ -627,12 +627,12 @@ impl MirLowerCtx<'_> {
current: BasicBlockId, current: BasicBlockId,
current_else: Option<BasicBlockId>, current_else: Option<BasicBlockId>,
args: &[PatId], args: &[PatId],
ellipsis: Option<usize>, ellipsis: Option<u32>,
fields: impl DoubleEndedIterator<Item = PlaceElem> + Clone, fields: impl DoubleEndedIterator<Item = PlaceElem> + Clone,
cond_place: &Place, cond_place: &Place,
mode: MatchingMode, mode: MatchingMode,
) -> Result<(BasicBlockId, Option<BasicBlockId>)> { ) -> Result<(BasicBlockId, Option<BasicBlockId>)> {
let (al, ar) = args.split_at(ellipsis.unwrap_or(args.len())); let (al, ar) = args.split_at(ellipsis.map_or(args.len(), |it| it as usize));
let it = al let it = al
.iter() .iter()
.zip(fields.clone()) .zip(fields.clone())

View file

@ -1806,6 +1806,16 @@ impl DefWithBody {
Some(s) => s.map(|it| it.into()), Some(s) => s.map(|it| it.into()),
None => continue, None => continue,
}, },
mir::MirSpan::BindingId(b) => {
match source_map
.patterns_for_binding(b)
.iter()
.find_map(|p| source_map.pat_syntax(*p).ok())
{
Some(s) => s.map(|it| it.into()),
None => continue,
}
}
mir::MirSpan::Unknown => continue, mir::MirSpan::Unknown => continue,
}; };
acc.push( acc.push(
@ -1822,8 +1832,8 @@ impl DefWithBody {
let Some(&local) = mir_body.binding_locals.get(binding_id) else { let Some(&local) = mir_body.binding_locals.get(binding_id) else {
continue; continue;
}; };
if body[binding_id] if source_map
.definitions .patterns_for_binding(binding_id)
.iter() .iter()
.any(|&pat| source_map.pat_syntax(pat).is_err()) .any(|&pat| source_map.pat_syntax(pat).is_err())
{ {
@ -1859,6 +1869,16 @@ impl DefWithBody {
Ok(s) => s.map(|it| it.into()), Ok(s) => s.map(|it| it.into()),
Err(_) => continue, Err(_) => continue,
}, },
mir::MirSpan::BindingId(b) => {
match source_map
.patterns_for_binding(*b)
.iter()
.find_map(|p| source_map.pat_syntax(*p).ok())
{
Some(s) => s.map(|it| it.into()),
None => continue,
}
}
mir::MirSpan::SelfParam => match source_map.self_param_syntax() mir::MirSpan::SelfParam => match source_map.self_param_syntax()
{ {
Some(s) => s.map(|it| it.into()), Some(s) => s.map(|it| it.into()),
@ -3291,8 +3311,8 @@ impl Local {
source: source.map(|ast| Either::Right(ast.to_node(&root))), source: source.map(|ast| Either::Right(ast.to_node(&root))),
}] }]
} }
_ => body[self.binding_id] _ => source_map
.definitions .patterns_for_binding(self.binding_id)
.iter() .iter()
.map(|&definition| { .map(|&definition| {
let src = source_map.pat_syntax(definition).unwrap(); // Hmm... let src = source_map.pat_syntax(definition).unwrap(); // Hmm...
@ -3320,8 +3340,8 @@ impl Local {
source: source.map(|ast| Either::Right(ast.to_node(&root))), source: source.map(|ast| Either::Right(ast.to_node(&root))),
} }
} }
_ => body[self.binding_id] _ => source_map
.definitions .patterns_for_binding(self.binding_id)
.first() .first()
.map(|&definition| { .map(|&definition| {
let src = source_map.pat_syntax(definition).unwrap(); // Hmm... let src = source_map.pat_syntax(definition).unwrap(); // Hmm...

View file

@ -32,9 +32,8 @@ pub(super) fn hints(
let def = sema.to_def(def)?; let def = sema.to_def(def)?;
let def: DefWithBody = def.into(); let def: DefWithBody = def.into();
let source_map = sema.db.body_with_source_map(def.into()).1; let (hir, source_map) = sema.db.body_with_source_map(def.into());
let hir = sema.db.body(def.into());
let mir = sema.db.mir_body(def.into()).ok()?; let mir = sema.db.mir_body(def.into()).ok()?;
let local_to_binding = mir.local_to_binding_map(); let local_to_binding = mir.local_to_binding_map();
@ -74,22 +73,33 @@ pub(super) fn hints(
Ok(s) => s.value.text_range(), Ok(s) => s.value.text_range(),
Err(_) => continue, Err(_) => continue,
}, },
MirSpan::BindingId(b) => {
match source_map
.patterns_for_binding(b)
.iter()
.find_map(|p| source_map.pat_syntax(*p).ok())
{
Some(s) => s.value.text_range(),
None => continue,
}
}
MirSpan::SelfParam => match source_map.self_param_syntax() { MirSpan::SelfParam => match source_map.self_param_syntax() {
Some(s) => s.value.text_range(), Some(s) => s.value.text_range(),
None => continue, None => continue,
}, },
MirSpan::Unknown => continue, MirSpan::Unknown => continue,
}; };
let binding_source = source_map
.patterns_for_binding(*binding)
.first()
.and_then(|d| source_map.pat_syntax(*d).ok())
.and_then(|d| {
Some(FileRange {
file_id: d.file_id.file_id()?.into(),
range: d.value.text_range(),
})
});
let binding = &hir.bindings[*binding]; let binding = &hir.bindings[*binding];
let binding_source =
binding.definitions.first().and_then(|d| source_map.pat_syntax(*d).ok()).and_then(
|d| {
Some(FileRange {
file_id: d.file_id.file_id()?.into(),
range: d.value.text_range(),
})
},
);
let name = binding.name.display_no_db().to_smolstr(); let name = binding.name.display_no_db().to_smolstr();
if name.starts_with("<ra@") { if name.starts_with("<ra@") {
continue; // Ignore desugared variables continue; // Ignore desugared variables