`vec_c()` should probably cast `xs` to a common type before handing off to `df_c_fallback()`
DavisVaughan opened this issue · comments
From tidyverse/tidyr#1507
Also ensure we fix it in list_unchop()
too!
See the 1970-01-02
?
library(tibble)
library(data.table)
library(vctrs)
xs <- list(
tibble(x = as.IDate('2012-01-01')),
tibble(y = 1)
)
vec_c(!!!xs)
#> # A tibble: 2 × 2
#> x y
#> <IDate> <dbl>
#> 1 2012-01-01 NA
#> 2 1970-01-02 1
# fallback class, so actual combination for this `x` column
# is delayed until `df_c_fallback()`
vctrs:::vec_ptype_common_fallback(!!!xs)
#> # A tibble: 0 × 2
#> # ℹ 2 variables: x <vct:::__>, y <dbl>
# but `df_c_fallback()` gets the _original_ `xs`, not the `xs` after they
# have been cast to a common type! so when it `list_pluck()`s out the 1st column,
# it takes `xs[[1]][[1]]` and `xs[[2]][[1]]` (i.e. the x column of the 1st
# element and the y column of the 2nd element).
# you can prove that it works if you go ahead and pre cast them to a common type
vec_c(!!!vec_cast_common(!!!xs))
#> # A tibble: 2 × 2
#> x y
#> <IDate> <dbl>
#> 1 2012-01-01 NA
#> 2 NA 1
You can break it further with list_unchop()
, since recycling of x
isn't carried over either
library(tibble)
library(data.table)
library(vctrs)
#>
#> Attaching package: 'vctrs'
#> The following object is masked from 'package:tibble':
#>
#> data_frame
xs <- list(
tibble(x = as.IDate('2012-01-01')),
tibble(y = 1)
)
list_unchop(xs, indices = list(1, 2:3))
#> Error in `list_unchop()`:
#> ! `c()` method returned a vector of unexpected size 2 instead of 3.
#> ℹ In file 'c.c' at line 414.
#> ℹ This is an internal error that was detected in the vctrs package.
#> Please report it at <https://github.com/r-lib/vctrs/issues> with a reprex (<https://tidyverse.org/help/>) and the full backtrace.
#> Backtrace:
#> ▆
#> 1. ├─vctrs::list_unchop(xs, indices = list(1, 2:3))
#> 2. └─rlang:::stop_internal_c_lib(...) at vctrs/R/slice-chop.R:164:3
#> 3. └─rlang::abort(message, call = call, .internal = TRUE, .frame = frame)
Created on 2023-11-02 with reprex v2.0.2
I am fairly certain we purposefully do not call vec_ptype_common()
and vec_recycle_common()
in this function, I think to avoid copying xs
if possible, so I don't think switching to those is a good solution. I imagine we should do some recursive pre check to see if we have any fallback classes, and if so then we put each x
from the core assignment loop into a list after casting and recycling it, then we pass that list to df_c_fallback()