diff --git a/R/data.table.R b/R/data.table.R index e95420b6e0..ccb7f36e60 100644 --- a/R/data.table.R +++ b/R/data.table.R @@ -2261,7 +2261,7 @@ is.na.data.table = function (x) { Ops.data.table = function(e1, e2 = NULL) { ans = NextMethod() - if (cedta() && is.data.frame(ans)) ans = as.data.table(ans) + if (cedta() && is.data.frame(ans)) ans = as.data.table(ans) else if (is.matrix(ans)) colnames(ans) = copy(colnames(ans)) ans } @@ -2358,7 +2358,10 @@ copy = function(x) { .Call(C_unlock, y) setalloccol(y) } else if (is.list(y)) { + oldClass = class(y) + setattr(y, 'class', NULL) # otherwise [[.person method (which returns itself) results in infinite recursion, #4620 y[] = lapply(y, reallocate) + if (!identical(oldClass, 'list')) setattr(y, 'class', oldClass) } y } diff --git a/inst/tests/tests.Rraw b/inst/tests/tests.Rraw index 774911872f..adaea569c6 100644 --- a/inst/tests/tests.Rraw +++ b/inst/tests/tests.Rraw @@ -17102,3 +17102,8 @@ options(old) # 1 is treated as . in dcast formula, #4615 DT = data.table(a = c("s", "x"), survmean = 1:2) test(2151, dcast(DT, 1 ~ a, value.var='survmean'), data.table('.'='.', s=1L, x=2L, key='.')) + +# list object with [[ method that returns itself (e.g. person) lead to infinite loop in copy(), #4620 +y = person(given='Joel', family='Mossong') +test(2152, copy(y), y) +