-
Notifications
You must be signed in to change notification settings - Fork 4k
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
List SetCount/AsSpan optimization should produce a list with same capacity as List made with new/Add #72318
Comments
Agree. Though note that we have permitted the compiler to do differently if it thinks it can do better. For example, like how we call So it would be fine for the compiler to bypass the constructor if it thinks it is in a better state. That includes in ways that might be observable though things like 'Capacity' (since that's a hint, and not something we guarantee). What's odd in this case is that the path we're taking produces what seems to be a worse result for the user (since it overallocates). So, in a sense, it's an odd-deoptimization. We def don't want those. But, to be clear, we should be willing to throw in optimizations when they going to be very good for the ecosystem, even if potentially minorly observable through things like capacity. The goal is to follow the intent and spirit of the APIs requirements here. Not to produce exactly identical semantics. |
For context: https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.list-1.capacity?view=net-8.0
There is no requirement (or desire for requirement) at the language level that this always return the same value. The only requirement is that we produce an instance that legally follows these rules and contains the elements. The only invariants we defined (for well behavedness) were things like: If the collection provides a Count/Length, then iterating hte elements in it shoudl produce the same number of elements, and things like that. |
I agree that yes we have the right to deviate on the capacity when optimizing. But, if we do, let's make sure it's because our different behavior is part of a better result "overall", rather than being a difference which is arbitrary, occurring by accident, or, which perhaps yields a worse result "overall". |
100% agree @RikkiGibson :) |
In absence of CollectionsMarshal.SetCount/AsSpan, the above program outputs 1, but in presence of those methods, it outputs 4.
It feels like the observable behavior of the optimized version should be the same as the non-optimized version, except if we have some really compelling reason to deviate.
Hopefully, we can simply fix by calling the 'List(int capacity)' constructor in the optimized case in addition to the non-optimized case (where we are already doing this.)
Relevant spec bits from https://github.com/dotnet/csharplang/blob/main/proposals/csharp-12.0/collection-expressions.md#known-length-translation:
In other words, the default expectation of an optimization for List codegen would be that it behaves the same as the quoted codegen.
The text was updated successfully, but these errors were encountered: