aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_expand
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2021-05-04 20:03:16 +0100
committerAleksey Kladov <[email protected]>2021-05-04 20:41:43 +0100
commit95dc8ef265183a624593a5ef49df31e53daf160e (patch)
tree33300902005a3496602849a72fecfc350f61a2ed /crates/hir_expand
parent7d9ea39de6d59fe59e628ef72983315e944412dc (diff)
make illegal states unrepresentable
only declarative macros have def-site token map
Diffstat (limited to 'crates/hir_expand')
-rw-r--r--crates/hir_expand/src/db.rs60
-rw-r--r--crates/hir_expand/src/hygiene.rs16
-rw-r--r--crates/hir_expand/src/lib.rs21
3 files changed, 48 insertions, 49 deletions
diff --git a/crates/hir_expand/src/db.rs b/crates/hir_expand/src/db.rs
index 5ea41ba78..935c547b0 100644
--- a/crates/hir_expand/src/db.rs
+++ b/crates/hir_expand/src/db.rs
@@ -28,9 +28,9 @@ const TOKEN_LIMIT: usize = 524288;
28#[derive(Debug, Clone, Eq, PartialEq)] 28#[derive(Debug, Clone, Eq, PartialEq)]
29pub enum TokenExpander { 29pub enum TokenExpander {
30 /// Old-style `macro_rules`. 30 /// Old-style `macro_rules`.
31 MacroRules(mbe::MacroRules), 31 MacroRules { mac: mbe::MacroRules, def_site_token_map: mbe::TokenMap },
32 /// AKA macros 2.0. 32 /// AKA macros 2.0.
33 MacroDef(mbe::MacroDef), 33 MacroDef { mac: mbe::MacroDef, def_site_token_map: mbe::TokenMap },
34 /// Stuff like `line!` and `file!`. 34 /// Stuff like `line!` and `file!`.
35 Builtin(BuiltinFnLikeExpander), 35 Builtin(BuiltinFnLikeExpander),
36 /// `derive(Copy)` and such. 36 /// `derive(Copy)` and such.
@@ -47,8 +47,8 @@ impl TokenExpander {
47 tt: &tt::Subtree, 47 tt: &tt::Subtree,
48 ) -> mbe::ExpandResult<tt::Subtree> { 48 ) -> mbe::ExpandResult<tt::Subtree> {
49 match self { 49 match self {
50 TokenExpander::MacroRules(it) => it.expand(tt), 50 TokenExpander::MacroRules { mac, .. } => mac.expand(tt),
51 TokenExpander::MacroDef(it) => it.expand(tt), 51 TokenExpander::MacroDef { mac, .. } => mac.expand(tt),
52 TokenExpander::Builtin(it) => it.expand(db, id, tt), 52 TokenExpander::Builtin(it) => it.expand(db, id, tt),
53 // FIXME switch these to ExpandResult as well 53 // FIXME switch these to ExpandResult as well
54 TokenExpander::BuiltinDerive(it) => it.expand(db, id, tt).into(), 54 TokenExpander::BuiltinDerive(it) => it.expand(db, id, tt).into(),
@@ -63,21 +63,21 @@ impl TokenExpander {
63 63
64 pub(crate) fn map_id_down(&self, id: tt::TokenId) -> tt::TokenId { 64 pub(crate) fn map_id_down(&self, id: tt::TokenId) -> tt::TokenId {
65 match self { 65 match self {
66 TokenExpander::MacroRules(it) => it.map_id_down(id), 66 TokenExpander::MacroRules { mac, .. } => mac.map_id_down(id),
67 TokenExpander::MacroDef(it) => it.map_id_down(id), 67 TokenExpander::MacroDef { mac, .. } => mac.map_id_down(id),
68 TokenExpander::Builtin(..) => id, 68 TokenExpander::Builtin(..)
69 TokenExpander::BuiltinDerive(..) => id, 69 | TokenExpander::BuiltinDerive(..)
70 TokenExpander::ProcMacro(..) => id, 70 | TokenExpander::ProcMacro(..) => id,
71 } 71 }
72 } 72 }
73 73
74 pub(crate) fn map_id_up(&self, id: tt::TokenId) -> (tt::TokenId, mbe::Origin) { 74 pub(crate) fn map_id_up(&self, id: tt::TokenId) -> (tt::TokenId, mbe::Origin) {
75 match self { 75 match self {
76 TokenExpander::MacroRules(it) => it.map_id_up(id), 76 TokenExpander::MacroRules { mac, .. } => mac.map_id_up(id),
77 TokenExpander::MacroDef(it) => it.map_id_up(id), 77 TokenExpander::MacroDef { mac, .. } => mac.map_id_up(id),
78 TokenExpander::Builtin(..) => (id, mbe::Origin::Call), 78 TokenExpander::Builtin(..)
79 TokenExpander::BuiltinDerive(..) => (id, mbe::Origin::Call), 79 | TokenExpander::BuiltinDerive(..)
80 TokenExpander::ProcMacro(..) => (id, mbe::Origin::Call), 80 | TokenExpander::ProcMacro(..) => (id, mbe::Origin::Call),
81 } 81 }
82 } 82 }
83} 83}
@@ -102,7 +102,7 @@ pub trait AstDatabase: SourceDatabase {
102 #[salsa::transparent] 102 #[salsa::transparent]
103 fn macro_arg(&self, id: MacroCallId) -> Option<Arc<(tt::Subtree, mbe::TokenMap)>>; 103 fn macro_arg(&self, id: MacroCallId) -> Option<Arc<(tt::Subtree, mbe::TokenMap)>>;
104 fn macro_arg_text(&self, id: MacroCallId) -> Option<GreenNode>; 104 fn macro_arg_text(&self, id: MacroCallId) -> Option<GreenNode>;
105 fn macro_def(&self, id: MacroDefId) -> Option<Arc<(TokenExpander, mbe::TokenMap)>>; 105 fn macro_def(&self, id: MacroDefId) -> Option<Arc<TokenExpander>>;
106 106
107 fn macro_expand(&self, macro_call: MacroCallId) -> ExpandResult<Option<Arc<tt::Subtree>>>; 107 fn macro_expand(&self, macro_call: MacroCallId) -> ExpandResult<Option<Arc<tt::Subtree>>>;
108 fn expand_proc_macro(&self, call: MacroCallId) -> Result<tt::Subtree, mbe::ExpandError>; 108 fn expand_proc_macro(&self, call: MacroCallId) -> Result<tt::Subtree, mbe::ExpandError>;
@@ -133,7 +133,7 @@ pub fn expand_hypothetical(
133 macro_expand_with_arg(db, macro_file.macro_call_id, Some(Arc::new((tt, tmap_1)))); 133 macro_expand_with_arg(db, macro_file.macro_call_id, Some(Arc::new((tt, tmap_1))));
134 let (node, tmap_2) = expansion_to_syntax(db, macro_file, hypothetical_expansion).value?; 134 let (node, tmap_2) = expansion_to_syntax(db, macro_file, hypothetical_expansion).value?;
135 135
136 let token_id = macro_def.0.map_id_down(token_id); 136 let token_id = macro_def.map_id_down(token_id);
137 let range = tmap_2.range_by_token(token_id)?.by_kind(token_to_map.kind())?; 137 let range = tmap_2.range_by_token(token_id)?.by_kind(token_to_map.kind())?;
138 let token = node.syntax_node().covering_element(range).into_token()?; 138 let token = node.syntax_node().covering_element(range).into_token()?;
139 Some((node.syntax_node(), token)) 139 Some((node.syntax_node(), token))
@@ -262,13 +262,13 @@ fn macro_arg_text(db: &dyn AstDatabase, id: MacroCallId) -> Option<GreenNode> {
262 Some(arg.green()) 262 Some(arg.green())
263} 263}
264 264
265fn macro_def(db: &dyn AstDatabase, id: MacroDefId) -> Option<Arc<(TokenExpander, mbe::TokenMap)>> { 265fn macro_def(db: &dyn AstDatabase, id: MacroDefId) -> Option<Arc<TokenExpander>> {
266 match id.kind { 266 match id.kind {
267 MacroDefKind::Declarative(ast_id) => match ast_id.to_node(db) { 267 MacroDefKind::Declarative(ast_id) => match ast_id.to_node(db) {
268 ast::Macro::MacroRules(macro_rules) => { 268 ast::Macro::MacroRules(macro_rules) => {
269 let arg = macro_rules.token_tree()?; 269 let arg = macro_rules.token_tree()?;
270 let (tt, tmap) = mbe::ast_to_token_tree(&arg); 270 let (tt, def_site_token_map) = mbe::ast_to_token_tree(&arg);
271 let rules = match mbe::MacroRules::parse(&tt) { 271 let mac = match mbe::MacroRules::parse(&tt) {
272 Ok(it) => it, 272 Ok(it) => it,
273 Err(err) => { 273 Err(err) => {
274 let name = macro_rules.name().map(|n| n.to_string()).unwrap_or_default(); 274 let name = macro_rules.name().map(|n| n.to_string()).unwrap_or_default();
@@ -276,12 +276,12 @@ fn macro_def(db: &dyn AstDatabase, id: MacroDefId) -> Option<Arc<(TokenExpander,
276 return None; 276 return None;
277 } 277 }
278 }; 278 };
279 Some(Arc::new((TokenExpander::MacroRules(rules), tmap))) 279 Some(Arc::new(TokenExpander::MacroRules { mac, def_site_token_map }))
280 } 280 }
281 ast::Macro::MacroDef(macro_def) => { 281 ast::Macro::MacroDef(macro_def) => {
282 let arg = macro_def.body()?; 282 let arg = macro_def.body()?;
283 let (tt, tmap) = mbe::ast_to_token_tree(&arg); 283 let (tt, def_site_token_map) = mbe::ast_to_token_tree(&arg);
284 let rules = match mbe::MacroDef::parse(&tt) { 284 let mac = match mbe::MacroDef::parse(&tt) {
285 Ok(it) => it, 285 Ok(it) => it,
286 Err(err) => { 286 Err(err) => {
287 let name = macro_def.name().map(|n| n.to_string()).unwrap_or_default(); 287 let name = macro_def.name().map(|n| n.to_string()).unwrap_or_default();
@@ -289,19 +289,15 @@ fn macro_def(db: &dyn AstDatabase, id: MacroDefId) -> Option<Arc<(TokenExpander,
289 return None; 289 return None;
290 } 290 }
291 }; 291 };
292 Some(Arc::new((TokenExpander::MacroDef(rules), tmap))) 292 Some(Arc::new(TokenExpander::MacroDef { mac, def_site_token_map }))
293 } 293 }
294 }, 294 },
295 MacroDefKind::BuiltIn(expander, _) => { 295 MacroDefKind::BuiltIn(expander, _) => Some(Arc::new(TokenExpander::Builtin(expander))),
296 Some(Arc::new((TokenExpander::Builtin(expander), mbe::TokenMap::default())))
297 }
298 MacroDefKind::BuiltInDerive(expander, _) => { 296 MacroDefKind::BuiltInDerive(expander, _) => {
299 Some(Arc::new((TokenExpander::BuiltinDerive(expander), mbe::TokenMap::default()))) 297 Some(Arc::new(TokenExpander::BuiltinDerive(expander)))
300 } 298 }
301 MacroDefKind::BuiltInEager(..) => None, 299 MacroDefKind::BuiltInEager(..) => None,
302 MacroDefKind::ProcMacro(expander, ..) => { 300 MacroDefKind::ProcMacro(expander, ..) => Some(Arc::new(TokenExpander::ProcMacro(expander))),
303 Some(Arc::new((TokenExpander::ProcMacro(expander), mbe::TokenMap::default())))
304 }
305 } 301 }
306} 302}
307 303
@@ -313,7 +309,7 @@ fn macro_expand_error(db: &dyn AstDatabase, macro_call: MacroCallId) -> Option<E
313 db.macro_expand(macro_call).err 309 db.macro_expand(macro_call).err
314} 310}
315 311
316fn expander(db: &dyn AstDatabase, id: MacroCallId) -> Option<Arc<(TokenExpander, mbe::TokenMap)>> { 312fn expander(db: &dyn AstDatabase, id: MacroCallId) -> Option<Arc<TokenExpander>> {
317 let lazy_id = match id { 313 let lazy_id = match id {
318 MacroCallId::LazyMacro(id) => id, 314 MacroCallId::LazyMacro(id) => id,
319 MacroCallId::EagerMacro(_id) => { 315 MacroCallId::EagerMacro(_id) => {
@@ -359,7 +355,7 @@ fn macro_expand_with_arg(
359 Some(it) => it, 355 Some(it) => it,
360 None => return ExpandResult::str_err("Fail to find macro definition".into()), 356 None => return ExpandResult::str_err("Fail to find macro definition".into()),
361 }; 357 };
362 let ExpandResult { value: tt, err } = macro_rules.0.expand(db, lazy_id, &macro_arg.0); 358 let ExpandResult { value: tt, err } = macro_rules.expand(db, lazy_id, &macro_arg.0);
363 // Set a hard limit for the expanded tt 359 // Set a hard limit for the expanded tt
364 let count = tt.count(); 360 let count = tt.count();
365 if count > TOKEN_LIMIT { 361 if count > TOKEN_LIMIT {
diff --git a/crates/hir_expand/src/hygiene.rs b/crates/hir_expand/src/hygiene.rs
index 779725629..ed61ebca3 100644
--- a/crates/hir_expand/src/hygiene.rs
+++ b/crates/hir_expand/src/hygiene.rs
@@ -5,6 +5,7 @@
5use std::sync::Arc; 5use std::sync::Arc;
6 6
7use base_db::CrateId; 7use base_db::CrateId;
8use db::TokenExpander;
8use either::Either; 9use either::Either;
9use mbe::Origin; 10use mbe::Origin;
10use parser::SyntaxKind; 11use parser::SyntaxKind;
@@ -115,7 +116,7 @@ struct HygieneInfo {
115 /// The `macro_rules!` arguments. 116 /// The `macro_rules!` arguments.
116 def_start: Option<InFile<TextSize>>, 117 def_start: Option<InFile<TextSize>>,
117 118
118 macro_def: Arc<(db::TokenExpander, mbe::TokenMap)>, 119 macro_def: Arc<TokenExpander>,
119 macro_arg: Arc<(tt::Subtree, mbe::TokenMap)>, 120 macro_arg: Arc<(tt::Subtree, mbe::TokenMap)>,
120 exp_map: Arc<mbe::TokenMap>, 121 exp_map: Arc<mbe::TokenMap>,
121} 122}
@@ -124,13 +125,16 @@ impl HygieneInfo {
124 fn map_ident_up(&self, token: TextRange) -> Option<(InFile<TextRange>, Origin)> { 125 fn map_ident_up(&self, token: TextRange) -> Option<(InFile<TextRange>, Origin)> {
125 let token_id = self.exp_map.token_by_range(token)?; 126 let token_id = self.exp_map.token_by_range(token)?;
126 127
127 let (token_id, origin) = self.macro_def.0.map_id_up(token_id); 128 let (token_id, origin) = self.macro_def.map_id_up(token_id);
128 let (token_map, tt) = match origin { 129 let (token_map, tt) = match origin {
129 mbe::Origin::Call => (&self.macro_arg.1, self.arg_start), 130 mbe::Origin::Call => (&self.macro_arg.1, self.arg_start),
130 mbe::Origin::Def => ( 131 mbe::Origin::Def => match (&*self.macro_def, self.def_start) {
131 &self.macro_def.1, 132 (TokenExpander::MacroDef { def_site_token_map, .. }, Some(tt))
132 *self.def_start.as_ref().expect("`Origin::Def` used with non-`macro_rules!` macro"), 133 | (TokenExpander::MacroRules { def_site_token_map, .. }, Some(tt)) => {
133 ), 134 (def_site_token_map, tt)
135 }
136 _ => panic!("`Origin::Def` used with non-`macro_rules!` macro"),
137 },
134 }; 138 };
135 139
136 let range = token_map.range_by_token(token_id)?.by_kind(SyntaxKind::IDENT)?; 140 let range = token_map.range_by_token(token_id)?.by_kind(SyntaxKind::IDENT)?;
diff --git a/crates/hir_expand/src/lib.rs b/crates/hir_expand/src/lib.rs
index a0e6aec62..0402640de 100644
--- a/crates/hir_expand/src/lib.rs
+++ b/crates/hir_expand/src/lib.rs
@@ -351,7 +351,7 @@ pub struct ExpansionInfo {
351 /// The `macro_rules!` arguments. 351 /// The `macro_rules!` arguments.
352 def: Option<InFile<ast::TokenTree>>, 352 def: Option<InFile<ast::TokenTree>>,
353 353
354 macro_def: Arc<(db::TokenExpander, mbe::TokenMap)>, 354 macro_def: Arc<db::TokenExpander>,
355 macro_arg: Arc<(tt::Subtree, mbe::TokenMap)>, 355 macro_arg: Arc<(tt::Subtree, mbe::TokenMap)>,
356 exp_map: Arc<mbe::TokenMap>, 356 exp_map: Arc<mbe::TokenMap>,
357} 357}
@@ -368,7 +368,7 @@ impl ExpansionInfo {
368 assert_eq!(token.file_id, self.arg.file_id); 368 assert_eq!(token.file_id, self.arg.file_id);
369 let range = token.value.text_range().checked_sub(self.arg.value.text_range().start())?; 369 let range = token.value.text_range().checked_sub(self.arg.value.text_range().start())?;
370 let token_id = self.macro_arg.1.token_by_range(range)?; 370 let token_id = self.macro_arg.1.token_by_range(range)?;
371 let token_id = self.macro_def.0.map_id_down(token_id); 371 let token_id = self.macro_def.map_id_down(token_id);
372 372
373 let range = self.exp_map.range_by_token(token_id)?.by_kind(token.value.kind())?; 373 let range = self.exp_map.range_by_token(token_id)?.by_kind(token.value.kind())?;
374 374
@@ -383,17 +383,16 @@ impl ExpansionInfo {
383 ) -> Option<(InFile<SyntaxToken>, Origin)> { 383 ) -> Option<(InFile<SyntaxToken>, Origin)> {
384 let token_id = self.exp_map.token_by_range(token.value.text_range())?; 384 let token_id = self.exp_map.token_by_range(token.value.text_range())?;
385 385
386 let (token_id, origin) = self.macro_def.0.map_id_up(token_id); 386 let (token_id, origin) = self.macro_def.map_id_up(token_id);
387 let (token_map, tt) = match origin { 387 let (token_map, tt) = match origin {
388 mbe::Origin::Call => (&self.macro_arg.1, self.arg.clone()), 388 mbe::Origin::Call => (&self.macro_arg.1, self.arg.clone()),
389 mbe::Origin::Def => ( 389 mbe::Origin::Def => match (&*self.macro_def, self.def.as_ref()) {
390 &self.macro_def.1, 390 (db::TokenExpander::MacroRules { def_site_token_map, .. }, Some(tt))
391 self.def 391 | (db::TokenExpander::MacroDef { def_site_token_map, .. }, Some(tt)) => {
392 .as_ref() 392 (def_site_token_map, tt.as_ref().map(|tt| tt.syntax().clone()))
393 .expect("`Origin::Def` used with non-`macro_rules!` macro") 393 }
394 .as_ref() 394 _ => panic!("`Origin::Def` used with non-`macro_rules!` macro"),
395 .map(|tt| tt.syntax().clone()), 395 },
396 ),
397 }; 396 };
398 397
399 let range = token_map.range_by_token(token_id)?.by_kind(token.value.kind())?; 398 let range = token_map.range_by_token(token_id)?.by_kind(token.value.kind())?;