Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove environment accessors #1721

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# rlang (development version)

* The SEXP iterator of the rlang C library (used in r-lib/memtools) is now
behind a feature flag because it requires private API accessors. Compile
rlang with `-DRLANG_USE_PRIVATE_ACCESSORS` to enable it.

* `env_unlock()` is now defunct because recent versions of R no long
make it possible to unlock an environment. Make sure to use an up-to-date
version of pkgload (>= 1.4.0) following this change.
Expand Down
6 changes: 5 additions & 1 deletion R/c-lib.R
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,10 @@
FALSE
}

has_private_accessors <- function() {
.Call(ffi_has_private_accessors)
}


# cnd.c

Expand Down Expand Up @@ -401,5 +405,5 @@
# walk.c

sexp_iterate <- function(x, fn) {
.Call(ffi_sexp_iterate, x, fn)
do.call(".Call", list(ffi_sexp_iterate, x, fn))

Check warning on line 408 in R/c-lib.R

View check run for this annotation

Codecov / codecov/patch

R/c-lib.R#L408

Added line #L408 was not covered by tests
}
6 changes: 0 additions & 6 deletions R/obj.R
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,6 @@ unmark_object <- function(x) {
true_length <- function(x) {
.Call(ffi_true_length, x)
}
env_frame <- function(x) {
.Call(ffi_env_frame, x)
}
env_hash_table <- function(x) {
.Call(ffi_env_hash_table, x)
}

promise_expr <- function(name, env = caller_env()) {
.Call(ffi_promise_expr, name, env)
Expand Down
19 changes: 12 additions & 7 deletions src/internal/exported.c
Original file line number Diff line number Diff line change
Expand Up @@ -475,13 +475,6 @@ r_obj* ffi_env_poke_parent(r_obj* env, r_obj* new_parent) {
return env;
}

r_obj* ffi_env_frame(r_obj* env) {
return FRAME(env);
}
r_obj* ffi_env_hash_table(r_obj* env) {
return HASHTAB(env);
}

r_obj* ffi_env_inherits(r_obj* env, r_obj* ancestor) {
return r_lgl(r_env_inherits(env, ancestor, r_envs.empty));
}
Expand Down Expand Up @@ -1067,6 +1060,16 @@ r_obj* protect_missing(r_obj* x) {
}
}

r_obj* ffi_has_private_accessors(void) {
#ifdef RLANG_USE_PRIVATE_ACCESSORS
return r_true;
#else
return r_false;
#endif
}

#ifdef RLANG_USE_PRIVATE_ACCESSORS

// [[ register() ]]
r_obj* ffi_sexp_iterate(r_obj* x, r_obj* fn) {
struct r_dyn_array* p_out = r_new_dyn_vector(R_TYPE_list, 256);
Expand Down Expand Up @@ -1125,3 +1128,5 @@ r_obj* ffi_sexp_iterate(r_obj* x, r_obj* fn) {
FREE(3);
return r_dyn_unwrap(p_out);
}

#endif
5 changes: 3 additions & 2 deletions src/internal/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,9 @@ static const R_CallMethodDef r_callables[] = {
{"ffi_env_browse", (DL_FUNC) &ffi_env_browse, 2},
{"ffi_env_clone", (DL_FUNC) &r_env_clone, 2},
{"ffi_env_coalesce", (DL_FUNC) &ffi_env_coalesce, 2},
{"ffi_env_frame", (DL_FUNC) &ffi_env_frame, 1},
{"ffi_env_get", (DL_FUNC) &ffi_env_get, 5},
{"ffi_env_get_list", (DL_FUNC) &ffi_env_get_list, 5},
{"ffi_env_has", (DL_FUNC) &ffi_env_has, 3},
{"ffi_env_hash_table", (DL_FUNC) &ffi_env_hash_table, 1},
{"ffi_env_inherits", (DL_FUNC) &ffi_env_inherits, 2},
{"ffi_env_is_browsed", (DL_FUNC) &ffi_env_is_browsed, 1},
{"ffi_env_poke", (DL_FUNC) &ffi_env_poke, 5},
Expand All @@ -100,6 +98,7 @@ static const R_CallMethodDef r_callables[] = {
{"ffi_glue_is_here", (DL_FUNC) &ffi_glue_is_here, 0},
{"ffi_has_dots_unnamed", (DL_FUNC) &ffi_has_dots_unnamed, 1},
{"ffi_has_local_precious_list", (DL_FUNC) &ffi_has_local_precious_list, 0},
{"ffi_has_private_accessors", (DL_FUNC) &ffi_has_private_accessors, 0},
{"ffi_has_size_one_bool", (DL_FUNC) &ffi_has_size_one_bool, 0},
{"ffi_hash", (DL_FUNC) &ffi_hash, 1},
{"ffi_hash_file", (DL_FUNC) &ffi_hash_file, 1},
Expand Down Expand Up @@ -201,7 +200,9 @@ static const R_CallMethodDef r_callables[] = {
{"ffi_replace_na", (DL_FUNC) &ffi_replace_na, 2},
{"ffi_run_c_test", (DL_FUNC) &ffi_run_c_test, 1},
{"ffi_set_names", (DL_FUNC) &ffi_set_names, 4},
#ifdef RLANG_USE_PRIVATE_ACCESSORS
{"ffi_sexp_iterate", (DL_FUNC) &ffi_sexp_iterate, 2},
#endif
{"ffi_squash", (DL_FUNC) &ffi_squash, 4},
{"ffi_standalone_check_number_1.0.7", (DL_FUNC) &ffi_standalone_check_number, 7},
{"ffi_standalone_is_bool_1.0.7", (DL_FUNC) &ffi_standalone_is_bool, 3},
Expand Down
4 changes: 3 additions & 1 deletion src/rlang/rlang.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,10 @@
#include "vec-chr.c"
#include "vec-lgl.c"
#include "vendor.c"
#include "walk.c"

#ifdef RLANG_USE_PRIVATE_ACCESSORS
#include "walk.c"
#endif

// Allows long vectors to be indexed with doubles
r_ssize r_arg_as_ssize(r_obj* n, const char* arg) {
Expand Down
2 changes: 2 additions & 0 deletions tests/testthat/test-c-api.R
Original file line number Diff line number Diff line change
Expand Up @@ -1164,6 +1164,8 @@ test_that("can push to arrays in dynamic list-of", {
})

test_that("sexp iterator visits in full order", {
skip_if_not(has_private_accessors())

it_dirs <- function(snapshot) {
dirs <- sapply(snapshot, `[[`, "dir")
dirs <- table(dirs)
Expand Down
23 changes: 0 additions & 23 deletions tests/testthat/test-env.R
Original file line number Diff line number Diff line change
Expand Up @@ -390,29 +390,6 @@ test_that("env_length() gives env length", {
expect_identical(env_length(env(a = "a")), 1L)
})

test_that("env_clone() duplicates frame", {
skip_silently("Would fail on non-GNU R")

e <- new.env(hash = FALSE)
e$x <- 1
c <- env_clone(e)
expect_false(is_reference(env_frame(e), env_frame(c)))
})

test_that("env_clone() duplicates hash table", {
skip_silently("Would fail on non-GNU R")

e <- env(x = 1)
c <- env_clone(e)

e_hash <- env_hash_table(e)
c_hash <- env_hash_table(c)
expect_false(is_reference(e_hash, c_hash))

i <- detect_index(e_hash, is_null, .p = is_false)
expect_false(is_reference(e_hash[[i]], c_hash[[i]]))
})

test_that("env_clone() increases refcounts (#621)", {
e <- env(x = 1:2)
env_bind_lazy(e, foo = 1)
Expand Down
Loading