@@ -425,7 +425,8 @@ tbl_subassign <- function(x, i, j, value, i_arg, j_arg, value_arg) {
425425 j <- vectbl_as_new_col_index(j , x , j_arg , names2(value ), value_arg )
426426 }
427427
428- value <- vectbl_recycle_rhs(value , fast_nrow(x ), length(j ), i_arg = NULL , value_arg )
428+ value <- vectbl_recycle_rhs_rows(value , fast_nrow(x ), i_arg = NULL , value_arg )
429+ value <- vectbl_recycle_rhs_cols(value , length(j ))
429430
430431 xo <- tbl_subassign_col(x , j , value )
431432 } else if (is.null(i_arg )) {
@@ -439,8 +440,7 @@ tbl_subassign <- function(x, i, j, value, i_arg, j_arg, value_arg) {
439440 value <- vectbl_wrap_rhs_row(value , value_arg )
440441
441442 if (is.null(j )) {
442- value <- vectbl_recycle_rhs(value , length(i ), length(x ), i_arg , value_arg )
443- xo <- tbl_subassign_row(x , i , value , value_arg )
443+ xo <- tbl_subassign_row(x , i , value , i_arg , value_arg )
444444 } else {
445445 # Optimization: match only once
446446 # (Invariant: x[[j]] is equivalent to x[[vec_as_location(j)]],
@@ -449,7 +449,6 @@ tbl_subassign <- function(x, i, j, value, i_arg, j_arg, value_arg) {
449449 j <- vectbl_as_new_col_index(j , x , j_arg , names2(value ), value_arg )
450450 }
451451 new <- which(j > length(x ))
452- value <- vectbl_recycle_rhs(value , length(i ), length(j ), i_arg , value_arg )
453452
454453 # Fill up columns if necessary
455454 if (has_length(new )) {
@@ -458,7 +457,7 @@ tbl_subassign <- function(x, i, j, value, i_arg, j_arg, value_arg) {
458457 }
459458
460459 xj <- .subset(x , j )
461- xj <- tbl_subassign_row(xj , i , value , value_arg )
460+ xj <- tbl_subassign_row(xj , i , value , i_arg , value_arg )
462461 xo <- tbl_subassign_col(x , j , unclass(xj ))
463462 }
464463 }
@@ -646,17 +645,21 @@ tbl_expand_to_nrow <- function(x, i) {
646645 x
647646}
648647
649- tbl_subassign_row <- function (x , i , value , value_arg ) {
648+ tbl_subassign_row <- function (x , i , value , i_arg , value_arg ) {
650649 nrow <- fast_nrow(x )
651650 x <- unclass(x )
651+ recycled_value <- vectbl_recycle_rhs_cols(value , length(x ))
652652
653653 withCallingHandlers(
654654 for (j in seq_along(x )) {
655- x [[j ]] <- vectbl_assign(x [[j ]], i , value [[j ]])
655+ x [[j ]] <- vectbl_assign(x [[j ]], i , recycled_value [[j ]])
656656 },
657657
658658 vctrs_error = function (cnd ) {
659- cnd_signal(error_assign_incompatible_type(x , value , j , value_arg , cnd_message(cnd )))
659+ # Side effect: check if `value` can be recycled
660+ vectbl_recycle_rhs_rows(value , length(i ), i_arg , value_arg )
661+
662+ cnd_signal(error_assign_incompatible_type(x , recycled_value , j , value_arg , cnd_message(cnd )))
660663 }
661664 )
662665
@@ -725,7 +728,12 @@ result_vectbl_wrap_rhs <- function(value) {
725728}
726729
727730vectbl_recycle_rhs <- function (value , nrow , ncol , i_arg , value_arg ) {
728- if (length(value ) > 0L && (nrow != 1L || vec_size(value [[1L ]]) != 1L )) {
731+ value <- vectbl_recycle_rhs_rows(value , nrow , i_arg , value_arg )
732+ vectbl_recycle_rhs_cols(value , ncol )
733+ }
734+
735+ vectbl_recycle_rhs_rows <- function (value , nrow , i_arg , value_arg ) {
736+ if (length(value ) > 0L ) {
729737 withCallingHandlers(
730738 for (j in seq_along(value )) {
731739 if (! is.null(value [[j ]])) {
@@ -739,8 +747,12 @@ vectbl_recycle_rhs <- function(value, nrow, ncol, i_arg, value_arg) {
739747 )
740748 }
741749
750+ value
751+ }
752+
753+ vectbl_recycle_rhs_cols <- function (value , ncol ) {
742754 if (length(value ) != 1L || ncol != 1L ) {
743- # Errors have been caught beforehand in vectbl_recycle_rhs_names ()
755+ # Errors have been caught beforehand in vectbl_as_new_col_index ()
744756 value <- vec_recycle(value , ncol )
745757 }
746758
0 commit comments