tag_classes don't support optional attrs
- Dominant language
- Java
- Stars
- 25.8k
- Forks
- 4.6k
- Avg merge
- 2d 20h
- Merged PRs (30d)
- 72
Description
### Description of the feature request:
In [migrating rules_rust's third-party resolver support](https://github.com/bazelbuild/rules_rust/pull/2392) to bzlmod we've run into an issue due to `tag_class` arguments being more typed than WORKSPACE functions were.
We want to support a structure along the lines of (WORKSPACE):
```starlark
crates_repostory(
name = "crates",
cargo_lockfile = "//third-party:Cargo.lock",
manifests = ["//third-party:Cargo.toml"],
default_generate_build_scripts = True,
annotations = {
"some-crate": [
crate.annotation(generate_build_scripts = False),
],
}
)
```
where `crate.annotation` is just a function with optional arguments which serializes its args as JSON (https://github.com/bazelbuild/rules_rust/blob/40232a07f11376c737b35bbfac89773880d09048/crate_universe/private/crate.bzl#L84-L212)
This allowed setting a default boolean to be used for all crates, and overriding it for specific crates.
In bzlmod, we're using a `tag_class` for these annotations, along the lines of:
```starlark
crate.from_cargo(
name = "crates",
cargo_lockfile = "//third-party:Cargo.lock",
manifests = ["//third-party:Cargo.toml"],
default_generate_build_scripts = True,
)
crate.annotation(
crate = "some-crate",
generate_build_scripts = False,
)
```
However, `tag_class`es take fully typed arguments (which is generally good) and don't allow for `None` values, so there doesn't appear to be a way for us to say "`generate_build_scripts` is an optional argument which may be `None` in which case we should fall back to the repo's default value". Because we need to set a non-`None` default for `crate.annotation`'s `generate_build_scripts` argument which means it will always have a value and never fall back to the repo's default.
As a workaround, we can use a string argument here (and perhaps copy rules_go's convention of using strings which are "on"/"off"/"auto" and default to "auto", rather than using a None-able boolean), but this feels kind of messy and hacky.
### Which category does this issue belong to?
External Dependency, Rules API
### What underlying problem are you trying to solve with this feature?
Allowing a bzlmod repo to set a default value for all of the third-party libraries which it generates rules, which may optionally be overridden in for some subset of those libraries.
### Which operating system are you running Bazel on?
_No response_
### What is the output of `bazel info release`?
_No response_
### If `bazel info release` returns `development version` or `(@non-git)`, tell us how you built Bazel.
_No response_
### What's the output of `git remote get-url origin; git rev-parse master; git rev-parse HEAD` ?
_No response_
### Have you found anything relevant by searching the web?
_No response_
### Any other information, logs, or outputs that you want to share?
_No response_
Contributor guide
Research direction
Start with Bazel's tag_class argument handling and compare it with the WORKSPACE example described here. Review the linked rules_rust crate.bzl implementation for the optional-attribute use case, then identify the relevant Bazel tests and define completion as allowing an omitted tag attribute to fall back to the repository default without weakening normal type checking.
Written by the indexing model from the issue text.
Assessment
- Domain
- build-system
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 30/100