Skip to content

Keep S7's := ahead of rlang and data.table - #718

Open
t-kalinowski wants to merge 15 commits into
mainfrom
suppress-s7-warnings
Open

Keep S7's := ahead of rlang and data.table#718
t-kalinowski wants to merge 15 commits into
mainfrom
suppress-s7-warnings

Conversation

@t-kalinowski

@t-kalinowski t-kalinowski commented Jun 24, 2026

Copy link
Copy Markdown
Member

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 with rlang::`:=` or data.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

  • The full test suite passes.
  • The pkgdown check passes.
  • R CMD check completes with no errors or warnings; the two existing notes remain.
  • Both attachment orders were tested on R 4.2.3 and R 4.3.3.

Comment thread R/compatibility.R Outdated
}

env <- as.environment(paste0("package:", pkgname))
env[[".conflicts.OK"]] <- TRUE

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread R/compatibility.R Outdated
Comment on lines +42 to +45
conflictRules <- get0("conflictRules", envir = baseenv(), inherits = FALSE)
if (is.null(conflictRules)) {
return(invisible())
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be clearer to use an explicit version here

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.
Comment thread R/compatibility.R Outdated
data.table = ":="
)

# Re-emit the conflict report that library() would have produced (see

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given we can switch to conflictRules(), I think we could drop this.

@t-kalinowski t-kalinowski Aug 18, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@t-kalinowski t-kalinowski changed the title Keep S7 := ahead of rlang and data.table Resolve S7 := attach-order conflicts with rlang and data.table Aug 24, 2026
@t-kalinowski t-kalinowski changed the title Resolve S7 := attach-order conflicts with rlang and data.table Keep S7's := ahead of rlang and data.table Aug 24, 2026
@t-kalinowski
t-kalinowski marked this pull request as ready for review August 24, 2026 15:39
@t-kalinowski
t-kalinowski requested a review from hadley August 24, 2026 15:39
Comment thread R/zzz.R
env[[".conflicts.OK"]] <- TRUE
# S7_at already supplies @ without conflicting with base::@.
env <- as.environment(paste0("package:", pkgname))
rm(list = "@", envir = env)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cunning!

Comment thread vignettes/packages.Rmd Outdated
Co-authored-by: Hadley Wickham <h.wickham@gmail.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.

Fix rlang/data.table conflicts

2 participants