Repository: bazelbuild/bazel
Issue: `alias` targets should expose `FilesToRunProvider` if `actual` has one
Labels: type: bug
P2
team-Configurability

### Description of the bug:


I have code which runs a `cquery` to gets the executable of a `FilesToRunProvider`:

`bazel cquery --output=starlark --starlark:expr="providers(target).get(\"FilesToRunProvider\").executable.path"`

This doesn't work for `alias` targets which point to binary targets. It probably should.

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


BUILD file:
```starlark
py_binary(
    name = "bin",
    srcs = ["bin.py"],
)

alias(
    name = "alias",
    actual = ":bin",
)
```

Run: `bazel cquery --output=starlark --starlark:expr="providers(target).get(\"FilesToRunProvider\").executable.path" :alias`

expect to get an output path. Instead, get an error because `providers(target).get("FilesToRunProvider")` is `None`.

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


_No response_

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


release 6.1.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:
Seems to be a much more general issue:
```
$ bazel cquery --output=starlark --starlark:expr="providers(target)" :alias
None
```

Pull request review comments:
The original change at https://github.com/bazelbuild/bazel/pull/17753/files doesn't impact lines 99-111.  Does that matter?
Yeah, that was the change I made. I removed this extra code that shouldn't have been included:) Looks like the file here is outdated.

Patch that resolved the issue:
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredTarget.java b/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredTarget.java
index c8c600ab4d557b..df3f79b7a524a1 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredTarget.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredTarget.java
@@ -20,6 +20,7 @@
 import com.google.devtools.build.lib.cmdline.Label;
 import com.google.devtools.build.lib.skyframe.BuildConfigurationKey;
 import javax.annotation.Nullable;
+import net.starlark.java.eval.Dict;
 import net.starlark.java.eval.Structure;
 
 /**
@@ -95,4 +96,13 @@ default Label getOriginalLabel() {
   default ImmutableMap<Label, ConfigMatchingProvider> getConfigConditions() {
     return ImmutableMap.of();
   }
+
+  /**
+   * This is only intended to be called from the query dialects of Starlark.
+   *
+   * @return a map of provider names to their values
+   */
+  default Dict<String, Object> getProvidersDict() {
+    return null;
+  }
 }
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/configuredtargets/AbstractConfiguredTarget.java b/src/main/java/com/google/devtools/build/lib/analysis/configuredtargets/AbstractConfiguredTarget.java
index e5156c1cf3eee5..0c3330d0f5586c 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/configuredtargets/AbstractConfiguredTarget.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/configuredtargets/AbstractConfiguredTarget.java
@@ -35,7 +35,6 @@
 import com.google.devtools.build.lib.skyframe.BuildConfigurationKey;
 import java.util.function.Consumer;
 import javax.annotation.Nullable;
-import net.starlark.java.eval.Dict;
 import net.starlark.java.eval.EvalException;
 import net.starlark.java.eval.Printer;
 import net.starlark.java.eval.Starlark;
@@ -255,12 +254,4 @@ public String getRuleClassString() {
   public void repr(Printer printer) {
     printer.append("<unknown target " + getLabel() + ">");
   }
-
-  /**
-   * Returns a map of provider names to their values. This is only intended to be called from the
-   * query dialects of Starlark. Implement in subclasses which can have providers.
-   */
-  public Dict<String, Object> getProvidersDict() {
-    return null;
-  }
 }
diff --git a/src/main/java/com/google/devtools/build/lib/query2/cquery/StarlarkOutputFormatterCallback.java b/src/main/java/com/google/devtools/build/lib/query2/cquery/StarlarkOutputFormatterCallback.java
index 267ec00df96c8b..d107529352ec4a 100644
--- a/src/main/java/com/google/devtools/build/lib/query2/cquery/StarlarkOutputFormatterCallback.java
+++ b/src/main/java/com/google/devtools/build/lib/query2/cquery/StarlarkOutputFormatterCallback.java
@@ -21,7 +21,6 @@
 import com.google.devtools.build.lib.analysis.config.BuildConfigurationValue;
 import com.google.devtools.build.lib.analysis.config.BuildOptions;
 import com.google.devtools.build.lib.analysis.config.FragmentOptions;
