Traverse custom alias-like rules in the rust analyzer aspect (#1190)

diff --git a/docs/flatten.md b/docs/flatten.md
index f650bc9..771c781 100644
--- a/docs/flatten.md
+++ b/docs/flatten.md
@@ -1740,6 +1740,7 @@
 | deps| String |
 | proc_macro_deps| String |
 | crate| String |
+| actual| String |
 
 
 **ATTRIBUTES**
diff --git a/docs/rust_analyzer.md b/docs/rust_analyzer.md
index 5a3c884..90b8888 100644
--- a/docs/rust_analyzer.md
+++ b/docs/rust_analyzer.md
@@ -109,6 +109,7 @@
 | deps| String |
 | proc_macro_deps| String |
 | crate| String |
+| actual| String |
 
 
 **ATTRIBUTES**
diff --git a/rust/private/rust_analyzer.bzl b/rust/private/rust_analyzer.bzl
index e28ca30..4e2d757 100644
--- a/rust/private/rust_analyzer.bzl
+++ b/rust/private/rust_analyzer.bzl
@@ -52,17 +52,21 @@
     if hasattr(ctx.rule.attr, "rustc_flags"):
         cfgs += [f[6:] for f in ctx.rule.attr.rustc_flags if f.startswith("--cfg ") or f.startswith("--cfg=")]
 
-    # Save BuildInfo if we find any (for build script output)
     build_info = None
-    for dep in ctx.rule.attr.deps:
-        if BuildInfo in dep:
-            build_info = dep[BuildInfo]
+    dep_infos = []
+    if hasattr(ctx.rule.attr, "deps"):
+        for dep in ctx.rule.attr.deps:
+            # Save BuildInfo if we find any (for build script output)
+            if BuildInfo in dep:
+                build_info = dep[BuildInfo]
+        dep_infos = [dep[RustAnalyzerInfo] for dep in ctx.rule.attr.deps if RustAnalyzerInfo in dep]
 
-    dep_infos = [dep[RustAnalyzerInfo] for dep in ctx.rule.attr.deps if RustAnalyzerInfo in dep]
     if hasattr(ctx.rule.attr, "proc_macro_deps"):
         dep_infos += [dep[RustAnalyzerInfo] for dep in ctx.rule.attr.proc_macro_deps if RustAnalyzerInfo in dep]
     if hasattr(ctx.rule.attr, "crate") and ctx.rule.attr.crate != None:
         dep_infos.append(ctx.rule.attr.crate[RustAnalyzerInfo])
+    if hasattr(ctx.rule.attr, "actual") and ctx.rule.attr.actual != None and RustAnalyzerInfo in ctx.rule.attr.actual:
+        dep_infos.append(ctx.rule.attr.actual[RustAnalyzerInfo])
 
     crate_spec = ctx.actions.declare_file(ctx.label.name + ".rust_analyzer_crate_spec")
 
@@ -111,7 +115,7 @@
     return None
 
 rust_analyzer_aspect = aspect(
-    attr_aspects = ["deps", "proc_macro_deps", "crate"],
+    attr_aspects = ["deps", "proc_macro_deps", "crate", "actual"],
     implementation = _rust_analyzer_aspect_impl,
     toolchains = [str(Label("//rust:toolchain"))],
     incompatible_use_toolchain_transition = True,
diff --git a/test/rust_analyzer/aspect_traversal_test/BUILD.bazel b/test/rust_analyzer/aspect_traversal_test/BUILD.bazel
index 2074fb1..32c1035 100644
--- a/test/rust_analyzer/aspect_traversal_test/BUILD.bazel
+++ b/test/rust_analyzer/aspect_traversal_test/BUILD.bazel
@@ -1,4 +1,5 @@
 load("@rules_rust//rust:defs.bzl", "rust_library", "rust_proc_macro", "rust_test")
+load(":custom_alias.bzl", "custom_alias")
 
 rust_library(
     name = "mylib",
@@ -6,6 +7,7 @@
     proc_macro_deps = [":proc_macro_dep"],
     deps = [
         ":alias_dep",
+        ":custom_alias_dep",
         ":lib_dep",
     ],
 )
@@ -31,6 +33,22 @@
     srcs = ["dep_of_aliased_dep.rs"],
 )
 
+custom_alias(
+    name = "custom_alias_dep",
+    actual = ":custom_actual_dep",
+)
+
+rust_library(
+    name = "custom_actual_dep",
+    srcs = ["custom_actual_dep.rs"],
+    deps = [":dep_of_custom_aliased_dep"],
+)
+
+rust_library(
+    name = "dep_of_custom_aliased_dep",
+    srcs = ["dep_of_custom_aliased_dep.rs"],
+)
+
 rust_proc_macro(
     name = "proc_macro_dep",
     srcs = ["proc_macro_dep.rs"],
diff --git a/test/rust_analyzer/aspect_traversal_test/custom_actual_dep.rs b/test/rust_analyzer/aspect_traversal_test/custom_actual_dep.rs
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/test/rust_analyzer/aspect_traversal_test/custom_actual_dep.rs
@@ -0,0 +1 @@
+
diff --git a/test/rust_analyzer/aspect_traversal_test/custom_alias.bzl b/test/rust_analyzer/aspect_traversal_test/custom_alias.bzl
new file mode 100644
index 0000000..cbf1bbe
--- /dev/null
+++ b/test/rust_analyzer/aspect_traversal_test/custom_alias.bzl
@@ -0,0 +1,17 @@
+"""Alias-like rule for testing."""
+
+load("@rules_rust//rust:defs.bzl", "rust_common")
+
+def _custom_alias_impl(ctx):
+    actual = ctx.attr.actual
+    return [actual[rust_common.crate_info], actual[rust_common.dep_info]]
+
+custom_alias = rule(
+    implementation = _custom_alias_impl,
+    attrs = {
+        "actual": attr.label(
+            allow_single_file = True,
+            mandatory = True,
+        ),
+    },
+)
diff --git a/test/rust_analyzer/aspect_traversal_test/dep_of_custom_aliased_dep.rs b/test/rust_analyzer/aspect_traversal_test/dep_of_custom_aliased_dep.rs
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/test/rust_analyzer/aspect_traversal_test/dep_of_custom_aliased_dep.rs
@@ -0,0 +1 @@
+
diff --git a/test/rust_analyzer/aspect_traversal_test/rust_project_json_test.rs b/test/rust_analyzer/aspect_traversal_test/rust_project_json_test.rs
index db77278..f347948 100644
--- a/test/rust_analyzer/aspect_traversal_test/rust_project_json_test.rs
+++ b/test/rust_analyzer/aspect_traversal_test/rust_project_json_test.rs
@@ -14,6 +14,8 @@
             "lib_dep",
             "actual_dep",
             "dep_of_aliased_dep",
+            "custom_actual_dep",
+            "dep_of_custom_aliased_dep",
             "extra_test_dep",
             "proc_macro_dep",
             "extra_proc_macro_dep",