Skip to content

check_dots_used() can give a false positive due to lazy evaluation #1875

Description

@jennybc

Motivated by r-lib/devtools#2672. In the matching PR, OP adds debug = as a formal argument to devtools::load_all(), even though devtools::load_all() explicitly has ... for the purpose of passing extra arguments along to pkgload::load_all().

https://github.com/r-lib/devtools/blob/ab097cc996b0e9e1fd067a95a71b28054a5b8a7c/R/pkgload.R#L2

https://github.com/r-lib/devtools/blob/ab097cc996b0e9e1fd067a95a71b28054a5b8a7c/R/pkgload.R#L26-L36

The problem is, even though debug is a formal argument of pkgload::load_all(), the most-commonly executed code paths don't actually evaluate debug and, therefore, rlang::check_dots_used() raises a false warning or error. This happens whenever there's no need to compile code, which is most of the time:

https://github.com/r-lib/pkgload/blob/ce84bbe18c56952da73d36c9cccc19820916919e/R/load.R#L178

The warning suggests that there's no match with formal arguments ("Did you misspell an argument name?"), but that's not the problem.

Here's a reprex.

inner <- function(x, debug = TRUE) {
  if (x > 0) {
    message("debugging is ", if (debug) "on" else "off")
  }
  x
}

outer <- function(x, ...) {
  rlang::check_dots_used(action = rlang::warn)
  result <- inner(x, ...)
  message("inner() completed successfully with result: ", result)
  result
}

# No warning: inner() evaluates `debug`
outer(1, debug = FALSE)
#> debugging is off
#> inner() completed successfully with result: 1
#> [1] 1

# False warning: inner() still runs fine, it just doesn't happen to
# evaluate `debug` in this code path
outer(-1, debug = FALSE)
#> inner() completed successfully with result: -1
#> Warning in outer(-1, debug = FALSE): Arguments in `...` must be used.
#> ✖ Problematic argument:
#> • debug = FALSE
#> ℹ Did you misspell an argument name?
#> [1] -1

Created on 2026-02-25 with reprex v2.1.1.9000

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions