microsoft / STL

MSVC's implementation of the C++ Standard Library.
Other
9.94k stars 1.46k forks source link

`<filesystem>`: compiler error using `directory_iterator`/`recursive_directory_iterator` inside a struct/class with modules #3661

Open 16-Bit-Dog opened 1 year ago

16-Bit-Dog commented 1 year ago

Describe the bug

when recursive_directory_iterator or directory_iterator is used inside a modules export block, the following code will compile; if this same code is then wrapped by a struct/class the code will never compile when the method is called with the following issue(s) of 2 depending on the code setup:

  1. missing std::partial_order from #<compare>, although if this header is included (which should not be required) the following error will happen instead

  2. ..\include\type_traits(2118,13): error C2678: binary '&': no operator found which takes a left-hand operand of type '_Bitmask' (or there is no acceptable conversion)
         with
         [
             _Bitmask=__std_fs_file_attr
         ]

Command-line test case

main.cpp

#include <compare> 

import brokenIter;

int main() {
    /*
    without #include <compare> code will complain about missing std::partial_order from #compare
    with #include <compare> the code during build output will generate the given error (which is also reflected as a compile error):
    ..\include\type_traits(2118,13): error C2678: binary '&': no operator found which takes a left-hand operand of type '_Bitmask' (or there is no acceptable conversion)
         with
         [
             _Bitmask=__std_fs_file_attr
         ]
    */

    //the problem functions defined are the 2 below, a static or non static method both exibits the compile error described above
    thing thingO = thing();
    thingO.iterDirBroken1(); 
    thing::iterDirBroken2();  

    //the following function will work though if the previous 2 are not compiled
    noStructIter();

    return 0;
}

brokenIter.ixx

module;

#include <filesystem>

export module brokenIter;

export{

    struct thing {
        void iterDirBroken1() {
            for (const auto& i : std::filesystem::recursive_directory_iterator(".")) {

            }
        }

        inline static void iterDirBroken2() {
            for (const auto& i : std::filesystem::recursive_directory_iterator(".")) {

            }
        }
    };
    void noStructIter(){
        for (const auto& i : std::filesystem::recursive_directory_iterator(".")) {

        }
    }
}

compile command: cl /EHsc /W4 /WX /std:c++latest .\brokenIter.ixx .\main.cpp

Expected behavior

code does not compile with or without #<compare> due to struct/class method using recursive_directory_iterator or directory_iterator (if you remove #<compare> there will be a different compile error which still is not supposed to be there)

STL version

Microsoft Visual Studio Community 2022
Version 17.6.0 Preview 4.0 although the behavior happened on 17.5.4, and 17.6 Preview 2.0, and Preview 3.0

Additional context

exact same (minimum reproducible code) I used to get a compile error: https://github.com/16-Bit-Dog/BrokenFileSystemOn17.6

same compiler issue but elaborated upon in relation to #3330

StephanTLavavej commented 1 year ago

FYI @cdacamar this looks like a compiler bug.

StephanTLavavej commented 1 year ago

I observe that this works if broken_iter.ixx says import std;.

16-Bit-Dog commented 1 year ago

The following imports should not be required though, no?

matlimatli commented 8 months ago

This is still present in 17.8. I noticed that by replacing #include <compare> with #include <filesystem> in your example, there are no errors. Whatever that means.

In my case, the problem occurs when using std::filesystem:exists() in a member function in a class in module. Indeed, if I replace the content of the functions of your example with std::filesystem::exists("."); I get the same error. The workaround mentioned above works in this minimal example, but not in my real code.

oliverportcnc commented 5 months ago

Using #include <filesystem> at the module import location (in the global module fragment, if necessary) definitely fixes the issue for me.

StephanTLavavej commented 2 months ago

Does this still repro with VS 2022 17.10 or later? I improved the STL so that include-before-import (but not the other order) works, with #4154 in VS 2022 17.10.

JulZimmermann commented 4 weeks ago

I can reproduce this problem with VS 2022 17.10.3