-import com.google.devtools.build.lib.analysis.configuredtargets.AbstractConfiguredTarget;
 import com.google.devtools.build.lib.cmdline.Label;
 import com.google.devtools.build.lib.events.Event;
 import com.google.devtools.build.lib.events.ExtendedEventHandler;
@@ -121,10 +120,7 @@ public Object buildOptions(ConfiguredTarget target) {
           @Param(name = "target"),
         })
     public Object providers(ConfiguredTarget target) {
-      if (!(target instanceof AbstractConfiguredTarget)) {
-        return Starlark.NONE;
-      }
-      Dict<String, Object> ret = ((AbstractConfiguredTarget) target).getProvidersDict();
+      Dict<String, Object> ret = target.getProvidersDict();
       if (ret == null) {
         return Starlark.NONE;
       }
diff --git a/src/main/java/com/google/devtools/build/lib/rules/AliasConfiguredTarget.java b/src/main/java/com/google/devtools/build/lib/rules/AliasConfiguredTarget.java
index b68e2fa9bcae57..6c3981cb2af9ab 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/AliasConfiguredTarget.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/AliasConfiguredTarget.java
@@ -38,6 +38,7 @@
 import com.google.devtools.build.lib.packages.Provider;
 import com.google.devtools.build.lib.skyframe.BuildConfigurationKey;
 import javax.annotation.Nullable;
+import net.starlark.java.eval.Dict;
 import net.starlark.java.eval.EvalException;
 import net.starlark.java.eval.Printer;
 import net.starlark.java.eval.StarlarkSemantics;
@@ -196,6 +197,11 @@ public Label getOriginalLabel() {
     return label;
   }
 
+  @Override
+  public Dict<String, Object> getProvidersDict() {
+    return actual.getProvidersDict();
+  }
+
   @Override
   public void repr(Printer printer) {
     printer.append("<alias target " + label + " of " + actual.getLabel() + ">");


Test patch:
diff --git a/src/test/shell/integration/configured_query_test.sh b/src/test/shell/integration/configured_query_test.sh
index 1d80a9539e9c43..53106731086f02 100755
--- a/src/test/shell/integration/configured_query_test.sh
+++ b/src/test/shell/integration/configured_query_test.sh
@@ -1268,6 +1268,37 @@ EOF
   assert_contains "some_value" output
 }
 
+function test_starlark_output_providers_starlark_provider_for_alias() {
+  local -r pkg=$FUNCNAME
+  mkdir -p $pkg
+  cat > $pkg/BUILD <<EOF
+load(":my_rule.bzl", "my_rule")
+my_rule(name="myrule")
+alias(name="myalias", actual="myrule")
+EOF
+  cat > $pkg/my_rule.bzl <<'EOF'
+# A no-op rule that manifests a provider
+MyRuleInfo = provider(fields={"label": "a_rule_label"})
+
+def _my_rule_impl(ctx):
+    return [MyRuleInfo(label="some_value")]
+
+my_rule = rule(
+    implementation = _my_rule_impl,
+    attrs = {},
+)
+EOF
+  cat > $pkg/outfunc.bzl <<EOF
+def format(target):
+    p = providers(target)
+    return p["//$pkg:my_rule.bzl%MyRuleInfo"].label
+EOF
+  bazel cquery "//$pkg:myalias" --output=starlark --starlark:file="$pkg/outfunc.bzl" >output \
+    2>"$TEST_log" || fail "Expected success"
+
+  assert_contains "some_value" output
+}
+
 function test_bazelignore_error_cquery_nocrash() {
   local -r pkg=$FUNCNAME