Create rust formatter configuration and apply it.

Format all Rust source files in the types crate.

Bug: 528225104
Change-Id: Ib7e3e37485f71f3d0a9b385e66fcb03e6a6a6964
Reviewed-on: https://gn-review.googlesource.com/c/gn/+/23640
Reviewed-by: Junji Watanabe <jwata@google.com>
Reviewed-by: Takuto Ikuta <tikuta@google.com>
Commit-Queue: Matt Stark <msta@google.com>
diff --git a/src/gn/starlark/crates/types/src/ctx_state.rs b/src/gn/starlark/crates/types/src/ctx_state.rs
index 0787ff8..4f1e69f 100644
--- a/src/gn/starlark/crates/types/src/ctx_state.rs
+++ b/src/gn/starlark/crates/types/src/ctx_state.rs
@@ -2,15 +2,18 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-use crate::{File, TargetRef};
 use starlark::collections::SmallSet;
 
-/// The state associated with the `ctx` object during the rule implementation function.
+use crate::{File, TargetRef};
+
+/// The state associated with the `ctx` object during the rule implementation
+/// function.
 #[derive(Clone, Debug, allocative::Allocative)]
 pub struct CtxState<T: TargetRef> {
     /// Reference to the underlying target.
     pub target: T,
-    /// All files declared by ctx.actions.declare_file that were never generated.
+    /// All files declared by ctx.actions.declare_file that were never
+    /// generated.
     pub unused_declared_outputs: SmallSet<File>,
     /// A list of phonies declared during this execution step.
     pub phonies: Vec<(File, Vec<File>)>,
diff --git a/src/gn/starlark/crates/types/src/errors.rs b/src/gn/starlark/crates/types/src/errors.rs
index 4db276b..24fb1db 100644
--- a/src/gn/starlark/crates/types/src/errors.rs
+++ b/src/gn/starlark/crates/types/src/errors.rs
@@ -12,7 +12,8 @@
     /// The string is not a valid label (e.g. doesn't start with "//" or ":").
     #[error("Not a label: {0}")]
     NotALabel(String),
-    /// An absolute label is invalid (e.g. missing a colon, or has too many colons).
+    /// An absolute label is invalid (e.g. missing a colon, or has too many
+    /// colons).
     #[error("Invalid absolute label, must contain exactly one colon: {0}")]
     InvalidAbsoluteLabel(String),
     /// A relative label contains a colon (which is invalid).
diff --git a/src/gn/starlark/crates/types/src/eval_context.rs b/src/gn/starlark/crates/types/src/eval_context.rs
index 6f32985..65a6cda 100644
--- a/src/gn/starlark/crates/types/src/eval_context.rs
+++ b/src/gn/starlark/crates/types/src/eval_context.rs
@@ -33,24 +33,28 @@
     fn current_toolchain(&self) -> LabelRef<'_>;
 
     /// Asserts that the current evaluation context is a macro context.
-    /// Use when a function cannot be called from other contexts (eg. `static_library` cannot be called inside rule evaluation)
+    /// Use when a function cannot be called from other contexts (eg.
+    /// `static_library` cannot be called inside rule evaluation)
     fn require_macro(&self) -> starlark::Result<()>;
 
     /// Asserts that the current evaluation context is a bzl file context.
     fn require_bzl(&self) -> starlark::Result<()>;
 
-    /// Asserts that the evaluator is executing a rule implementation, and returns the state of the rule implementation.
+    /// Asserts that the evaluator is executing a rule implementation, and
+    /// returns the state of the rule implementation.
     fn require_rule_impl(
         &self,
     ) -> starlark::Result<&crate::CtxState<<Self::Session as Session>::TargetRef>>;
 
-    /// Asserts that the evaluator is executing a rule implementation, and returns the mutable state of the rule implementation.
+    /// Asserts that the evaluator is executing a rule implementation, and
+    /// returns the mutable state of the rule implementation.
     fn require_rule_impl_mut(
         &mut self,
     ) -> starlark::Result<&mut crate::CtxState<<Self::Session as Session>::TargetRef>>;
 }
 
-/// Extension trait to add the methods `.context` and `.context_mut` to the starlark Evaluator.
+/// Extension trait to add the methods `.context` and `.context_mut` to the
+/// starlark Evaluator.
 pub trait EvaluatorContextExt<'v, 'a, 'e> {
     /// Returns a reference to the evaluation context.
     fn context<C: EvalContext>(&self) -> &C;
