Skip to content

Commit c88ba88

Browse files
authored
[ADT] Refine MutableArrayRef forwarding constructor constraints (#183806)
Keep MutableArrayRef on a single C&& constructor, with SFINAE on direct check on `C::data()`. This keeps const std::span<int> supported and rejects const vector/smallvector sources for MutableArrayRef<int>.
1 parent 02e9b08 commit c88ba88

2 files changed

Lines changed: 17 additions & 3 deletions

File tree

llvm/include/llvm/ADT/ArrayRef.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -322,16 +322,16 @@ namespace llvm {
322322
/// Construct a MutableArrayRef from a range.
323323
MutableArrayRef(T *begin, T *end) : ArrayRef<T>(begin, end) {}
324324

325-
/// Construct a MutableArrayRef from a type that has a data() method that
326-
/// returns a pointer convertible to T *.
325+
/// Construct a MutableArrayRef from a type that has data() and size(),
326+
/// where data() returns a pointer convertible to T *const *.
327327
template <typename C,
328328
typename = std::enable_if_t<
329329
std::conjunction_v<
330330
std::is_convertible<
331331
decltype(std::declval<C &>().data()) *, T *const *>,
332332
std::is_integral<decltype(std::declval<C &>().size())>>,
333333
void>>
334-
/*implicit*/ constexpr MutableArrayRef(const C &V) : ArrayRef<T>(V) {}
334+
/*implicit*/ constexpr MutableArrayRef(C &&V) : ArrayRef<T>(V) {}
335335

336336
/// Construct a MutableArrayRef from a C array.
337337
template <size_t N>

llvm/unittests/ADT/ArrayRefTest.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,12 @@ static_assert(
340340
static_assert(!std::is_constructible_v<ArrayRef<TestBase *>,
341341
iterator_range<TestDerived **>>,
342342
"cannot construct ArrayRef pointer of base type");
343+
static_assert(!std::is_constructible_v<MutableArrayRef<TestBase>,
344+
iterator_range<TestDerived *>>,
345+
"cannot construct MutableArrayRef base type");
346+
static_assert(!std::is_constructible_v<MutableArrayRef<TestBase *>,
347+
iterator_range<TestDerived **>>,
348+
"cannot construct MutableArrayRef pointer of base type");
343349

344350
static_assert(
345351
!std::is_constructible_v<ArrayRef<int>, iterator_range<const int *>>,
@@ -468,6 +474,10 @@ TEST(ArrayRefTest, MutableArrayRefDeductionGuides) {
468474
}
469475
}
470476

477+
static_assert(
478+
!std::is_constructible_v<MutableArrayRef<int>, const SmallVector<int>>,
479+
"cannot construct MutableArrayRef from const std::SmallVector<int>");
480+
471481
#ifdef __cpp_lib_span
472482
static_assert(std::is_constructible_v<ArrayRef<int>, std::span<const int>>,
473483
"should be able to construct ArrayRef from const std::span");
@@ -491,6 +501,10 @@ static_assert(
491501
std::is_constructible_v<MutableArrayRef<int>, const std::span<int>>,
492502
"should be able to construct MutableArrayRef from const std::span with "
493503
"mutable elements");
504+
static_assert(
505+
!std::is_constructible_v<MutableArrayRef<TestBase>, std::span<TestDerived>>,
506+
"cannot construct MutableArrayRef base type from std::span with derived "
507+
"elements");
494508
#endif
495509

496510
} // end anonymous namespace

0 commit comments

Comments
 (0)