TL;DR Does Rust provide specific stability guarantees about the behaviour of its lexer, specifically in regards to how it lexes non-Rust source code?
For context:
It occurred to me that this is possible:
let query = stringify!(
CREATE TABLE table (
row TEXT NOT NULL,
another_row TEXT NOT NULL,
);
);
query will now be a &'static str that contains a SQL query ready for use with whatever SQL library is in use. This can be a drop-in replacement for any embedded queries in your code. Obviously there are some problems and then there is the question of why, but those are besides the point.
Can the Rust lexer be relied upon to not break this code in a future update?
I would not recommend using stringify! for non-Rust code.
A macro gets its input tokens after lexing which means whitespace is mostly stripped (except for symbols where its spacing indicates whether it was next to another symbol). Besides that, the rest of the source is available so you can create almost any DSL.
The problem with using stringify! though, is that it doesn't necessarily generate a string that respects your DSL's understanding of symbols based on the tokens given to it. In particular, the current implementation seems to generate Rust-like spacing. So non-Rust combinations of symbols that are meaningful in other languages may get split apart.
Examples:
fn main() {
let sql_statement = stringify!(SELECT [1,2] @> [3,4]);
dbg!(sql_statement);
}
[src/main.rs:3] sql_statement = "SELECT [1, 2] @ > [3, 4]"
which is an invalid Postgres operator @>
fn main() {
let python_code = stringify!(1 ** 2);
dbg!(python_code);
}
[src/main.rs:3] python_code = "1 * * 2"
which is an invalid Python exponentiation operator **
In addition, the documentation says:
Note that the expanded results of the input tokens may change in the future. You should be careful if you rely on the output.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With