Skip to content

GCC 15 cannot directly compare std::expected in REQUIRE #2977

Open
@Hackerl

Description

@Hackerl

Describe the bug
GCC 15 cannot directly compare std::expected in REQUIRE

Expected behavior
REQUIRE(std::expected<int, std::error_code>{0} == 0) should be compilable.

Reproduction steps
https://godbolt.org/z/xYn1ooPTh

Platform information:

  • OS: Any
  • Compiler+version: GCC v15.1.0
  • Catch version: v3.8.1

Additional context

In file included from <source>:1:
/opt/compiler-explorer/gcc-15.1.0/include/c++/15.1.0/expected: In substitution of 'template<class _Up>  requires !(__is_expected<_Up>) && requires(const _Tp& __t, const _Up& __u) {{__t == __u} -> decltype(auto) [requires std::convertible_to<<placeholder>, bool>];} constexpr bool std::operator==(const expected<int, error_code>&, const _Up&) [with _Up = Catch::ExprLhs<const std::expected<int, std::error_code>&>]':
/opt/compiler-explorer/gcc-15.1.0/include/c++/15.1.0/expected:1175:12:   required by substitution of 'template<class _Up>  requires !(__is_expected<_Up>) && requires(const _Tp& __t, const _Up& __u) {{__t == __u} -> decltype(auto) [requires std::convertible_to<<placeholder>, bool>];} constexpr bool std::operator==(const expected<int, error_code>&, const _Up&) [with _Up = Catch::ExprLhs<const std::expected<int, std::error_code>&>]'
 1175 |             { __t == __u } -> convertible_to<bool>;
      |               ~~~~^~~~~~
<source>:6:5:   required from here
    6 |     REQUIRE(std::expected<int, std::error_code>{0} == 0);
      |                                                       ^
/opt/compiler-explorer/gcc-15.1.0/include/c++/15.1.0/expected:1178:2:   required by the constraints of 'template<class _Tp, class _Er> template<class _Up>  requires !(__is_expected<_Up>) && requires(const _Tp& __t, const _Up& __u) {{__t == __u} -> decltype(auto) [requires std::convertible_to<<placeholder>, bool>];} constexpr bool std::operator==(const expected<_Tp, _Er>&, const _Up&)'
/opt/compiler-explorer/gcc-15.1.0/include/c++/15.1.0/expected:1174:7:   in requirements with 'const _Tp& __t', 'const _Up& __u' [with _Tp = int; _Up = Catch::ExprLhs<const std::expected<int, std::error_code>&>]
/opt/compiler-explorer/gcc-15.1.0/include/c++/15.1.0/expected:1174:14: error: satisfaction of atomic constraint 'requires(const _Tp& __t, const _Up& __u) {{__t == __u} -> decltype(auto) [requires std::convertible_to<<placeholder>, bool>];} [with _Tp = _Tp; _Up = _Up]' depends on itself
 1174 |           && requires (const _Tp& __t, const _Up& __u) {
      |              ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 1175 |             { __t == __u } -> convertible_to<bool>;
      |             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 1176 |           }
      |           ~   
ASM generation compiler returned: 1
In file included from <source>:1:
/opt/compiler-explorer/gcc-15.1.0/include/c++/15.1.0/expected: In substitution of 'template<class _Up>  requires !(__is_expected<_Up>) && requires(const _Tp& __t, const _Up& __u) {{__t == __u} -> decltype(auto) [requires std::convertible_to<<placeholder>, bool>];} constexpr bool std::operator==(const expected<int, error_code>&, const _Up&) [with _Up = Catch::ExprLhs<const std::expected<int, std::error_code>&>]':
/opt/compiler-explorer/gcc-15.1.0/include/c++/15.1.0/expected:1175:12:   required by substitution of 'template<class _Up>  requires !(__is_expected<_Up>) && requires(const _Tp& __t, const _Up& __u) {{__t == __u} -> decltype(auto) [requires std::convertible_to<<placeholder>, bool>];} constexpr bool std::operator==(const expected<int, error_code>&, const _Up&) [with _Up = Catch::ExprLhs<const std::expected<int, std::error_code>&>]'
 1175 |             { __t == __u } -> convertible_to<bool>;
      |               ~~~~^~~~~~
<source>:6:5:   required from here
    6 |     REQUIRE(std::expected<int, std::error_code>{0} == 0);
      |                                                       ^
/opt/compiler-explorer/gcc-15.1.0/include/c++/15.1.0/expected:1178:2:   required by the constraints of 'template<class _Tp, class _Er> template<class _Up>  requires !(__is_expected<_Up>) && requires(const _Tp& __t, const _Up& __u) {{__t == __u} -> decltype(auto) [requires std::convertible_to<<placeholder>, bool>];} constexpr bool std::operator==(const expected<_Tp, _Er>&, const _Up&)'
/opt/compiler-explorer/gcc-15.1.0/include/c++/15.1.0/expected:1174:7:   in requirements with 'const _Tp& __t', 'const _Up& __u' [with _Tp = int; _Up = Catch::ExprLhs<const std::expected<int, std::error_code>&>]
/opt/compiler-explorer/gcc-15.1.0/include/c++/15.1.0/expected:1174:14: error: satisfaction of atomic constraint 'requires(const _Tp& __t, const _Up& __u) {{__t == __u} -> decltype(auto) [requires std::convertible_to<<placeholder>, bool>];} [with _Tp = _Tp; _Up = _Up]' depends on itself
 1174 |           && requires (const _Tp& __t, const _Up& __u) {
      |              ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 1175 |             { __t == __u } -> convertible_to<bool>;
      |             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 1176 |           }
      |           ~   
Execution build compiler returned: 1
Build failed

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions