Skip to content

Commit 743b302

Browse files
committed
improve way to hash function
1 parent 635b6c4 commit 743b302

File tree

1 file changed

+8
-3
lines changed

1 file changed

+8
-3
lines changed

src/dict.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,8 @@ static_inline const char* digest(SEXP self, SEXP x) {
6666
// we need to mask the object in order to make `base::serialize` work
6767
SEXP xsym = install("x");
6868
SEXP new_env = PROTECT(Rf_lang3(Rf_install("::"), Rf_install("base"), Rf_install("new.env")));
69-
SEXP mask = PROTECT(Rf_eval(Rf_lang1(new_env), self));
69+
SEXP new_env_call = PROTECT(Rf_lang1(new_env));
70+
SEXP mask = PROTECT(Rf_eval(new_env_call, self));
7071
Rf_defineVar(xsym, x, mask);
7172
SEXP digestfun = PROTECT(get_sexp_value(self, "digest"));
7273
SEXP l = PROTECT(Rf_lang2(digestfun, xsym));
@@ -76,7 +77,7 @@ static_inline const char* digest(SEXP self, SEXP x) {
7677
if (errorOccurred || TYPEOF(result) != STRSXP) {
7778
Rf_error("cannot compute digest of the key");
7879
}
79-
UNPROTECT(4);
80+
UNPROTECT(5);
8081
return R_CHAR(Rf_asChar(result));
8182
}
8283

@@ -89,7 +90,11 @@ tommy_hash_t strhash(SEXP self, SEXP key) {
8990
} else if (Rf_isVector(key)) {
9091
key_c = digest(self, key);
9192
} else if (Rf_isFunction(key)) {
92-
key_c = digest(self, BODY(key));
93+
SEXP key2 = PROTECT(Rf_duplicate(key));
94+
// the digest function will also hash the enclosure
95+
SET_CLOENV(key2, R_NilValue);
96+
key_c = digest(self, key2);
97+
UNPROTECT(1);
9398
} else {
9499
const char* buf = R_alloc(sizeof(char), 30);
95100
sprintf((char*) buf, "<%p>", key);

0 commit comments

Comments
 (0)