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

Should we provide a linter to statically detect unsupported currying of base functions? #2558

Open
IndrajeetPatil opened this issue Apr 17, 2024 · 2 comments

Comments

@IndrajeetPatil
Copy link
Collaborator

Although R CMD check can detect such usages, it might be a nice feature to detect this statically.

dir <- withr::local_tempdir()
withr::local_options(list(usethis.quiet = TRUE))
library(usethis)
pkg_dir <- create_package(dir, open = FALSE, rstudio = FALSE)

withr::with_dir(pkg_dir, {
  usethis::use_mit_license()
  fs::dir_create("R")
  writeLines(
    c('f <- purrr::partial(gsub, pattern = "/$", replacement = "")', "NULL"), 
    "R/script.R"
  )
  
  rcmdcheck::rcmdcheck(error_on = "warning", quiet = TRUE)
})
#> ── R CMD check results ──────────────────────── file70d53cb58d55 0.0.0.9000 ────
#> Duration: 36.4s
#> 
#> ❯ checking R code for possible problems ... WARNING
#>   Found a .Internal call in the following function:
#>     ‘f’
#>   with calls to .Internal functions
#>     ‘gsub’
#>   
#>   Packages should not call .Internal(): it is not part of the API, for
#>   use only by R itself and subject to change without notice.
#> 
#> 0 errors ✔ | 1 warning ✖ | 0 notes ✔
#> Error: R CMD check found WARNINGs

Created on 2024-04-17 with reprex v2.1.0

That said, I am not sure how to get a list of {base} functions that call .Internal().

@MichaelChirico
Copy link
Collaborator

MichaelChirico commented Apr 17, 2024

How could we detect this statically? Specifically for the case of purrr::partial(), which is a run-time replacement of the code with the partialized code. We can of course just look for calls to .Internal(), maybe that should be a default undesirable function, but I'm not sure what such a linter for partial would look like.

@MichaelChirico
Copy link
Collaborator

Here's how {tools} does it:

https://github.com/r-devel/r-svn/blob/52b4541138551afb7c20b01c7acb06e0a99535a0/src/library/tools/R/QC.R#L6908-L7000

We need to evaluate f, which means we need to execute the package code object_usage_linter() does the same, IIRC, so it's not out of the question, just harder.

That said, I am not sure how to get a list of {base} functions that call .Internal().

That's not needed, once f is evaluated, we just look for an .Internal() call in it.

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

No branches or pull requests

2 participants