Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-def/src/body.rs')
-rw-r--r--crates/hir-def/src/body.rs84
1 files changed, 67 insertions, 17 deletions
diff --git a/crates/hir-def/src/body.rs b/crates/hir-def/src/body.rs
index 684eaf1c3b..1bfd7d2b73 100644
--- a/crates/hir-def/src/body.rs
+++ b/crates/hir-def/src/body.rs
@@ -33,6 +33,22 @@ use crate::{
BlockId, DefWithBodyId, HasModule, Lookup,
};
+/// A wrapper around [`span::SyntaxContextId`] that is intended only for comparisons.
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub struct HygieneId(pub(crate) span::SyntaxContextId);
+
+impl HygieneId {
+ pub const ROOT: Self = Self(span::SyntaxContextId::ROOT);
+
+ pub fn new(ctx: span::SyntaxContextId) -> Self {
+ Self(ctx)
+ }
+
+ pub(crate) fn is_root(self) -> bool {
+ self.0.is_root()
+ }
+}
+
/// The body of an item (function, const etc.).
#[derive(Debug, Eq, PartialEq)]
pub struct Body {
@@ -55,6 +71,22 @@ pub struct Body {
pub body_expr: ExprId,
/// Block expressions in this body that may contain inner items.
block_scopes: Vec<BlockId>,
+
+ /// A map from binding to its hygiene ID.
+ ///
+ /// Bindings that don't come from macro expansion are not allocated to save space, so not all bindings appear here.
+ /// If a binding does not appear here it has `SyntaxContextId::ROOT`.
+ ///
+ /// Note that this may not be the direct `SyntaxContextId` of the binding's expansion, because transparent
+ /// expansions are attributed to their parent expansion (recursively).
+ binding_hygiene: FxHashMap<BindingId, HygieneId>,
+ /// A map from an variable usages to their hygiene ID.
+ ///
+ /// Expressions that can be recorded here are single segment path, although not all single segments path refer
+ /// to variables and have hygiene (some refer to items, we don't know at this stage).
+ expr_hygiene: FxHashMap<ExprId, HygieneId>,
+ /// A map from a destructuring assignment possible variable usages to their hygiene ID.
+ pat_hygiene: FxHashMap<PatId, HygieneId>,
}
pub type ExprPtr = AstPtr<ast::Expr>;
@@ -107,10 +139,11 @@ pub struct BodySourceMap {
field_map_back: FxHashMap<ExprId, FieldSource>,
pat_field_map_back: FxHashMap<PatId, PatFieldSource>,
+ // FIXME: Make this a sane struct.
template_map: Option<
Box<(
// format_args!
- FxHashMap<ExprId, Vec<(syntax::TextRange, Name)>>,
+ FxHashMap<ExprId, (HygieneId, Vec<(syntax::TextRange, Name)>)>,
// asm!
FxHashMap<ExprId, Vec<Vec<(syntax::TextRange, usize)>>>,
)>,
@@ -268,6 +301,9 @@ impl Body {
pats,
bindings,
binding_owners,
+ binding_hygiene,
+ expr_hygiene,
+ pat_hygiene,
} = self;
block_scopes.shrink_to_fit();
exprs.shrink_to_fit();
@@ -275,6 +311,9 @@ impl Body {
pats.shrink_to_fit();
bindings.shrink_to_fit();
binding_owners.shrink_to_fit();
+ binding_hygiene.shrink_to_fit();
+ expr_hygiene.shrink_to_fit();
+ pat_hygiene.shrink_to_fit();
}
pub fn walk_bindings_in_pat(&self, pat_id: PatId, mut f: impl FnMut(BindingId)) {
@@ -381,7 +420,7 @@ impl Body {
self.walk_exprs_in_pat(*pat, &mut f);
}
Statement::Expr { expr: expression, .. } => f(*expression),
- Statement::Item => (),
+ Statement::Item(_) => (),
}
}
if let &Some(expr) = tail {
@@ -467,6 +506,25 @@ impl Body {
}
});
}
+
+ fn binding_hygiene(&self, binding: BindingId) -> HygieneId {
+ self.binding_hygiene.get(&binding).copied().unwrap_or(HygieneId::ROOT)
+ }
+
+ pub fn expr_path_hygiene(&self, expr: ExprId) -> HygieneId {
+ self.expr_hygiene.get(&expr).copied().unwrap_or(HygieneId::ROOT)
+ }
+
+ pub fn pat_path_hygiene(&self, pat: PatId) -> HygieneId {
+ self.pat_hygiene.get(&pat).copied().unwrap_or(HygieneId::ROOT)
+ }
+
+ pub fn expr_or_pat_path_hygiene(&self, id: ExprOrPatId) -> HygieneId {
+ match id {
+ ExprOrPatId::ExprId(id) => self.expr_path_hygiene(id),
+ ExprOrPatId::PatId(id) => self.pat_path_hygiene(id),
+ }
+ }
}
impl Default for Body {
@@ -481,6 +539,9 @@ impl Default for Body {
block_scopes: Default::default(),
binding_owners: Default::default(),
self_param: Default::default(),
+ binding_hygiene: Default::default(),
+ expr_hygiene: Default::default(),
+ pat_hygiene: Default::default(),
}
}
}
@@ -594,13 +655,11 @@ impl BodySourceMap {
pub fn implicit_format_args(
&self,
node: InFile<&ast::FormatArgsExpr>,
- ) -> Option<&[(syntax::TextRange, Name)]> {
+ ) -> Option<(HygieneId, &[(syntax::TextRange, Name)])> {
let src = node.map(AstPtr::new).map(AstPtr::upcast::<ast::Expr>);
- self.template_map
- .as_ref()?
- .0
- .get(&self.expr_map.get(&src)?.as_expr()?)
- .map(std::ops::Deref::deref)
+ let (hygiene, names) =
+ self.template_map.as_ref()?.0.get(&self.expr_map.get(&src)?.as_expr()?)?;
+ Some((*hygiene, &**names))
}
pub fn asm_template_args(
@@ -649,13 +708,4 @@ impl BodySourceMap {
diagnostics.shrink_to_fit();
binding_definitions.shrink_to_fit();
}
-
- pub fn template_map(
- &self,
- ) -> Option<&(
- FxHashMap<Idx<Expr>, Vec<(tt::TextRange, Name)>>,
- FxHashMap<Idx<Expr>, Vec<Vec<(tt::TextRange, usize)>>>,
- )> {
- self.template_map.as_deref()
- }
}