diff options
-rw-r--r-- | crates/hir_def/src/nameres/collector.rs | 12 | ||||
-rw-r--r-- | crates/hir_expand/src/builtin_macro.rs | 25 | ||||
-rw-r--r-- | crates/hir_expand/src/name.rs | 2 | ||||
-rw-r--r-- | crates/hir_expand/src/quote.rs | 1 | ||||
-rw-r--r-- | crates/mbe/src/lib.rs | 6 | ||||
-rw-r--r-- | crates/mbe/src/tests/expand.rs | 15 | ||||
-rw-r--r-- | crates/mbe/src/tt_iter.rs | 11 |
7 files changed, 67 insertions, 5 deletions
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs index 6f946a6dd..c8f494707 100644 --- a/crates/hir_def/src/nameres/collector.rs +++ b/crates/hir_def/src/nameres/collector.rs | |||
@@ -1402,8 +1402,18 @@ impl ModCollector<'_, '_> { | |||
1402 | 1402 | ||
1403 | // Case 1: builtin macros | 1403 | // Case 1: builtin macros |
1404 | if attrs.by_key("rustc_builtin_macro").exists() { | 1404 | if attrs.by_key("rustc_builtin_macro").exists() { |
1405 | // `#[rustc_builtin_macro = "builtin_name"]` overrides the `macro_rules!` name. | ||
1406 | let name; | ||
1407 | let name = match attrs.by_key("rustc_builtin_macro").string_value() { | ||
1408 | Some(it) => { | ||
1409 | // FIXME: a hacky way to create a Name from string. | ||
1410 | name = tt::Ident { text: it.clone(), id: tt::TokenId::unspecified() }.as_name(); | ||
1411 | &name | ||
1412 | } | ||
1413 | None => &mac.name, | ||
1414 | }; | ||
1405 | let krate = self.def_collector.def_map.krate; | 1415 | let krate = self.def_collector.def_map.krate; |
1406 | if let Some(macro_id) = find_builtin_macro(&mac.name, krate, ast_id) { | 1416 | if let Some(macro_id) = find_builtin_macro(name, krate, ast_id) { |
1407 | self.def_collector.define_macro_rules( | 1417 | self.def_collector.define_macro_rules( |
1408 | self.module_id, | 1418 | self.module_id, |
1409 | mac.name.clone(), | 1419 | mac.name.clone(), |
diff --git a/crates/hir_expand/src/builtin_macro.rs b/crates/hir_expand/src/builtin_macro.rs index 4d52904b9..3aa3d8997 100644 --- a/crates/hir_expand/src/builtin_macro.rs +++ b/crates/hir_expand/src/builtin_macro.rs | |||
@@ -1,10 +1,10 @@ | |||
1 | //! Builtin macro | 1 | //! Builtin macro |
2 | use crate::{ | 2 | use crate::{ |
3 | db::AstDatabase, name, quote, AstId, CrateId, EagerMacroId, LazyMacroId, MacroCallId, | 3 | db::AstDatabase, name, quote, AstId, CrateId, EagerMacroId, LazyMacroId, MacroCallId, |
4 | MacroDefId, MacroDefKind, TextSize, | 4 | MacroCallLoc, MacroDefId, MacroDefKind, TextSize, |
5 | }; | 5 | }; |
6 | 6 | ||
7 | use base_db::{AnchoredPath, FileId}; | 7 | use base_db::{AnchoredPath, Edition, FileId}; |
8 | use cfg::CfgExpr; | 8 | use cfg::CfgExpr; |
9 | use either::Either; | 9 | use either::Either; |
10 | use mbe::{parse_exprs_with_sep, parse_to_token_tree, ExpandResult}; | 10 | use mbe::{parse_exprs_with_sep, parse_to_token_tree, ExpandResult}; |
@@ -111,6 +111,8 @@ register_builtin! { | |||
111 | (llvm_asm, LlvmAsm) => asm_expand, | 111 | (llvm_asm, LlvmAsm) => asm_expand, |
112 | (asm, Asm) => asm_expand, | 112 | (asm, Asm) => asm_expand, |
113 | (cfg, Cfg) => cfg_expand, | 113 | (cfg, Cfg) => cfg_expand, |
114 | (core_panic, CorePanic) => panic_expand, | ||
115 | (std_panic, StdPanic) => panic_expand, | ||
114 | 116 | ||
115 | EAGER: | 117 | EAGER: |
116 | (compile_error, CompileError) => compile_error_expand, | 118 | (compile_error, CompileError) => compile_error_expand, |
@@ -284,6 +286,25 @@ fn cfg_expand( | |||
284 | ExpandResult::ok(expanded) | 286 | ExpandResult::ok(expanded) |
285 | } | 287 | } |
286 | 288 | ||
289 | fn panic_expand( | ||
290 | db: &dyn AstDatabase, | ||
291 | id: LazyMacroId, | ||
292 | tt: &tt::Subtree, | ||
293 | ) -> ExpandResult<tt::Subtree> { | ||
294 | let loc: MacroCallLoc = db.lookup_intern_macro(id); | ||
295 | // Expand to a macro call `$crate::panic::panic_{edition}` | ||
296 | let krate = tt::Ident { text: "$crate".into(), id: tt::TokenId::unspecified() }; | ||
297 | let mut call = if db.crate_graph()[loc.krate].edition == Edition::Edition2021 { | ||
298 | quote!(#krate::panic::panic_2021!) | ||
299 | } else { | ||
300 | quote!(#krate::panic::panic_2015!) | ||
301 | }; | ||
302 | |||
303 | // Pass the original arguments | ||
304 | call.token_trees.push(tt::TokenTree::Subtree(tt.clone())); | ||
305 | ExpandResult::ok(call) | ||
306 | } | ||
307 | |||
287 | fn unquote_str(lit: &tt::Literal) -> Option<String> { | 308 | fn unquote_str(lit: &tt::Literal) -> Option<String> { |
288 | let lit = ast::make::tokens::literal(&lit.to_string()); | 309 | let lit = ast::make::tokens::literal(&lit.to_string()); |
289 | let token = ast::String::cast(lit)?; | 310 | let token = ast::String::cast(lit)?; |
diff --git a/crates/hir_expand/src/name.rs b/crates/hir_expand/src/name.rs index 203ebbe85..a0f8766b0 100644 --- a/crates/hir_expand/src/name.rs +++ b/crates/hir_expand/src/name.rs | |||
@@ -208,6 +208,8 @@ pub mod known { | |||
208 | line, | 208 | line, |
209 | module_path, | 209 | module_path, |
210 | assert, | 210 | assert, |
211 | core_panic, | ||
212 | std_panic, | ||
211 | stringify, | 213 | stringify, |
212 | concat, | 214 | concat, |
213 | include, | 215 | include, |
diff --git a/crates/hir_expand/src/quote.rs b/crates/hir_expand/src/quote.rs index 08bc5aa49..c82487ef0 100644 --- a/crates/hir_expand/src/quote.rs +++ b/crates/hir_expand/src/quote.rs | |||
@@ -104,6 +104,7 @@ macro_rules! __quote { | |||
104 | ( . ) => {$crate::__quote!(@PUNCT '.')}; | 104 | ( . ) => {$crate::__quote!(@PUNCT '.')}; |
105 | ( < ) => {$crate::__quote!(@PUNCT '<')}; | 105 | ( < ) => {$crate::__quote!(@PUNCT '<')}; |
106 | ( > ) => {$crate::__quote!(@PUNCT '>')}; | 106 | ( > ) => {$crate::__quote!(@PUNCT '>')}; |
107 | ( ! ) => {$crate::__quote!(@PUNCT '!')}; | ||
107 | 108 | ||
108 | ( $first:tt $($tail:tt)+ ) => { | 109 | ( $first:tt $($tail:tt)+ ) => { |
109 | { | 110 | { |
diff --git a/crates/mbe/src/lib.rs b/crates/mbe/src/lib.rs index e74f8cf3f..3af5bc18b 100644 --- a/crates/mbe/src/lib.rs +++ b/crates/mbe/src/lib.rs | |||
@@ -220,9 +220,11 @@ impl MacroDef { | |||
220 | while src.len() > 0 { | 220 | while src.len() > 0 { |
221 | let rule = Rule::parse(&mut src, true)?; | 221 | let rule = Rule::parse(&mut src, true)?; |
222 | rules.push(rule); | 222 | rules.push(rule); |
223 | if let Err(()) = src.expect_char(';') { | 223 | if let Err(()) = src.expect_any_char(&[';', ',']) { |
224 | if src.len() > 0 { | 224 | if src.len() > 0 { |
225 | return Err(ParseError::Expected("expected `;`".to_string())); | 225 | return Err(ParseError::Expected( |
226 | "expected `;` or `,` to delimit rules".to_string(), | ||
227 | )); | ||
226 | } | 228 | } |
227 | break; | 229 | break; |
228 | } | 230 | } |
diff --git a/crates/mbe/src/tests/expand.rs b/crates/mbe/src/tests/expand.rs index 8951f3813..e02d038b6 100644 --- a/crates/mbe/src/tests/expand.rs +++ b/crates/mbe/src/tests/expand.rs | |||
@@ -663,6 +663,21 @@ macro foo { | |||
663 | } | 663 | } |
664 | 664 | ||
665 | #[test] | 665 | #[test] |
666 | fn test_macro_2_0_panic_2015() { | ||
667 | parse_macro2( | ||
668 | r#" | ||
669 | macro panic_2015 { | ||
670 | () => ( | ||
671 | ), | ||
672 | (bar) => ( | ||
673 | ), | ||
674 | } | ||
675 | "#, | ||
676 | ) | ||
677 | .assert_expand_items("panic_2015!(bar);", ""); | ||
678 | } | ||
679 | |||
680 | #[test] | ||
666 | fn test_path() { | 681 | fn test_path() { |
667 | parse_macro( | 682 | parse_macro( |
668 | r#" | 683 | r#" |
diff --git a/crates/mbe/src/tt_iter.rs b/crates/mbe/src/tt_iter.rs index 319a40f2a..195b8cf30 100644 --- a/crates/mbe/src/tt_iter.rs +++ b/crates/mbe/src/tt_iter.rs | |||
@@ -34,6 +34,17 @@ impl<'a> TtIter<'a> { | |||
34 | } | 34 | } |
35 | } | 35 | } |
36 | 36 | ||
37 | pub(crate) fn expect_any_char(&mut self, chars: &[char]) -> Result<(), ()> { | ||
38 | match self.next() { | ||
39 | Some(tt::TokenTree::Leaf(tt::Leaf::Punct(tt::Punct { char: c, .. }))) | ||
40 | if chars.contains(c) => | ||
41 | { | ||
42 | Ok(()) | ||
43 | } | ||
44 | _ => Err(()), | ||
45 | } | ||
46 | } | ||
47 | |||
37 | pub(crate) fn expect_subtree(&mut self) -> Result<&'a tt::Subtree, ()> { | 48 | pub(crate) fn expect_subtree(&mut self) -> Result<&'a tt::Subtree, ()> { |
38 | match self.next() { | 49 | match self.next() { |
39 | Some(tt::TokenTree::Subtree(it)) => Ok(it), | 50 | Some(tt::TokenTree::Subtree(it)) => Ok(it), |