diff options
author | Aleksey Kladov <[email protected]> | 2021-05-04 20:03:16 +0100 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2021-05-04 20:41:43 +0100 |
commit | 95dc8ef265183a624593a5ef49df31e53daf160e (patch) | |
tree | 33300902005a3496602849a72fecfc350f61a2ed /crates | |
parent | 7d9ea39de6d59fe59e628ef72983315e944412dc (diff) |
make illegal states unrepresentable
only declarative macros have def-site token map
Diffstat (limited to 'crates')
-rw-r--r-- | crates/hir_expand/src/db.rs | 60 | ||||
-rw-r--r-- | crates/hir_expand/src/hygiene.rs | 16 | ||||
-rw-r--r-- | crates/hir_expand/src/lib.rs | 21 |
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)] |
29 | pub enum TokenExpander { | 29 | pub 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 | ||
265 | fn macro_def(db: &dyn AstDatabase, id: MacroDefId) -> Option<Arc<(TokenExpander, mbe::TokenMap)>> { | 265 | fn 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 | ||
316 | fn expander(db: &dyn AstDatabase, id: MacroCallId) -> Option<Arc<(TokenExpander, mbe::TokenMap)>> { | 312 | fn 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, ¯o_arg.0); | 358 | let ExpandResult { value: tt, err } = macro_rules.expand(db, lazy_id, ¯o_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 @@ | |||
5 | use std::sync::Arc; | 5 | use std::sync::Arc; |
6 | 6 | ||
7 | use base_db::CrateId; | 7 | use base_db::CrateId; |
8 | use db::TokenExpander; | ||
8 | use either::Either; | 9 | use either::Either; |
9 | use mbe::Origin; | 10 | use mbe::Origin; |
10 | use parser::SyntaxKind; | 11 | use 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())?; |