Bug 17401 - match.arg() evaluates default choices in wrong environment
Summary: match.arg() evaluates default choices in wrong environment
Status: CLOSED FIXED
Alias: None
Product: R
Classification: Unclassified
Component: Low-level (show other bugs)
Version: R 3.4.3
Hardware: Other Other
: P5 enhancement
Assignee: R-core
URL:
Depends on:
Blocks:
 
Reported: 2018-03-21 21:53 UTC by Duncan Murdoch
Modified: 2018-04-03 09:12 UTC (History)
1 user (show)

See Also:


Attachments
Patch to R-devel (560 bytes, patch)
2018-03-21 21:53 UTC, Duncan Murdoch
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Duncan Murdoch 2018-03-21 21:53:51 UTC
Created attachment 2330 [details]
Patch to R-devel

When match.arg() is called with just one argument that is a parameter to the function, it looks up the value for choices in the default value for that parameter.  But it evaluates the default in the wrong environment, so we can get errors like this:

f <- function(x = y) {
	y <- c("a", "b", "c")
	match.arg(x)
}
f()

# Error in eval(formal.args[[as.character(substitute(arg))]]) : 
#  object 'y' not found

The fix is to evaluate in parent.frame(), not the current environment.  I'll attach a patch to do this.
Comment 1 Martin Maechler 2018-03-29 09:01:24 UTC
Thank you, Duncan.

You are right that this is a bug   ((though the example is pretty unnatural))

I'm testing your patch and will commit it if I don't see problems.
Comment 2 Duncan Murdoch 2018-03-30 10:36:24 UTC
Thanks Martin.  The real example wasn't so artificial.  It had the default defined in a package global variable, because it was shared by several functions.  This failed when the global wasn't exported from the package.
Comment 3 Duncan Murdoch 2018-03-30 12:17:26 UTC
Whoops, I forgot:  it also failed when the global variable was exported from the package but the package wasn't attached, and the function was called using :: notation.