Skip to content

Commit 99a5b9d

Browse files
authored
Merge pull request #3352 from stan-dev/fix/3351-indexing-checks-vector-of-eigen
Direct all std::vector assigns through size-aware version
2 parents c89d0bf + 9d6bbdb commit 99a5b9d

File tree

2 files changed

+29
-4
lines changed

2 files changed

+29
-4
lines changed

src/stan/model/indexing/assign.hpp

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ inline void assign(Tuple1&& x, Tuple2&& y, const char* name);
5959
template <
6060
typename T, typename U,
6161
require_t<std::is_assignable<std::decay_t<T>&, std::decay_t<U>>>* = nullptr,
62+
require_all_not_std_vector_t<T, U>* = nullptr,
6263
math::require_all_not_tuple_t<T, U>* = nullptr>
6364
inline void assign(T&& x, U&& y, const char* name) {
6465
internal::assign_impl(x, std::forward<U>(y), name);
@@ -776,15 +777,25 @@ inline void assign(Mat1&& x, Mat2&& y, const char* name, const Idx& row_idx,
776777
* @param[in] y rvalue variable
777778
* @param[in] name name of lvalue variable
778779
*/
779-
template <typename T, typename U, require_all_std_vector_t<T, U>* = nullptr,
780-
require_not_t<
781-
std::is_assignable<std::decay_t<T>&, std::decay_t<U>>>* = nullptr>
780+
template <typename T, typename U, require_all_std_vector_t<T, U>* = nullptr>
782781
inline void assign(T&& x, U&& y, const char* name) {
783782
if (unlikely(x.size() != 0)) {
784783
stan::math::check_size_match("assign array size", name, x.size(),
785784
"right hand side", y.size());
786785
}
787-
if (std::is_rvalue_reference<U&&>::value) {
786+
787+
if constexpr (std::is_assignable_v<std::decay_t<T>&, std::decay_t<U>>) {
788+
if (is_stan_scalar_v<value_type_t<T>> || x.size() == 0) {
789+
x = std::forward<U>(y);
790+
return;
791+
}
792+
}
793+
794+
// If we've made it this far, we need x to have elements to assign to,
795+
// and we know this is either a no-op or x has size 0, which we treat as
796+
// a wildcard that can take any size.
797+
x.resize(y.size());
798+
if constexpr (std::is_rvalue_reference_v<U&&>) {
788799
for (size_t i = 0; i < y.size(); ++i) {
789800
assign(x[i], std::move(y[i]), name);
790801
}

src/test/unit/model/indexing/assign_test.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1197,3 +1197,17 @@ TEST(model_indexing, tuples_non_trivially_assignable) {
11971197
},
11981198
A, B);
11991199
}
1200+
1201+
TEST(model_indexing, stdvec_of_eigvec_errors) {
1202+
using stan::model::assign;
1203+
using stan::model::index_min_max;
1204+
1205+
std::vector<Eigen::VectorXd> x(1);
1206+
x[0] = Eigen::VectorXd(2);
1207+
x[0] << 1, 2;
1208+
std::vector<Eigen::VectorXd> y(1);
1209+
y[0] = Eigen::VectorXd(3);
1210+
y[0] << 3, 4, 5;
1211+
1212+
test_throw_ia(x, y);
1213+
}

0 commit comments

Comments
 (0)