diff options
-rw-r--r-- | crates/hir_expand/src/db.rs | 44 | ||||
-rw-r--r-- | docs/dev/style.md | 33 |
2 files changed, 50 insertions, 27 deletions
diff --git a/crates/hir_expand/src/db.rs b/crates/hir_expand/src/db.rs index 935c547b0..8f27a7fc9 100644 --- a/crates/hir_expand/src/db.rs +++ b/crates/hir_expand/src/db.rs | |||
@@ -122,16 +122,27 @@ pub fn expand_hypothetical( | |||
122 | hypothetical_args: &ast::TokenTree, | 122 | hypothetical_args: &ast::TokenTree, |
123 | token_to_map: SyntaxToken, | 123 | token_to_map: SyntaxToken, |
124 | ) -> Option<(SyntaxNode, SyntaxToken)> { | 124 | ) -> Option<(SyntaxNode, SyntaxToken)> { |
125 | let macro_file = MacroFile { macro_call_id: actual_macro_call }; | ||
126 | let (tt, tmap_1) = mbe::syntax_node_to_token_tree(hypothetical_args.syntax()); | 125 | let (tt, tmap_1) = mbe::syntax_node_to_token_tree(hypothetical_args.syntax()); |
127 | let range = | 126 | let range = |
128 | token_to_map.text_range().checked_sub(hypothetical_args.syntax().text_range().start())?; | 127 | token_to_map.text_range().checked_sub(hypothetical_args.syntax().text_range().start())?; |
129 | let token_id = tmap_1.token_by_range(range)?; | 128 | let token_id = tmap_1.token_by_range(range)?; |
130 | let macro_def = expander(db, actual_macro_call)?; | ||
131 | 129 | ||
132 | let hypothetical_expansion = | 130 | let lazy_id = match actual_macro_call { |
133 | macro_expand_with_arg(db, macro_file.macro_call_id, Some(Arc::new((tt, tmap_1)))); | 131 | MacroCallId::LazyMacro(id) => id, |
134 | let (node, tmap_2) = expansion_to_syntax(db, macro_file, hypothetical_expansion).value?; | 132 | MacroCallId::EagerMacro(_) => return None, |
133 | }; | ||
134 | |||
135 | let macro_def = { | ||
136 | let loc = db.lookup_intern_macro(lazy_id); | ||
137 | db.macro_def(loc.def)? | ||
138 | }; | ||
139 | |||
140 | let hypothetical_expansion = macro_def.expand(db, lazy_id, &tt); | ||
141 | |||
142 | let fragment_kind = to_fragment_kind(db, actual_macro_call); | ||
143 | |||
144 | let (node, tmap_2) = | ||
145 | mbe::token_tree_to_syntax_node(&hypothetical_expansion.value, fragment_kind).ok()?; | ||
135 | 146 | ||
136 | let token_id = macro_def.map_id_down(token_id); | 147 | 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())?; | 148 | let range = tmap_2.range_by_token(token_id)?.by_kind(token_to_map.kind())?; |
@@ -157,16 +168,8 @@ fn parse_macro_expansion( | |||
157 | db: &dyn AstDatabase, | 168 | db: &dyn AstDatabase, |
158 | macro_file: MacroFile, | 169 | macro_file: MacroFile, |
159 | ) -> ExpandResult<Option<(Parse<SyntaxNode>, Arc<mbe::TokenMap>)>> { | 170 | ) -> ExpandResult<Option<(Parse<SyntaxNode>, Arc<mbe::TokenMap>)>> { |
160 | let result = db.macro_expand(macro_file.macro_call_id); | ||
161 | expansion_to_syntax(db, macro_file, result) | ||
162 | } | ||
163 | |||
164 | fn expansion_to_syntax( | ||
165 | db: &dyn AstDatabase, | ||
166 | macro_file: MacroFile, | ||
167 | result: ExpandResult<Option<Arc<tt::Subtree>>>, | ||
168 | ) -> ExpandResult<Option<(Parse<SyntaxNode>, Arc<mbe::TokenMap>)>> { | ||
169 | let _p = profile::span("parse_macro_expansion"); | 171 | let _p = profile::span("parse_macro_expansion"); |
172 | let result = db.macro_expand(macro_file.macro_call_id); | ||
170 | 173 | ||
171 | if let Some(err) = &result.err { | 174 | if let Some(err) = &result.err { |
172 | // Note: | 175 | // Note: |
@@ -309,19 +312,6 @@ fn macro_expand_error(db: &dyn AstDatabase, macro_call: MacroCallId) -> Option<E | |||
309 | db.macro_expand(macro_call).err | 312 | db.macro_expand(macro_call).err |
310 | } | 313 | } |
311 | 314 | ||
312 | fn expander(db: &dyn AstDatabase, id: MacroCallId) -> Option<Arc<TokenExpander>> { | ||
313 | let lazy_id = match id { | ||
314 | MacroCallId::LazyMacro(id) => id, | ||
315 | MacroCallId::EagerMacro(_id) => { | ||
316 | return None; | ||
317 | } | ||
318 | }; | ||
319 | |||
320 | let loc = db.lookup_intern_macro(lazy_id); | ||
321 | let macro_rules = db.macro_def(loc.def)?; | ||
322 | Some(macro_rules) | ||
323 | } | ||
324 | |||
325 | fn macro_expand_with_arg( | 315 | fn macro_expand_with_arg( |
326 | db: &dyn AstDatabase, | 316 | db: &dyn AstDatabase, |
327 | id: MacroCallId, | 317 | id: MacroCallId, |
diff --git a/docs/dev/style.md b/docs/dev/style.md index 6ab60b50e..00de7a711 100644 --- a/docs/dev/style.md +++ b/docs/dev/style.md | |||
@@ -449,6 +449,39 @@ fn query_all(name: String, case_sensitive: bool) -> Vec<Item> { ... } | |||
449 | fn query_first(name: String, case_sensitive: bool) -> Option<Item> { ... } | 449 | fn query_first(name: String, case_sensitive: bool) -> Option<Item> { ... } |
450 | ``` | 450 | ``` |
451 | 451 | ||
452 | ## Prefer Separate Functions Over Parameters | ||
453 | |||
454 | If a function has a `bool` or an `Option` parameter, and it is always called with `true`, `false`, `Some` and `None` literals, split the function in two. | ||
455 | |||
456 | ```rust | ||
457 | // GOOD | ||
458 | fn caller_a() { | ||
459 | foo() | ||
460 | } | ||
461 | |||
462 | fn caller_b() { | ||
463 | foo_with_bar(Bar::new()) | ||
464 | } | ||
465 | |||
466 | fn foo() { ... } | ||
467 | fn foo_with_bar(bar: Bar) { ... } | ||
468 | |||
469 | // BAD | ||
470 | fn caller_a() { | ||
471 | foo(None) | ||
472 | } | ||
473 | |||
474 | fn caller_b() { | ||
475 | foo(Some(Bar::new())) | ||
476 | } | ||
477 | |||
478 | fn foo(bar: Option<Bar>) { ... } | ||
479 | ``` | ||
480 | |||
481 | **Rationale:** more often than not, such functions display "`false sharing`" -- they have additional `if` branching inside for two different cases. | ||
482 | Splitting the two different control flows into two functions simplifies each path, and remove cross-dependencies between the two paths. | ||
483 | If there's common code between `foo` and `foo_with_bar`, extract *that* into a common helper. | ||
484 | |||
452 | ## Avoid Monomorphization | 485 | ## Avoid Monomorphization |
453 | 486 | ||
454 | Avoid making a lot of code type parametric, *especially* on the boundaries between crates. | 487 | Avoid making a lot of code type parametric, *especially* on the boundaries between crates. |