Skip to content

Commit 1fbaccd

Browse files
authored
Merge pull request rust-lang#18264 from ChayimFriedman2/semi-transparent
fix: Implement mixed site hygiene
2 parents c8a04e3 + 8f36d1c commit 1fbaccd

File tree

27 files changed

+671
-164
lines changed

27 files changed

+671
-164
lines changed

src/tools/rust-analyzer/Cargo.lock

+1
Original file line numberDiff line numberDiff line change
@@ -556,6 +556,7 @@ dependencies = [
556556
"syntax-bridge",
557557
"test-fixture",
558558
"test-utils",
559+
"text-size",
559560
"tracing",
560561
"triomphe",
561562
"tt",

src/tools/rust-analyzer/crates/hir-def/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ smallvec.workspace = true
2929
hashbrown.workspace = true
3030
triomphe.workspace = true
3131
rustc_apfloat = "0.2.0"
32+
text-size.workspace = true
3233

3334
ra-ap-rustc_parse_format.workspace = true
3435
ra-ap-rustc_abi.workspace = true

src/tools/rust-analyzer/crates/hir-def/src/body.rs

+67-17
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,22 @@ use crate::{
3333
BlockId, DefWithBodyId, HasModule, Lookup,
3434
};
3535

36+
/// A wrapper around [`span::SyntaxContextId`] that is intended only for comparisons.
37+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
38+
pub struct HygieneId(pub(crate) span::SyntaxContextId);
39+
40+
impl HygieneId {
41+
pub const ROOT: Self = Self(span::SyntaxContextId::ROOT);
42+
43+
pub fn new(ctx: span::SyntaxContextId) -> Self {
44+
Self(ctx)
45+
}
46+
47+
pub(crate) fn is_root(self) -> bool {
48+
self.0.is_root()
49+
}
50+
}
51+
3652
/// The body of an item (function, const etc.).
3753
#[derive(Debug, Eq, PartialEq)]
3854
pub struct Body {
@@ -55,6 +71,22 @@ pub struct Body {
5571
pub body_expr: ExprId,
5672
/// Block expressions in this body that may contain inner items.
5773
block_scopes: Vec<BlockId>,
74+
75+
/// A map from binding to its hygiene ID.
76+
///
77+
/// Bindings that don't come from macro expansion are not allocated to save space, so not all bindings appear here.
78+
/// If a binding does not appear here it has `SyntaxContextId::ROOT`.
79+
///
80+
/// Note that this may not be the direct `SyntaxContextId` of the binding's expansion, because transparent
81+
/// expansions are attributed to their parent expansion (recursively).
82+
binding_hygiene: FxHashMap<BindingId, HygieneId>,
83+
/// A map from an variable usages to their hygiene ID.
84+
///
85+
/// Expressions that can be recorded here are single segment path, although not all single segments path refer
86+
/// to variables and have hygiene (some refer to items, we don't know at this stage).
87+
expr_hygiene: FxHashMap<ExprId, HygieneId>,
88+
/// A map from a destructuring assignment possible variable usages to their hygiene ID.
89+
pat_hygiene: FxHashMap<PatId, HygieneId>,
5890
}
5991

6092
pub type ExprPtr = AstPtr<ast::Expr>;
@@ -107,10 +139,11 @@ pub struct BodySourceMap {
107139
field_map_back: FxHashMap<ExprId, FieldSource>,
108140
pat_field_map_back: FxHashMap<PatId, PatFieldSource>,
109141

142+
// FIXME: Make this a sane struct.
110143
template_map: Option<
111144
Box<(
112145
// format_args!
113-
FxHashMap<ExprId, Vec<(syntax::TextRange, Name)>>,
146+
FxHashMap<ExprId, (HygieneId, Vec<(syntax::TextRange, Name)>)>,
114147
// asm!
115148
FxHashMap<ExprId, Vec<Vec<(syntax::TextRange, usize)>>>,
116149
)>,
@@ -268,13 +301,19 @@ impl Body {
268301
pats,
269302
bindings,
270303
binding_owners,
304+
binding_hygiene,
305+
expr_hygiene,
306+
pat_hygiene,
271307
} = self;
272308
block_scopes.shrink_to_fit();
273309
exprs.shrink_to_fit();
274310
labels.shrink_to_fit();
275311
pats.shrink_to_fit();
276312
bindings.shrink_to_fit();
277313
binding_owners.shrink_to_fit();
314+
binding_hygiene.shrink_to_fit();
315+
expr_hygiene.shrink_to_fit();
316+
pat_hygiene.shrink_to_fit();
278317
}
279318

280319
pub fn walk_bindings_in_pat(&self, pat_id: PatId, mut f: impl FnMut(BindingId)) {
@@ -381,7 +420,7 @@ impl Body {
381420
self.walk_exprs_in_pat(*pat, &mut f);
382421
}
383422
Statement::Expr { expr: expression, .. } => f(*expression),
384-
Statement::Item => (),
423+
Statement::Item(_) => (),
385424
}
386425
}
387426
if let &Some(expr) = tail {
@@ -467,6 +506,25 @@ impl Body {
467506
}
468507
});
469508
}
509+
510+
fn binding_hygiene(&self, binding: BindingId) -> HygieneId {
511+
self.binding_hygiene.get(&binding).copied().unwrap_or(HygieneId::ROOT)
512+
}
513+
514+
pub fn expr_path_hygiene(&self, expr: ExprId) -> HygieneId {
515+
self.expr_hygiene.get(&expr).copied().unwrap_or(HygieneId::ROOT)
516+
}
517+
518+
pub fn pat_path_hygiene(&self, pat: PatId) -> HygieneId {
519+
self.pat_hygiene.get(&pat).copied().unwrap_or(HygieneId::ROOT)
520+
}
521+
522+
pub fn expr_or_pat_path_hygiene(&self, id: ExprOrPatId) -> HygieneId {
523+
match id {
524+
ExprOrPatId::ExprId(id) => self.expr_path_hygiene(id),
525+
ExprOrPatId::PatId(id) => self.pat_path_hygiene(id),
526+
}
527+
}
470528
}
471529

