Naios / continuable

C++14 asynchronous allocation aware futures (supporting then, exception handling, coroutines and connections)
https://naios.github.io/continuable/
MIT License
815 stars 44 forks source link

Confusing error regarding `result` from VC++ when making a continuable from a lambda that captures a variable called `result` #55

Open tom-seddon opened 1 year ago

tom-seddon commented 1 year ago

@Naios

Using Continuable 4.1.0

Reproduction steps:

  1. Launch Visual Studio 2019 native tools command prompt
  2. Create folder somewhere and switch to it
    mkdir C:\temp\bug55
    cd /d C:\temp\bug55
  3. Change to folder and clone Continuable
    git clone --recursive https://github.com/naios/continuable
  4. Create test.cpp with the following contents (e.g., via copy con test.cpp)
    #include <continuable/continuable.hpp>
    static void Test() {
        int result = 0;
        cti::make_continuable<int>([result](auto&& promise) {});
    }
  5. Compile
    cl /I .\continuable\include test.cpp /I .\continuable\dep\function2\function2\include

Note probably-unexpected error...

Microsoft (R) C/C++ Optimizing Compiler Version 19.29.30146 for x64
Copyright (C) Microsoft Corporation.  All rights reserved.

test.cpp
C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.29.30133\include\ppltasks.h(1571): warning C4530: C++ exception handler used, but unwind semantics are not enabled. Specify /EHsc
.\continuable\include\continuable/detail/core/base.hpp(143): error C2327: 'Test::<lambda_ce49853aebba6891891f5a54e1664ea4>::result': is not a type name, static, or enumerator
.\continuable\include\continuable/detail/core/base.hpp(168): note: see reference to class template instantiation 'cti::detail::base::proxy_continuable<hint_t,Test::<lambda_ce49853aebba6891891f5a54e1664ea4>>' being compiled
.\continuable\include\continuable/continuable-base.hpp(898): note: see reference to function template instantiation 'auto cti::detail::base::attorney::create_from<_Ty,cti::detail::identity<int>>(T &&,Hint,cti::detail::util::ownership)' being compiled
        with
        [
            _Ty=Test::<lambda_ce49853aebba6891891f5a54e1664ea4>,
            T=Test::<lambda_ce49853aebba6891891f5a54e1664ea4>,
            Hint=cti::detail::identity<int>
        ]
test.cpp(4): note: see reference to function template instantiation 'auto cti::make_continuable<int,Test::<lambda_ce49853aebba6891891f5a54e1664ea4>>(Continuation &&)' being compiled
        with
        [
            Continuation=Test::<lambda_ce49853aebba6891891f5a54e1664ea4>
        ]

In the end I tracked this down to captured variables in msvc apparently giving their lambda's type member variables of the same name. So result is a member variable on the base class for proxy_continuable in this case.

This feels like a msvc problem - looks like clang and gcc must rename the captured variables, or use some other mechanism? - but perhaps it's fixable. I'm afraid I stopped at C++14 so I have no specific suggestions. Maybe a note in the documentation would suffice.

Compiler Explorer example that I think narrows it down to the issue: https://godbolt.org/z/7qz4sd7sT

Thanks,

--Tom

Naios commented 1 year ago

Hey, awesome reproduction!

This looks like a critical compiler bug indeed and you might want to report it to MSVC directly. Additionally you could open a thread on https://www.reddit.com/r/cpp, maybe someone from the MSVC team or someone with deeper knowledge of the MSVC internals could elaborate on it there. Definitly seems like a bug worth elaborating about, because it has a larger impact.

For this particular library it is difficult to work around this bug. Sadly it is impossible to rename the result class just for the reason of this bug for backwards compatibility reasons.

Do you have any suggestions beside a hint in the documentation?