-
Notifications
You must be signed in to change notification settings - Fork 12.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Type ascription syntax can subtly change the behaviour of macros #30531
Comments
If I'm not mistaken, the macro future proofing RFC should make macros like this illegal? |
Well honestly I'm not sure; that RFC was tightening up rules for a single rewrite rule; I'm not sure how a we handle/check interactions between multiple rules. .. |
Even with the future-proofing, |
I think removing |
I guess another (distasteful) option is changing the type ascription syntax so that it would be covered by the extant future-proofing. For example allowing expr-but-not-ident, so |
Is there a way to know that the second part describes a type? |
@hoodie what do you mean? Macros are expanded before name resolution and type checking so AFAIK they can only really look at syntax. |
Yes you are right, I thought of that too right after I posted. This just means that the colon character is to be avoided in macros. |
To be clear, what I meant by this is that we might be able to walk across all of the rules in parallel, maintaining multiple cursors into the rules, rather than separately with a single cursor, and have the |
In the meantime, its possible that a workaround could be to just reorder the rewrite arms in the macro definition itself so that the case with |
@pnkfelix I'm afraid macro_rules! cell {
($style:ident : $value:expr) => { 1 };
($value:expr) => { 0 };
}
fn main() {
println!("{}", cell!(t : T));
println!("{}", cell!(42));
} produces the following on stable:
In cases like this, |
So, @brson and I were just talking about this. I think my preferred solution is to fix the "macro future proofing RFC", since it seems obvious that this is basically a bug in that RFC and it is not achieving its aims. However, the precise best way to do that -- and the fallout from doing so -- is unknown. In the meantime, perhaps the most prudent course of action is to either disable parsing of type ascription or else to require that a type ascription expression occurs within parentheses ( Longer term, it seems likely but not certain that this crate will eventually break, but hopefully that is because we tighten the macro future-proofing RFC, and not as an unintentional side-effect of adding a new expression form. Alternatively, if we decide we cannot fix the macro future-proofing RFC, we will have to be very careful about adding new expression forms, and probably wind up limiting ourselves to forms that require parentheses or are otherwise unambiguous. |
ah fun, we get to fix future proofing a second time. :) |
I personally think the best fix would be to solve the " |
@DanielKeep +1 |
@DanielKeep that seems like a good idea but it doesn't fix the fact that we would be breaking the code until the workaround is applied. That said, it may be that if we fix macro-rules future-proofing, we also have to fix that problem, so that at least a workaround exists. |
Operator
Requiring |
That should count against the possible syntax, IMO (not instantly disqualify it, but count against it), as this issue should count against the current formulation of type ascription syntax. Macro future-proofing becomes a bit of a sham if you can't future-proof your macro against future changes to future-proofing. |
We discussed this issue in yesterday's @rust-lang/lang meeting. The rough consensus was that we should not revert the type ascription change (nor other future extensions to the expression grammar). The bug here is that these macro definitions were accepted in the first place, basically, and we hope soon to revise the macro rules to correct that. For some background: when we released 1.0, we set some parameters for what sorts of changes we could make to the Rust grammar. In particular, for things like expressions and types, which can be referenced from macro definitions, we established (in RFC 550) a set of legal "follow" tokens that must never be added to the grammar. For example, the follow set for an expression was defined as RFC 550 also defined a static analysis that was intended to reject macro definitions which might be affected by (legal) changes to the expression grammar. For example, that analysis would reject a macro arm such as In the medium to long term, we need to patch RFC 550 to correctly account for multiple macro arms. In the short term, however, macro authors will have to look at their own macros to check whether they might be broken by changes to the extension grammar. We considered reverting the addition of type ascription but decided against it. Basically, once we fix RFC 550, those crates that are affected by type ascription are going to break anyway. On balance, it seems better to regress them now and gain type ascription (and the |
The "soundness bug" does not apply only to multiple arms. The trouble is that |
If the intention is that macro authors must pay attention to the spirit of RFC 550, rather than its actual implementation, this should be publicized widely. |
It has broken librand too, for the record. |
@ticki huh? Which macros in rand? |
I believe that only matters if there are multiple arms in play. Do you have an example that would suggest otherwise? |
@nikomatsakis hmm I see what you are saying. I can't come up with an example where |
It was fixed a couple of days ago in the upstream rust. |
Closing as "won't fix" per #30531 (comment) |
In the wild: phsym/prettytable-rs#11
This program prints "1" on stable and beta, but "0" on nightly:
Originally reported by @hoodie
The text was updated successfully, but these errors were encountered: