# Public API tests for optional NULL defaults in local closures skip_on_cran() test_that("optional NULL default treats explicit NULL as missing", { fn <- function(x) { declare(type(x = double(1))) f <- function(a = NULL) { if (is.null(a)) { a <- x + 1 } a * 2 } f(NULL) } expect_quick_identical(fn, list(2), list(5)) }) test_that("optional NULL defaults work with multiple optional arguments", { fn <- function(x) { declare(type(x = double(1))) f <- function(a = NULL, b = NULL) { if (is.null(a)) { a <- x + 1 } if (is.null(b)) { b <- 2 } a + b } c( f(), f(b = 5), f(a = 10), f(a = 10, b = 5) ) } qfn <- quick(fn) expect_identical(qfn(2), c(5, 8, 12, 15)) expect_identical(qfn(5), c(8, 11, 12, 15)) }) test_that("local closure calls error for unknown or missing arguments", { unknown_arg <- function(x) { declare(type(x = double(1))) f <- function(a = NULL, ...) a f(b = x) } expect_error( quick(unknown_arg), "call has unknown argument\\(s\\): b", fixed = FALSE ) missing_required <- function(x) { declare(type(x = double(1))) f <- function(a) a + x f() } expect_error( quick(missing_required), "call is missing required argument\\(s\\): a", fixed = FALSE ) }) test_that("local closure calls error when required arguments have no inferred type", { bad <- function(x) { declare(type(x = double(1))) f <- function(a) a + x f(NULL) } expect_error( quick(bad), "call has argument\\(s\\) without inferred types", fixed = FALSE ) }) test_that("optional NULL defaults must be initialized before use", { bad <- function(x) { declare(type(x = double(n))) f <- function(i, shift = NULL) { x[i] + shift } f(1L) } expect_error( quick(bad), "optional argument\\(s\\) used without initializing when NULL: shift", fixed = FALSE ) }) test_that("optional NULL defaults can be assigned before use", { fn <- function(x) { declare(type(x = double(1))) f <- function(shift = NULL) { shift <- 2 x + shift } f() } expect_quick_identical(fn, list(3)) }) test_that("optional arg shadow names avoid existing fortran names", { fn <- function(x) { declare(type(x = double(1))) declare(type(`x..local.` = double(1))) `x..local.` <- x + 1 f <- function(x = NULL) { if (is.null(x)) { x <- 2 } x + `x..local.` } f() } expect_quick_identical(fn, list(1)) }) test_that("local closure calls returning NULL cannot be used as values", { bad <- function(x) { declare(type(x = double(1))) f <- function() NULL 1 + f() } expect_error( quick(bad), "local closure calls that return `NULL` cannot be used as values", fixed = TRUE ) })