Refactor (File, Vec<File>) into Phony

Bug: 528225104
Change-Id: I1c538b5d02a1e8af23f17f3a46ee242f6a6a6964
Reviewed-on: https://gn-review.googlesource.com/c/gn/+/28420
Reviewed-by: Takuto Ikuta <tikuta@google.com>
Commit-Queue: Matt Stark <msta@google.com>
diff --git a/src/gn/starlark/crates/depset/src/depset.rs b/src/gn/starlark/crates/depset/src/depset.rs
index 6ed0104..5e5d9de 100644
--- a/src/gn/starlark/crates/depset/src/depset.rs
+++ b/src/gn/starlark/crates/depset/src/depset.rs
@@ -337,15 +337,18 @@
         // This is to ensure we don't accidentally use File::new.
         // We cannot mix File::new and File::from_rust to get the same file object.
         let f = |s: &str| File::intern(s);
+        let make_phony = |phony: &str, expansion: &[&str]| types::Phony {
+            phony: f(phony),
+            expansion: expansion.iter().copied().map(f).collect(),
+        };
 
         let mut upto_phony = 0;
-        // Collect the phonies we've seen since last time we called new_phonies.
-        let mut new_phonies = |a: &Assert| {
+        let mut assert_new_phonies = |a: &Assert, expected: &[types::Phony]| {
             use types::EvalContext as _;
-            let phonies = &a.context().require_rule_impl().unwrap().borrow().phonies;
-            let result = phonies[upto_phony..].to_vec();
+            let binding = a.context().require_rule_impl().unwrap();
+            let phonies = &binding.borrow().phonies;
+            assert_eq!(&phonies[upto_phony..], expected);
             upto_phony = phonies.len();
-            result
         };
 
         assert!(
@@ -353,14 +356,14 @@
         );
 
         a.eq("depset()", UnpackFileDepset(None));
-        assert_eq!(new_phonies(&a), &[]);
+        assert_new_phonies(&a, &[]);
 
         // Because the outer depset only phonies to one item, we shouldn't make a phony.
         a.eq(
             "depset([make_file('a.txt')])",
             UnpackFileDepset(Some(f("a.txt"))),
         );
-        assert_eq!(new_phonies(&a), &[]);
+        assert_new_phonies(&a, &[]);
 
         // We should make a phony here for the inner depset.
         // Because the outer depset only phonies to one phony, it shouldn't make a
@@ -369,39 +372,30 @@
             "depset(transitive = [depset([make_file('a.txt'), make_file('b.txt')])])",
             UnpackFileDepset(Some(f("phony/:default_0"))),
         );
-        assert_eq!(
-            new_phonies(&a),
-            &[(f("phony/:default_0"), vec![f("a.txt"), f("b.txt")])]
-        );
+        assert_new_phonies(&a, &[make_phony("phony/:default_0", &["a.txt", "b.txt"])]);
         a.eq(
             "depset([make_file('c.txt')], transitive=[depset([make_file('a.txt'), make_file('b.txt')])])",
             UnpackFileDepset(Some(f("phony/:default_2"))),
         );
-        assert_eq!(
-            new_phonies(&a),
+        assert_new_phonies(
+            &a,
             &[
-                (f("phony/:default_1"), vec![f("a.txt"), f("b.txt")]),
-                (
-                    f("phony/:default_2"),
-                    vec![f("c.txt"), f("phony/:default_1")]
-                ),
-            ]
+                make_phony("phony/:default_1", &["a.txt", "b.txt"]),
+                make_phony("phony/:default_2", &["c.txt", "phony/:default_1"]),
+            ],
         );
-        assert_eq!(new_phonies(&a), &[]);
+        assert_new_phonies(&a, &[]);
 
         a.eq(
             "new_file_depset([make_file('a.txt')])",
             UnpackFileDepset(Some(f("a.txt"))),
         );
-        assert_eq!(new_phonies(&a), &[]);
+        assert_new_phonies(&a, &[]);
 
         a.eq(
             "new_file_depset([make_file('a.txt'), make_file('b.txt')])",
             UnpackFileDepset(Some(f("phony/:default_3"))),
         );
-        assert_eq!(
-            new_phonies(&a),
-            &[(f("phony/:default_3"), vec![f("a.txt"), f("b.txt")])]
-        );
+        assert_new_phonies(&a, &[make_phony("phony/:default_3", &["a.txt", "b.txt"])]);
     }
 }
diff --git a/src/gn/starlark/crates/types/src/ctx_state.rs b/src/gn/starlark/crates/types/src/ctx_state.rs
index 9004a30..20bf6a9 100644
--- a/src/gn/starlark/crates/types/src/ctx_state.rs
+++ b/src/gn/starlark/crates/types/src/ctx_state.rs
@@ -8,9 +8,18 @@
 
 use crate::{File, TargetRef};
 
+/// A Ninja phony target and its expanded dependencies.
+#[derive(Debug, PartialEq, Eq, allocative::Allocative)]
+pub struct Phony {
+    /// The phony file.
+    pub phony: File,
+    /// The inputs that the phony expands to.
+    pub expansion: Vec<File>,
+}
+
 /// The state associated with the `ctx` object during the rule implementation
 /// function.
-#[derive(Clone, Debug, allocative::Allocative)]
+#[derive(Debug, allocative::Allocative)]
 pub struct CtxState<T: TargetRef> {
     /// Reference to the underlying target.
     pub target: T,
@@ -20,7 +29,7 @@
     /// All files declared by ctx.actions.declare_file.
     declared_outputs: SmallSet<File>,
     /// A list of phonies declared during this execution step.
-    pub phonies: Vec<(File, Vec<File>)>,
+    pub phonies: Vec<Phony>,
 }
 
 impl<T: TargetRef> CtxState<T> {
@@ -49,7 +58,10 @@
         path.push('_');
         path.push_str(&count.to_string());
         let phony = File::intern(&path);
-        self.phonies.push((phony.clone(), deps));
+        self.phonies.push(Phony {
+            phony: phony.clone(),
+            expansion: deps,
+        });
         phony
     }
 
diff --git a/src/gn/starlark/crates/types/src/lib.rs b/src/gn/starlark/crates/types/src/lib.rs
index 413138b..0f9eef9 100644
--- a/src/gn/starlark/crates/types/src/lib.rs
+++ b/src/gn/starlark/crates/types/src/lib.rs
@@ -17,7 +17,7 @@
 pub mod target_ref;
 pub mod util;
 
-pub use ctx_state::CtxState;
+pub use ctx_state::{CtxState, Phony};
 pub(crate) use errors::Error;
 pub use eval_context::{CtxMethods, EvalContext, EvaluatorContextExt};
 pub use file::{File, intern_string};