Skip to content

Commit d6ce649

Browse files
committed
refactor: Substitute bindings in macro arguments
1 parent 7acc265 commit d6ce649

File tree

2 files changed

+51
-3
lines changed

2 files changed

+51
-3
lines changed

c2rust-refactor/src/matcher/mod.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,9 @@ mod bindings;
6666
mod impls;
6767
mod subst;
6868

69-
pub use self::bindings::{parse_bindings, BindingTypes, Bindings, Type as BindingType};
69+
pub use self::bindings::{
70+
parse_bindings, BindingTypes, Bindings, Type as BindingType, Value as BindingValue,
71+
};
7072
pub use self::subst::Subst;
7173

7274
pub type Result<T> = result::Result<T, Error>;

c2rust-refactor/src/matcher/subst.rs

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,13 @@
1919
2020
use rustc_ast::mut_visit::{self, MutVisitor};
2121
use rustc_ast::ptr::P;
22+
use rustc_ast::token::{Nonterminal, Token, TokenKind};
23+
use rustc_ast::tokenstream::{TokenStream, TokenStreamBuilder, TokenTree};
2224
use rustc_ast::MacCall;
2325
use rustc_ast::{
24-
Expr, ExprKind, Item, ItemKind, Label, Pat, PatKind, Path, Stmt, StmtKind, Ty, TyKind,
26+
Expr, ExprKind, Item, ItemKind, Label, MacArgs, Pat, PatKind, Path, Stmt, StmtKind, Ty, TyKind,
2527
};
28+
use rustc_data_structures::sync::Lrc;
2629
use rustc_parse::parser::{ForceCollect, Parser};
2730
use rustc_span::symbol::Ident;
2831
use smallvec::smallvec;
@@ -31,7 +34,7 @@ use smallvec::SmallVec;
3134
use crate::ast_manip::util::PatternSymbol;
3235
use crate::ast_manip::{AstNode, MutVisit};
3336
use crate::command::CommandState;
34-
use crate::matcher::Bindings;
37+
use crate::matcher::{BindingValue, Bindings};
3538
use crate::RefactorCtxt;
3639

3740
// `st` and `cx` were previously used for `def!` substitution, which has been removed. I expect
@@ -62,6 +65,39 @@ impl<'a, 'tcx> SubstFolder<'a, 'tcx> {
6265
}
6366
}
6467
}
68+
69+
fn subst_tokenstream_bindings(&mut self, ts: TokenStream) -> TokenStream {
70+
let mut tsb = TokenStreamBuilder::new();
71+
let mut c = ts.into_trees();
72+
while let Some(tt) = c.next() {
73+
if let TokenTree::Token(
74+
Token {
75+
kind: TokenKind::Ident(ident, _is_raw),
76+
span,
77+
},
78+
spacing,
79+
) = tt && let Some(bv) = self.bindings.get::<_, BindingValue>(ident) {
80+
let nt = match bv.clone() {
81+
BindingValue::Path(x) => Nonterminal::NtPath(P(x)),
82+
BindingValue::Expr(x) => Nonterminal::NtExpr(x),
83+
BindingValue::Pat(x) => Nonterminal::NtPat(x),
84+
BindingValue::Ty(x) => Nonterminal::NtTy(x),
85+
BindingValue::Stmt(x) => Nonterminal::NtStmt(P(x)),
86+
BindingValue::Item(x) => Nonterminal::NtItem(x),
87+
88+
_ => unimplemented!("Unsupported binding:{bv:#?}")
89+
};
90+
let new_tt = TokenTree::Token(Token {
91+
kind: TokenKind::Interpolated(Lrc::new(nt)),
92+
span,
93+
}, spacing);
94+
tsb.push(TokenStream::new(vec![new_tt]));
95+
} else {
96+
tsb.push(TokenStream::new(vec![tt]));
97+
}
98+
}
99+
tsb.build()
100+
}
65101
}
66102

67103
impl<'a, 'tcx> MutVisitor for SubstFolder<'a, 'tcx> {
@@ -235,6 +271,16 @@ impl<'a, 'tcx> MutVisitor for SubstFolder<'a, 'tcx> {
235271
}
236272

237273
fn visit_mac_call(&mut self, mac: &mut MacCall) {
274+
match *mac.args {
275+
MacArgs::Empty => {}
276+
MacArgs::Delimited(_span, _delim, ref mut ts) => {
277+
*ts = self.subst_tokenstream_bindings(std::mem::take(ts));
278+
}
279+
MacArgs::Eq(_span, ref eq) => {
280+
log::warn!("Skipping substitution for MacArgsEq:{eq:#?}");
281+
}
282+
}
283+
238284
mut_visit::noop_visit_mac(mac, self)
239285
}
240286
}

0 commit comments

Comments
 (0)