-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
identical() for strings is not transitive #27681
Comments
I assume this is the VM. The rules for canonicalization of strings are not trivial. The expression So, the first test is true because the test is compile-time constant. Or, to put it differently: It's not a problem with transitivity - it's the fact that var x = "a" + "b";
print(identical("a" + "b", x)); // false Even if So, the behavior is allowed by the specification. I'll check if we have a bug open for changing the language to require canonicalization of compile-time constant string expressions. Otherwise we might want that. Considering the closing message on #1918, it's probably an oversight that the specification doesn't actually require canonicalization. |
There actually does seem to be a bug in the VM: var r = [];
for (var i = 0; i < r; i++) r.add("a" + "b");
print(identical(r[0], r[1])); This prints
This example shows the value of the constant expression Arguably, the spec saying:
does require that the |
I think this confirms that the vm ought to consistently detect constant expressions of type About the invocations of |
See also issue #25024. Back when Dart was still Dash, I remember discussions that the language shall not require all expressions that can be compile-time constants to be canonicalized, due to the runt-time cost. You don't want to spend the time to canonicalize every "a"+"b" (xyz+"b", "a"+X.c, ...) for the rare case where it's needed. |
If we don't canonicalize all compile-time constant string expressions, then we need to make it predictable for users when they are canonicalized and when they are not. Is the VM following a rule or is it more ad-hoc which compile-time string expressions are canonicalized and which are not? I wouldn't mind if |
I suspect this will be obsolete with the new front-end, but it needs to be verified. |
I tried to verify that this was fixed, and write a regression test. It seems that the behavior has changed since this bug was opened, but void main() {
String ab = 'ab';
print(identical('a' + 'b', 'ab')); // false
print(identical('ab', ab)); // true
print(identical('a' + 'b', ab)); // false
var x = "a" + "b";
print(identical("a" + "b", x)); // false
var r = [];
for (var i = 0; i < 10; i++) r.add("a" + "b");
print(identical(r[0], r[1])); // false
} Note that the first print has switched from true to false. Is this the intended behavior now? |
We don't specify that every constant expression must be evaluated at compile time, only that an expression must satisfy a very strict set of rules in order to be a constant expression, and a compiler is then allowed to evaluate it at compile time. So it's OK for Dart compilers to postpone the evaluation of With specific expressions we have a more strict rule: A class C {
final String s;
const C(this.s);
}
void main() => print(identical(const C('a' + 'b'), const C('ab'))); // 'true'. I'll close this issue because the transitivity discrepancy has been resolved, and because the more general issue about canonicalization of strings is handled in dart-lang/language#985. |
The text was updated successfully, but these errors were encountered: