Repository: bazelbuild/bazel
Issue: `repr` representation of starlarkified rules is too generic
Labels: type: bug
P3
team-Rules-API

### Description of the bug:


Running `str` on a built-in rule function written in java, such as `py_library`, returns strings like `<built-in rule py_library>`, while for one whose implementation has been rewritten in starlark, such as `cc_library`, it merely returns `<rule>`.  Upgrading from Bazel 4 to 6 broke some of our macros which take those functions as inputs and make decisions based on what rules they correspond to.  Given such a function, there no longer seems to be a way to determine the name of the rule to which it corresponds.  One can work around it by explicitly comparing things against `native.cc_library` and so on, but the difference in output seems like an unintended regression.  Preferably, the string representations of internal starlarkified rules should somehow expose the rules' names, but another generic means of determining the names of arbitrary rules would suffice instead.

### What's the simplest, easiest way to reproduce this bug? Please provide a minimal example if possible.


Compare the outputs of `str(cc_library)` and `str(py_library)` using Bazel 6, which are `<rule>` and `<built-in rule py_binary>` respectively.

### Which operating system are you running Bazel on?


Ubuntu

### What is the output of `bazel info release`?


release 6.0.0

### 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_

Issue comments:
I think it's acceptable to change str representation of Starlark rules to return label of .bzl file and rule name.

On the other hand, you probably shouldn't depend on this string. Can you expand you use-case further, provide an example macro? I find it weird you'd need rule kind in a macro, as they are usually written for specific rules.
> On the other hand, you probably shouldn't depend on this string. Can you expand you use-case further, provide an example macro? I find it weird you'd need rule kind in a macro, as they are usually written for specific rules.

We have a macro which works in tandem with a few repository rules to allow someone doing a build to choose which generation of CUDA and TensorFlow-related libraries they want to use so we can upgrade subsets of the repository to new TF versions incrementally.  It looks similar to this:

```
mlinfra_platform_target(
    cc_library,
    name = "foo",
    ...,
)
```

This macro wraps arbitrary rules, stubs them out when the build isn't compatible with them, and applies tags based on a generic notion of the rules' categories (binary, library, test, etc.) so we can track the progress of these upgrades using queries.  The `repr` representation of these rules is the only thing this macro has at its disposal to do this categorization; rule functions have no other means of introspection.  Apart from this tagging, there simply is no need to have different macros for different rules, so we opted to simplify and not deal with proliferating nearly-identical macros.
A fix for this issue has been included in [Bazel 6.4.0 RC1](https://releases.bazel.build/6.4.0/rc1/index.html). Please test out the release candidate and report any issues as soon as possible. Thanks!

Pull request review comments:

Patch that resolved the issue:
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/starlark/StarlarkRuleClassFunctions.java b/src/main/java/com/google/devtools/build/lib/analysis/starlark/StarlarkRuleClassFunctions.java
index 2ae33deca51935..b0ab97ac757f2f 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/starlark/StarlarkRuleClassFunctions.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/starlark/StarlarkRuleClassFunctions.java
@@ -977,7 +977,11 @@ public boolean isExported() {
 
     @Override
     public void repr(Printer printer) {
-      printer.append("<rule>");
+      if (isExported()) {
+        printer.append("<rule ").append(getRuleClass().getName()).append(">");
+      } else {
+        printer.append("<rule>");
+      }
     }
 
     @Override


Test patch:
diff --git a/src/test/java/com/google/devtools/build/lib/starlark/StarlarkStringRepresentationsTest.java b/src/test/java/com/google/devtools/build/lib/starlark/StarlarkStringRepresentationsTest.java
index 35c1f6515d149a..e3b651271c4443 100644
--- a/src/test/java/com/google/devtools/build/lib/starlark/StarlarkStringRepresentationsTest.java
+++ b/src/test/java/com/google/devtools/build/lib/starlark/StarlarkStringRepresentationsTest.java
@@ -268,7 +268,7 @@ public void testStringRepresentations_functions() throws Exception {
   @Test
   public void testStringRepresentations_rules() throws Exception {
     setBuildLanguageOptions("--experimental_builtins_injection_override=+cc_library");
-    assertStringRepresentation("native.cc_library", "<rule>");
+    assertStringRepresentation("native.cc_library", "<rule cc_library>");
     assertStringRepresentation("def f(): pass", "rule(implementation=f)", "<rule>");
   }