Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

vec_c() should probably cast xs to a common type before handing off to df_c_fallback() #1892

Open
DavisVaughan opened this issue Nov 2, 2023 · 2 comments

Comments

@DavisVaughan
Copy link
Member

DavisVaughan commented Nov 2, 2023

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
@DavisVaughan
Copy link
Member Author

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

@DavisVaughan
Copy link
Member Author

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()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant