[all-commits] [llvm/llvm-project] 16f349: [libc++] restrict the expected conversion construc...

Hui via All-commits all-commits at lists.llvm.org
Wed Jun 26 04:11:20 PDT 2024


  Branch: refs/heads/main
  Home:   https://github.com/llvm/llvm-project
  Commit: 16f349251fabacfdba4acac3b25baf0e6890c1a0
      https://github.com/llvm/llvm-project/commit/16f349251fabacfdba4acac3b25baf0e6890c1a0
  Author: Hui <hui.xie1990 at gmail.com>
  Date:   2024-06-26 (Wed, 26 Jun 2024)

  Changed paths:
    M libcxx/include/__expected/expected.h
    M libcxx/test/std/utilities/expected/expected.expected/ctor/ctor.copy.pass.cpp

  Log Message:
  -----------
  [libc++] restrict the expected conversion constructor not compete against copy constructor (#96101)

fixes #92676

So right now clang does not like 
```
std::expected<std::any, int> e1;
auto e2 = e1;

```

So basically when clang tries to do overload resolution of `auto e2 =
e1;`

It finds

```
expected(const expected&);  // 1. This is OK
expected(const expected<_Up, _OtherErr>&)  requires __can_convert; // 2. This needs to check its constraints
```

Then in `__can_convert`, one of the check is 

```
_Not<is_constructible<_Tp, expected<_Up, _OtherErr>&>>
```
which is checking 
```
is_constructible<std::any, expected<_Up, _OtherErr>&>
```

Then it looks at `std::any`'s constructor
```
  template < class _ValueType,
             class _Tp = decay_t<_ValueType>,
             class     = enable_if_t< !is_same<_Tp, any>::value && !__is_inplace_type<_ValueType>::value &&
                                      is_copy_constructible<_Tp>::value> >
  any(_ValueType&& __value);
```
In the above, `is_copy_constructible<_Tp>` expands to
```
is_copy_constructible<std::expected<std::any, int>>
```

And the above goes back to the original thing we asked : copy the
`std::expected`, which goes to the overload resolution again.

```
expected(const expected&);
expected(const expected<_Up, _OtherErr>&)  requires __can_convert;
```

So the second overload results in a logical cycle. 

I am not a language lawyer. We could argue that clang should give up on
the second overload which has logical cycle, as the first overload is a
perfect match.

Anyway, the fix in this patch tries to short-circuiting the second
overload's constraint check: that is, if the argument matches exact same
`expected<T, E>`, we give up immediately and let the copy constructor to
deal with it



To unsubscribe from these emails, change your notification settings at https://github.com/llvm/llvm-project/settings/notifications


More information about the All-commits mailing list