tcbrindle / NanoRange

Range-based goodness for C++17
Boost Software License 1.0
358 stars 29 forks source link

NanoRange failed to build due to errors C2677 C3536 C2893 C2062 C2607 C2672 C2676 with MSVC on windows #54

Closed spacelg closed 5 years ago

spacelg commented 5 years ago

Environment: Windows Server 2016 + VS2017 + NanoRange master branch latest srouce code.

NanoRange failed to build due to errors C2677 C3536 C2893 C2062 C2607 C2672 C2676 with MSVC on windows. It can be reproduced on master revision 391cc95 . Could you help have a look about this issue? Thanks in advance!

Steps to reproduce the behavior: 1.Open VS2017 x86 Native tools command tool 2.git clone https://github.com/tcbrindle/nanorange d:\NanoRange\src 3.cd D:\NanoRange 4.mkdir build_x86 && pushd build_x86 5.cmake -G "Visual Studio 15 2017" -DCMAKE_SYSTEM_VERSION=10.0.17134.0 -DCMAKE_CXX_STANDARD=17 ..\src\ 6.msbuild /m /p:Configuration=Release;Platform=Win32 nanorange.sln /t:Rebuild

log_x86_build.log

Actual result: D:\NanoRange\src\test\view\filter_view.cpp(45): error C2677: binary '|': no global operator found which takes type D:\NanoRange\src\test\view\filter_view.cpp(48): error C3536: 'rng': cannot be used before it is initialized [D:\NanoRange\build_x86\test\test_nanorange.vcxproj] D:\NanoRange\src\test\view\filterview.cpp(48): error C2893: Failed to specialize function template 'unknown-type nano::ranges::detail::begin::fn::operator ()(T &&) noexcept() const' [D:\NanoRange\build_x86\test\test_nanorange.vcxproj] D:\NanoRange\src\test\view\filter_view.cpp(48): error C2062: type 'unknown-type' unexpected [D:\NanoRange\build_x86\test\test_nanorange.vcxproj] D:\NanoRange\src\test\view\filter_view.cpp(49): error C2607: static assertion failed [D:\NanoRange\build_x86\test\test_nanorange.vcxproj] D:\NanoRange\src\test\view\filter_view.cpp(141): error C2672: 'operator __surrogate_func': no matching overloaded function found [D:\NanoRange\build_x86\test\test_nanorange.vcxproj] D:\NanoRange\src\test\view\filter_view.cpp(135): error C2676: binary '|': 'nano::ranges::iota_view<_Ty,nano::ranges::unreachable_sentinel_t>' does not define this operator or a conversion to a type acceptable to the predefined operator [D:\NanoRange\build_x86\test\test_nanorange.vcxproj]

tcbrindle commented 5 years ago

Hi, thanks for the bug report.

This is a known issue in older MSVC versions that we have a workaround for. I thought it had been fixed in VS 16.1, but apparently not. PR #55 extends the workaround to compiler version 19.22 (VS 16.2), which should fix the problem you're seeing. This might break again when MS release 16.3 if the compiler bug hasn't been fixed, in which case I'll bump the workaround version number again.

(The actual problem appears to be that using a lambda as a template parameter to the rao_proxy class somehow prevents the compiler from finding the overloads of operator| via ADL (or perhaps prevents it from correctly calculating the constraints). Unfortunately I haven't yet been able to come up with a minimal reproducible example to submit a bug report -- every cut-down version I've tried seems to work correctly, so I'm not sure exactly what's causing the problem!)

tcbrindle commented 5 years ago

Hi @spacelg, this should now be fixed in master (at least until the next Visual Studio update). Can you give it a try and let me know if it works?

spacelg commented 5 years ago

Hi @tcbrindle, thanks for your reply.

We build NanoRange with latest commit 88e771d. These errors still exist and it seems that they have not been fixed. Could you help have a look about this issue? Thanks in advance!

log_x86_build.log

Thanks, Lin

spacelg commented 5 years ago

Hi @tcbrindle,

We use VS2017 but the compiler uses the latest binary. We communicate with the MSVC team.

Updated the logic to enable source workaround to

if defined(_MSC_VER) && _MSC_VER < 1923

But latest compiler uses 1923, so the source workaround is not applied. Probably want to change the condition to _MSC_VER <= 1923

Thanks, Lin

CaseyCarter commented 5 years ago

@tcbrindle, what's the "supposedly fixed" bug? Do you have a DevCom link? (If it's a lambda bug, it might only be "fixed" with the new lambda processor, which is only active in /std:c++latest.)

tcbrindle commented 5 years ago

Hi @spacelg, thanks again for the bug report. I've updated the workaround version number again in PR #57, but it will probably need to be changed again when _MSC_VER is next incremented.

@CaseyCarter I don't have a bug number (yet) because I haven't been able to come up with a minimal reproducible example -- everything I've tried on Godbolt works correctly! But if it only works with /std:c++latest then that would explain why my reduced cases work, and also why it appeared to (briefly) be fixed when I tried out 16.1.

(The problem appears to be that my detail::rao_proxy class inherits from a lambda which is supplied via a template parameter, and that seems to prevent the compiler from finding the overloads of operator| in the same namespace.)

CaseyCarter commented 5 years ago

The problem appears to be that my detail::rao_proxy class inherits from a lambda which is supplied via a template parameter, and that seems to prevent the compiler from finding the overloads of operator| in the same namespace.

range-v3 is currently failing to build (but not in /std:c++latest mode) with a similar syndrome, minus the "inheritance" bit. pipeable_binder<bind_back_fn<some_lambda, args...>> doesn't inherit from some_lambda, but having a lambda type as a template parameter seems to be breaking ADL for |.

I'll investigate.

tcbrindle commented 5 years ago

@CaseyCarter Thanks!

@spacelg I've now merged #57 which uses the MSVC workaround for_MSC_VER < 1924. Again, this may need to be updated when MS next bump the version number. Please let me know if you have any other problems.

QuellaZhang commented 5 years ago

@tcbrindle This issue still can be reproduced on MSVC even through I use the latest NanoRange source code. This issue has resolved with the new lambda processor. The old processor cannot handle complex explicit return types in lambdas, and this is what is triggering the original error, the rest are cascades.

I try to add /experimenal:newLambdaProcessor under default and /permissive- modes this issue is gone. Casey said "but not in /std:c++latest mode" since C++Latest already uses this switch implicitly.

If need open a new issue please let me know.

tcbrindle commented 5 years ago

Hi @spacelg and @QuellaZhang,

I've made another attempt to solve this, thanks to the information @QuellaZhang provided about the problem being related to the lambda's explicit return type. I've also got rid of the version checking macro -- the "workaround" (using a deduced rather than explicit return type) is used unconditionally for now if the compiler is MSVC.

Please let me know if this fixes the issue for you :)

QuellaZhang commented 5 years ago

@tcbrindle Thank you very much. The fix works fine. Now Nanorange compiles well on MSVC without /experimenal:newLambdaProcessor.

tcbrindle commented 5 years ago

@QuellaZhang Thanks for the info. Hopefully I can now close this bug for good!

If you have any more problems with NanoRange please file them :)