Découvert en essayant d'implémenter des correctifs pour # 46241. Risque de compatibilité de retour possible pour la prise en charge de la virgule de fin, mais j'espère que non.
macro_rules! panic {
() => (/* default message */);
($msg:expr) => (/* use msg as literal */);
($fmt:expr, $($arg:tt)+) => (/* use format_args! */);
}
macro_rules! panic {
() => (/* default message */);
($msg:expr) => (/* use msg as literal */);
($fmt:expr, $($arg:tt)*) => (/* use format_args! */);
}
Pouvez-vous repérer la différence?
La définition dans std ne prend pas en charge les virgules de fin après un seul littéral de chaîne:
fn main() {
panic!("a");
panic!("a",); //~ ERROR unexpected end of macro invocation
panic!("{}");
panic!("{}",); //~ ERROR unexpected end of macro invocation
}
La définition dans core accepte une virgule à la fin, mais suit un chemin de code complètement différent avec une sémantique potentiellement différente.
#![no_std]
fn main() {
panic!("a");
panic!("a",);
panic!("{}");
panic!("{}",); //~ ERROR 1 positional argument in format string, but no arguments were given
}
~ Fortuitement, il me semble que la définition de libcore produit un comportement équivalent pour panic!(<literal>,)
et panic!(<literal>)
dans tous les cas où les deux formes se compilent avec succès, ce qui signifie qu'il devrait être prudent de changer panic!(<literal>,)
se comporter comme panic!(<literal>)
. ~
Merde. J'ai trouvé un exemple du genre de risque de rétrocompatibilité dont je parlais.
Dans la rouille d'aujourd'hui, les deux programmes suivants sont différents:
#![no_std]
fn main() {
panic!("{{}}"); // panics with "{{}}"
}
#![no_std]
fn main() {
panic!("{{}}",); // panics with "{}"
}
Commentaire le plus utile
Merde. J'ai trouvé un exemple du genre de risque de rétrocompatibilité dont je parlais.
Dans la rouille d'aujourd'hui, les deux programmes suivants sont différents: