Skip to content

Inconsistent Imports Sorting Order #4648

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

Open
davidBar-On opened this issue Jan 17, 2021 · 3 comments
Open

Inconsistent Imports Sorting Order #4648

davidBar-On opened this issue Jan 17, 2021 · 3 comments
Assignees
Labels

Comments

@davidBar-On
Copy link
Contributor

davidBar-On commented Jan 17, 2021

Input

use ::Foo;
use ::foo;
use ::foo::bar;
use ::foo::Bar;
use Foo;
use ::*;

Output

Same as input.

Expected output

Either:

use ::foo;
use ::Foo;
use ::foo::bar;
use ::foo::Bar;
use ::*;
use Foo;

or:

use ::Foo;
use ::foo;
use ::foo::Bar;
use ::foo::bar;
use ::*;
use Foo;

This issue is based on problems found while developing PR #4591 that related to imports sorting order. The following are the two problems that were identified, but they were not fixed as their fix is not backward compatible with the current imports sorting order.

For the discussion, an import that starts with :: is referred to as it starts with the global prefix segment. The issues are:

  1. Inconsistency in lower and upper case letters sorting order: for simple segments following a global prefix segment, uppercase letters precede lowercase letters. However, in the following segments, lowercase letters precede uppercase letters. E.g., use ::Foo precede use ::foo but use ::foo::bar precede use ::foo::Bar.
    Note that according to the Style Guide, uppercase letters should precede lowercase letters, as this is the ascii-betically order.

  2. ::* is sorted last: it is expected that this import will be sorted as the last of the imports that start with the global prefix, but that it will precede other prefixes.

The root cause for these issues is that if the first segment is the global segment, for sorting purposes it is concatenated with the next segment. E.g. sorting of ::foo is not done by sorting first by the global prefix "::" and then sorting by "foo", but the first element that is sorted is "::foo".

The problem with this is that when the sorted element starts with a letter, Ord for UseSegment cmp() puts lowercase letters before uppercase. However, because the :: was added, compare_as_versions() is used, and that function sort uppercase letters before lowercase letters.

The right behavior, if backward compatibility is ignored, is probably that Ord for UseSegment cmp() will sort according to the ascii-betically order, i.e. uppercase letters before lowercase letters. In addition, the global prefix segment :: should be sorted on is own and not be combined with the following segment.

Meta

  • rustfmt version: 2.0.0-rc.2-nightly (2d52e71 2021-01-05)
  • From where did you install rustfmt?: self build
@calebcartwright
Copy link
Member

Thank you for opening this. Could you extend the snippet to include more non-global use statements as points of comparison? Know there's more detail in the linked issue but will be helpful to have them inline with the issue for direct comparison instead of having to link out to other issues

@davidBar-On
Copy link
Contributor Author

Could you extend the snippet to include more non-global use statements as points of comparison?

Updated the issue description.

@ytmimi
Copy link
Contributor

ytmimi commented Jul 26, 2022

Feels like this is related to #3943

@ytmimi ytmimi added the a-imports `use` syntax label Jul 26, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants