diff options
Diffstat (limited to 'crates/hir_expand')
-rw-r--r-- | crates/hir_expand/src/builtin_derive.rs | 10 | ||||
-rw-r--r-- | crates/hir_expand/src/builtin_macro.rs | 36 | ||||
-rw-r--r-- | crates/hir_expand/src/db.rs | 15 | ||||
-rw-r--r-- | crates/hir_expand/src/eager.rs | 9 | ||||
-rw-r--r-- | crates/hir_expand/src/lib.rs | 21 | ||||
-rw-r--r-- | crates/hir_expand/src/name.rs | 11 | ||||
-rw-r--r-- | crates/hir_expand/src/quote.rs | 1 |
7 files changed, 70 insertions, 33 deletions
diff --git a/crates/hir_expand/src/builtin_derive.rs b/crates/hir_expand/src/builtin_derive.rs index 6ece4b289..537c03028 100644 --- a/crates/hir_expand/src/builtin_derive.rs +++ b/crates/hir_expand/src/builtin_derive.rs | |||
@@ -269,7 +269,7 @@ mod tests { | |||
269 | use expect_test::{expect, Expect}; | 269 | use expect_test::{expect, Expect}; |
270 | use name::AsName; | 270 | use name::AsName; |
271 | 271 | ||
272 | use crate::{test_db::TestDB, AstId, MacroCallId, MacroCallKind, MacroCallLoc}; | 272 | use crate::{test_db::TestDB, AstId, AttrId, MacroCallId, MacroCallKind, MacroCallLoc}; |
273 | 273 | ||
274 | use super::*; | 274 | use super::*; |
275 | 275 | ||
@@ -308,7 +308,7 @@ $0 | |||
308 | 308 | ||
309 | let expander = BuiltinDeriveExpander::find_by_name(&name).unwrap(); | 309 | let expander = BuiltinDeriveExpander::find_by_name(&name).unwrap(); |
310 | 310 | ||
311 | let attr_id = AstId::new(file_id.into(), ast_id_map.ast_id(&items[0])); | 311 | let ast_id = AstId::new(file_id.into(), ast_id_map.ast_id(&items[0])); |
312 | 312 | ||
313 | let loc = MacroCallLoc { | 313 | let loc = MacroCallLoc { |
314 | def: MacroDefId { | 314 | def: MacroDefId { |
@@ -317,7 +317,11 @@ $0 | |||
317 | local_inner: false, | 317 | local_inner: false, |
318 | }, | 318 | }, |
319 | krate: CrateId(0), | 319 | krate: CrateId(0), |
320 | kind: MacroCallKind::Derive(attr_id, name.to_string()), | 320 | kind: MacroCallKind::Derive { |
321 | ast_id, | ||
322 | derive_name: name.to_string(), | ||
323 | derive_attr: AttrId(0), | ||
324 | }, | ||
321 | }; | 325 | }; |
322 | 326 | ||
323 | let id: MacroCallId = db.intern_macro(loc).into(); | 327 | let id: MacroCallId = db.intern_macro(loc).into(); |
diff --git a/crates/hir_expand/src/builtin_macro.rs b/crates/hir_expand/src/builtin_macro.rs index 4d52904b9..80365fc16 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)?; |
@@ -469,7 +490,7 @@ fn env_expand( | |||
469 | // unnecessary diagnostics for eg. `CARGO_PKG_NAME`. | 490 | // unnecessary diagnostics for eg. `CARGO_PKG_NAME`. |
470 | if key == "OUT_DIR" { | 491 | if key == "OUT_DIR" { |
471 | err = Some(mbe::ExpandError::Other( | 492 | err = Some(mbe::ExpandError::Other( |
472 | r#"`OUT_DIR` not set, enable "load out dirs from check" to fix"#.into(), | 493 | r#"`OUT_DIR` not set, enable "run build scripts" to fix"#.into(), |
473 | )); | 494 | )); |
474 | } | 495 | } |
475 | 496 | ||
@@ -545,10 +566,9 @@ mod tests { | |||
545 | let loc = MacroCallLoc { | 566 | let loc = MacroCallLoc { |
546 | def, | 567 | def, |
547 | krate, | 568 | krate, |
548 | kind: MacroCallKind::FnLike(AstId::new( | 569 | kind: MacroCallKind::FnLike { |
549 | file_id.into(), | 570 | ast_id: AstId::new(file_id.into(), ast_id_map.ast_id(¯o_call)), |
550 | ast_id_map.ast_id(¯o_call), | 571 | }, |
551 | )), | ||
552 | }; | 572 | }; |
553 | 573 | ||
554 | let id: MacroCallId = db.intern_macro(loc).into(); | 574 | let id: MacroCallId = db.intern_macro(loc).into(); |
@@ -563,7 +583,7 @@ mod tests { | |||
563 | }; | 583 | }; |
564 | 584 | ||
565 | let args = macro_call.token_tree().unwrap(); | 585 | let args = macro_call.token_tree().unwrap(); |
566 | let parsed_args = mbe::ast_to_token_tree(&args).unwrap().0; | 586 | let parsed_args = mbe::ast_to_token_tree(&args).0; |
567 | let call_id = AstId::new(file_id.into(), ast_id_map.ast_id(¯o_call)); | 587 | let call_id = AstId::new(file_id.into(), ast_id_map.ast_id(¯o_call)); |
568 | 588 | ||
569 | let arg_id = db.intern_eager_expansion({ | 589 | let arg_id = db.intern_eager_expansion({ |
diff --git a/crates/hir_expand/src/db.rs b/crates/hir_expand/src/db.rs index c0ab70b60..ca705ee9d 100644 --- a/crates/hir_expand/src/db.rs +++ b/crates/hir_expand/src/db.rs | |||
@@ -119,7 +119,7 @@ pub fn expand_hypothetical( | |||
119 | token_to_map: syntax::SyntaxToken, | 119 | token_to_map: syntax::SyntaxToken, |
120 | ) -> Option<(SyntaxNode, syntax::SyntaxToken)> { | 120 | ) -> Option<(SyntaxNode, syntax::SyntaxToken)> { |
121 | let macro_file = MacroFile { macro_call_id: actual_macro_call }; | 121 | let macro_file = MacroFile { macro_call_id: actual_macro_call }; |
122 | let (tt, tmap_1) = mbe::syntax_node_to_token_tree(hypothetical_args.syntax()).unwrap(); | 122 | let (tt, tmap_1) = mbe::syntax_node_to_token_tree(hypothetical_args.syntax()); |
123 | let range = | 123 | let range = |
124 | token_to_map.text_range().checked_sub(hypothetical_args.syntax().text_range().start())?; | 124 | token_to_map.text_range().checked_sub(hypothetical_args.syntax().text_range().start())?; |
125 | let token_id = tmap_1.token_by_range(range)?; | 125 | let token_id = tmap_1.token_by_range(range)?; |
@@ -143,10 +143,7 @@ fn macro_def(db: &dyn AstDatabase, id: MacroDefId) -> Option<Arc<(TokenExpander, | |||
143 | MacroDefKind::Declarative(ast_id) => match ast_id.to_node(db) { | 143 | MacroDefKind::Declarative(ast_id) => match ast_id.to_node(db) { |
144 | syntax::ast::Macro::MacroRules(macro_rules) => { | 144 | syntax::ast::Macro::MacroRules(macro_rules) => { |
145 | let arg = macro_rules.token_tree()?; | 145 | let arg = macro_rules.token_tree()?; |
146 | let (tt, tmap) = mbe::ast_to_token_tree(&arg).or_else(|| { | 146 | let (tt, tmap) = mbe::ast_to_token_tree(&arg); |
147 | log::warn!("fail on macro_rules to token tree: {:#?}", arg); | ||
148 | None | ||
149 | })?; | ||
150 | let rules = match MacroRules::parse(&tt) { | 147 | let rules = match MacroRules::parse(&tt) { |
151 | Ok(it) => it, | 148 | Ok(it) => it, |
152 | Err(err) => { | 149 | Err(err) => { |
@@ -159,10 +156,7 @@ fn macro_def(db: &dyn AstDatabase, id: MacroDefId) -> Option<Arc<(TokenExpander, | |||
159 | } | 156 | } |
160 | syntax::ast::Macro::MacroDef(macro_def) => { | 157 | syntax::ast::Macro::MacroDef(macro_def) => { |
161 | let arg = macro_def.body()?; | 158 | let arg = macro_def.body()?; |
162 | let (tt, tmap) = mbe::ast_to_token_tree(&arg).or_else(|| { | 159 | let (tt, tmap) = mbe::ast_to_token_tree(&arg); |
163 | log::warn!("fail on macro_def to token tree: {:#?}", arg); | ||
164 | None | ||
165 | })?; | ||
166 | let rules = match MacroDef::parse(&tt) { | 160 | let rules = match MacroDef::parse(&tt) { |
167 | Ok(it) => it, | 161 | Ok(it) => it, |
168 | Err(err) => { | 162 | Err(err) => { |
@@ -202,7 +196,7 @@ fn macro_arg_text(db: &dyn AstDatabase, id: MacroCallId) -> Option<GreenNode> { | |||
202 | 196 | ||
203 | fn macro_arg(db: &dyn AstDatabase, id: MacroCallId) -> Option<Arc<(tt::Subtree, mbe::TokenMap)>> { | 197 | fn macro_arg(db: &dyn AstDatabase, id: MacroCallId) -> Option<Arc<(tt::Subtree, mbe::TokenMap)>> { |
204 | let arg = db.macro_arg_text(id)?; | 198 | let arg = db.macro_arg_text(id)?; |
205 | let (tt, tmap) = mbe::syntax_node_to_token_tree(&SyntaxNode::new_root(arg))?; | 199 | let (tt, tmap) = mbe::syntax_node_to_token_tree(&SyntaxNode::new_root(arg)); |
206 | Some(Arc::new((tt, tmap))) | 200 | Some(Arc::new((tt, tmap))) |
207 | } | 201 | } |
208 | 202 | ||
@@ -445,6 +439,7 @@ fn to_fragment_kind(db: &dyn AstDatabase, id: MacroCallId) -> FragmentKind { | |||
445 | match parent.kind() { | 439 | match parent.kind() { |
446 | MACRO_ITEMS | SOURCE_FILE => FragmentKind::Items, | 440 | MACRO_ITEMS | SOURCE_FILE => FragmentKind::Items, |
447 | MACRO_STMTS => FragmentKind::Statements, | 441 | MACRO_STMTS => FragmentKind::Statements, |
442 | MACRO_PAT => FragmentKind::Pattern, | ||
448 | ITEM_LIST => FragmentKind::Items, | 443 | ITEM_LIST => FragmentKind::Items, |
449 | LET_STMT => { | 444 | LET_STMT => { |
450 | // FIXME: Handle LHS Pattern | 445 | // FIXME: Handle LHS Pattern |
diff --git a/crates/hir_expand/src/eager.rs b/crates/hir_expand/src/eager.rs index 9eedc8461..ef126e4ad 100644 --- a/crates/hir_expand/src/eager.rs +++ b/crates/hir_expand/src/eager.rs | |||
@@ -106,7 +106,7 @@ pub fn expand_eager_macro( | |||
106 | mut diagnostic_sink: &mut dyn FnMut(mbe::ExpandError), | 106 | mut diagnostic_sink: &mut dyn FnMut(mbe::ExpandError), |
107 | ) -> Result<EagerMacroId, ErrorEmitted> { | 107 | ) -> Result<EagerMacroId, ErrorEmitted> { |
108 | let parsed_args = diagnostic_sink.option_with( | 108 | let parsed_args = diagnostic_sink.option_with( |
109 | || Some(mbe::ast_to_token_tree(¯o_call.value.token_tree()?)?.0), | 109 | || Some(mbe::ast_to_token_tree(¯o_call.value.token_tree()?).0), |
110 | || err("malformed macro invocation"), | 110 | || err("malformed macro invocation"), |
111 | )?; | 111 | )?; |
112 | 112 | ||
@@ -161,7 +161,7 @@ pub fn expand_eager_macro( | |||
161 | } | 161 | } |
162 | 162 | ||
163 | fn to_subtree(node: &SyntaxNode) -> Option<tt::Subtree> { | 163 | fn to_subtree(node: &SyntaxNode) -> Option<tt::Subtree> { |
164 | let mut subtree = mbe::syntax_node_to_token_tree(node)?.0; | 164 | let mut subtree = mbe::syntax_node_to_token_tree(node).0; |
165 | subtree.delimiter = None; | 165 | subtree.delimiter = None; |
166 | Some(subtree) | 166 | Some(subtree) |
167 | } | 167 | } |
@@ -174,8 +174,9 @@ fn lazy_expand( | |||
174 | ) -> ExpandResult<Option<InFile<SyntaxNode>>> { | 174 | ) -> ExpandResult<Option<InFile<SyntaxNode>>> { |
175 | let ast_id = db.ast_id_map(macro_call.file_id).ast_id(¯o_call.value); | 175 | let ast_id = db.ast_id_map(macro_call.file_id).ast_id(¯o_call.value); |
176 | 176 | ||
177 | let id: MacroCallId = | 177 | let id: MacroCallId = def |
178 | def.as_lazy_macro(db, krate, MacroCallKind::FnLike(macro_call.with_value(ast_id))).into(); | 178 | .as_lazy_macro(db, krate, MacroCallKind::FnLike { ast_id: macro_call.with_value(ast_id) }) |
179 | .into(); | ||
179 | 180 | ||
180 | let err = db.macro_expand_error(id); | 181 | let err = db.macro_expand_error(id); |
181 | let value = db.parse_or_expand(id.as_file()).map(|node| InFile::new(id.as_file(), node)); | 182 | let value = db.parse_or_expand(id.as_file()).map(|node| InFile::new(id.as_file(), node)); |
diff --git a/crates/hir_expand/src/lib.rs b/crates/hir_expand/src/lib.rs index 3e332ee47..a0e6aec62 100644 --- a/crates/hir_expand/src/lib.rs +++ b/crates/hir_expand/src/lib.rs | |||
@@ -290,22 +290,27 @@ pub struct MacroCallLoc { | |||
290 | 290 | ||
291 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 291 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
292 | pub enum MacroCallKind { | 292 | pub enum MacroCallKind { |
293 | FnLike(AstId<ast::MacroCall>), | 293 | FnLike { ast_id: AstId<ast::MacroCall> }, |
294 | Derive(AstId<ast::Item>, String), | 294 | Derive { ast_id: AstId<ast::Item>, derive_name: String, derive_attr: AttrId }, |
295 | } | 295 | } |
296 | 296 | ||
297 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
298 | pub struct AttrId(pub u32); | ||
299 | |||
297 | impl MacroCallKind { | 300 | impl MacroCallKind { |
298 | fn file_id(&self) -> HirFileId { | 301 | fn file_id(&self) -> HirFileId { |
299 | match self { | 302 | match self { |
300 | MacroCallKind::FnLike(ast_id) => ast_id.file_id, | 303 | MacroCallKind::FnLike { ast_id, .. } => ast_id.file_id, |
301 | MacroCallKind::Derive(ast_id, _) => ast_id.file_id, | 304 | MacroCallKind::Derive { ast_id, .. } => ast_id.file_id, |
302 | } | 305 | } |
303 | } | 306 | } |
304 | 307 | ||
305 | fn node(&self, db: &dyn db::AstDatabase) -> InFile<SyntaxNode> { | 308 | fn node(&self, db: &dyn db::AstDatabase) -> InFile<SyntaxNode> { |
306 | match self { | 309 | match self { |
307 | MacroCallKind::FnLike(ast_id) => ast_id.with_value(ast_id.to_node(db).syntax().clone()), | 310 | MacroCallKind::FnLike { ast_id, .. } => { |
308 | MacroCallKind::Derive(ast_id, _) => { | 311 | ast_id.with_value(ast_id.to_node(db).syntax().clone()) |
312 | } | ||
313 | MacroCallKind::Derive { ast_id, .. } => { | ||
309 | ast_id.with_value(ast_id.to_node(db).syntax().clone()) | 314 | ast_id.with_value(ast_id.to_node(db).syntax().clone()) |
310 | } | 315 | } |
311 | } | 316 | } |
@@ -313,10 +318,10 @@ impl MacroCallKind { | |||
313 | 318 | ||
314 | fn arg(&self, db: &dyn db::AstDatabase) -> Option<SyntaxNode> { | 319 | fn arg(&self, db: &dyn db::AstDatabase) -> Option<SyntaxNode> { |
315 | match self { | 320 | match self { |
316 | MacroCallKind::FnLike(ast_id) => { | 321 | MacroCallKind::FnLike { ast_id, .. } => { |
317 | Some(ast_id.to_node(db).token_tree()?.syntax().clone()) | 322 | Some(ast_id.to_node(db).token_tree()?.syntax().clone()) |
318 | } | 323 | } |
319 | MacroCallKind::Derive(ast_id, _) => Some(ast_id.to_node(db).syntax().clone()), | 324 | MacroCallKind::Derive { ast_id, .. } => Some(ast_id.to_node(db).syntax().clone()), |
320 | } | 325 | } |
321 | } | 326 | } |
322 | } | 327 | } |
diff --git a/crates/hir_expand/src/name.rs b/crates/hir_expand/src/name.rs index cd691b1d2..a0f8766b0 100644 --- a/crates/hir_expand/src/name.rs +++ b/crates/hir_expand/src/name.rs | |||
@@ -55,6 +55,15 @@ impl Name { | |||
55 | } | 55 | } |
56 | } | 56 | } |
57 | 57 | ||
58 | /// A fake name for things missing in the source code. | ||
59 | /// | ||
60 | /// For example, `impl Foo for {}` should be treated as a trait impl for a | ||
61 | /// type with a missing name. Similarly, `struct S { : u32 }` should have a | ||
62 | /// single field with a missing name. | ||
63 | /// | ||
64 | /// Ideally, we want a `gensym` semantics for missing names -- each missing | ||
65 | /// name is equal only to itself. It's not clear how to implement this in | ||
66 | /// salsa though, so we punt on that bit for a moment. | ||
58 | pub fn missing() -> Name { | 67 | pub fn missing() -> Name { |
59 | Name::new_text("[missing name]".into()) | 68 | Name::new_text("[missing name]".into()) |
60 | } | 69 | } |
@@ -199,6 +208,8 @@ pub mod known { | |||
199 | line, | 208 | line, |
200 | module_path, | 209 | module_path, |
201 | assert, | 210 | assert, |
211 | core_panic, | ||
212 | std_panic, | ||
202 | stringify, | 213 | stringify, |
203 | concat, | 214 | concat, |
204 | 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 | { |