From 173b4232bff810f563e1739211ea7545ed0651e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Fri, 16 Aug 2024 02:23:48 +0200 Subject: [PATCH] Fix edge case when coercing data frames to matrices (#7070) Closes #7004 --- NEWS.md | 2 ++ R/data-mask.R | 17 ++++++++++++++++- tests/testthat/_snaps/filter.md | 2 +- tests/testthat/_snaps/mutate.md | 2 +- tests/testthat/_snaps/summarise.md | 2 +- tests/testthat/test-data-mask.R | 7 +++++++ 6 files changed, 28 insertions(+), 4 deletions(-) create mode 100644 tests/testthat/test-data-mask.R diff --git a/NEWS.md b/NEWS.md index 9df8a4c1e0..903031d296 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,5 +1,7 @@ # dplyr (development version) +* Fixed an edge case when coercing data frames to matrices (#7004). + * Fixed an issue where duckplyr's ALTREP data frames were being materialized early due to internal usage of `ncol()` (#7049). diff --git a/R/data-mask.R b/R/data-mask.R index b72a708289..b50aa182c3 100644 --- a/R/data-mask.R +++ b/R/data-mask.R @@ -11,7 +11,22 @@ DataMask <- R6Class("DataMask", frame <- caller_env(n = 2) local_mask(self, frame) - names_bindings <- chr_unserialise_unicode(names2(data)) + names <- names(data) + + if (is.null(names)) { + cli::cli_abort( + "Can't transform a data frame with `NULL` names.", + call = error_call + ) + } + if (vec_any_missing(names)) { + cli::cli_abort( + "Can't transform a data frame with missing names.", + call = error_call + ) + } + + names_bindings <- chr_unserialise_unicode(names) if (any(names_bindings == "")) { # `names2()` converted potential `NA` names to `""` already abort("Can't transform a data frame with `NA` or `\"\"` names.", call = error_call) diff --git a/tests/testthat/_snaps/filter.md b/tests/testthat/_snaps/filter.md index 3d24697ea5..39a0f26903 100644 --- a/tests/testthat/_snaps/filter.md +++ b/tests/testthat/_snaps/filter.md @@ -243,7 +243,7 @@ filter(df2) Condition Error in `filter()`: - ! Can't transform a data frame with `NA` or `""` names. + ! Can't transform a data frame with missing names. # can't use `.by` with `.preserve` diff --git a/tests/testthat/_snaps/mutate.md b/tests/testthat/_snaps/mutate.md index de71d9da8c..8c4c2f7de7 100644 --- a/tests/testthat/_snaps/mutate.md +++ b/tests/testthat/_snaps/mutate.md @@ -361,5 +361,5 @@ mutate(df2) Condition Error in `mutate()`: - ! Can't transform a data frame with `NA` or `""` names. + ! Can't transform a data frame with missing names. diff --git a/tests/testthat/_snaps/summarise.md b/tests/testthat/_snaps/summarise.md index 3f80a60a5a..8040d43a9d 100644 --- a/tests/testthat/_snaps/summarise.md +++ b/tests/testthat/_snaps/summarise.md @@ -77,7 +77,7 @@ summarise(df2) Condition Error in `summarise()`: - ! Can't transform a data frame with `NA` or `""` names. + ! Can't transform a data frame with missing names. # summarise() gives meaningful errors diff --git a/tests/testthat/test-data-mask.R b/tests/testthat/test-data-mask.R new file mode 100644 index 0000000000..e82f4b4b08 --- /dev/null +++ b/tests/testthat/test-data-mask.R @@ -0,0 +1,7 @@ +test_that("Empty matrix can be coerced to a data frame (#7004)", { + skip_if_not(getRversion() >= "4.4") + expect_equal( + slice(as.data.frame(matrix(nrow = 0, ncol = 0)), 1), + data.frame() + ) +})