Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit e36b3f7

Browse files
committed
Proper span representation with syntax context
1 parent 890eb17 commit e36b3f7

File tree

16 files changed

+413
-469
lines changed

16 files changed

+413
-469
lines changed

crates/base-db/src/span.rs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use std::fmt;
22

33
use salsa::InternId;
4+
use tt::SyntaxContext;
45
use vfs::FileId;
56

67
pub type ErasedFileAstId = la_arena::Idx<syntax::SyntaxNodePtr>;
@@ -9,10 +10,17 @@ pub type ErasedFileAstId = la_arena::Idx<syntax::SyntaxNodePtr>;
910
pub const ROOT_ERASED_FILE_AST_ID: ErasedFileAstId =
1011
la_arena::Idx::from_raw(la_arena::RawIdx::from_u32(0));
1112

12-
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
13-
pub struct SyntaxContext;
13+
pub type SpanData = tt::SpanData<SpanAnchor, SyntaxContextId>;
1414

15-
pub type SpanData = tt::SpanData<SpanAnchor>;
15+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
16+
pub struct SyntaxContextId(InternId);
17+
crate::impl_intern_key!(SyntaxContextId);
18+
19+
impl SyntaxContext for SyntaxContextId {
20+
// FIXME: This is very much UB, salsa exposes no way to create an InternId in a const context
21+
// currently (which kind of makes sense but we need it here!)
22+
const DUMMY: Self = SyntaxContextId(unsafe { core::mem::transmute(1) });
23+
}
1624

1725
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
1826
pub struct SpanAnchor {
@@ -26,7 +34,7 @@ impl fmt::Debug for SpanAnchor {
2634
}
2735
}
2836

