<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/110146>110146</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            C++20 module error: moving the function into module causes the wrong template instantiation
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            new issue
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          stripe2933
      </td>
    </tr>
</table>

<pre>
    Following code works with Clang 19 + libc++.

`main.cpp`
```c++
import std;

#define FWD(...) static_cast<decltype(__VA_ARGS__)&&>(__VA_ARGS__)

namespace ranges::views {
    constexpr auto deref = std::views::transform([](auto &&x) { return *FWD(x); });
}

int main() {
    auto opts = { std::optional { 1 }, std::optional { 2 } };
    std::println("{}", opts | ranges::views::deref); // [1, 2]
}
```

But this does not:

`main.cpp`
```c++
import std;
import ranges;

int main() {
    auto opts = { std::optional { 1 }, std::optional { 2 } };
 std::println("{}", opts | ranges::views::deref);
}
```

`ranges.cppm`
```c++
export module ranges;

import std;

#define FWD(...) static_cast<decltype(__VA_ARGS__)&&>(__VA_ARGS__)

namespace ranges::views {
    export constexpr auto deref = std::views::transform([](auto &&x) { return *FWD(x); });
}
```

```
====================[ Build | hello | macos-clang-19 ]==========================
/opt/homebrew/Cellar/cmake/3.30.0/bin/cmake --build /Users/stripe2933/Desktop/hello/build/macos-clang-19 --target hello -j 6
[3/4] Building CXX object CMakeFiles/hello.dir/main.cpp.o
FAILED: CMakeFiles/hello.dir/main.cpp.o 
/opt/homebrew/opt/llvm@19/bin/clang++ -nostdinc++ -nostdlib++ -isystem /opt/homebrew/opt/llvm@19/include/c++/v1 -fexperimental-modules-reduced-bmi -std=gnu++23 -arch arm64 -isysroot /Applications/Xcode-beta.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.0.sdk -fcolor-diagnostics -MD -MT CMakeFiles/hello.dir/main.cpp.o -MF CMakeFiles/hello.dir/main.cpp.o.d @CMakeFiles/hello.dir/main.cpp.o.modmap -o CMakeFiles/hello.dir/main.cpp.o -c /Users/stripe2933/Desktop/hello/main.cpp
/Users/stripe2933/Desktop/hello/main.cpp:6:29: error: invalid operands to binary expression ('std::initializer_list<std::optional<int>>' (aka 'initializer_list<optional<int>>') and 'const __range_adaptor_closure_t<__bind_back_t<__fn, tuple<(lambda at /Users/stripe2933/Desktop/hello/ranges.cppm:8:57)>>>' (aka 'const std::__1::ranges::__range_adaptor_closure_t<std::__bind_back_t<std::__1::ranges::views::__transform::__fn, std::__1::tuple<ranges::views::(lambda at /Users/stripe2933/Desktop/hello/ranges.cppm:8:57)>>>'))
    6 | std::println("{}", opts | ranges::views::deref);
      | ~~~~ ^ ~~~~~~~~~~~~~~~~~~~~
/opt/homebrew/opt/llvm@19/include/c++/v1/cstddef:73:45: note: candidate function not viable: no known conversion from 'std::initializer_list<std::optional<int>>' (aka 'initializer_list<optional<int>>') to 'byte' for 1st argument
   73 | _LIBCPP_HIDE_FROM_ABI inline constexpr byte operator|(byte __lhs, byte __rhs) noexcept {
      |                                             ^ ~~~~~~~~~~
/opt/homebrew/opt/llvm@19/include/c++/v1/__charconv/chars_format.h:34:53: note: candidate function not viable: no known conversion from 'std::initializer_list<std::optional<int>>' (aka 'initializer_list<optional<int>>') to 'chars_format' for 1st argument
 34 | inline _LIBCPP_HIDE_FROM_ABI constexpr chars_format operator|(chars_format __x, chars_format __y) {
      | ^ ~~~~~~~~~~~~~~~~
/opt/homebrew/opt/llvm@19/include/c++/v1/future:431:47: note: candidate function not viable: no known conversion from 'std::initializer_list<std::optional<int>>' (aka 'initializer_list<optional<int>>') to 'launch' for 1st argument
  431 | inline _LIBCPP_HIDE_FROM_ABI constexpr launch operator|(launch __x, launch __y) {
      |                                               ^ ~~~~~~~~~~
/opt/homebrew/opt/llvm@19/include/c++/v1/bitset:932:1: note: candidate template ignored: could not match 'bitset' against 'std::initializer_list'
  932 | operator|(const bitset<_Size>& __x, const bitset<_Size>& __y) _NOEXCEPT {
      | ^
/opt/homebrew/opt/llvm@19/include/c++/v1/__ranges/range_adaptor.h:71:1: note: candidate template ignored: constraints not satisfied [with _Range = std::initializer_list<std::optional<int>> &, _Closure = const __range_adaptor_closure_t<__bind_back_t<__fn, tuple<(lambda at /Users/stripe2933/Desktop/hello/ranges.cppm:8:57)>>> &]
   71 | operator|(_Range&& __range, _Closure&& __closure) noexcept(is_nothrow_invocable_v<_Closure, _Range>) {
      | ^
/opt/homebrew/opt/llvm@19/include/c++/v1/__ranges/range_adaptor.h:69:12: note: because 'invocable<const std::__1::ranges::__range_adaptor_closure_t<std::__bind_back_t<std::__1::ranges::views::__transform::__fn, std::__1::tuple<ranges::views::(lambda at /Users/stripe2933/Desktop/hello/ranges.cppm:8:57)> > > &, std::initializer_list<std::__1::optional<int> > &>' evaluated to false
 69 |   requires invocable<_Closure, _Range>
      | ^
/opt/homebrew/opt/llvm@19/include/c++/v1/__concepts/invocable.h:28:3: note: because 'std::invoke(std::forward<_Fn>(__fn), std::forward<_Args>(__args)...)' would be invalid: no matching function for call to 'invoke'
   28 |   std::invoke(std::forward<_Fn>(__fn), std::forward<_Args>(__args)...); // not required to be equality preserving
      | ^
/opt/homebrew/opt/llvm@19/include/c++/v1/__ranges/range_adaptor.h:77:52: note: candidate template ignored: constraints not satisfied [with _Closure = std::initializer_list<std::optional<int>> &, _OtherClosure = const __range_adaptor_closure_t<__bind_back_t<__fn, tuple<(lambda at /Users/stripe2933/Desktop/hello/ranges.cppm:8:57)>>> &]
   77 | [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator|(_Closure&& __c1, _OtherClosure&& __c2) noexcept(
      | ^
/opt/homebrew/opt/llvm@19/include/c++/v1/__ranges/range_adaptor.h:75:11: note: because 'std::initializer_list<std::__1::optional<int>> &' does not satisfy '_RangeAdaptorClosure'
   75 | template <_RangeAdaptorClosure _Closure, _RangeAdaptorClosure _OtherClosure>
      | ^
/opt/homebrew/opt/llvm@19/include/c++/v1/__ranges/range_adaptor.h:62:32: note: because '!ranges::range<remove_cvref_t<initializer_list<optional<int> > &> >' evaluated to false
   62 | concept _RangeAdaptorClosure = !ranges::range<remove_cvref_t<_Tp>> && requires {
      | ^
/opt/homebrew/opt/llvm@19/include/c++/v1/valarray:2858:1: note: candidate template ignored: requirement '__is_val_expr<std::initializer_list<std::__1::optional<int>>>::value' was not satisfied [with _Expr1 = std::initializer_list<std::optional<int>>, _Expr2 = __range_adaptor_closure_t<__bind_back_t<__fn, tuple<(lambda at /Users/stripe2933/Desktop/hello/ranges.cppm:8:57)>>>]
 2858 | operator|(const _Expr1& __x, const _Expr2& __y) {
      | ^
/opt/homebrew/opt/llvm@19/include/c++/v1/valarray:2867:1: note: candidate template ignored: requirement '__is_val_expr<std::initializer_list<std::__1::optional<int>>>::value' was not satisfied [with _Expr = std::initializer_list<std::optional<int>>]
 2867 | operator|(const _Expr& __x, const typename _Expr::value_type& __y) {
      | ^
/opt/homebrew/opt/llvm@19/include/c++/v1/valarray:2876:1: note: candidate template ignored: requirement '__is_val_expr<std::__1::ranges::__range_adaptor_closure_t<std::__bind_back_t<std::__1::ranges::views::__transform::__fn, std::__1::tuple<ranges::views::(lambda at /Users/stripe2933/Desktop/hello/ranges.cppm:8:57)>>>>::value' was not satisfied [with _Expr = __range_adaptor_closure_t<__bind_back_t<__fn, tuple<(lambda at /Users/stripe2933/Desktop/hello/ranges.cppm:8:57)>>>]
 2876 | operator|(const typename _Expr::value_type& __x, const _Expr& __y) {
      | ^
1 error generated.
ninja: build stopped: subcommand failed.
```

