diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2021-05-29 16:19:44 +0100 |
---|---|---|
committer | GitHub <[email protected]> | 2021-05-29 16:19:44 +0100 |
commit | 8cd98bde39c67af8a5ab742b6a688edd355f5025 (patch) | |
tree | 21c155b7d95fd393765238aa09b99a895341854a | |
parent | 247faf271b9098624cb0b09dd4914da66497dd5a (diff) | |
parent | 31588aea04aa1240fdc7b5279535f63b9f1681f8 (diff) |
Merge #9046
9046: fix: make `include!` etc. work in expression position r=jonas-schievink a=jonas-schievink
This PR removes determination of fragment kinds from the eager macro implementations. The fragment kind is always determined by the syntax position in which a macro is invoked, not by the macro implementation, even for eager macros.
This makes `include!` work in expression position, and should have the same effect for all macros that may be used in different positions.
bors r+
Co-authored-by: Jonas Schievink <[email protected]>
-rw-r--r-- | crates/hir_expand/src/builtin_macro.rs | 37 | ||||
-rw-r--r-- | crates/hir_expand/src/eager.rs | 3 | ||||
-rw-r--r-- | crates/hir_ty/src/tests/macros.rs | 18 |
3 files changed, 35 insertions, 23 deletions
diff --git a/crates/hir_expand/src/builtin_macro.rs b/crates/hir_expand/src/builtin_macro.rs index 94d7aecb6..0b310ba2f 100644 --- a/crates/hir_expand/src/builtin_macro.rs +++ b/crates/hir_expand/src/builtin_macro.rs | |||
@@ -8,7 +8,6 @@ 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}; |
11 | use parser::FragmentKind; | ||
12 | use syntax::ast::{self, AstToken}; | 11 | use syntax::ast::{self, AstToken}; |
13 | 12 | ||
14 | macro_rules! register_builtin { | 13 | macro_rules! register_builtin { |
@@ -47,7 +46,7 @@ macro_rules! register_builtin { | |||
47 | let expander = match *self { | 46 | let expander = match *self { |
48 | $( EagerExpander::$e_kind => $e_expand, )* | 47 | $( EagerExpander::$e_kind => $e_expand, )* |
49 | }; | 48 | }; |
50 | expander(db,arg_id,tt) | 49 | expander(db, arg_id, tt) |
51 | } | 50 | } |
52 | } | 51 | } |
53 | 52 | ||
@@ -64,14 +63,13 @@ macro_rules! register_builtin { | |||
64 | #[derive(Debug)] | 63 | #[derive(Debug)] |
65 | pub struct ExpandedEager { | 64 | pub struct ExpandedEager { |
66 | pub(crate) subtree: tt::Subtree, | 65 | pub(crate) subtree: tt::Subtree, |
67 | pub(crate) fragment: FragmentKind, | ||
68 | /// The included file ID of the include macro. | 66 | /// The included file ID of the include macro. |
69 | pub(crate) included_file: Option<FileId>, | 67 | pub(crate) included_file: Option<FileId>, |
70 | } | 68 | } |
71 | 69 | ||
72 | impl ExpandedEager { | 70 | impl ExpandedEager { |
73 | fn new(subtree: tt::Subtree, fragment: FragmentKind) -> Self { | 71 | fn new(subtree: tt::Subtree) -> Self { |
74 | ExpandedEager { subtree, fragment, included_file: None } | 72 | ExpandedEager { subtree, included_file: None } |
75 | } | 73 | } |
76 | } | 74 | } |
77 | 75 | ||
@@ -340,7 +338,7 @@ fn compile_error_expand( | |||
340 | _ => mbe::ExpandError::BindingError("`compile_error!` argument must be a string".into()), | 338 | _ => mbe::ExpandError::BindingError("`compile_error!` argument must be a string".into()), |
341 | }; | 339 | }; |
342 | 340 | ||
343 | ExpandResult { value: Some(ExpandedEager::new(quote! {}, FragmentKind::Items)), err: Some(err) } | 341 | ExpandResult { value: Some(ExpandedEager::new(quote! {})), err: Some(err) } |
344 | } | 342 | } |
345 | 343 | ||
346 | fn concat_expand( | 344 | fn concat_expand( |
@@ -371,7 +369,7 @@ fn concat_expand( | |||
371 | } | 369 | } |
372 | } | 370 | } |
373 | } | 371 | } |
374 | ExpandResult { value: Some(ExpandedEager::new(quote!(#text), FragmentKind::Expr)), err } | 372 | ExpandResult { value: Some(ExpandedEager::new(quote!(#text))), err } |
375 | } | 373 | } |
376 | 374 | ||
377 | fn concat_idents_expand( | 375 | fn concat_idents_expand( |
@@ -393,7 +391,7 @@ fn concat_idents_expand( | |||
393 | } | 391 | } |
394 | } | 392 | } |
395 | let ident = tt::Ident { text: ident.into(), id: tt::TokenId::unspecified() }; | 393 | let ident = tt::Ident { text: ident.into(), id: tt::TokenId::unspecified() }; |
396 | ExpandResult { value: Some(ExpandedEager::new(quote!(#ident), FragmentKind::Expr)), err } | 394 | ExpandResult { value: Some(ExpandedEager::new(quote!(#ident))), err } |
397 | } | 395 | } |
398 | 396 | ||
399 | fn relative_file( | 397 | fn relative_file( |
@@ -442,14 +440,7 @@ fn include_expand( | |||
442 | 440 | ||
443 | match res { | 441 | match res { |
444 | Ok((subtree, file_id)) => { | 442 | Ok((subtree, file_id)) => { |
445 | // FIXME: | 443 | ExpandResult::ok(Some(ExpandedEager { subtree, included_file: Some(file_id) })) |
446 | // Handle include as expression | ||
447 | |||
448 | ExpandResult::ok(Some(ExpandedEager { | ||
449 | subtree, | ||
450 | fragment: FragmentKind::Items, | ||
451 | included_file: Some(file_id), | ||
452 | })) | ||
453 | } | 444 | } |
454 | Err(e) => ExpandResult::only_err(e), | 445 | Err(e) => ExpandResult::only_err(e), |
455 | } | 446 | } |
@@ -472,7 +463,7 @@ fn include_bytes_expand( | |||
472 | id: tt::TokenId::unspecified(), | 463 | id: tt::TokenId::unspecified(), |
473 | }))], | 464 | }))], |
474 | }; | 465 | }; |
475 | ExpandResult::ok(Some(ExpandedEager::new(res, FragmentKind::Expr))) | 466 | ExpandResult::ok(Some(ExpandedEager::new(res))) |
476 | } | 467 | } |
477 | 468 | ||
478 | fn include_str_expand( | 469 | fn include_str_expand( |
@@ -492,14 +483,14 @@ fn include_str_expand( | |||
492 | let file_id = match relative_file(db, arg_id.into(), &path, true) { | 483 | let file_id = match relative_file(db, arg_id.into(), &path, true) { |
493 | Ok(file_id) => file_id, | 484 | Ok(file_id) => file_id, |
494 | Err(_) => { | 485 | Err(_) => { |
495 | return ExpandResult::ok(Some(ExpandedEager::new(quote!(""), FragmentKind::Expr))); | 486 | return ExpandResult::ok(Some(ExpandedEager::new(quote!("")))); |
496 | } | 487 | } |
497 | }; | 488 | }; |
498 | 489 | ||
499 | let text = db.file_text(file_id); | 490 | let text = db.file_text(file_id); |
500 | let text = &*text; | 491 | let text = &*text; |
501 | 492 | ||
502 | ExpandResult::ok(Some(ExpandedEager::new(quote!(#text), FragmentKind::Expr))) | 493 | ExpandResult::ok(Some(ExpandedEager::new(quote!(#text)))) |
503 | } | 494 | } |
504 | 495 | ||
505 | fn get_env_inner(db: &dyn AstDatabase, arg_id: MacroCallId, key: &str) -> Option<String> { | 496 | fn get_env_inner(db: &dyn AstDatabase, arg_id: MacroCallId, key: &str) -> Option<String> { |
@@ -535,7 +526,7 @@ fn env_expand( | |||
535 | }); | 526 | }); |
536 | let expanded = quote! { #s }; | 527 | let expanded = quote! { #s }; |
537 | 528 | ||
538 | ExpandResult { value: Some(ExpandedEager::new(expanded, FragmentKind::Expr)), err } | 529 | ExpandResult { value: Some(ExpandedEager::new(expanded)), err } |
539 | } | 530 | } |
540 | 531 | ||
541 | fn option_env_expand( | 532 | fn option_env_expand( |
@@ -553,7 +544,7 @@ fn option_env_expand( | |||
553 | Some(s) => quote! { std::option::Some(#s) }, | 544 | Some(s) => quote! { std::option::Some(#s) }, |
554 | }; | 545 | }; |
555 | 546 | ||
556 | ExpandResult::ok(Some(ExpandedEager::new(expanded, FragmentKind::Expr))) | 547 | ExpandResult::ok(Some(ExpandedEager::new(expanded))) |
557 | } | 548 | } |
558 | 549 | ||
559 | #[cfg(test)] | 550 | #[cfg(test)] |
@@ -565,6 +556,7 @@ mod tests { | |||
565 | }; | 556 | }; |
566 | use base_db::{fixture::WithFixture, SourceDatabase}; | 557 | use base_db::{fixture::WithFixture, SourceDatabase}; |
567 | use expect_test::{expect, Expect}; | 558 | use expect_test::{expect, Expect}; |
559 | use parser::FragmentKind; | ||
568 | use std::sync::Arc; | 560 | use std::sync::Arc; |
569 | use syntax::ast::NameOwner; | 561 | use syntax::ast::NameOwner; |
570 | 562 | ||
@@ -617,6 +609,7 @@ mod tests { | |||
617 | local_inner: false, | 609 | local_inner: false, |
618 | }; | 610 | }; |
619 | 611 | ||
612 | let fragment = crate::to_fragment_kind(¯o_call); | ||
620 | let args = macro_call.token_tree().unwrap(); | 613 | let args = macro_call.token_tree().unwrap(); |
621 | let parsed_args = mbe::ast_to_token_tree(&args).0; | 614 | let parsed_args = mbe::ast_to_token_tree(&args).0; |
622 | let call_id = AstId::new(file_id.into(), ast_id_map.ast_id(¯o_call)); | 615 | let call_id = AstId::new(file_id.into(), ast_id_map.ast_id(¯o_call)); |
@@ -639,7 +632,7 @@ mod tests { | |||
639 | arg_or_expansion: Arc::new(expanded.subtree), | 632 | arg_or_expansion: Arc::new(expanded.subtree), |
640 | included_file: expanded.included_file, | 633 | included_file: expanded.included_file, |
641 | }), | 634 | }), |
642 | kind: MacroCallKind::FnLike { ast_id: call_id, fragment: expanded.fragment }, | 635 | kind: MacroCallKind::FnLike { ast_id: call_id, fragment }, |
643 | }; | 636 | }; |
644 | 637 | ||
645 | let id: MacroCallId = db.intern_macro(loc).into(); | 638 | let id: MacroCallId = db.intern_macro(loc).into(); |
diff --git a/crates/hir_expand/src/eager.rs b/crates/hir_expand/src/eager.rs index 1464320ba..14af628a1 100644 --- a/crates/hir_expand/src/eager.rs +++ b/crates/hir_expand/src/eager.rs | |||
@@ -113,6 +113,7 @@ pub fn expand_eager_macro( | |||
113 | 113 | ||
114 | let ast_map = db.ast_id_map(macro_call.file_id); | 114 | let ast_map = db.ast_id_map(macro_call.file_id); |
115 | let call_id = InFile::new(macro_call.file_id, ast_map.ast_id(¯o_call.value)); | 115 | let call_id = InFile::new(macro_call.file_id, ast_map.ast_id(¯o_call.value)); |
116 | let fragment = crate::to_fragment_kind(¯o_call.value); | ||
116 | 117 | ||
117 | // Note: | 118 | // Note: |
118 | // When `lazy_expand` is called, its *parent* file must be already exists. | 119 | // When `lazy_expand` is called, its *parent* file must be already exists. |
@@ -152,7 +153,7 @@ pub fn expand_eager_macro( | |||
152 | arg_or_expansion: Arc::new(expanded.subtree), | 153 | arg_or_expansion: Arc::new(expanded.subtree), |
153 | included_file: expanded.included_file, | 154 | included_file: expanded.included_file, |
154 | }), | 155 | }), |
155 | kind: MacroCallKind::FnLike { ast_id: call_id, fragment: expanded.fragment }, | 156 | kind: MacroCallKind::FnLike { ast_id: call_id, fragment }, |
156 | }; | 157 | }; |
157 | 158 | ||
158 | Ok(db.intern_macro(loc)) | 159 | Ok(db.intern_macro(loc)) |
diff --git a/crates/hir_ty/src/tests/macros.rs b/crates/hir_ty/src/tests/macros.rs index 6588aa46c..7647bb08b 100644 --- a/crates/hir_ty/src/tests/macros.rs +++ b/crates/hir_ty/src/tests/macros.rs | |||
@@ -752,6 +752,24 @@ fn bar() -> u32 {0} | |||
752 | } | 752 | } |
753 | 753 | ||
754 | #[test] | 754 | #[test] |
755 | fn infer_builtin_macros_include_expression() { | ||
756 | check_types( | ||
757 | r#" | ||
758 | //- /main.rs | ||
759 | #[rustc_builtin_macro] | ||
760 | macro_rules! include {() => {}} | ||
761 | fn main() { | ||
762 | let i = include!("bla.rs"); | ||
763 | i; | ||
764 | //^ i32 | ||
765 | } | ||
766 | //- /bla.rs | ||
767 | 0 | ||
768 | "#, | ||
769 | ) | ||
770 | } | ||
771 | |||
772 | #[test] | ||
755 | fn infer_builtin_macros_include_child_mod() { | 773 | fn infer_builtin_macros_include_child_mod() { |
756 | check_types( | 774 | check_types( |
757 | r#" | 775 | r#" |