472530
impl Default for Body {
@@ -481,6 +539,9 @@ impl Default for Body {
481539
block_scopes: Default::default(),
482540
binding_owners: Default::default(),
483541
self_param: Default::default(),
542+
binding_hygiene: Default::default(),
543+
expr_hygiene: Default::default(),
544+
pat_hygiene: Default::default(),
484545
}
485546
}
486547
}
@@ -594,13 +655,11 @@ impl BodySourceMap {
594655
pub fn implicit_format_args(
595656
&self,
596657
node: InFile<&ast::FormatArgsExpr>,
597-
) -> Option<&[(syntax::TextRange, Name)]> {
658+
) -> Option<(HygieneId, &[(syntax::TextRange, Name)])> {
598659
let src = node.map(AstPtr::new).map(AstPtr::upcast::<ast::Expr>);
599-
self.template_map
600-
.as_ref()?
601-
.0
602-
.get(&self.expr_map.get(&src)?.as_expr()?)
603-
.map(std::ops::Deref::deref)
660+
let (hygiene, names) =
661+
self.template_map.as_ref()?.0.get(&self.expr_map.get(&src)?.as_expr()?)?;
662+
Some((*hygiene, &**names))
604663
}
605664

606665
pub fn asm_template_args(
@@ -649,13 +708,4 @@ impl BodySourceMap {
649708
diagnostics.shrink_to_fit();
650709
binding_definitions.shrink_to_fit();
651710
}
652-
653-
pub fn template_map(
654-
&self,
655-
) -> Option<&(
656-
FxHashMap<Idx<Expr>, Vec<(tt::TextRange, Name)>>,
657-
FxHashMap<Idx<Expr>, Vec<Vec<(tt::TextRange, usize)>>>,
658-
)> {
659-
self.template_map.as_deref()
660-
}
661711
}

0 commit comments

Comments
 (0)