Skip to content

[BUG] Lowered UFCS doesn't SFINAE #497

Description

@JohelEGP

Title: Lowered UFCS doesn't SFINAE.

Description:

Suppose #496 was fixed.
Attempting to check whether a UFCS candidate expression is well-formed
results in a hard error inside the UFCS machinery.

Minimal reproducer (https://cpp2.godbolt.org/z/Pn46vKMej):

#include "cpp2util.h"
template<typename T> [[nodiscard]] auto f()
requires (CPP2_UFCS_0_NONLOCAL(a, T()))
  {
}
struct B { };
static_assert([]<class T>() {
  return !requires { f<T>(); };
}.template operator()<B>());
Commands:
cppfront -clean-cpp1 main.cpp2
clang++17 -std=c++23 -stdlib=libc++ -lc++abi -pedantic-errors -Wall -Wextra -Wconversion -I . main.cpp

Expected result:

The assertion to pass.

Actual result and error:

Output:
build/_cppfront/main.cpp:3:32: error: use of undeclared identifier 'a'
    3 | requires (CPP2_UFCS_0_NONLOCAL(a, T()))
      |                                ^
build/_cppfront/main.cpp:3:11: note: in instantiation of function template specialization 'f()::(anonymous class)::operator()<B>' requested here
    3 | requires (CPP2_UFCS_0_NONLOCAL(a, T()))
      |           ^
raw.githubusercontent.com/hsutter/cppfront/main/include/cpp2util.h:746:47: note: expanded from macro 'CPP2_UFCS_0_NONLOCAL'
  746 | #define CPP2_UFCS_0_NONLOCAL(FUNCNAME,PARAM1) \
      |                                               ^
build/_cppfront/main.cpp:3:11: note: while substituting template arguments into constraint expression here
    3 | requires (CPP2_UFCS_0_NONLOCAL(a, T()))
      |           ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
raw.githubusercontent.com/hsutter/cppfront/main/include/cpp2util.h:746:47: note: expanded from macro 'CPP2_UFCS_0_NONLOCAL'
  746 | #define CPP2_UFCS_0_NONLOCAL(FUNCNAME,PARAM1) \
      |                                               ^
  747 | [](auto&& obj) CPP2_FORCE_INLINE_LAMBDA -> decltype(auto) { \
      | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  748 |     if constexpr (requires{ CPP2_FORWARD(obj).FUNCNAME(); }) { \
      |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  749 |         return CPP2_FORWARD(obj).FUNCNAME(); \
      |         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  750 |     } else { \
      |     ~~~~~~~~~~
  751 |         return FUNCNAME(CPP2_FORWARD(obj)); \
      |         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  752 |     } \
      |     ~~~
  753 | }(PARAM1)
      | ~~~~~~~~~
build/_cppfront/main.cpp:8:22: note: while checking constraint satisfaction for template 'f<B>' required here
    8 |   return !requires { f<T>(); };
      |                      ^
build/_cppfront/main.cpp:8:22: note: in instantiation of function template specialization 'f<B>' requested here
build/_cppfront/main.cpp:8:22: note: in instantiation of requirement here
    8 |   return !requires { f<T>(); };
      |                      ^~~~~~
build/_cppfront/main.cpp:9:12: note: in instantiation of function template specialization '(anonymous class)::operator()<B>' requested here
    9 | }.template operator()<B>());
      |            ^
build/_cppfront/main.cpp:3:32: error: no matching function for call to 'a'
    3 | requires (CPP2_UFCS_0_NONLOCAL(a, T()))
      |                                ^
raw.githubusercontent.com/hsutter/cppfront/main/include/cpp2util.h:751:16: note: expanded from macro 'CPP2_UFCS_0_NONLOCAL'
  751 |         return FUNCNAME(CPP2_FORWARD(obj)); \
      |                ^~~~~~~~
build/_cppfront/main.cpp:3:11: note: in instantiation of function template specialization 'f()::(anonymous class)::operator()<B>' requested here
    3 | requires (CPP2_UFCS_0_NONLOCAL(a, T()))
      |           ^
raw.githubusercontent.com/hsutter/cppfront/main/include/cpp2util.h:746:47: note: expanded from macro 'CPP2_UFCS_0_NONLOCAL'
  746 | #define CPP2_UFCS_0_NONLOCAL(FUNCNAME,PARAM1) \
      |                                               ^
build/_cppfront/main.cpp:3:11: note: while substituting template arguments into constraint expression here
    3 | requires (CPP2_UFCS_0_NONLOCAL(a, T()))
      |           ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
raw.githubusercontent.com/hsutter/cppfront/main/include/cpp2util.h:746:47: note: expanded from macro 'CPP2_UFCS_0_NONLOCAL'
  746 | #define CPP2_UFCS_0_NONLOCAL(FUNCNAME,PARAM1) \
      |                                               ^
  747 | [](auto&& obj) CPP2_FORCE_INLINE_LAMBDA -> decltype(auto) { \
      | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  748 |     if constexpr (requires{ CPP2_FORWARD(obj).FUNCNAME(); }) { \
      |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  749 |         return CPP2_FORWARD(obj).FUNCNAME(); \
      |         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  750 |     } else { \
      |     ~~~~~~~~~~
  751 |         return FUNCNAME(CPP2_FORWARD(obj)); \
      |         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  752 |     } \
      |     ~~~
  753 | }(PARAM1)
      | ~~~~~~~~~
build/_cppfront/main.cpp:8:22: note: while checking constraint satisfaction for template 'f<B>' required here
    8 |   return !requires { f<T>(); };
      |                      ^
build/_cppfront/main.cpp:8:22: note: while substituting deduced template arguments into function template 'f' [with T = B]
build/_cppfront/main.cpp:8:22: note: in instantiation of requirement here
    8 |   return !requires { f<T>(); };
      |                      ^~~~~~
build/_cppfront/main.cpp:9:12: note: in instantiation of function template specialization '(anonymous class)::operator()<B>' requested here
    9 | }.template operator()<B>());
      |            ^
2 errors generated.
References:

Activity

  1. JohelEGP commented on Jun 6, 2023

    @JohelEGP
    Author
  2. JohelEGP commented on Jun 6, 2023

    @JohelEGP
    Author
  3. JohelEGP commented on Jun 7, 2023

    @JohelEGP
    ContributorAuthor

    There's also noexcept propagation.
    Building on #490 (comment): https://compiler-explorer.com/z/PvTx5qrr1.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions