I'd like to emphasize that although Iñaki's example uses print(), it also happens with other S3 generics. Please note that each of the following examples might need to be run in a clean R session to work.
=========== Here's an example that doesn't use S3 dispatch. The finalizer runs correctly. ident <- function(x) invisible(x) env_with_finalizer <- function() { reg.finalizer(environment(), function(e) message("Finalizer called")) environment() } ident(env_with_finalizer()) gc() # Still in .Last.value gc() # Finalizer called =========== Here's an example that uses S3. In this case, the finalizer doesn't run. ident <- function(x) UseMethod("ident") ident.default <- function(x) invisible(x) env_with_finalizer <- function() { reg.finalizer(environment(), function(e) message("Finalizer called")) environment() } ident(env_with_finalizer()) gc() gc() # Nothing However, if the S3 generic is called with another object, the finalizer will run on the next GC: ident(1) gc() # Finalizer called =========== This example is the same as the previous one, except that, at the end, instead of calling the same S3 generic on a different object (that is, ident(1)), it calls a _different_ S3 generic on a different object (mean(1)). ident <- function(x) UseMethod("ident") ident.default <- function(x) invisible(x) env_with_finalizer <- function() { reg.finalizer(environment(), function(e) message("Finalizer called")) environment() } ident(env_with_finalizer()) gc() gc() # Nothing # Call a different S3 generic mean(1) gc() # Finalizer called -Winston On Mon, Mar 26, 2018 at 4:46 PM, Iñaki Úcar <i.uca...@gmail.com> wrote: > Hi, > > I initially opened an issue in the R6 repo because my issue was with > an R6 object. But Winston (thanks!) further simplified my example, and > it turns out that the issue (whether a feature or a bug is yet to be > seen) had to do with S3 dispatching. > > The following example, by Winston, depicts the issue: > > print.foo <- function(x, ...) { > cat("print.foo called\n") > invisible(x) > } > > new_foo <- function() { > e <- new.env() > reg.finalizer(e, function(e) message("Finalizer called")) > class(e) <- "foo" > e > } > > new_foo() > gc() # still in .Last.value > gc() # nothing > > I would expect that the second call to gc() should free 'e', but it's > not. However, if we call now *any* S3 method, then the object can be > finally gc'ed: > > print(1) > gc() # Finalizer called > > So the hypothesis is that there is some kind of caching (?) mechanism > going on. Intended behaviour or not, this is something that was > introduced between R 3.2.3 and 3.3.2 (the first succeeds; from the > second on, the example fails as described above). > > Regards, > Iñaki > > PS: Further discussion and examples in https://github.com/r-lib/R6/issues/140 > > ______________________________________________ > R-devel@r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-devel ______________________________________________ R-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel