Skip to content

Commit afd322d

Browse files
authored
Remove SET_BODY() usage (#1845)
* Remove `SET_BODY()` usage * Explicitly `r_clone()` when we zap `srcref`
1 parent f5b6476 commit afd322d

File tree

3 files changed

+26
-11
lines changed

3 files changed

+26
-11
lines changed

src/internal/attr.c

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -205,13 +205,30 @@ r_obj* zap_srcref(r_obj* x) {
205205

206206
static
207207
r_obj* fn_zap_srcref(r_obj* x) {
208-
x = KEEP(r_clone(x));
208+
r_obj* formals = r_fn_formals(x);
209+
r_obj* body = r_fn_body(x);
210+
r_obj* env = r_fn_env(x);
209211

210-
r_fn_poke_body(x, zap_srcref(r_fn_body(x)));
211-
r_attrib_poke(x, r_syms.srcref, r_null);
212+
body = KEEP(zap_srcref(body));
212213

213-
FREE(1);
214-
return x;
214+
r_obj* out = KEEP(r_new_function(formals, body, env));
215+
216+
// Copy over attributes, but zap any `srcref` attribute
217+
if (r_attrib_get(x, r_syms.srcref) == r_null) {
218+
// Nothing to zap
219+
r_obj* attrib = r_attrib(x);
220+
r_poke_attrib(out, attrib);
221+
} else {
222+
// Clone so we can zap `srcref`
223+
r_obj* attrib = r_attrib(x);
224+
attrib = KEEP(r_clone(attrib));
225+
r_poke_attrib(out, attrib);
226+
FREE(1);
227+
r_attrib_poke(out, r_syms.srcref, r_null);
228+
}
229+
230+
FREE(2);
231+
return out;
215232
}
216233

217234
static

src/rlang/fn.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,6 @@ void r_fn_poke_env(r_obj* fn, r_obj* env) {
3737
SET_CLOENV(fn, env);
3838
}
3939

40-
// TODO: C API compliance
41-
static inline
42-
void r_fn_poke_body(r_obj* fn, r_obj* body) {
43-
SET_BODY(fn, body);
44-
}
45-
4640
static inline
4741
r_obj* r_new_function(r_obj* formals, r_obj* body, r_obj* env) {
4842
#if R_VERSION >= R_Version(4, 5, 0)

tests/testthat/test-attr.R

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,10 @@ test_that("zap_srcref() preserves attributes", {
134134
out <- zap_srcref(fn)
135135
expect_equal(attributes(out), list(bar = TRUE))
136136
expect_null(attributes(body(out)))
137+
138+
# `fn` attributes are not mutated
139+
expect_equal(attr(fn, "bar"), TRUE)
140+
expect_s3_class(attr(fn, "srcref"), "srcref")
137141
})
138142

139143
test_that("can zap_srcref() on functions with `[[` methods", {

0 commit comments

Comments
 (0)