Keep S7's := ahead of rlang and data.table - #718
Conversation
| } | ||
|
|
||
| env <- as.environment(paste0("package:", pkgname)) | ||
| env[[".conflicts.OK"]] <- TRUE |
There was a problem hiding this comment.
I think we should only ever apply this to S7 itself, and I think we can move it up to .onAttach() so we use it unconditionally when conflictRules() is not available.
| conflictRules <- get0("conflictRules", envir = baseenv(), inherits = FALSE) | ||
| if (is.null(conflictRules)) { | ||
| return(invisible()) | ||
| } |
There was a problem hiding this comment.
I think it would be clearer to use an explicit version here
bdaee29 to
54ebeeb
Compare
Inline the former activate_attach_compatibility() helper so the flag is only ever applied to S7's own attached environment, per review.
conflictRules() has been in base since R 3.6.0 and S7 now requires R >= 4.2.0, so the get0() availability check was dead code.
.conflicts.OK makes library() skip its conflict report wholesale, which also swallowed messages about genuine, unrelated conflicts. Re-emit the report ourselves, minus S7's deliberate masks (@ over base, := over rlang and data.table), reusing base's .maskedMsg formatter and message catalog so the output is identical to what library() would print.
A strict conflicts.policy errors on undeclared conflicts and ignores .conflicts.OK, so register mask.ok rules for S7 (@ over base, := over rlang and data.table). library() reads conflictRules() before loading the namespace, so this takes effect once S7's namespace is already loaded, e.g. imported by another package; a cold library(S7) under a strict policy still requires user-declared rules, as that policy intends.
S7 has no expectations about these conflicts; they are simply conflicts other than the masks S7 itself creates.
The mask filtering is an implementation detail already documented in the function comment; the qualifier only invited ambiguity.
| data.table = ":=" | ||
| ) | ||
|
|
||
| # Re-emit the conflict report that library() would have produced (see |
There was a problem hiding this comment.
Given we can switch to conflictRules(), I think we could drop this.
There was a problem hiding this comment.
conflictRules() only solves the case when rlang or data.table are loaded after S7. We also need a solution for when they're loaded before S7.
The .conflicts.OK binding is the only lever within our control there, and unfortunately, it's quite coarse: it only lets us opt into disabling all warnings. In which case, if there are other conflict warnings that we don't want to suppress (meaning, not :=), then it's our responsibility to report them.
:= ahead of rlang and data.table| env[[".conflicts.OK"]] <- TRUE | ||
| # S7_at already supplies @ without conflicting with base::@. | ||
| env <- as.environment(paste0("package:", pkgname)) | ||
| rm(list = "@", envir = env) |
Co-authored-by: Hadley Wickham <h.wickham@gmail.com>
Fixes #697.
S7, rlang, and data.table all export
:=. Before this change, the version found on the search path depended on the order in which the packages were attached, and R could print a masking message.This PR makes S7's
:=win in either order. R no longer prints an attach-time message saying that one package's:=masks another's. Messages about other masked objects are still shown.When rlang or data.table is already attached, S7 changes only the
:=binding that the package added to the search path. It does not change the package namespace, so explicit access withrlang::`:=`ordata.table::`:=`is unchanged. The original search-path binding is restored if S7 is detached.The package vignette also shows how to import
:=from S7 when a package imports rlang or data.table.Testing