diff --git a/NEWS.md b/NEWS.md index 29e038e7c..c3880ed01 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,5 +1,7 @@ # vctrs (development version) +* `obj_check_vector()` now throws a clearer error message. In particular, special info bullets have been added that link out to FAQ pages and explain common issues around incompatible S3 lists and data frames (#2061). + * R >=4.0.0 is now required. This is still more permissive than the general tidyverse policy of supporting the [5 most recent versions of R](https://www.tidyverse.org/blog/2019/04/r-version-support/). * `vec_interleave()` gains new `.size` and `.error_call` arguments. diff --git a/R/conditions.R b/R/conditions.R index b309a5913..c1637ce4f 100644 --- a/R/conditions.R +++ b/R/conditions.R @@ -678,15 +678,107 @@ stop_scalar_type <- function(x, arg = NULL, call = caller_env()) { } else { arg <- glue::backtick(arg) } - msg <- glue::glue("{arg} must be a vector, not {obj_type_friendly(x)}.") + + message <- glue::glue("{arg} must be a vector, not {obj_type_friendly(x)}.") + + # Use the first detected issue, with a fallthrough to point to our scalar FAQ + message <- + with_incompatible_s3_list_bullets(message, x) %||% + with_incompatible_data_frame_bullets(message, x) %||% + with_scalar_faq_bullet(message) + stop_vctrs( - msg, + message, "vctrs_error_scalar_type", actual = x, call = call ) } +with_incompatible_s3_list_bullets <- function(message, x) { + is_list_typeof <- typeof(x) == "list" + + classes <- class(x) + doesnt_contain_explicit_list_class <- !any(classes == "list") + doesnt_contain_data_frame_class <- !any(classes == "data.frame") + + # We also assume no `vec_proxy()` method exists, otherwise one would have + # been invoked, avoiding the error + is_incompatible_s3_list <- + is_list_typeof && + doesnt_contain_explicit_list_class && + doesnt_contain_data_frame_class + + if (!is_incompatible_s3_list) { + return(NULL) + } + + c( + message, + x = cli::format_inline(paste( + "Detected incompatible scalar S3 list.", + "To be treated as a vector, the object must explicitly inherit from {.cls list}", + "or should implement a {.fn vec_proxy} method.", + "Class: {.cls {classes}}." + )), + i = "If this object comes from a package, please report this error to the package author.", + i = cli::format_inline(paste( + "Read our FAQ about", + "{.topic [creating vector types](howto_faq_fix_scalar_type_error)}", + "to learn more." + )) + ) +} + +with_incompatible_data_frame_bullets <- function(message, x) { + classes <- class(x) + n_classes <- length(classes) + + contains_data_frame_class <- any(classes == "data.frame") + + if (n_classes == 0L) { + # Edge case of `NULL` or `character()` classes + last_class_is_not_data_frame <- TRUE + } else { + last_class_is_not_data_frame <- classes[n_classes] != "data.frame" + } + + is_incompatible_data_frame <- + contains_data_frame_class && last_class_is_not_data_frame + + if (!is_incompatible_data_frame) { + return(NULL) + } + + subclasses <- setdiff(classes, "data.frame") + + c( + message, + x = cli::format_inline(paste( + "Detected incompatible data frame structure.", + "A data frame is normally treated as a vector, but an incompatible class ordering was detected.", + "To be compatible, the subclass {.cls {subclasses}} must come before {.cls data.frame}, not after.", + "Class: {.cls {classes}}." + )), + i = "If this object comes from a package, please report this error to the package author.", + i = cli::format_inline(paste( + "Read our FAQ about", + "{.topic [creating vector types](howto_faq_fix_scalar_type_error)}", + "to learn more." + )) + ) +} + +with_scalar_faq_bullet <- function(message) { + c( + message, + i = cli::format_inline(paste( + "Read our FAQ about {.topic [scalar types](faq_error_scalar_type)}", + "to learn more." + )) + ) +} + stop_corrupt_factor_levels <- function(x, arg = "x", call = caller_env()) { msg <- glue::glue("`{arg}` is a corrupt factor with non-character levels") abort(msg, call = call) diff --git a/R/faq-developer.R b/R/faq-developer.R index b9f2ec6b3..f98a46b15 100644 --- a/R/faq-developer.R +++ b/R/faq-developer.R @@ -42,4 +42,5 @@ NULL #' @includeRmd man/faq/developer/howto-faq-fix-scalar-type-error.Rmd description #' #' @name howto-faq-fix-scalar-type-error +#' @aliases howto_faq_fix_scalar_type_error NULL diff --git a/R/faq.R b/R/faq.R index 18c1b4ea8..3f22c784c 100644 --- a/R/faq.R +++ b/R/faq.R @@ -28,4 +28,5 @@ NULL #' @includeRmd man/faq/user/faq-error-scalar-type.Rmd description #' #' @name faq-error-scalar-type +#' @aliases faq_error_scalar_type NULL diff --git a/man/faq-error-scalar-type.Rd b/man/faq-error-scalar-type.Rd index 0ec78d028..f5044f96d 100644 --- a/man/faq-error-scalar-type.Rd +++ b/man/faq-error-scalar-type.Rd @@ -2,6 +2,7 @@ % Please edit documentation in R/faq.R \name{faq-error-scalar-type} \alias{faq-error-scalar-type} +\alias{faq_error_scalar_type} \title{FAQ - Error: Input must be a vector} \description{ This error occurs when a function expects a vector and gets a scalar @@ -51,6 +52,9 @@ fit[c(1, 4)] vctrs::vec_slice(fit, c(1, 4)) #> Error in `vctrs::vec_slice()`: #> ! `x` must be a vector, not a object. +#> x Detected incompatible scalar S3 list. To be treated as a vector, the object must explicitly inherit from or should implement a `vec_proxy()` method. Class: . +#> i If this object comes from a package, please report this error to the package author. +#> i Read our FAQ about creating vector types (`?howto_faq_fix_scalar_type_error`) to learn more. }\if{html}{\out{}} Defused function calls are another (more esoteric) example: @@ -76,6 +80,7 @@ lapply(call, function(x) x) vctrs::vec_slice(call, 1:2) #> Error in `vctrs::vec_slice()`: #> ! `x` must be a vector, not a call. +#> i Read our FAQ about scalar types (`?faq_error_scalar_type`) to learn more. }\if{html}{\out{}} } diff --git a/man/howto-faq-fix-scalar-type-error.Rd b/man/howto-faq-fix-scalar-type-error.Rd index 91438cd81..4ac85bde7 100644 --- a/man/howto-faq-fix-scalar-type-error.Rd +++ b/man/howto-faq-fix-scalar-type-error.Rd @@ -2,6 +2,7 @@ % Please edit documentation in R/faq-developer.R \name{howto-faq-fix-scalar-type-error} \alias{howto-faq-fix-scalar-type-error} +\alias{howto_faq_fix_scalar_type_error} \title{FAQ - Why isn't my class treated as a vector?} \description{ The tidyverse is a bit stricter than base R regarding what kind of @@ -65,6 +66,9 @@ class(my_df) <- c("data.frame", "my_class") vctrs::obj_check_vector(my_df) #> Error: #> ! `my_df` must be a vector, not a object. +#> x Detected incompatible data frame structure. A data frame is normally treated as a vector, but an incompatible class ordering was detected. To be compatible, the subclass must come before , not after. Class: . +#> i If this object comes from a package, please report this error to the package author. +#> i Read our FAQ about creating vector types (`?howto_faq_fix_scalar_type_error`) to learn more. }\if{html}{\out{}} This is problematic as many tidyverse functions won’t work properly: @@ -72,6 +76,9 @@ This is problematic as many tidyverse functions won’t work properly: \if{html}{\out{
}}\preformatted{dplyr::slice(my_df, 1) #> Error in `vec_slice()`: #> ! `x` must be a vector, not a object. +#> x Detected incompatible data frame subclass. To be treated as a vector, the subclass must come before in the class, not after. Class: . +#> i If this object comes from a package, please report this error to the package author. +#> i Read our FAQ about creating vector types (`?howto_faq_fix_scalar_type_error`) to learn more. }\if{html}{\out{
}} It is generally not appropriate to declare your class to be a superclass diff --git a/tests/testthat/_snaps/assert.md b/tests/testthat/_snaps/assert.md index df6fd6392..dbfe564a1 100644 --- a/tests/testthat/_snaps/assert.md +++ b/tests/testthat/_snaps/assert.md @@ -5,6 +5,7 @@ Condition Error: ! `quote(foo)` must be a vector, not a symbol. + i Read our FAQ about scalar types (`?faq_error_scalar_type`) to learn more. --- @@ -13,6 +14,9 @@ Condition Error: ! `foobar()` must be a vector, not a object. + x Detected incompatible scalar S3 list. To be treated as a vector, the object must explicitly inherit from or should implement a `vec_proxy()` method. Class: . + i If this object comes from a package, please report this error to the package author. + i Read our FAQ about creating vector types (`?howto_faq_fix_scalar_type_error`) to learn more. # obj_check_vector() error respects `arg` and `call` @@ -21,6 +25,40 @@ Condition Error in `my_check_vector()`: ! `foo` must be a vector, not a object. + x Detected incompatible scalar S3 list. To be treated as a vector, the object must explicitly inherit from or should implement a `vec_proxy()` method. Class: . + i If this object comes from a package, please report this error to the package author. + i Read our FAQ about creating vector types (`?howto_faq_fix_scalar_type_error`) to learn more. + +# obj_check_vector() error contains FAQ links and correct bullets + + Code + obj_check_vector(x) + Condition + Error: + ! `x` must be a vector, not an expression vector. + i Read our FAQ about scalar types (`?faq_error_scalar_type`) to learn more. + +--- + + Code + obj_check_vector(x) + Condition + Error: + ! `x` must be a vector, not a object. + x Detected incompatible scalar S3 list. To be treated as a vector, the object must explicitly inherit from or should implement a `vec_proxy()` method. Class: . + i If this object comes from a package, please report this error to the package author. + i Read our FAQ about creating vector types (`?howto_faq_fix_scalar_type_error`) to learn more. + +--- + + Code + obj_check_vector(x) + Condition + Error: + ! `x` must be a vector, not a object. + x Detected incompatible data frame structure. A data frame is normally treated as a vector, but an incompatible class ordering was detected. To be compatible, the subclass must come before , not after. Class: . + i If this object comes from a package, please report this error to the package author. + i Read our FAQ about creating vector types (`?howto_faq_fix_scalar_type_error`) to learn more. # assertion failures are explained @@ -235,6 +273,7 @@ Condition Error: ! `quote(foo)` must be a vector, not a symbol. + i Read our FAQ about scalar types (`?faq_error_scalar_type`) to learn more. --- @@ -243,6 +282,9 @@ Condition Error: ! `foobar()` must be a vector, not a object. + x Detected incompatible scalar S3 list. To be treated as a vector, the object must explicitly inherit from or should implement a `vec_proxy()` method. Class: . + i If this object comes from a package, please report this error to the package author. + i Read our FAQ about creating vector types (`?howto_faq_fix_scalar_type_error`) to learn more. # vec_check_size() error respects `arg` and `call` @@ -259,6 +301,9 @@ Condition Error in `my_check_size()`: ! `foo` must be a vector, not a object. + x Detected incompatible scalar S3 list. To be treated as a vector, the object must explicitly inherit from or should implement a `vec_proxy()` method. Class: . + i If this object comes from a package, please report this error to the package author. + i Read our FAQ about creating vector types (`?howto_faq_fix_scalar_type_error`) to learn more. # vec_check_size() validates `size` @@ -307,6 +352,7 @@ Condition Error: ! `quote(foo)` must be a vector, not a symbol. + i Read our FAQ about scalar types (`?faq_error_scalar_type`) to learn more. --- @@ -315,6 +361,9 @@ Condition Error: ! `foobar()` must be a vector, not a object. + x Detected incompatible scalar S3 list. To be treated as a vector, the object must explicitly inherit from or should implement a `vec_proxy()` method. Class: . + i If this object comes from a package, please report this error to the package author. + i Read our FAQ about creating vector types (`?howto_faq_fix_scalar_type_error`) to learn more. # vec_check_recyclable() error respects `arg` and `call` @@ -331,6 +380,9 @@ Condition Error in `my_check_recyclable()`: ! `foo` must be a vector, not a object. + x Detected incompatible scalar S3 list. To be treated as a vector, the object must explicitly inherit from or should implement a `vec_proxy()` method. Class: . + i If this object comes from a package, please report this error to the package author. + i Read our FAQ about creating vector types (`?howto_faq_fix_scalar_type_error`) to learn more. # vec_check_recyclable() validates `size` @@ -398,18 +450,21 @@ Error in `my_function()`: ! `my_arg[[2]]` must be a vector, not an environment. + i Read our FAQ about scalar types (`?faq_error_scalar_type`) to learn more. Code (expect_error(my_function(list(1, name = env())))) Output Error in `my_function()`: ! `my_arg$name` must be a vector, not an environment. + i Read our FAQ about scalar types (`?faq_error_scalar_type`) to learn more. Code (expect_error(my_function(list(1, foo = env())))) Output Error in `my_function()`: ! `my_arg$foo` must be a vector, not an environment. + i Read our FAQ about scalar types (`?faq_error_scalar_type`) to learn more. # list_check_all_size() works @@ -465,6 +520,7 @@ Error in `list_all_size()`: ! `x[[1]]` must be a vector, not an environment. + i Read our FAQ about scalar types (`?faq_error_scalar_type`) to learn more. Code my_function <- (function(my_arg, size) list_check_all_size(my_arg, size)) (expect_error(my_function(x, 2))) @@ -472,6 +528,7 @@ Error in `my_function()`: ! `my_arg[[1]]` must be a vector, not an environment. + i Read our FAQ about scalar types (`?faq_error_scalar_type`) to learn more. # list_all_recyclable() and list_check_all_recyclable() error on scalars @@ -481,6 +538,7 @@ Error in `list_all_recyclable()`: ! `x[[1]]` must be a vector, not an environment. + i Read our FAQ about scalar types (`?faq_error_scalar_type`) to learn more. Code my_function <- (function(my_arg, size) { list_check_all_recyclable(my_arg, size) @@ -490,6 +548,7 @@ Error in `my_function()`: ! `my_arg[[1]]` must be a vector, not an environment. + i Read our FAQ about scalar types (`?faq_error_scalar_type`) to learn more. # list_all_size() and list_check_all_size() throw error using internal call on non-list input @@ -567,6 +626,7 @@ Condition Error: ! `x[[2]]` must be a vector, not `NULL`. + i Read our FAQ about scalar types (`?faq_error_scalar_type`) to learn more. --- @@ -575,6 +635,7 @@ Condition Error: ! `x[[2]]` must be a vector, not `NULL`. + i Read our FAQ about scalar types (`?faq_error_scalar_type`) to learn more. --- @@ -583,6 +644,7 @@ Condition Error: ! `x[[3]]` must be a vector, not an environment. + i Read our FAQ about scalar types (`?faq_error_scalar_type`) to learn more. # list_check_all_recyclable() works with `allow_null` diff --git a/tests/testthat/_snaps/bind.md b/tests/testthat/_snaps/bind.md index 333914dd3..181158e21 100644 --- a/tests/testthat/_snaps/bind.md +++ b/tests/testthat/_snaps/bind.md @@ -117,12 +117,18 @@ Error in `vec_cbind()`: ! `..1` must be a vector, not a object. + x Detected incompatible scalar S3 list. To be treated as a vector, the object must explicitly inherit from or should implement a `vec_proxy()` method. Class: . + i If this object comes from a package, please report this error to the package author. + i Read our FAQ about creating vector types (`?howto_faq_fix_scalar_type_error`) to learn more. Code (expect_error(vec_cbind(foobar(list()), .error_call = call("foo")))) Output Error in `foo()`: ! `..1` must be a vector, not a object. + x Detected incompatible scalar S3 list. To be treated as a vector, the object must explicitly inherit from or should implement a `vec_proxy()` method. Class: . + i If this object comes from a package, please report this error to the package author. + i Read our FAQ about creating vector types (`?howto_faq_fix_scalar_type_error`) to learn more. Code (expect_error(vec_cbind(a = 1:2, b = int()))) Output diff --git a/tests/testthat/_snaps/case-when.md b/tests/testthat/_snaps/case-when.md index b8b5250ea..2c225f672 100644 --- a/tests/testthat/_snaps/case-when.md +++ b/tests/testthat/_snaps/case-when.md @@ -280,6 +280,7 @@ Condition Error in `vec_case_when()`: ! `values[[1]]` must be a vector, not `NULL`. + i Read our FAQ about scalar types (`?faq_error_scalar_type`) to learn more. --- @@ -288,6 +289,7 @@ Condition Error in `vec_case_when()`: ! `values$x` must be a vector, not `NULL`. + i Read our FAQ about scalar types (`?faq_error_scalar_type`) to learn more. --- @@ -296,6 +298,7 @@ Condition Error in `vec_case_when()`: ! `foo[[1]]` must be a vector, not `NULL`. + i Read our FAQ about scalar types (`?faq_error_scalar_type`) to learn more. --- @@ -304,6 +307,7 @@ Condition Error in `vec_case_when()`: ! `foo$x` must be a vector, not `NULL`. + i Read our FAQ about scalar types (`?faq_error_scalar_type`) to learn more. --- @@ -312,6 +316,7 @@ Condition Error in `vec_case_when()`: ! `..1` must be a vector, not `NULL`. + i Read our FAQ about scalar types (`?faq_error_scalar_type`) to learn more. --- @@ -320,6 +325,7 @@ Condition Error in `vec_case_when()`: ! `x` must be a vector, not `NULL`. + i Read our FAQ about scalar types (`?faq_error_scalar_type`) to learn more. # `unmatched` errors are correct diff --git a/tests/testthat/_snaps/complete.md b/tests/testthat/_snaps/complete.md index 954f505fa..e5c8c931d 100644 --- a/tests/testthat/_snaps/complete.md +++ b/tests/testthat/_snaps/complete.md @@ -13,4 +13,7 @@ Condition Error in `vec_size()`: ! `x` must be a vector, not a object. + x Detected incompatible scalar S3 list. To be treated as a vector, the object must explicitly inherit from or should implement a `vec_proxy()` method. Class: . + i If this object comes from a package, please report this error to the package author. + i Read our FAQ about creating vector types (`?howto_faq_fix_scalar_type_error`) to learn more. diff --git a/tests/testthat/_snaps/conditions.md b/tests/testthat/_snaps/conditions.md index e2b642403..fdc0681c5 100644 --- a/tests/testthat/_snaps/conditions.md +++ b/tests/testthat/_snaps/conditions.md @@ -49,6 +49,9 @@ Error in `vec_slice()`: ! `x` must be a vector, not a object. + x Detected incompatible scalar S3 list. To be treated as a vector, the object must explicitly inherit from or should implement a `vec_proxy()` method. Class: . + i If this object comes from a package, please report this error to the package author. + i Read our FAQ about creating vector types (`?howto_faq_fix_scalar_type_error`) to learn more. Code (expect_error(stop_scalar_type(foobar(list(1)), arg = "foo"), class = "vctrs_error_scalar_type") ) @@ -56,6 +59,9 @@ Error: ! `foo` must be a vector, not a object. + x Detected incompatible scalar S3 list. To be treated as a vector, the object must explicitly inherit from or should implement a `vec_proxy()` method. Class: . + i If this object comes from a package, please report this error to the package author. + i Read our FAQ about creating vector types (`?howto_faq_fix_scalar_type_error`) to learn more. # empty names errors are informative diff --git a/tests/testthat/_snaps/equal.md b/tests/testthat/_snaps/equal.md index b54307a40..128f1d9a9 100644 --- a/tests/testthat/_snaps/equal.md +++ b/tests/testthat/_snaps/equal.md @@ -5,6 +5,7 @@ Condition Error in `vec_equal()`: ! `x` must be a vector, not an expression vector. + i Read our FAQ about scalar types (`?faq_error_scalar_type`) to learn more. # `na_equal` is validated diff --git a/tests/testthat/_snaps/error-call.md b/tests/testthat/_snaps/error-call.md index c3214b0c4..d8fc4dcd2 100644 --- a/tests/testthat/_snaps/error-call.md +++ b/tests/testthat/_snaps/error-call.md @@ -88,6 +88,9 @@ Error in `my_function()`: ! `foobar()` must be a vector, not a object. + x Detected incompatible scalar S3 list. To be treated as a vector, the object must explicitly inherit from or should implement a `vec_proxy()` method. Class: . + i If this object comes from a package, please report this error to the package author. + i Read our FAQ about creating vector types (`?howto_faq_fix_scalar_type_error`) to learn more. # size error reports correct error call @@ -260,12 +263,16 @@ Error in `my_function()`: ! Input must be a vector, not an environment. + i Read our FAQ about scalar types (`?faq_error_scalar_type`) to learn more. Code (expect_error(my_function(foobar(list())))) Output Error in `my_function()`: ! Input must be a vector, not a object. + x Detected incompatible scalar S3 list. To be treated as a vector, the object must explicitly inherit from or should implement a `vec_proxy()` method. Class: . + i If this object comes from a package, please report this error to the package author. + i Read our FAQ about creating vector types (`?howto_faq_fix_scalar_type_error`) to learn more. # `vec_slice()` uses `error_call` @@ -275,6 +282,7 @@ Error in `my_function()`: ! `x` must be a vector, not an environment. + i Read our FAQ about scalar types (`?faq_error_scalar_type`) to learn more. Code (expect_error(my_function(1, 2))) Output @@ -292,6 +300,9 @@ Error in `vec_slice()`: ! `x` must be a vector, not a object. + x Detected incompatible scalar S3 list. To be treated as a vector, the object must explicitly inherit from or should implement a `vec_proxy()` method. Class: . + i If this object comes from a package, please report this error to the package author. + i Read our FAQ about creating vector types (`?howto_faq_fix_scalar_type_error`) to learn more. Code (expect_error(vec_slice(list(), env()))) Output @@ -314,18 +325,21 @@ Error in `list_sizes()`: ! `x[[1]]` must be a vector, not an environment. + i Read our FAQ about scalar types (`?faq_error_scalar_type`) to learn more. Code (expect_error(list_sizes(list(1, 2, env())))) Output Error in `list_sizes()`: ! `x[[3]]` must be a vector, not an environment. + i Read our FAQ about scalar types (`?faq_error_scalar_type`) to learn more. Code (expect_error(list_sizes(list(1, 2, foo = env())))) Output Error in `list_sizes()`: ! `x$foo` must be a vector, not an environment. + i Read our FAQ about scalar types (`?faq_error_scalar_type`) to learn more. # vec_size() reports error context @@ -335,6 +349,7 @@ Error in `vec_size()`: ! `x` must be a vector, not an environment. + i Read our FAQ about scalar types (`?faq_error_scalar_type`) to learn more. # vec_cast_common() reports error context diff --git a/tests/testthat/_snaps/expand.md b/tests/testthat/_snaps/expand.md index 8e3c62f5b..616244264 100644 --- a/tests/testthat/_snaps/expand.md +++ b/tests/testthat/_snaps/expand.md @@ -32,6 +32,7 @@ Condition Error in `vec_expand_grid()`: ! `y` must be a vector, not an environment. + i Read our FAQ about scalar types (`?faq_error_scalar_type`) to learn more. # can adjust the `.error_call` @@ -40,6 +41,7 @@ Condition Error in `my_expand_grid()`: ! `x` must be a vector, not an environment. + i Read our FAQ about scalar types (`?faq_error_scalar_type`) to learn more. # errors nicely when expansion results in a size larger than `R_len_t` diff --git a/tests/testthat/_snaps/if-else.md b/tests/testthat/_snaps/if-else.md index a5882768c..eefe3b762 100644 --- a/tests/testthat/_snaps/if-else.md +++ b/tests/testthat/_snaps/if-else.md @@ -7,6 +7,9 @@ Condition Error in `vec_if_else()`: ! `condition` must be a vector, not a object. + x Detected incompatible scalar S3 list. To be treated as a vector, the object must explicitly inherit from or should implement a `vec_proxy()` method. Class: . + i If this object comes from a package, please report this error to the package author. + i Read our FAQ about creating vector types (`?howto_faq_fix_scalar_type_error`) to learn more. --- @@ -17,6 +20,9 @@ Condition Error in `vec_if_else()`: ! `condition` must be a vector, not a object. + x Detected incompatible scalar S3 list. To be treated as a vector, the object must explicitly inherit from or should implement a `vec_proxy()` method. Class: . + i If this object comes from a package, please report this error to the package author. + i Read our FAQ about creating vector types (`?howto_faq_fix_scalar_type_error`) to learn more. --- @@ -85,6 +91,9 @@ Condition Error in `vec_if_else()`: ! `true` must be a vector, not a object. + x Detected incompatible scalar S3 list. To be treated as a vector, the object must explicitly inherit from or should implement a `vec_proxy()` method. Class: . + i If this object comes from a package, please report this error to the package author. + i Read our FAQ about creating vector types (`?howto_faq_fix_scalar_type_error`) to learn more. --- @@ -93,6 +102,9 @@ Condition Error in `vec_if_else()`: ! `false` must be a vector, not a object. + x Detected incompatible scalar S3 list. To be treated as a vector, the object must explicitly inherit from or should implement a `vec_proxy()` method. Class: . + i If this object comes from a package, please report this error to the package author. + i Read our FAQ about creating vector types (`?howto_faq_fix_scalar_type_error`) to learn more. --- @@ -101,6 +113,9 @@ Condition Error in `vec_if_else()`: ! `missing` must be a vector, not a object. + x Detected incompatible scalar S3 list. To be treated as a vector, the object must explicitly inherit from or should implement a `vec_proxy()` method. Class: . + i If this object comes from a package, please report this error to the package author. + i Read our FAQ about creating vector types (`?howto_faq_fix_scalar_type_error`) to learn more. # `true`, `false`, and `missing` must recycle to size of `condition` diff --git a/tests/testthat/_snaps/list-combine.md b/tests/testthat/_snaps/list-combine.md index a6cebf9ed..5f228ce28 100644 --- a/tests/testthat/_snaps/list-combine.md +++ b/tests/testthat/_snaps/list-combine.md @@ -313,6 +313,9 @@ Condition Error in `list_combine()`: ! `d` must be a vector, not a object. + x Detected incompatible scalar S3 list. To be treated as a vector, the object must explicitly inherit from or should implement a `vec_proxy()` method. Class: . + i If this object comes from a package, please report this error to the package author. + i Read our FAQ about creating vector types (`?howto_faq_fix_scalar_type_error`) to learn more. --- @@ -324,6 +327,9 @@ Condition Error in `list_combine()`: ! `d` must be a vector, not a object. + x Detected incompatible scalar S3 list. To be treated as a vector, the object must explicitly inherit from or should implement a `vec_proxy()` method. Class: . + i If this object comes from a package, please report this error to the package author. + i Read our FAQ about creating vector types (`?howto_faq_fix_scalar_type_error`) to learn more. --- @@ -335,6 +341,9 @@ Condition Error in `list_combine()`: ! `d` must be a vector, not a object. + x Detected incompatible scalar S3 list. To be treated as a vector, the object must explicitly inherit from or should implement a `vec_proxy()` method. Class: . + i If this object comes from a package, please report this error to the package author. + i Read our FAQ about creating vector types (`?howto_faq_fix_scalar_type_error`) to learn more. # list_combine() `default` size check is done diff --git a/tests/testthat/_snaps/recode.md b/tests/testthat/_snaps/recode.md index 9f3dc605e..6da679f04 100644 --- a/tests/testthat/_snaps/recode.md +++ b/tests/testthat/_snaps/recode.md @@ -73,6 +73,9 @@ Condition Error in `vec_recode_values()`: ! `ptype` must be a vector, not a object. + x Detected incompatible scalar S3 list. To be treated as a vector, the object must explicitly inherit from or should implement a `vec_proxy()` method. Class: . + i If this object comes from a package, please report this error to the package author. + i Read our FAQ about creating vector types (`?howto_faq_fix_scalar_type_error`) to learn more. --- @@ -155,6 +158,9 @@ Condition Error in `vec_recode_values()`: ! `.x` must be a vector, not a object. + x Detected incompatible scalar S3 list. To be treated as a vector, the object must explicitly inherit from or should implement a `vec_proxy()` method. Class: . + i If this object comes from a package, please report this error to the package author. + i Read our FAQ about creating vector types (`?howto_faq_fix_scalar_type_error`) to learn more. # `from` must be a vector or list of vectors @@ -163,6 +169,9 @@ Condition Error in `vec_recode_values()`: ! `.from` must be a vector, not a object. + x Detected incompatible scalar S3 list. To be treated as a vector, the object must explicitly inherit from or should implement a `vec_proxy()` method. Class: . + i If this object comes from a package, please report this error to the package author. + i Read our FAQ about creating vector types (`?howto_faq_fix_scalar_type_error`) to learn more. --- @@ -181,6 +190,9 @@ Condition Error in `vec_recode_values()`: ! `.from$a` must be a vector, not a object. + x Detected incompatible scalar S3 list. To be treated as a vector, the object must explicitly inherit from or should implement a `vec_proxy()` method. Class: . + i If this object comes from a package, please report this error to the package author. + i Read our FAQ about creating vector types (`?howto_faq_fix_scalar_type_error`) to learn more. # `to` must be a vector or list of vectors @@ -189,6 +201,9 @@ Condition Error in `vec_recode_values()`: ! `.to` must be a vector, not a object. + x Detected incompatible scalar S3 list. To be treated as a vector, the object must explicitly inherit from or should implement a `vec_proxy()` method. Class: . + i If this object comes from a package, please report this error to the package author. + i Read our FAQ about creating vector types (`?howto_faq_fix_scalar_type_error`) to learn more. --- @@ -206,6 +221,9 @@ Condition Error in `vec_recode_values()`: ! `.to$a` must be a vector, not a object. + x Detected incompatible scalar S3 list. To be treated as a vector, the object must explicitly inherit from or should implement a `vec_proxy()` method. Class: . + i If this object comes from a package, please report this error to the package author. + i Read our FAQ about creating vector types (`?howto_faq_fix_scalar_type_error`) to learn more. # `default` must be a vector @@ -214,6 +232,9 @@ Condition Error in `vec_recode_values()`: ! `.default` must be a vector, not a object. + x Detected incompatible scalar S3 list. To be treated as a vector, the object must explicitly inherit from or should implement a `vec_proxy()` method. Class: . + i If this object comes from a package, please report this error to the package author. + i Read our FAQ about creating vector types (`?howto_faq_fix_scalar_type_error`) to learn more. # `from_as_list_of_vectors` and `to_as_list_of_vectors` are validated diff --git a/tests/testthat/_snaps/recycle.md b/tests/testthat/_snaps/recycle.md index 6350c9c97..b9384fddf 100644 --- a/tests/testthat/_snaps/recycle.md +++ b/tests/testthat/_snaps/recycle.md @@ -79,6 +79,9 @@ Condition Error: ! `..2` must be a vector, not a object. + x Detected incompatible scalar S3 list. To be treated as a vector, the object must explicitly inherit from or should implement a `vec_proxy()` method. Class: . + i If this object comes from a package, please report this error to the package author. + i Read our FAQ about creating vector types (`?howto_faq_fix_scalar_type_error`) to learn more. --- @@ -87,6 +90,9 @@ Condition Error: ! `..3` must be a vector, not a object. + x Detected incompatible scalar S3 list. To be treated as a vector, the object must explicitly inherit from or should implement a `vec_proxy()` method. Class: . + i If this object comes from a package, please report this error to the package author. + i Read our FAQ about creating vector types (`?howto_faq_fix_scalar_type_error`) to learn more. # recycling matrices respects incompatible sizes diff --git a/tests/testthat/_snaps/rep.md b/tests/testthat/_snaps/rep.md index 33478f600..2fec51b8a 100644 --- a/tests/testthat/_snaps/rep.md +++ b/tests/testthat/_snaps/rep.md @@ -155,4 +155,5 @@ Condition Error in `vec_unrep()`: ! `x` must be a vector, not an environment. + i Read our FAQ about scalar types (`?faq_error_scalar_type`) to learn more. diff --git a/tests/testthat/_snaps/runs.md b/tests/testthat/_snaps/runs.md index da34489a3..e77f3a083 100644 --- a/tests/testthat/_snaps/runs.md +++ b/tests/testthat/_snaps/runs.md @@ -5,6 +5,9 @@ Condition Error in `vec_identify_runs()`: ! `x` must be a vector, not a object. + x Detected incompatible scalar S3 list. To be treated as a vector, the object must explicitly inherit from or should implement a `vec_proxy()` method. Class: . + i If this object comes from a package, please report this error to the package author. + i Read our FAQ about creating vector types (`?howto_faq_fix_scalar_type_error`) to learn more. --- @@ -13,6 +16,9 @@ Condition Error in `vec_run_sizes()`: ! `x` must be a vector, not a object. + x Detected incompatible scalar S3 list. To be treated as a vector, the object must explicitly inherit from or should implement a `vec_proxy()` method. Class: . + i If this object comes from a package, please report this error to the package author. + i Read our FAQ about creating vector types (`?howto_faq_fix_scalar_type_error`) to learn more. # vec_locate_run_bounds() validates `which` diff --git a/tests/testthat/_snaps/slice-assign.md b/tests/testthat/_snaps/slice-assign.md index 8be447520..28378000d 100644 --- a/tests/testthat/_snaps/slice-assign.md +++ b/tests/testthat/_snaps/slice-assign.md @@ -5,6 +5,7 @@ Condition Error in `vec_assign()`: ! Input must be a vector, not `NULL`. + i Read our FAQ about scalar types (`?faq_error_scalar_type`) to learn more. --- @@ -13,6 +14,7 @@ Condition Error in `vec_assign()`: ! Input must be a vector, not `NULL`. + i Read our FAQ about scalar types (`?faq_error_scalar_type`) to learn more. --- @@ -21,6 +23,7 @@ Condition Error in `vec_assign()`: ! `foo` must be a vector, not `NULL`. + i Read our FAQ about scalar types (`?faq_error_scalar_type`) to learn more. --- @@ -29,6 +32,7 @@ Condition Error in `vec_assign()`: ! `foo` must be a vector, not `NULL`. + i Read our FAQ about scalar types (`?faq_error_scalar_type`) to learn more. --- @@ -37,6 +41,7 @@ Condition Error in `vec_assign()`: ! `foo` must be a vector, not an environment. + i Read our FAQ about scalar types (`?faq_error_scalar_type`) to learn more. --- @@ -45,6 +50,7 @@ Condition Error in `vec_assign()`: ! `foo` must be a vector, not an environment. + i Read our FAQ about scalar types (`?faq_error_scalar_type`) to learn more. # can assign using logical index diff --git a/tests/testthat/_snaps/slice-interleave.md b/tests/testthat/_snaps/slice-interleave.md index 5cc810ba1..bb51f2793 100644 --- a/tests/testthat/_snaps/slice-interleave.md +++ b/tests/testthat/_snaps/slice-interleave.md @@ -119,6 +119,9 @@ Condition Error in `vec_interleave()`: ! `..1` must be a vector, not a object. + x Detected incompatible scalar S3 list. To be treated as a vector, the object must explicitly inherit from or should implement a `vec_proxy()` method. Class: . + i If this object comes from a package, please report this error to the package author. + i Read our FAQ about creating vector types (`?howto_faq_fix_scalar_type_error`) to learn more. --- @@ -127,6 +130,9 @@ Condition Error in `foo()`: ! `..1` must be a vector, not a object. + x Detected incompatible scalar S3 list. To be treated as a vector, the object must explicitly inherit from or should implement a `vec_proxy()` method. Class: . + i If this object comes from a package, please report this error to the package author. + i Read our FAQ about creating vector types (`?howto_faq_fix_scalar_type_error`) to learn more. --- @@ -135,6 +141,9 @@ Condition Error in `vec_interleave()`: ! `..3` must be a vector, not a object. + x Detected incompatible scalar S3 list. To be treated as a vector, the object must explicitly inherit from or should implement a `vec_proxy()` method. Class: . + i If this object comes from a package, please report this error to the package author. + i Read our FAQ about creating vector types (`?howto_faq_fix_scalar_type_error`) to learn more. --- @@ -143,6 +152,9 @@ Condition Error in `foo()`: ! `..3` must be a vector, not a object. + x Detected incompatible scalar S3 list. To be treated as a vector, the object must explicitly inherit from or should implement a `vec_proxy()` method. Class: . + i If this object comes from a package, please report this error to the package author. + i Read our FAQ about creating vector types (`?howto_faq_fix_scalar_type_error`) to learn more. # `list_interleave()` checks for a list diff --git a/tests/testthat/_snaps/type-sf.md b/tests/testthat/_snaps/type-sf.md deleted file mode 100644 index bf214d42b..000000000 --- a/tests/testthat/_snaps/type-sf.md +++ /dev/null @@ -1,8 +0,0 @@ -# `crs` attributes of `sfc` vectors must be the same - - Code - vctrs::vec_c(x, y) - Condition - Error: - ! arguments have different crs - diff --git a/tests/testthat/_snaps/type2.md b/tests/testthat/_snaps/type2.md index e24e343ca..e3a8f7cf4 100644 --- a/tests/testthat/_snaps/type2.md +++ b/tests/testthat/_snaps/type2.md @@ -38,6 +38,7 @@ Error: ! `foo` must be a vector, not a symbol. + i Read our FAQ about scalar types (`?faq_error_scalar_type`) to learn more. Code (expect_error(vec_ptype2(quote(x), NULL, x_arg = "foo"), class = "vctrs_error_scalar_type") ) @@ -45,6 +46,7 @@ Error: ! `foo` must be a vector, not a symbol. + i Read our FAQ about scalar types (`?faq_error_scalar_type`) to learn more. # can override scalar vector error message for S3 types @@ -55,6 +57,9 @@ Error: ! `foo` must be a vector, not a object. + x Detected incompatible scalar S3 list. To be treated as a vector, the object must explicitly inherit from or should implement a `vec_proxy()` method. Class: . + i If this object comes from a package, please report this error to the package author. + i Read our FAQ about creating vector types (`?howto_faq_fix_scalar_type_error`) to learn more. Code (expect_error(vec_ptype2(foobar(), NULL, x_arg = "foo"), class = "vctrs_error_scalar_type") ) @@ -62,6 +67,9 @@ Error: ! `foo` must be a vector, not a object. + x Detected incompatible scalar S3 list. To be treated as a vector, the object must explicitly inherit from or should implement a `vec_proxy()` method. Class: . + i If this object comes from a package, please report this error to the package author. + i Read our FAQ about creating vector types (`?howto_faq_fix_scalar_type_error`) to learn more. # ptype2 and cast errors when same class fallback is impossible are informative diff --git a/tests/testthat/test-assert.R b/tests/testthat/test-assert.R index 2df13efad..fc0285198 100644 --- a/tests/testthat/test-assert.R +++ b/tests/testthat/test-assert.R @@ -166,6 +166,28 @@ test_that("obj_check_vector() error respects `arg` and `call`", { }) }) +test_that("obj_check_vector() error contains FAQ links and correct bullets", { + # Expect to see: + # - Link to general FAQ about scalar types + x <- expression() + expect_snapshot(error = TRUE, obj_check_vector(x)) + + # Expect to see: + # - Bullet about incompatible S3 list + # - Full class list + # - Link to specific FAQ about creating vectors + x <- structure(list(), class = "my_list") + expect_snapshot(error = TRUE, obj_check_vector(x)) + + # Expect to see: + # - Bullet about incompatible data frame + # - Full class list + # - Link to specific FAQ about creating vectors + x <- data_frame(a = 1) + class(x) <- c("data.frame", "my_df") + expect_snapshot(error = TRUE, obj_check_vector(x)) +}) + test_that("vec_assert() uses friendly type in error messages", { # Friendly type will be generated in rlang in the future. Upstream # changes should not cause CRAN failures.