29-
impl tt::Span for SpanAnchor {
37+
impl tt::SpanAnchor for SpanAnchor {
3038
const DUMMY: Self = SpanAnchor { file_id: HirFileId(0), ast_id: ROOT_ERASED_FILE_AST_ID };
3139
}
3240

crates/cfg/src/tests.rs

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,28 +2,43 @@ use arbitrary::{Arbitrary, Unstructured};
22
use expect_test::{expect, Expect};
33
use mbe::syntax_node_to_token_tree;
44
use syntax::{ast, AstNode};
5-
use tt::Span;
5+
use tt::{SpanAnchor, SyntaxContext};
66

77
use crate::{CfgAtom, CfgExpr, CfgOptions, DnfExpr};
88

99
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
1010
struct DummyFile;
11-
impl Span for DummyFile {
11+
impl SpanAnchor for DummyFile {
1212
const DUMMY: Self = DummyFile;
1313
}
14+
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
15+
struct DummyCtx;
16+
impl SyntaxContext for DummyCtx {
17+
const DUMMY: Self = DummyCtx;
18+
}
1419

1520
fn assert_parse_result(input: &str, expected: CfgExpr) {
1621
let source_file = ast::SourceFile::parse(input).ok().unwrap();
1722
let tt = source_file.syntax().descendants().find_map(ast::TokenTree::cast).unwrap();
18-
let tt = syntax_node_to_token_tree(tt.syntax(), DummyFile, 0.into(), &Default::default());
23+
let tt = syntax_node_to_token_tree::<_, DummyCtx>(
24+
tt.syntax(),
25+
DummyFile,
26+
0.into(),
27+
&Default::default(),
28+
);
1929
let cfg = CfgExpr::parse(&tt);
2030
assert_eq!(cfg, expected);
2131
}
2232

2333
fn check_dnf(input: &str, expect: Expect) {
2434
let source_file = ast::SourceFile::parse(input).ok().unwrap();
2535
let tt = source_file.syntax().descendants().find_map(ast::TokenTree::cast).unwrap();
26-
let tt = syntax_node_to_token_tree(tt.syntax(), DummyFile, 0.into(), &Default::default());
36+
let tt = syntax_node_to_token_tree::<_, DummyCtx>(
37+
tt.syntax(),
38+
DummyFile,
39+
0.into(),
40+
&Default::default(),
41+
);
2742
let cfg = CfgExpr::parse(&tt);
2843
let actual = format!("#![cfg({})]", DnfExpr::new(cfg));
2944
expect.assert_eq(&actual);
@@ -32,7 +47,12 @@ fn check_dnf(input: &str, expect: Expect) {
3247
fn check_why_inactive(input: &str, opts: &CfgOptions, expect: Expect) {
3348
let source_file = ast::SourceFile::parse(input).ok().unwrap();
3449
let tt = source_file.syntax().descendants().find_map(ast::TokenTree::cast).unwrap();
35-
let tt = syntax_node_to_token_tree(tt.syntax(), DummyFile, 0.into(), &Default::default());
50+
let tt = syntax_node_to_token_tree::<_, DummyCtx>(
51+
tt.syntax(),
52+
DummyFile,
53+
0.into(),
54+
&Default::default(),
55+
);
3656
let cfg = CfgExpr::parse(&tt);
3757
let dnf = DnfExpr::new(cfg);
3858
let why_inactive = dnf.why_inactive(opts).unwrap().to_string();
@@ -43,7 +63,12 @@ fn check_why_inactive(input: &str, opts: &CfgOptions, expect: Expect) {
4363
fn check_enable_hints(input: &str, opts: &CfgOptions, expected_hints: &[&str]) {
4464
let source_file = ast::SourceFile::parse(input).ok().unwrap();
4565
let tt = source_file.syntax().descendants().find_map(ast::TokenTree::cast).unwrap();
46-
let tt = syntax_node_to_token_tree(tt.syntax(), DummyFile, 0.into(), &Default::default());
66+
let tt = syntax_node_to_token_tree::<_, DummyCtx>(
67+
tt.syntax(),
68+
DummyFile,
69+
0.into(),
70+
&Default::default(),
71+
);
4772
let cfg = CfgExpr::parse(&tt);
4873
let dnf = DnfExpr::new(cfg);
4974
let hints = dnf.compute_enable_hints(opts).map(|diff| diff.to_string()).collect::<Vec<_>>();

crates/hir-def/src/attr/tests.rs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,25 @@
44
use base_db::span::SpanAnchor;
55
use mbe::syntax_node_to_token_tree;
66
use syntax::{ast, AstNode};
7-
use tt::Span;
7+
use tt::{SpanAnchor as _, SyntaxContext};
88

99
use crate::attr::{DocAtom, DocExpr};
1010

11+
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
12+
struct DummyCtx;
13+
impl SyntaxContext for DummyCtx {
14+
const DUMMY: Self = DummyCtx;
15+
}
16+
1117
fn assert_parse_result(input: &str, expected: DocExpr) {
1218
let source_file = ast::SourceFile::parse(input).ok().unwrap();
1319
let tt = source_file.syntax().descendants().find_map(ast::TokenTree::cast).unwrap();
14-
let tt =
15-
syntax_node_to_token_tree(tt.syntax(), SpanAnchor::DUMMY, 0.into(), &Default::default());
20+
let tt = syntax_node_to_token_tree::<_, DummyCtx>(
21+
tt.syntax(),
22+
SpanAnchor::DUMMY,
23+
0.into(),
24+
&Default::default(),
25+
);
1626
let cfg = DocExpr::parse(&tt);
1727
assert_eq!(cfg, expected);
1828
}

crates/hir-expand/src/attrs.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! A higher level attributes based on TokenTree, with also some shortcuts.
22
use std::{fmt, ops};
33

4-
use ::tt::Span;
4+
use ::tt::SpanAnchor as _;
55
use base_db::{span::SpanAnchor, CrateId};
66
use cfg::CfgExpr;
77
use either::Either;

crates/hir-expand/src/builtin_fn_macro.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
//! Builtin macro
22
3+
use ::tt::Span;
34
use base_db::{
45
span::{SpanAnchor, ROOT_ERASED_FILE_AST_ID},
56
AnchoredPath, Edition, FileId,
@@ -15,7 +16,7 @@ use syntax::{
1516
use crate::{
1617
db::ExpandDatabase,
1718
name, quote,
18-
tt::{self, Span},
19+
tt::{self},
1920
EagerCallInfo, ExpandError, ExpandResult, HirFileIdExt, MacroCallId, MacroCallLoc,
2021
};
2122

crates/hir-expand/src/db.rs

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
//! Defines database & queries for macro expansion.
22
3+
use ::tt::SyntaxContext;
34
use base_db::{
45
salsa,
5-
span::{SpanAnchor, ROOT_ERASED_FILE_AST_ID},
6+
span::{SpanAnchor, SyntaxContextId, ROOT_ERASED_FILE_AST_ID},
67
CrateId, Edition, SourceDatabase,
78
};
89
use either::Either;
@@ -15,11 +16,13 @@ use syntax::{
1516
use triomphe::Arc;
1617

1718
use crate::{
18-
ast_id_map::AstIdMap, builtin_attr_macro::pseudo_derive_attr_expansion,
19-
builtin_fn_macro::EagerExpander, hygiene::HygieneFrame, tt, AstId, BuiltinAttrExpander,
20-
BuiltinDeriveExpander, BuiltinFnLikeExpander, EagerCallInfo, ExpandError, ExpandResult,
21-
ExpandTo, HirFileId, HirFileIdRepr, MacroCallId, MacroCallKind, MacroCallLoc, MacroDefId,
22-
MacroDefKind, MacroFile, ProcMacroExpander, SpanMap, SyntaxContext, SyntaxContextId,
19+
ast_id_map::AstIdMap,
20+
builtin_attr_macro::pseudo_derive_attr_expansion,
21+
builtin_fn_macro::EagerExpander,
22+
hygiene::{self, HygieneFrame, SyntaxContextData},
23+
tt, AstId, BuiltinAttrExpander, BuiltinDeriveExpander, BuiltinFnLikeExpander, EagerCallInfo,
24+
ExpandError, ExpandResult, ExpandTo, HirFileId, HirFileIdRepr, MacroCallId, MacroCallKind,
25+
MacroCallLoc, MacroDefId, MacroDefKind, MacroFile, ProcMacroExpander, SpanMap,
2326
};
2427

2528
/// Total limit on the number of tokens produced by any macro invocation.
@@ -89,7 +92,15 @@ pub trait ExpandDatabase: SourceDatabase {
8992
#[salsa::interned]
9093
fn intern_macro_call(&self, macro_call: MacroCallLoc) -> MacroCallId;
9194
#[salsa::interned]
92-
fn intern_syntax_context(&self, ctx: SyntaxContext) -> SyntaxContextId;
95+
fn intern_syntax_context(&self, ctx: SyntaxContextData) -> SyntaxContextId;
96+
#[salsa::transparent]
97+
#[salsa::invoke(hygiene::apply_mark)]
98+
fn apply_mark(
99+
&self,
100+
ctxt: SyntaxContextData,
101+
file_id: HirFileId,
102+
transparency: hygiene::Transparency,
103+
) -> SyntaxContextId;
93104

94105
/// Lowers syntactic macro call to a token tree representation. That's a firewall
95106
/// query, only typing in the macro call itself changes the returned
@@ -225,6 +236,7 @@ pub fn expand_speculative(
225236
.ranges_with_span(tt::SpanData {
226237
range: token_to_map.text_range(),
227238
anchor: SpanAnchor { file_id, ast_id: ROOT_ERASED_FILE_AST_ID },
239+
ctx: SyntaxContextId::DUMMY,
228240
})
229241
.filter_map(|range| syntax_node.covering_element(range).into_token())
230242
.min_by_key(|t| {

0 commit comments

Comments
 (0)