Even if I removed `-fexperimental-modules-reduced-bmi` argument, it still throws errors.
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzsWs1y2zgSfhr4gpJKBCRSOuigH2s3tZNNajK7mxsLJCEJMQhwAFCy55Bn32qAomhbcuTEniRTo1JiEj-NxtfdXzdIMWvFRnE-RaM5Gi2vWO222kytM6LiZELpVaaLu-lKS6n3Qm1wrguO99rcWLwXbosXkqkNjiYYkTmWIssRmSMy76PBEg1mzf_xoGRC9fOqQvGgbQvfZkJoFWWljcPWFYjO74kgtOBroThe_W-JyLjf7yMywdYxJ_I0Z9Yhuih4Lt1dxREZp-l_Z-ns1398SFNEJojE8KXXj3s6ayhWcluxnGPD1IZbRGeIznaC7y1GSaMOxhjnWlnHbyuDWe00Lrjha4zoMujdTgqXzjBl19qUiIwDyIiM_byg1S3sAyVzbLirjcKIzMIWoQPROUbJMlw1uibLrtJCOQzggvQg6KinX0VXznrlYI1WQV05oRWTvjUKayzOdBPo9kNoR3g7tjJCORkUILA-yCIgLiydLB7jGS49cIddkhUiK4xG8wimEsDpwX4PHtPd_rx22G2FxYXmFivtQPJLuV7TdNB-_v1xf1nQLwEYxYMgCCAsv4Ahv_WAlbqoJT-D208R4c1GfpBAP2OXe410-fXf0RzPayEL7zZbLqX2VyXLte3lQPA9IPjRNyxx8tvYfaUrh8hqq0ueGb5HZLXgUjKDyCov2Q1HZEX7dNAfILLKIOJCM-71sqA1Wf3HcmMRWR3zFiKrJbc3TlcgGvYEs2E8IqsHO-v1HDMb7pq99z7huNFtNAdBQzRaBoQgAy4-fsQ6-8Rzhxdv2Q1fCcntYZF-IYxfIHBOXwdBq9mbX66XiM4umYLPAxMapNyVaDiIJkdAYCshEnFPaesKofJ791Jkh3th76zjJb5sAaFyWRdghEOok9Uuwr01v624ESVXjsleCHnbM7yoc170slLgno-S5UbVYSKhuMdMvsXMlPEw6GG0dqDIrKqkyBmwHwDzEcqMXsYd67MKLLjQynHlrDfrjktdcQDtvWQOQg7a37L83YeP_appejDyw_Jfx0HRqD_o2-IG99a5ltr0CsE2AJPILe69XeLe298uslTv7eqScf0Co-HgkoGlLkpW4Z6-bPn8Gc7f5sGDdz13Hp3FiM6AoWaYG6MNXAi1Y1IUGGBmqrDYaZwJxcwdkKjh1goNXDdGJGlZUyjhBJPiD25SKTyzP0qBiC6EcsDoQOoJiGA3DCOSnJh9ZhIwLlPAEImncpymnvhTVrDKaZPmUtva8BRkpGkmVJFmLL9p7tcKEqqrK8kRXSAylqzMCoaZewbs3exJZ2NEZ6PE0_z1qb0FNVsw0jQKF9189dQmOjPv7-ZpkZ00lqbHRNY0BBweSzggc0bS6wHmE_7kmK5jn69eozjC_gMzPn_-_Bmj0bW_ePh5DmOfJlS4ta4o-BrRWUIRnQ1HEF9KOw5_c6YKUTDH8bpWOXg7dOGdYJnkYSC-UXqvoGjZcePDbm000Pz3CTxf-CTZneMgZa0NjqzDzGxqyBktvAn18Ka_vJkv3r9P__lmeZ2ufn33Np3N32ChJFSExzoMxAWucdqgBILSN6Wp3FqwcHNn4G6Clea3Oa_c_eouGPQ5n_t2fxFrp2m-ZQaMBX1bZmwKMcdcf4vojA7B7-lfwQO6e3vCE-jQW6Wx-Gl3OPpBV-gDf7jXlaa34BUP2u4eHdmCS5wK7xcx9rp2tQEjDSlw5zD5KxhWslrl26eCe0ij5xg1CHxgzqaxMWR7d86Ez_u8QlxnwlnuEJ1NKEF0Fp22tOMlFKoci43Shhe-V9ey8KYvmcu3nj2DMJJgtmECSoMnTU6SAxwTSjwcD0LDVxcHDRfpB_EH91aN20B5aoTHPP33u-uPi-v3v50JoBcixyZBN-XAodbx3JhEz8VVWWeYUM4_IcKWOWHXghcYjeb-IWb6Kyxy_2T_3HgKp_wFThehHPPSftiq02t7eMQGWTg64S4BlvD04rCJ7hbbnvxwf8y4iIyFTZV2W6P3qVA7nQOdpTvYYzt_0UDvXewcJb--R8VwpolI16UynrPa8sCNjfKILv6uz59wLdz-C6FwUSy12j4KqlZUSFZ8x2TNHC8g_ayZtLzxlXjSML_hv9fCcIu7FjvtbK_mZblW4P7Wj2q08D5GACl6xsU6SO30DUdk3LastdkzU8BOVurwgBMsPrkHcWfYzGzsYSCDazIJD1MBxb1PMhk_HNyb-sJnHKE2xxIEcnrOpGyS_UGxNsNgMm5g_5OUP74kABJvbO2dIeOY_14zKdwdrgy33OyE2nyf3ASV3Yi8aHLqJpRvT0_v3JabnzNHJY0d52g0V7oQNgenGS3RaPnF2rJ5J3MvvT1KY9EjhI595EF2-z7uNYJEFX2ZRb6Gb1svSdq3aY073oH0QJ6zoE0Lz5EPkpHHoXVycJQTU_BjQn444J4BXpOsnyoJIIbpuZIAkaibVENlRBeGl3rH03xn-NpHyiXHqk6aw19KdRjHoa5v0sxpAP1bxws1TH-ruqaPj0n0FYuxHZPMGHbn0-Jo_LxyvlEQzpneLVNh0x2TKYR519G_Ogj819dKTNb-4dWenSXn69vKRN9GzT4QQA7xcn5AJj6yMJjr7MEygPHoNBn21jlC_lmeFSc_u2d9o2N1zBYnT5vtkdXcXcUVK3nTfVQ7DS_g_3RrJvHrWPPvM9yJgP8qR_3BmSuJz4bAJc7-kNEuDIEovCvFG65gXV40P41TQn1ivqzwP2KwTldVcFxbZ7kuS6YKvGZCtjNO_g7kescVFmv8BofUXmAUD778ch7Fg-PTWrLAwmHrBJz2tkbvbdDZ9q-KKS0mdMKu-DRKSEKTwYTGV9vpJBrTnMZxxnieJSTmfDLOingwGPHBOIriKzElAzIcTEgcJdGIDvvDnAwmQ7LO4mycZ9EEDQe8ZEL2gQn62myuhLU1n0bRIBrGV5JlXFr_s0RCFN9j34sIQaPllZnCpF5WbywaDoAK7VGME07y6aL5zcHg8Guk9o11qeF0iN2287xdKKcPA32RZ33_3mgY2ZKLso4pJ_zPFK5qI6db5yofif5guhFuW2f9XJcHggt_epXRn3gOtOd3AX7dbHM3Jf8PAAD__6WYo50">