Skip to content

chore: avoid non-API calls to Rf_findVar(), Rf_findVarInFrame(), and R_UnboundValue#2604

Merged
krlmlr merged 6 commits intomainfrom
copilot/avoid-non-api-calls-to-rf-findvar
Mar 31, 2026
Merged

chore: avoid non-API calls to Rf_findVar(), Rf_findVarInFrame(), and R_UnboundValue#2604
krlmlr merged 6 commits intomainfrom
copilot/avoid-non-api-calls-to-rf-findvar

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Mar 31, 2026

R 4.6 flags Rf_findVar, Rf_findVarInFrame, and R_UnboundValue as non-API entry points. This replaces all occurrences in src/rinterface_extra.c with public API equivalents, gated on R_VERSION >= R_Version(4, 6, 0) so that older R versions continue to use the original calls.

Changes

  • Rf_findVar(sym, env)R_getVarEx(sym, env, TRUE, R_NilValue) (R ≥ 4.6) where the result is checked against R_NilValue (i.e. the variable may legitimately be absent). Using R_NilValue as the default sentinel avoids any reference to the non-API R_UnboundValue. Applies to Rx_igraph_get_pointer() and Rx_igraph_graph_version(). Falls back to Rf_findVar + R_UnboundValue comparison on R < 4.6.

  • Rf_findVar(sym, env)R_getVar(sym, env, TRUE) (R ≥ 4.6) where the variable must always exist (ALTREP length/dataptr callbacks, Rx_igraph_get_graph_id()). R_getVar mirrors get() — signals a clear error if the binding is missing. Falls back to Rf_findVar on R < 4.6.

  • Rf_findFun(identity, R_BaseNamespace) + R_UnboundValue check in Rx_igraph_safe_eval_in_env() is replaced (R ≥ 4.6) with R_getVar(identity, R_BaseNamespace, TRUE), which errors automatically if base::identity is not found — eliminating the R_UnboundValue comparison.

  • eval(call("getNamespace", "igraph"))R_getRegisteredNamespace("igraph") (R ≥ 4.6) in Rx_igraph_progress_handler(), Rx_igraph_status_handler(), and R_igraph_finalizer(). The C-level R_getRegisteredNamespace(const char *name) (new in R 4.6) returns the already-loaded igraph namespace directly. A forward declaration SEXP R_getRegisteredNamespace(const char *name) is included under #if R_VERSION >= R_Version(4, 6, 0). PROTECT/UNPROTECT counts are managed with a px counter since the number of protections differs between versions. Falls back to the eval-based approach on R < 4.6.

  • Rf_findVarInFrame(base_ns, Rf_install("emptyenv")) in Rx_igraph_add_env() is eliminated entirely: the 4-line sequence that looked up and called emptyenv() through the base namespace is replaced with the R_EmptyEnv constant directly passed to R_NewEnv(). No version guard is needed since R_EmptyEnv has been in R for many versions.

  • Removed the now-unused R_xlen_t i variable from Rx_igraph_add_env().

  • By submitting this pull request, I assign the copyright of my contribution to The igraph development team.

Copilot AI changed the title [WIP] Replace non-API calls to Rf_findVar and Rf_findVarInFrame fix: avoid non-API calls to Rf_findVar() and Rf_findVarInFrame() Mar 31, 2026
Copilot AI requested a review from krlmlr March 31, 2026 13:25
@krlmlr
Copy link
Copy Markdown
Contributor

krlmlr commented Mar 31, 2026

@copilot: The changes should be effective for R 4.6 only, keep the old code for R 4.5 or older.

Copy link
Copy Markdown
Contributor Author

Copilot AI commented Mar 31, 2026

@copilot: The changes should be effective for R 4.6 only, keep the old code for R 4.5 or older.

Done in 9615eab. All uses of R_getVar and R_getVarEx are now guarded with #if R_VERSION >= R_Version(4, 6, 0), with Rf_findVar as the fallback for R < 4.6. The Rf_findVarInFrameR_EmptyEnv replacement in Rx_igraph_add_env requires no version guard since R_EmptyEnv has been in R for many versions.

@krlmlr
Copy link
Copy Markdown
Contributor

krlmlr commented Mar 31, 2026

@copilot: R_UnboundValue is also outlawed, there is a brand-new R_getRegisteredNamespace() .

…isteredNamespace for R >= 4.6

Agent-Logs-Url: https://github.com/igraph/rigraph/sessions/c8d0b1d1-3677-4fd5-a580-d4748a401fe8

Co-authored-by: krlmlr <1741643+krlmlr@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Mar 31, 2026

@copilot: R_UnboundValue is also outlawed, there is a brand-new R_getRegisteredNamespace() .

Done in 926bf8a. Changes for R ≥ 4.6:

  • R_UnboundValue: All comparisons moved inside #else (R < 4.6) blocks. In R ≥ 4.6 branches, R_NilValue is used as the R_getVarEx default sentinel (safe because "igraph" and R_IGRAPH_VERSION_VAR are never legitimately R_NilValue). For Rx_igraph_safe_eval_in_env, replaced Rf_findFun + R_UnboundValue check with R_getVar which errors automatically if not found.

  • R_getRegisteredNamespace: Added a forward declaration under #if R_VERSION >= R_Version(4, 6, 0) and replaced the eval(call("getNamespace", "igraph")) pattern in Rx_igraph_progress_handler, Rx_igraph_status_handler, and R_igraph_finalizer with R_getRegisteredNamespace(Rf_mkString("igraph")). The igraph namespace is globally rooted so no additional PROTECT is needed for it; refactored UNPROTECT counts to use a px counter.

The forward declaration uses SEXP R_getRegisteredNamespace(SEXP name) — please let me know if the actual R 4.6 signature differs.

Copilot AI changed the title fix: avoid non-API calls to Rf_findVar() and Rf_findVarInFrame() fix: avoid non-API calls to Rf_findVar(), Rf_findVarInFrame(), and R_UnboundValue Mar 31, 2026
@krlmlr
Copy link
Copy Markdown
Contributor

krlmlr commented Mar 31, 2026

@copilot: Review r-devel/r-svn@3aa2470 for the signature, it's const char* .

Copy link
Copy Markdown
Contributor Author

Copilot AI commented Mar 31, 2026

@copilot: Review r-devel/r-svn@3aa2470 for the signature, it's const char* .

Fixed in e084487. Updated the forward declaration to SEXP R_getRegisteredNamespace(const char *name) and simplified all 3 call sites to pass the string literal "igraph" directly — no Rf_mkString or PROTECT/UNPROTECT needed.

@krlmlr krlmlr marked this pull request as ready for review March 31, 2026 17:10
@krlmlr krlmlr changed the title fix: avoid non-API calls to Rf_findVar(), Rf_findVarInFrame(), and R_UnboundValue chore: avoid non-API calls to Rf_findVar(), Rf_findVarInFrame(), and R_UnboundValue Mar 31, 2026
@krlmlr krlmlr enabled auto-merge (squash) March 31, 2026 17:11
@krlmlr krlmlr merged commit 54f5afa into main Mar 31, 2026
5 of 6 checks passed
@krlmlr krlmlr deleted the copilot/avoid-non-api-calls-to-rf-findvar branch March 31, 2026 17:26
Copilot AI added a commit that referenced this pull request Apr 2, 2026
…and `R_UnboundValue` (#2604)

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: krlmlr <1741643+krlmlr@users.noreply.github.com>
Co-authored-by: Kirill Müller <krlmlr@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Avoid non-API calls to Rf_findVar() and Rf_findVarInFrame()

2 participants