diff --git a/src/gn/starlark/crates/types/src/file.rs b/src/gn/starlark/crates/types/src/file.rs
index 4cade31..a4221e2 100644
--- a/src/gn/starlark/crates/types/src/file.rs
+++ b/src/gn/starlark/crates/types/src/file.rs
@@ -2,25 +2,17 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-use std::borrow::Cow;
-use std::path::Path;
+use std::{borrow::Cow, path::Path};
 
-use starlark::collections::StarlarkHasher;
-use starlark::environment::Methods;
-use starlark::environment::MethodsBuilder;
-use starlark::environment::MethodsStatic;
-use starlark::starlark_simple_value;
-use starlark::values::Freeze;
-use starlark::values::FreezeResult;
-use starlark::values::Freezer;
-use starlark::values::ProvidesStaticType;
-use starlark::values::StarlarkValue;
-use starlark::values::Trace;
-use starlark::values::Tracer;
-use starlark::values::ValueLike;
-use starlark_derive::starlark_module;
-use starlark_derive::starlark_value;
-use starlark_derive::NoSerialize;
+use starlark::{
+    collections::StarlarkHasher,
+    environment::{Methods, MethodsBuilder, MethodsStatic},
+    starlark_simple_value,
+    values::{
+        Freeze, FreezeResult, Freezer, ProvidesStaticType, StarlarkValue, Trace, Tracer, ValueLike,
+    },
+};
+use starlark_derive::{starlark_module, starlark_value, NoSerialize};
 
 /// File is equivalent to GN's OutputFile. Like OutputFile, its path is relative
 /// to the root_build_dir (which is also the execution directory).
@@ -36,7 +28,8 @@
 ///
 /// We use a &str instead of an &Path, as would be standard in rust, because:
 /// * Path::new(&str) is a zero cost transmute and always succeeds
-/// * Path::new(&str).to_string_lossy() always returns the input str but has to perform an error check.
+/// * Path::new(&str).to_string_lossy() always returns the input str but has to
+///   perform an error check.
 #[derive(Clone, Debug, ProvidesStaticType, NoSerialize, allocative::Allocative)]
 pub struct File(#[allocative(skip)] &'static str);
 
@@ -71,7 +64,8 @@
         self.0
     }
 
-    /// Returns the file path with proper escaping applied for use in the inputs section of a ninja file.
+    /// Returns the file path with proper escaping applied for use in the inputs
+    /// section of a ninja file.
     pub fn ninja_escaped_path(&self) -> Cow<'static, str> {
         let s = self.0;
         if s.contains(|c| c == ' ' || c == '$' || c == ':') {
@@ -116,6 +110,7 @@
 
 impl Freeze for File {
     type Frozen = File;
+
     fn freeze(self, _freezer: &Freezer) -> FreezeResult<Self::Frozen> {
         Ok(self)
     }
@@ -202,7 +197,8 @@
         let f2 = File::intern("foo/bar.txt");
 
         assert_eq!(f1.as_str(), "foo/bar.txt");
-        // Verify pointer equality (they point to the exact same static string backing memory)
+        // Verify pointer equality (they point to the exact same static string backing
+        // memory)
         assert!(std::ptr::eq(f1.as_str(), f2.as_str()));
     }
 
diff --git a/src/gn/starlark/crates/types/src/label.rs b/src/gn/starlark/crates/types/src/label.rs
index 73c27ce..e2fc540 100644
--- a/src/gn/starlark/crates/types/src/label.rs
+++ b/src/gn/starlark/crates/types/src/label.rs
@@ -2,29 +2,21 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-use starlark::collections::StarlarkHasher;
-use starlark::environment::Methods;
-use starlark::environment::MethodsBuilder;
-use starlark::environment::MethodsStatic;
-use starlark::starlark_simple_value;
-use starlark::values::Freeze;
-use starlark::values::FreezeResult;
-use starlark::values::Freezer;
-use starlark::values::ProvidesStaticType;
-use starlark::values::StarlarkValue;
-use starlark::values::Trace;
-use starlark::values::Tracer;
-use starlark::values::ValueLike;
-use starlark_derive::starlark_module;
-use starlark_derive::starlark_value;
-use starlark_derive::NoSerialize;
+use starlark::{
+    collections::StarlarkHasher,
+    environment::{Methods, MethodsBuilder, MethodsStatic},
+    starlark_simple_value,
+    values::{
+        Freeze, FreezeResult, Freezer, ProvidesStaticType, StarlarkValue, Trace, Tracer, ValueLike,
+    },
+};
+use starlark_derive::{starlark_module, starlark_value, NoSerialize};
 
-use crate::LabelRef;
-use crate::Package;
-use crate::PackageRef;
+use crate::{LabelRef, Package, PackageRef};
 
 /// A Label represents a target label, e.g., "//foo/bar:baz".
-/// Note that unlike a regular GN label, this label does *not* include a toolchain.
+/// Note that unlike a regular GN label, this label does *not* include a
+/// toolchain.
 ///
 /// In Starlark, a fully qualified GN label is represented as a tuple
 /// (label, toolchain). "//foo:bar(//toolchain:name)" would thus convert to
@@ -99,7 +91,8 @@
         })
     }
 
