dart-lang / language

Design of the Dart language
Other
2.65k stars 201 forks source link

Disallow identity-escapes in string literals. #2601

Open lrhn opened 1 year ago

lrhn commented 1 year ago

Dart string literals allow you to write "\z" even if z is not a recognized escape. It just means "z".

The escape is unnecessary and potentially allowing it is error-prone.

I have seen RegExps that forget to use a raw string, like RegExp('^(foo|bar|baz)\.') or RegExp('[^\w]'). Those intended the \ to be passed to the RegExp parser, but because the string isn't raw, that backslash gets eaten by the string parser. The RegExp still does something like what it's intended to do (it does match . and all non-alphanumeric characters, it just also allow more characters).

I've seen the feature used in interpolations like "foo$bar\qux" where the \q ends the interpolation variable, and is one character shorter than "foo${bar}qux". It's also much less readable, and much more error-prone. If the text for qux is changed to nup, blindly changing it to "foo$bar\nup" would give an entirely wrong result. This is a use which should be strongly discouraged.

Another issue is that it prevents us from adding new escapes in the future. If we want to add a new \o octal escape, we cannot because \o has a (meaningless) meaning today, and some code might be using it. (Not really a problem, with language versioning, we can tool-migrate everybody to the new meaning, but it's just easier if we don't have to.)

All in all, there is no real upside to allowing identity escapes, and a number of pitfalls when used accidentally or "cleverly".

It should be an easy feature to implement, and I'll wager donuts that actual code broken by the change will be better (or possibly correct for the first time) for being fixed. There will be such code, so it is a breaking change.

eernstg commented 1 year ago

Perhaps a lint would suffice? If it is done using a lint at first, and it gets included in a widely used set of lints at some point, then we're in a good position to make it a language feature with no actual breakage.

lrhn commented 1 year ago

We do have that: https://dart-lang.github.io/linter/lints/unnecessary_string_escapes.html It's even in our recommended set, so that first step is well on its way.

I still want to prevent it in the language if possible.