Sanitize rust macros to avoid forcing user's environment
Closed this issue · 0 comments
clembu commented
Problem to Solve
Currently the builder macros rely on a particular lexical environment.
For example
typeql_lang::typeql_define()
// will expand to
TypeQLDefine::new(vec![])
requiring the user to have TypeQLDefine
in the lexical environment.
This is a problem because it lets users do this sort of thing:
struct TypeQLDefine;
impl TypeQLDefine {
fn new(Vec<typeql_lang::pattern::Definable>) -> Self { Self }
}
// somewhere where that TypeQLDefine is in scope...
typeql_define!(my_type, my_rule) // <-- this line doesn't error
This is a minimal example, but you can see where major problems can arise.
Proposed Solution
Using proper rust macro hygiene fixes this issue, by expanding to fully qualified identifiers.
To fix the define query, for example, is as simple as replacing it with
#[macro_export]
macro_rules! typeql_define {
($($pattern:expr),* $(,)?) => {{
$crate::query::TypeQLDefine::new(vec![$($pattern.into()),*])
}}
}
With this we have
typeql_define!()
// will expand to
typeql_lang::query::TypeQLDefine::new(vec![])
Read more on macro hygiene at: https://veykril.github.io/tlborm/decl-macros/minutiae/hygiene.html