-    /// Parses a label. If it is relative, it is parsed as relative to the given package.
+    /// Parses a label. If it is relative, it is parsed as relative to the given
+    /// package.
     pub fn parse(s: &str, relative_to: &PackageRef) -> starlark::Result<Self> {
         if s.starts_with("//") {
             Self::parse_absolute(s)
@@ -141,6 +134,7 @@
 
 impl Freeze for Label {
     type Frozen = Label;
+
     fn freeze(self, _freezer: &Freezer) -> FreezeResult<Self::Frozen> {
         Ok(self)
     }
diff --git a/src/gn/starlark/crates/types/src/label_ref.rs b/src/gn/starlark/crates/types/src/label_ref.rs
index 892d215..b5223c5 100644
--- a/src/gn/starlark/crates/types/src/label_ref.rs
+++ b/src/gn/starlark/crates/types/src/label_ref.rs
@@ -2,8 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-use crate::Label;
-use crate::PackageRef;
+use crate::{Label, PackageRef};
 
 /// A borrowed reference to a `Label`.
 ///
diff --git a/src/gn/starlark/crates/types/src/package.rs b/src/gn/starlark/crates/types/src/package.rs
index 76876c7..2b5803c 100644
--- a/src/gn/starlark/crates/types/src/package.rs
+++ b/src/gn/starlark/crates/types/src/package.rs
@@ -17,6 +17,7 @@
 
 impl std::ops::Deref for Package {
     type Target = PackageRef;
+
     fn deref(&self) -> &Self::Target {
         // Safety: already validated
         unsafe { PackageRef::new_unchecked(&self.0) }
diff --git a/src/gn/starlark/crates/types/src/package_ref.rs b/src/gn/starlark/crates/types/src/package_ref.rs
index 9f80e42..0cdfacf 100644
--- a/src/gn/starlark/crates/types/src/package_ref.rs
+++ b/src/gn/starlark/crates/types/src/package_ref.rs
@@ -29,7 +29,8 @@
     /// Requires that the string starts with "//"
     pub unsafe fn new_unchecked(s: &str) -> &Self {
         debug_assert!(s.starts_with("//"), "Package name must start with //");
-        // Safety: PackageRef is #[repr(transparent)] wrapping str, so their memory layouts are identical.
+        // Safety: PackageRef is #[repr(transparent)] wrapping str, so their memory
+        // layouts are identical.
         unsafe { &*(s as *const str as *const PackageRef) }
     }
 
@@ -59,6 +60,7 @@
 
 impl ToOwned for PackageRef {
     type Owned = Package;
+
     fn to_owned(&self) -> Self::Owned {
         Package(self.0.to_owned())
     }
diff --git a/src/gn/starlark/crates/types/src/path_resolver.rs b/src/gn/starlark/crates/types/src/path_resolver.rs
index ae1aad0..b1b4627 100644
--- a/src/gn/starlark/crates/types/src/path_resolver.rs
+++ b/src/gn/starlark/crates/types/src/path_resolver.rs
@@ -17,7 +17,8 @@
 }
 
 impl PathResolver {
-    /// Creates a new `PathResolver` with the given absolute and relative root paths.
+    /// Creates a new `PathResolver` with the given absolute and relative root
+    /// paths.
     pub fn new(source_root: PathBuf, source_root_rel: String) -> Self {
         assert!(source_root_rel.ends_with('/'));
         Self {
@@ -26,7 +27,8 @@
         }
     }
 
-    /// Creates a new PathResolver preconfigured for the starlark testdata directory.
+    /// Creates a new PathResolver preconfigured for the starlark testdata
+    /// directory.
     pub fn new_for_testing() -> Self {
         Self::new(
             PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../../src/testdata"),
diff --git a/src/gn/starlark/crates/types/src/target_ref.rs b/src/gn/starlark/crates/types/src/target_ref.rs
index f418bce..30f4f42 100644
--- a/src/gn/starlark/crates/types/src/target_ref.rs
+++ b/src/gn/starlark/crates/types/src/target_ref.rs
@@ -2,9 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-use crate::File;
 use starlark::values::{AllocValue, StarlarkValue};
 
+use crate::File;
+
 /// An interface for a target in the build graph.
 ///
 /// Since the real Target involves a lot of C++ interop, this allows us to
@@ -16,7 +17,8 @@
     /// Returns the target's output directory path string.
     /// Toolchain_prefix goes right at the very front, before the toolchain
     /// Label_prefix goes in between the toolchain and the label
-    /// Package_name_separator is what separates packages and labels (usually ":" or "/").
+    /// Package_name_separator is what separates packages and labels (usually
+    /// ":" or "/").
     fn target_out_dir(
         &self,
         toolchain_prefix: &str,
diff --git a/src/gn/starlark/rustfmt-nightly.toml b/src/gn/starlark/rustfmt-nightly.toml
new file mode 100644
index 0000000..764fbe7
--- /dev/null
+++ b/src/gn/starlark/rustfmt-nightly.toml
@@ -0,0 +1,29 @@
+# This enables unstable features *for the formatter*.
+# It does not do so for the compiler.
+unstable_features = true
+
+# Automatically group imports into distinct, standard sections
+group_imports = "StdExternalCrate"
+# Merge imports from the same crate into a single nested block
+imports_granularity = "Crate"
+
+# Bring macros into the formatting pipeline
+format_macro_matchers = true
+format_macro_bodies = true
+
+# Logical grouping inside impl blocks
+reorder_impl_items = true
+
+# Tidier visual layouts
+normalize_comments = true
+
+# Stable formatter features.
+# LINT.IfChange
+
+# Automatically wrap comments and documentation at the line limit
+wrap_comments = true
+
+# Ensure match blocks have trailing commas for cleaner git diffs
+match_block_trailing_comma = true
+
+# LINT.ThenChange(//src/gn/starlark/rustfmt.toml)
\ No newline at end of file
diff --git a/src/gn/starlark/rustfmt.toml b/src/gn/starlark/rustfmt.toml
new file mode 100644
index 0000000..92bf7a3
--- /dev/null
+++ b/src/gn/starlark/rustfmt.toml
@@ -0,0 +1,9 @@
+# LINT.IfChange
+
+# Automatically wrap comments and documentation at the line limit
+wrap_comments = true
+
+# Ensure match blocks have trailing commas for cleaner git diffs
+match_block_trailing_comma = true
+
+# LINT.ThenChange(//src/gn/starlark/rustfmt-nightly.toml)
\ No newline at end of file
diff --git a/tools/run_formatter.sh b/tools/run_formatter.sh
index b53184d..82bdd5b 100755
--- a/tools/run_formatter.sh
+++ b/tools/run_formatter.sh
@@ -4,8 +4,10 @@
 
 if [ "${1:-}" = "--diff" ]; then
   opts="--dry-run -Werror"
+  fmt_opts="--check"
 else
   opts="-i"
+  fmt_opts=""
 fi
 
 if [ -z "${CLANG_FORMAT:-}" ]; then
@@ -18,3 +20,13 @@
 
 git ls-files | egrep '\.(h|cc)$' | grep -Ev 'third_party|vendor' |\
     xargs "$CLANG_FORMAT" $opts
+
+if command -v cargo >/dev/null 2>&1; then
+  cargo_cmd="cargo"
+  extra_opts=""
+  if cargo +nightly --version >/dev/null 2>&1; then
+    cargo_cmd="cargo +nightly"
+    extra_opts="-- --config-path rustfmt-nightly.toml"
+  fi
+  (cd src/gn/starlark && $cargo_cmd fmt --all $fmt_opts $extra_opts)
+fi