Skip to content

Commit 5b59cbc

Browse files
authored
Make onLoad mechanisms more consistent (RConsortium#355)
1 parent 72e68a9 commit 5b59cbc

File tree

5 files changed

+47
-30
lines changed

5 files changed

+47
-30
lines changed

R/base.R

+7-2
Original file line numberDiff line numberDiff line change
@@ -158,8 +158,6 @@ class_function <- new_base_class("function", "fun")
158158
#' @order 1
159159
class_environment <- new_base_class("environment")
160160

161-
# Base unions are created .onLoad
162-
163161
#' @export
164162
#' @rdname base_classes
165163
#' @format NULL
@@ -177,3 +175,10 @@ class_atomic <- NULL
177175
#' @format NULL
178176
#' @order 2
179177
class_vector <- NULL
178+
179+
# Define onload to avoid dependencies between files
180+
on_load_define_union_classes <- function() {
181+
class_numeric <<- new_union(class_integer, class_double)
182+
class_atomic <<- new_union(class_logical, class_numeric, class_complex, class_character, class_raw)
183+
class_vector <<- new_union(class_atomic, class_expression, class_list)
184+
}

R/class.R

+1-1
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,7 @@ str.S7_object <- function(object, ..., nest.lev = 0) {
290290
cat(if (nest.lev > 0) " ")
291291
cat(obj_desc(object))
292292

293-
if (typeof(object) != .S7_type) {
293+
if (!is_S7_type(object)) {
294294
if (!typeof(object) %in% c("numeric", "integer", "character", "double"))
295295
cat(" ")
296296

R/convert.R

+9-1
Original file line numberDiff line numberDiff line change
@@ -101,4 +101,12 @@ convert <- function(from, to, ...) {
101101
stop(msg, call. = FALSE)
102102
}
103103
}
104-
# Converted to S7_generic on .onLoad
104+
105+
# Converted to S7_generic onLoad in order to avoid dependency between files
106+
on_load_make_convert_generic <- function() {
107+
convert <<- S7_generic(
108+
convert,
109+
name = "convert",
110+
dispatch_args = c("from", "to")
111+
)
112+
}

R/union.R

+13-4
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,19 @@ new_union <- function(...) {
5353
`|.S7_class` <- function(e1, e2) {
5454
new_union(e1, e2)
5555
}
56-
57-
# Method registration for the remaining classes happens onLoad so that
58-
# their pointers are identical, working around a bug that was fixed in
59-
# R 4.1: https://github.com/wch/r-source/commit/b41344e3d0da7d78fd
56+
# Register remaining methods onLoad so that their pointers are identical,
57+
# working around a bug that was fixed in R 4.1:
58+
# https://github.com/wch/r-source/commit/b41344e3d0da7d78fd
59+
on_load_define_or_methods <- function() {
60+
registerS3method("|", "S7_union", `|.S7_class`)
61+
registerS3method("|", "S7_base_class", `|.S7_class`)
62+
registerS3method("|", "S7_S3_class", `|.S7_class`)
63+
registerS3method("|", "S7_any", `|.S7_class`)
64+
registerS3method("|", "S7_missing", `|.S7_class`)
65+
registerS3method("|", "classGeneratorFunction", `|.S7_class`)
66+
registerS3method("|", "ClassUnionRepresentation", `|.S7_class`)
67+
registerS3method("|", "classRepresentation", `|.S7_class`)
68+
}
6069

6170
is_union <- function(x) inherits(x, "S7_union")
6271

R/zzz.R

+17-22
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,22 @@ S7_object <- new_class(
1515
.Call(S7_object_)
1616
},
1717
validator = function(self) {
18-
if (typeof(self) != .S7_type) {
18+
if (!is_S7_type(self)) {
1919
"Underlying data is corrupt"
2020
}
2121
}
2222
)
2323
methods::setOldClass("S7_object")
2424

25+
.S7_type <- NULL
26+
# Defined onLoad because it depends on R version
27+
on_load_define_S7_type <- function() {
28+
.S7_type <<- typeof(.Call(S7_object_))
29+
}
30+
is_S7_type <- function(x) {
31+
typeof(x) == .S7_type
32+
}
33+
2534
#' @export
2635
`$.S7_object` <- function(x, name) {
2736
if (typeof(x) %in% c("list", "environment")) {
@@ -100,6 +109,8 @@ S7_method <- new_class("S7_method",
100109
)
101110
methods::setOldClass(c("S7_method", "function", "S7_object"))
102111

112+
# hooks -------------------------------------------------------------------
113+
103114
.onAttach <- function(libname, pkgname) {
104115
env <- as.environment(paste0("package:", pkgname))
105116
if (getRversion() < "4.3.0") {
@@ -108,26 +119,10 @@ methods::setOldClass(c("S7_method", "function", "S7_object"))
108119
}
109120

110121
.onLoad <- function(...) {
111-
on_load_define_ops()
122+
on_load_make_convert_generic()
112123
on_load_define_matrixOps()
113-
114-
## "S4" or [in R-devel 2023-07-x] "object"
115-
assign(".S7_type", typeof(.Call(S7_object_)), topenv())
116-
117-
convert <<- S7_generic(convert, name = "convert", dispatch_args = c("from", "to"))
118-
119-
class_numeric <<- new_union(class_integer, class_double)
120-
class_atomic <<- new_union(class_logical, class_numeric, class_complex, class_character, class_raw)
121-
class_vector <<- new_union(class_atomic, class_expression, class_list)
122-
123-
# Dynamic register so that function pointers are the same, avoiding R 4.0
124-
# and earlier bug related to incompatible S3 methods during Ops dispatch
125-
registerS3method("|", "S7_union", `|.S7_class`)
126-
registerS3method("|", "S7_base_class", `|.S7_class`)
127-
registerS3method("|", "S7_S3_class", `|.S7_class`)
128-
registerS3method("|", "S7_any", `|.S7_class`)
129-
registerS3method("|", "S7_missing", `|.S7_class`)
130-
registerS3method("|", "classGeneratorFunction", `|.S7_class`)
131-
registerS3method("|", "ClassUnionRepresentation", `|.S7_class`)
132-
registerS3method("|", "classRepresentation", `|.S7_class`)
124+
on_load_define_ops()
125+
on_load_define_or_methods()
126+
on_load_define_S7_type()
127+
on_load_define_union_classes()
133128
}

0 commit comments

Comments
 (0)