Skip to content

Commit 4ea5d7f

Browse files
committed
Re-introduce option for macro_arg to prevent calling macros with empty inputs
1 parent a2a3fec commit 4ea5d7f

File tree

7 files changed

+56
-28
lines changed

7 files changed

+56
-28
lines changed

crates/hir-def/src/macro_expansion_tests/mbe/matching.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ m!(&k");
3333
"#,
3434
expect![[r#"
3535
macro_rules! m { ($i:literal) => {}; }
36-
/* error: Failed to lower macro args to token tree */"#]],
36+
/* error: invalid token tree */"#]],
3737
);
3838
}
3939

crates/hir-def/src/macro_expansion_tests/mbe/tt_conversion.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ macro_rules! m1 { ($x:ident) => { ($x } }
9898
macro_rules! m2 { ($x:ident) => {} }
9999
100100
/* error: invalid macro definition: expected subtree */
101-
/* error: Failed to lower macro args to token tree */
101+
/* error: invalid token tree */
102102
"#]],
103103
)
104104
}

crates/hir-def/src/macro_expansion_tests/mod.rs

+8-7
Original file line numberDiff line numberDiff line change
@@ -183,13 +183,14 @@ pub fn identity_when_valid(_attr: TokenStream, item: TokenStream) -> TokenStream
183183
let range: Range<usize> = range.into();
184184

