[Rd] Making parent.env<- an error for package namespaces and package imports
Tierney, Luke
luke-tierney at uiowa.edu
Sat Oct 18 18:03:53 CEST 2014
I'll look into it
Sent from my iPhone
> On Oct 17, 2014, at 1:13 AM, "Karl Millar" <kmillar at google.com> wrote:
>
> I'd like to propose a change to the R language so that calling
> 'parent.env<-' on a package namespace or package imports is a runtime
> error.
>
> Currently the documentation warns that it's dangerous behaviour and
> might go away:
> The replacement function ‘parent.env<-’ is extremely dangerous as
> it can be used to destructively change environments in ways that
> violate assumptions made by the internal C code. It may be
> removed in the near future.
>
> This change would both eliminate some potential dangerous behaviours,
> and make it significantly easier for runtime compilation systems to
> optimize symbol lookups for code in packages.
>
> The following patch against current svn implements this functionality.
> It allows calls to 'parent.env<-' only until the namespace is locked,
> allowing the namespace to be built correctly while preventing user
> code from subsequently messing with it.
>
> I'd also like to make calling parent.env<- on an environment on the
> call stack an error, for the same reasons, but it's not so obvious to
> me how to implement that efficiently right now. Could we at least
> document that as being 'undefined behaviour'?
>
> Thanks,
>
> Karl
>
>
> Index: src/main/builtin.c
> ===================================================================
> --- src/main/builtin.c (revision 66783)
> +++ src/main/builtin.c (working copy)
> @@ -356,6 +356,24 @@
> return( ENCLOS(arg) );
> }
>
> +static Rboolean R_IsImportsEnv(SEXP env)
> +{
> + if (isNull(env) || !isEnvironment(env))
> + return FALSE;
> + if (ENCLOS(env) != R_BaseNamespace)
> + return FALSE;
> + SEXP name = getAttrib(env, R_NameSymbol);
> + if (!isString(name) || length(name) != 1)
> + return FALSE;
> +
> + const char *imports_prefix = "imports:";
> + const char *name_string = CHAR(STRING_ELT(name, 0));
> + if (!strncmp(name_string, imports_prefix, strlen(imports_prefix)))
> + return TRUE;
> + else
> + return FALSE;
> +}
> +
> SEXP attribute_hidden do_parentenvgets(SEXP call, SEXP op, SEXP args, SEXP rho)
> {
> SEXP env, parent;
> @@ -371,6 +389,10 @@
> error(_("argument is not an environment"));
> if( env == R_EmptyEnv )
> error(_("can not set parent of the empty environment"));
> + if (R_EnvironmentIsLocked(env) && R_IsNamespaceEnv(env))
> + error(_("can not set the parent environment of a namespace"));
> + if (R_EnvironmentIsLocked(env) && R_IsImportsEnv(env))
> + error(_("can not set the parent environment of package imports"));
> parent = CADR(args);
> if (isNull(parent)) {
> error(_("use of NULL environment is defunct"));
> 
>
> ______________________________________________
> R-devel at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel
More information about the R-devel
mailing list