dart-lang / dart-lang/language
String canonicalization
- Dominant language
- TeX
- Stars
- 2.9k
- Forks
- 239
- Avg merge
- 2d 18h
- Merged PRs (30d)
- 14
Description
The degree to which canonicalization occurs in Dart, in particular for strings, has always been somewhat unclear.
We have explicit rules requiring that the following forms of constant expressions must be evaluated to the same (canonical) object when evaluating any of the occurrences of such an expression:
- Symbol literals (such as `#foo` or `#+`) are canonicalized.
- List, set, and map literals with the same elements/keys/values are canonicalized.
- The value of a `` (such as `const C(2)`) is canonicalized.
The definition of `identical()` ensures that instances of `bool`, `int`, and `double` are canonicalized, in the sense that they are considered identical when they represent the same value (and it is not observable whether this happens because the representation is a tagged bit string, or because `identical` treats distinct boxed representations in a special way).
Strings have traditionally been treated differently:
```dart
void main() {
var s1 = "ab";
var s2 = "a" "b"; // or `"a" + "b"`.
print(identical(s1, s2)); // 'false' with dart, 'true' with dart2js.
}
```
The specification of `identical` actually [requires](https://github.com/dart-lang/language/blob/5e31f64da811f568e81b9791db1995cecc2e5c64/specification/dartLangSpec.tex#L6200) that `identical(c1, c2)` must evaluate to true when
> `c1` and `c2` are constant strings and `c1 == c2`
which implies that the behavior of `dart` is wrong, and `dart2js` is correct: `"ab"` is a constant expression of type `String`, `"a" "b"` is a constant expression of type `String`, and the two strings are equal according to `operator ==`. (We haven't specified the behavior of `operator ==` on strings, but we hardly want to make those two strings unequal).
I believe that all non-string objects are canonicalized or not in a way which is well-defined: It is specified for the basic forms mentioned above that _every_ constant expression of these forms has a canonicalized value, and constant expressions do not allow for creating composite objects from existing objects, canonicalized or not, other than constant collection literals (e.g., we can't have `const C(x)`). In particular, we do not have to specify any additional rules saying that the value of a constant variable is canonicalized.
It is unfortunate that different tools behave differently, but it is also likely to be a serious breaking change to change the behavior of any of these tools. So do we wish to proceed and change the specification to make `identical()` implementation dependent on strings, or do we wish to choose a specific behavior and get that implemented?
@munificent, @lrhn, @leafpetersen, WDYT?
Contributor guide
Assessment
This issue has not been assessed yet.