185185
if show_token_ids {
186-
let (tree, map, _) = &*arg;
187-
let tt_range = call.token_tree().unwrap().syntax().text_range();
188-
let mut ranges = Vec::new();
189-
extract_id_ranges(&mut ranges, map, tree);
190-
for (range, id) in ranges {
191-
let idx = (tt_range.start() + range.end()).into();
192-
text_edits.push((idx..idx, format!("#{}", id.0)));
186+
if let Some((tree, map, _)) = arg.as_deref() {
187+
let tt_range = call.token_tree().unwrap().syntax().text_range();
188+
let mut ranges = Vec::new();
189+
extract_id_ranges(&mut ranges, map, tree);
190+
for (range, id) in ranges {
191+
let idx = (tt_range.start() + range.end()).into();
192+
text_edits.push((idx..idx, format!("#{}", id.0)));
193+
}
193194
}
194195
text_edits.push((range.start..range.start, "// ".into()));
195196
call.to_string().match_indices('\n').for_each(|(offset, _)| {

crates/hir-def/src/nameres/tests/incremental.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ fn typing_inside_a_macro_should_not_invalidate_def_map() {
109109
}
110110

111111
#[test]
112-
fn typing_inside_a_function_should_not_invalidate_expansions() {
112+
fn typing_inside_a_function_should_not_invalidate_item_expansions() {
113113
let (mut db, pos) = TestDB::with_position(
114114
r#"
115115
//- /lib.rs
@@ -161,7 +161,7 @@ m!(Z);
161161
let n_recalculated_item_trees = events.iter().filter(|it| it.contains("item_tree")).count();
162162
assert_eq!(n_recalculated_item_trees, 1);
163163
let n_reparsed_macros =
164-
events.iter().filter(|it| it.contains("parse_macro_expansion")).count();
164+
events.iter().filter(|it| it.contains("parse_macro_expansion(")).count();
165165
assert_eq!(n_reparsed_macros, 0);
166166
}
167167
}

crates/hir-expand/src/db.rs

+30-15
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ pub trait ExpandDatabase: SourceDatabase {
120120
fn macro_arg(
121121
&self,
122122
id: MacroCallId,
123-
) -> Arc<(tt::Subtree, mbe::TokenMap, fixup::SyntaxFixupUndoInfo)>;
123+
) -> Option<Arc<(tt::Subtree, mbe::TokenMap, fixup::SyntaxFixupUndoInfo)>>;
124124
/// Extracts syntax node, corresponding to a macro call. That's a firewall
125125
/// query, only typing in the macro call itself changes the returned
126126
/// subtree.
@@ -318,17 +318,8 @@ fn parse_macro_expansion(
318318
fn macro_arg(
319319
db: &dyn ExpandDatabase,
320320
id: MacroCallId,
321-
) -> Arc<(tt::Subtree, mbe::TokenMap, fixup::SyntaxFixupUndoInfo)> {
322-
let Some(arg) = db.macro_arg_text(id) else {
323-
return Arc::new((
324-
tt::Subtree {
325-
delimiter: tt::Delimiter::UNSPECIFIED,
326-
token_trees: Vec::new(),
327-
},
328-
Default::default(),
329-
Default::default())
330-
);
331-
};
321+
) -> Option<Arc<(tt::Subtree, mbe::TokenMap, fixup::SyntaxFixupUndoInfo)>> {
322+
let arg = db.macro_arg_text(id)?;
332323
let loc = db.lookup_intern_macro_call(id);
333324

334325
let node = SyntaxNode::new_root(arg);
@@ -347,7 +338,7 @@ fn macro_arg(
347338
// proc macros expect their inputs without parentheses, MBEs expect it with them included
348339
tt.delimiter = tt::Delimiter::unspecified();
349340
}
350-
Arc::new((tt, tmap, fixups.undo_info))
341+
Some(Arc::new((tt, tmap, fixups.undo_info)))
351342
}
352343

353344
fn censor_for_macro_input(loc: &MacroCallLoc, node: &SyntaxNode) -> FxHashSet<SyntaxNode> {
@@ -472,7 +463,20 @@ fn macro_expand(db: &dyn ExpandDatabase, id: MacroCallId) -> ExpandResult<Arc<tt
472463
}
473464
}
474465
};
475-
let macro_arg = db.macro_arg(id);
466+
let Some(macro_arg) = db.macro_arg(id) else {
467+
return ExpandResult {
468+
value: Arc::new(
469+
tt::Subtree {
470+
delimiter: tt::Delimiter::UNSPECIFIED,
471+
token_trees: Vec::new(),
472+
},
473+
),
474+
err: Some(ExpandError::Other(
475+
"invalid token tree"
476+
.into(),
477+
)),
478+
};
479+
};
476480
let ExpandResult { value: mut tt, err } = expander.expand(db, id, &macro_arg.0);
477481
// Set a hard limit for the expanded tt
478482
let count = tt.count();
@@ -508,7 +512,18 @@ fn parse_macro_expansion_error(
508512

509513
fn expand_proc_macro(db: &dyn ExpandDatabase, id: MacroCallId) -> ExpandResult<tt::Subtree> {
510514
let loc: MacroCallLoc = db.lookup_intern_macro_call(id);
511-
let macro_arg = db.macro_arg(id);
515+
let Some(macro_arg) = db.macro_arg(id) else {
516+
return ExpandResult {
517+
value: tt::Subtree {
518+
delimiter: tt::Delimiter::UNSPECIFIED,
519+
token_trees: Vec::new(),
520+
},
521+
err: Some(ExpandError::Other(
522+
"invalid token tree"
523+
.into(),
524+
)),
525+
};
526+
};
512527

513528
let expander = match loc.def.kind {
514529
MacroDefKind::ProcMacro(expander, ..) => expander,

crates/hir-expand/src/hygiene.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,13 @@ fn make_hygiene_info(
201201

202202
let macro_def = db.macro_def(loc.def).ok()?;
203203
let (_, exp_map) = db.parse_macro_expansion(macro_file).value;
204-
let macro_arg = db.macro_arg(macro_file.macro_call_id);
204+
let macro_arg = db.macro_arg(macro_file.macro_call_id).unwrap_or_else(|| {
205+
Arc::new((
206+
tt::Subtree { delimiter: tt::Delimiter::UNSPECIFIED, token_trees: Vec::new() },
207+
Default::default(),
208+
Default::default(),
209+
))
210+
});
205211

206212
Some(HygieneInfo {
207213
file: macro_file,

crates/hir-expand/src/lib.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,13 @@ impl HirFileId {
258258

259259
let macro_def = db.macro_def(loc.def).ok()?;
260260
let (parse, exp_map) = db.parse_macro_expansion(macro_file).value;
261-
let macro_arg = db.macro_arg(macro_file.macro_call_id);
261+
let macro_arg = db.macro_arg(macro_file.macro_call_id).unwrap_or_else(|| {
262+
Arc::new((
263+
tt::Subtree { delimiter: tt::Delimiter::UNSPECIFIED, token_trees: Vec::new() },
264+
Default::default(),
265+
Default::default(),
266+
))
267+
});
262268

263269
let def = loc.def.ast_id().left().and_then(|id| {
264270
let def_tt = match id.to_node(db) {

0 commit comments

Comments
 (0)