diff options
Diffstat (limited to 'crates/ra_hir_expand')
-rw-r--r-- | crates/ra_hir_expand/src/builtin_derive.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir_expand/src/builtin_macro.rs | 8 | ||||
-rw-r--r-- | crates/ra_hir_expand/src/db.rs | 39 | ||||
-rw-r--r-- | crates/ra_hir_expand/src/hygiene.rs | 31 | ||||
-rw-r--r-- | crates/ra_hir_expand/src/lib.rs | 2 |
5 files changed, 66 insertions, 16 deletions
diff --git a/crates/ra_hir_expand/src/builtin_derive.rs b/crates/ra_hir_expand/src/builtin_derive.rs index e60f879a3..1dc9cac66 100644 --- a/crates/ra_hir_expand/src/builtin_derive.rs +++ b/crates/ra_hir_expand/src/builtin_derive.rs | |||
@@ -38,7 +38,7 @@ macro_rules! register_builtin { | |||
38 | _ => return None, | 38 | _ => return None, |
39 | }; | 39 | }; |
40 | 40 | ||
41 | Some(MacroDefId { krate: None, ast_id: None, kind: MacroDefKind::BuiltInDerive(kind) }) | 41 | Some(MacroDefId { krate: None, ast_id: None, kind: MacroDefKind::BuiltInDerive(kind), local_inner: false }) |
42 | } | 42 | } |
43 | }; | 43 | }; |
44 | } | 44 | } |
diff --git a/crates/ra_hir_expand/src/builtin_macro.rs b/crates/ra_hir_expand/src/builtin_macro.rs index e0fef613d..3bce8f673 100644 --- a/crates/ra_hir_expand/src/builtin_macro.rs +++ b/crates/ra_hir_expand/src/builtin_macro.rs | |||
@@ -73,11 +73,13 @@ pub fn find_builtin_macro( | |||
73 | krate: Some(krate), | 73 | krate: Some(krate), |
74 | ast_id: Some(ast_id), | 74 | ast_id: Some(ast_id), |
75 | kind: MacroDefKind::BuiltIn(kind), | 75 | kind: MacroDefKind::BuiltIn(kind), |
76 | local_inner: false, | ||
76 | }), | 77 | }), |
77 | Either::Right(kind) => Some(MacroDefId { | 78 | Either::Right(kind) => Some(MacroDefId { |
78 | krate: Some(krate), | 79 | krate: Some(krate), |
79 | ast_id: Some(ast_id), | 80 | ast_id: Some(ast_id), |
80 | kind: MacroDefKind::BuiltInEager(kind), | 81 | kind: MacroDefKind::BuiltInEager(kind), |
82 | local_inner: false, | ||
81 | }), | 83 | }), |
82 | } | 84 | } |
83 | } | 85 | } |
@@ -358,7 +360,7 @@ fn env_expand( | |||
358 | // However, we cannot use an empty string here, because for | 360 | // However, we cannot use an empty string here, because for |
359 | // `include!(concat!(env!("OUT_DIR"), "/foo.rs"))` will become | 361 | // `include!(concat!(env!("OUT_DIR"), "/foo.rs"))` will become |
360 | // `include!("foo.rs"), which might go to infinite loop | 362 | // `include!("foo.rs"), which might go to infinite loop |
361 | let s = get_env_inner(db, arg_id, &key).unwrap_or_else(|| "__RA_UNIMPLEMENTATED__".to_string()); | 363 | let s = get_env_inner(db, arg_id, &key).unwrap_or_else(|| "__RA_UNIMPLEMENTED__".to_string()); |
362 | let expanded = quote! { #s }; | 364 | let expanded = quote! { #s }; |
363 | 365 | ||
364 | Ok((expanded, FragmentKind::Expr)) | 366 | Ok((expanded, FragmentKind::Expr)) |
@@ -406,6 +408,7 @@ mod tests { | |||
406 | krate: Some(CrateId(0)), | 408 | krate: Some(CrateId(0)), |
407 | ast_id: Some(AstId::new(file_id.into(), ast_id_map.ast_id(¯o_calls[0]))), | 409 | ast_id: Some(AstId::new(file_id.into(), ast_id_map.ast_id(¯o_calls[0]))), |
408 | kind: MacroDefKind::BuiltIn(expander), | 410 | kind: MacroDefKind::BuiltIn(expander), |
411 | local_inner: false, | ||
409 | }; | 412 | }; |
410 | 413 | ||
411 | let loc = MacroCallLoc { | 414 | let loc = MacroCallLoc { |
@@ -425,6 +428,7 @@ mod tests { | |||
425 | krate: Some(CrateId(0)), | 428 | krate: Some(CrateId(0)), |
426 | ast_id: Some(AstId::new(file_id.into(), ast_id_map.ast_id(¯o_calls[0]))), | 429 | ast_id: Some(AstId::new(file_id.into(), ast_id_map.ast_id(¯o_calls[0]))), |
427 | kind: MacroDefKind::BuiltInEager(expander), | 430 | kind: MacroDefKind::BuiltInEager(expander), |
431 | local_inner: false, | ||
428 | }; | 432 | }; |
429 | 433 | ||
430 | let args = macro_calls[1].token_tree().unwrap(); | 434 | let args = macro_calls[1].token_tree().unwrap(); |
@@ -504,7 +508,7 @@ mod tests { | |||
504 | "#, | 508 | "#, |
505 | ); | 509 | ); |
506 | 510 | ||
507 | assert_eq!(expanded, "\"__RA_UNIMPLEMENTATED__\""); | 511 | assert_eq!(expanded, "\"__RA_UNIMPLEMENTED__\""); |
508 | } | 512 | } |
509 | 513 | ||
510 | #[test] | 514 | #[test] |
diff --git a/crates/ra_hir_expand/src/db.rs b/crates/ra_hir_expand/src/db.rs index 047452306..bf30d7151 100644 --- a/crates/ra_hir_expand/src/db.rs +++ b/crates/ra_hir_expand/src/db.rs | |||
@@ -34,7 +34,12 @@ impl TokenExpander { | |||
34 | // FIXME switch these to ExpandResult as well | 34 | // FIXME switch these to ExpandResult as well |
35 | TokenExpander::Builtin(it) => it.expand(db, id, tt).into(), | 35 | TokenExpander::Builtin(it) => it.expand(db, id, tt).into(), |
36 | TokenExpander::BuiltinDerive(it) => it.expand(db, id, tt).into(), | 36 | TokenExpander::BuiltinDerive(it) => it.expand(db, id, tt).into(), |
37 | TokenExpander::ProcMacro(it) => it.expand(db, id, tt).into(), | 37 | TokenExpander::ProcMacro(_) => { |
38 | // We store the result in salsa db to prevent non-determinisc behavior in | ||
39 | // some proc-macro implementation | ||
40 | // See #4315 for details | ||
41 | db.expand_proc_macro(id.into()).into() | ||
42 | } | ||
38 | } | 43 | } |
39 | } | 44 | } |
40 | 45 | ||
@@ -75,6 +80,8 @@ pub trait AstDatabase: SourceDatabase { | |||
75 | 80 | ||
76 | #[salsa::interned] | 81 | #[salsa::interned] |
77 | fn intern_eager_expansion(&self, eager: EagerCallLoc) -> EagerMacroId; | 82 | fn intern_eager_expansion(&self, eager: EagerCallLoc) -> EagerMacroId; |
83 | |||
84 | fn expand_proc_macro(&self, call: MacroCallId) -> Result<tt::Subtree, mbe::ExpandError>; | ||
78 | } | 85 | } |
79 | 86 | ||
80 | /// This expands the given macro call, but with different arguments. This is | 87 | /// This expands the given macro call, but with different arguments. This is |
@@ -216,6 +223,33 @@ fn macro_expand_with_arg( | |||
216 | (Some(Arc::new(tt)), err.map(|e| format!("{:?}", e))) | 223 | (Some(Arc::new(tt)), err.map(|e| format!("{:?}", e))) |
217 | } | 224 | } |
218 | 225 | ||
226 | pub(crate) fn expand_proc_macro( | ||
227 | db: &dyn AstDatabase, | ||
228 | id: MacroCallId, | ||
229 | ) -> Result<tt::Subtree, mbe::ExpandError> { | ||
230 | let lazy_id = match id { | ||
231 | MacroCallId::LazyMacro(id) => id, | ||
232 | MacroCallId::EagerMacro(_) => unreachable!(), | ||
233 | }; | ||
234 | |||
235 | let loc = db.lookup_intern_macro(lazy_id); | ||
236 | let macro_arg = match db.macro_arg(id) { | ||
237 | Some(it) => it, | ||
238 | None => { | ||
239 | return Err( | ||
240 | tt::ExpansionError::Unknown("No arguments for proc-macro".to_string()).into() | ||
241 | ) | ||
242 | } | ||
243 | }; | ||
244 | |||
245 | let expander = match loc.def.kind { | ||
246 | MacroDefKind::CustomDerive(expander) => expander, | ||
247 | _ => unreachable!(), | ||
248 | }; | ||
249 | |||
250 | expander.expand(db, lazy_id, ¯o_arg.0) | ||
251 | } | ||
252 | |||
219 | pub(crate) fn parse_or_expand(db: &dyn AstDatabase, file_id: HirFileId) -> Option<SyntaxNode> { | 253 | pub(crate) fn parse_or_expand(db: &dyn AstDatabase, file_id: HirFileId) -> Option<SyntaxNode> { |
220 | match file_id.0 { | 254 | match file_id.0 { |
221 | HirFileIdRepr::FileId(file_id) => Some(db.parse(file_id).tree().syntax().clone()), | 255 | HirFileIdRepr::FileId(file_id) => Some(db.parse(file_id).tree().syntax().clone()), |
@@ -330,7 +364,7 @@ fn to_fragment_kind(db: &dyn AstDatabase, id: MacroCallId) -> FragmentKind { | |||
330 | FragmentKind::Expr | 364 | FragmentKind::Expr |
331 | } | 365 | } |
332 | // FIXME: Expand to statements in appropriate positions; HIR lowering needs to handle that | 366 | // FIXME: Expand to statements in appropriate positions; HIR lowering needs to handle that |
333 | EXPR_STMT | BLOCK => FragmentKind::Expr, | 367 | EXPR_STMT | BLOCK_EXPR => FragmentKind::Expr, |
334 | ARG_LIST => FragmentKind::Expr, | 368 | ARG_LIST => FragmentKind::Expr, |
335 | TRY_EXPR => FragmentKind::Expr, | 369 | TRY_EXPR => FragmentKind::Expr, |
336 | TUPLE_EXPR => FragmentKind::Expr, | 370 | TUPLE_EXPR => FragmentKind::Expr, |
@@ -342,7 +376,6 @@ fn to_fragment_kind(db: &dyn AstDatabase, id: MacroCallId) -> FragmentKind { | |||
342 | CONDITION => FragmentKind::Expr, | 376 | CONDITION => FragmentKind::Expr, |
343 | BREAK_EXPR => FragmentKind::Expr, | 377 | BREAK_EXPR => FragmentKind::Expr, |
344 | RETURN_EXPR => FragmentKind::Expr, | 378 | RETURN_EXPR => FragmentKind::Expr, |
345 | BLOCK_EXPR => FragmentKind::Expr, | ||
346 | MATCH_EXPR => FragmentKind::Expr, | 379 | MATCH_EXPR => FragmentKind::Expr, |
347 | MATCH_ARM => FragmentKind::Expr, | 380 | MATCH_ARM => FragmentKind::Expr, |
348 | MATCH_GUARD => FragmentKind::Expr, | 381 | MATCH_GUARD => FragmentKind::Expr, |
diff --git a/crates/ra_hir_expand/src/hygiene.rs b/crates/ra_hir_expand/src/hygiene.rs index 53866bbcb..6b482a60c 100644 --- a/crates/ra_hir_expand/src/hygiene.rs +++ b/crates/ra_hir_expand/src/hygiene.rs | |||
@@ -16,31 +16,34 @@ use crate::{ | |||
16 | pub struct Hygiene { | 16 | pub struct Hygiene { |
17 | // This is what `$crate` expands to | 17 | // This is what `$crate` expands to |
18 | def_crate: Option<CrateId>, | 18 | def_crate: Option<CrateId>, |
19 | |||
20 | // Indiciate this is a local inner macro | ||
21 | local_inner: bool, | ||
19 | } | 22 | } |
20 | 23 | ||
21 | impl Hygiene { | 24 | impl Hygiene { |
22 | pub fn new(db: &dyn AstDatabase, file_id: HirFileId) -> Hygiene { | 25 | pub fn new(db: &dyn AstDatabase, file_id: HirFileId) -> Hygiene { |
23 | let def_crate = match file_id.0 { | 26 | let (def_crate, local_inner) = match file_id.0 { |
24 | HirFileIdRepr::FileId(_) => None, | 27 | HirFileIdRepr::FileId(_) => (None, false), |
25 | HirFileIdRepr::MacroFile(macro_file) => match macro_file.macro_call_id { | 28 | HirFileIdRepr::MacroFile(macro_file) => match macro_file.macro_call_id { |
26 | MacroCallId::LazyMacro(id) => { | 29 | MacroCallId::LazyMacro(id) => { |
27 | let loc = db.lookup_intern_macro(id); | 30 | let loc = db.lookup_intern_macro(id); |
28 | match loc.def.kind { | 31 | match loc.def.kind { |
29 | MacroDefKind::Declarative => loc.def.krate, | 32 | MacroDefKind::Declarative => (loc.def.krate, loc.def.local_inner), |
30 | MacroDefKind::BuiltIn(_) => None, | 33 | MacroDefKind::BuiltIn(_) => (None, false), |
31 | MacroDefKind::BuiltInDerive(_) => None, | 34 | MacroDefKind::BuiltInDerive(_) => (None, false), |
32 | MacroDefKind::BuiltInEager(_) => None, | 35 | MacroDefKind::BuiltInEager(_) => (None, false), |
33 | MacroDefKind::CustomDerive(_) => None, | 36 | MacroDefKind::CustomDerive(_) => (None, false), |
34 | } | 37 | } |
35 | } | 38 | } |
36 | MacroCallId::EagerMacro(_id) => None, | 39 | MacroCallId::EagerMacro(_id) => (None, false), |
37 | }, | 40 | }, |
38 | }; | 41 | }; |
39 | Hygiene { def_crate } | 42 | Hygiene { def_crate, local_inner } |
40 | } | 43 | } |
41 | 44 | ||
42 | pub fn new_unhygienic() -> Hygiene { | 45 | pub fn new_unhygienic() -> Hygiene { |
43 | Hygiene { def_crate: None } | 46 | Hygiene { def_crate: None, local_inner: false } |
44 | } | 47 | } |
45 | 48 | ||
46 | // FIXME: this should just return name | 49 | // FIXME: this should just return name |
@@ -52,4 +55,12 @@ impl Hygiene { | |||
52 | } | 55 | } |
53 | Either::Left(name_ref.as_name()) | 56 | Either::Left(name_ref.as_name()) |
54 | } | 57 | } |
58 | |||
59 | pub fn local_inner_macros(&self) -> Option<CrateId> { | ||
60 | if self.local_inner { | ||
61 | self.def_crate | ||
62 | } else { | ||
63 | None | ||
64 | } | ||
65 | } | ||
55 | } | 66 | } |
diff --git a/crates/ra_hir_expand/src/lib.rs b/crates/ra_hir_expand/src/lib.rs index 754a0f005..f440c073b 100644 --- a/crates/ra_hir_expand/src/lib.rs +++ b/crates/ra_hir_expand/src/lib.rs | |||
@@ -204,6 +204,8 @@ pub struct MacroDefId { | |||
204 | pub krate: Option<CrateId>, | 204 | pub krate: Option<CrateId>, |
205 | pub ast_id: Option<AstId<ast::MacroCall>>, | 205 | pub ast_id: Option<AstId<ast::MacroCall>>, |
206 | pub kind: MacroDefKind, | 206 | pub kind: MacroDefKind, |
207 | |||
208 | pub local_inner: bool, | ||
207 | } | 209 | } |
208 | 210 | ||
209 | impl MacroDefId { | 211 | impl MacroDefId { |