It turns out that the order in which we provide completions for expressions is nondeterministic. This leads to confusing user experience and also breaks the reproducer tests (as two LLDB tests can go out of sync due to the non-determinism in the completion lists)
The reason for the non-determinism is that the CompletionConsumer informs us about decls in the order in which it finds declarations in the lookup store of the DeclContexts it visits (mainly this snippet in SemaLookup.cpp):
// Enumerate all of the results in this context. for (DeclContextLookupResult R : Load ? Ctx->lookups() : Ctx->noload_lookups(/*PreserveInternalState=*/false)) { [...]
This storage of the lookup is sorted by pointer values (see the hash of DeclarationName) and can therefore be non-deterministic. The LLDB code completion consumer that receives these calls originally expected that the order of declarations is defined by Clang, but it seems the API expects the client to provide an order to the completions.
This patch fixes the issue as follows:
- We sort the completions we get from Clang alphabetically and also by the priority value we get from Clang (with priority value sorting having precedence over the alphabetical sorting)
- We make all the functions/variables that touch a completion before the sorting const-qualified. The idea is that this should prevent that we never have observable side-effect from touching these declarations in a non-deterministic order (e.g., we don't try to complete the type by accident).
This way we behave like the other parts of Clang which also sort the results by some deterministic value (usually the name or something computed from a name, e.g., edit distance to a given string).
We most likely also need to fix the Clang code to make the loop I listed above deterministic to prevent these issues in the future (tracked in rdar://63442513 ). This wouldn't replace the functionality provided in this patch though as we would still need the priority and overall alphabetical sorting.
Note: I had to increase the lldb-vscode completion limit to 100 as the tests look for strings that aren't in the first 50 results anymore due to variable names starting with letters like 'v' (which are now always shown much further down in the list due to the alphabetical sorting).
Fixes rdar://63200995
Any reason you didn't make this the regular comparison operator for CompletionWithPriority?