Replace `Option<String>` with `Option<Rc<str>>` in ir.rs to improve `Clone` performance

PiperOrigin-RevId: 491633447
diff --git a/rs_bindings_from_cc/ir.rs b/rs_bindings_from_cc/ir.rs
index b086d23..9b2cc88 100644
--- a/rs_bindings_from_cc/ir.rs
+++ b/rs_bindings_from_cc/ir.rs
@@ -31,7 +31,7 @@
     public_headers: Vec<HeaderName>,
     current_target: BazelLabel,
     top_level_item_ids: Vec<ItemId>,
-    crate_root_path: Option<String>,
+    crate_root_path: Option<Rc<str>>,
 ) -> Result<IR> {
     make_ir(FlatIR { public_headers, current_target, items, top_level_item_ids, crate_root_path })
 }
@@ -118,7 +118,7 @@
 
 #[derive(Debug, PartialEq, Eq, Hash, Clone, Deserialize)]
 pub struct RsType {
-    pub name: Option<String>,
+    pub name: Option<Rc<str>>,
     pub lifetime_args: Rc<[LifetimeId]>,
     pub type_args: Rc<[RsType]>,
     pub decl_id: Option<ItemId>,
@@ -132,7 +132,7 @@
 
 #[derive(Debug, PartialEq, Eq, Hash, Clone, Deserialize)]
 pub struct CcType {
-    pub name: Option<String>,
+    pub name: Option<Rc<str>>,
     pub is_const: bool,
     pub type_args: Vec<CcType>,
     pub decl_id: Option<ItemId>,
@@ -306,7 +306,7 @@
     pub name: UnqualifiedIdentifier,
     pub owning_target: BazelLabel,
     pub mangled_name: Rc<str>,
-    pub doc_comment: Option<String>,
+    pub doc_comment: Option<Rc<str>>,
     pub return_type: MappedType,
     pub params: Vec<FuncParam>,
     /// For tests and internal use only.
@@ -344,7 +344,7 @@
 #[derive(Debug, PartialEq, Eq, Hash, Clone, Deserialize)]
 pub struct Field {
     pub identifier: Option<Identifier>,
-    pub doc_comment: Option<String>,
+    pub doc_comment: Option<Rc<str>>,
     #[serde(rename(deserialize = "type"))]
     pub type_: Result<MappedType, String>,
     pub access: AccessSpecifier,
@@ -406,7 +406,7 @@
     pub mangled_cc_name: Rc<str>,
     pub id: ItemId,
     pub owning_target: BazelLabel,
-    pub doc_comment: Option<String>,
+    pub doc_comment: Option<Rc<str>>,
     pub unambiguous_public_bases: Vec<BaseClass>,
     pub fields: Vec<Field>,
     pub lifetime_params: Vec<LifetimeName>,
@@ -488,7 +488,7 @@
     pub identifier: Identifier,
     pub id: ItemId,
     pub owning_target: BazelLabel,
-    pub doc_comment: Option<String>,
+    pub doc_comment: Option<Rc<str>>,
     pub underlying_type: MappedType,
     pub source_loc: SourceLoc,
     pub enclosing_record_id: Option<ItemId>,
@@ -697,7 +697,7 @@
     #[serde(default)]
     top_level_item_ids: Vec<ItemId>,
     #[serde(default)]
-    crate_root_path: Option<String>,
+    crate_root_path: Option<Rc<str>>,
 }
 
 /// Struct providing the necessary information about the API of a C++ target to
diff --git a/rs_bindings_from_cc/ir_from_cc_test.rs b/rs_bindings_from_cc/ir_from_cc_test.rs
index 04999db..beceb63 100644
--- a/rs_bindings_from_cc/ir_from_cc_test.rs
+++ b/rs_bindings_from_cc/ir_from_cc_test.rs
@@ -545,8 +545,10 @@
             struct MultilineOneStar {};
         "#,
     )?;
-    let comments: HashMap<_, _> =
-        ir.records().map(|r| (r.rs_name.as_ref(), r.doc_comment.as_ref().unwrap())).collect();
+    let comments: HashMap<_, _> = ir
+        .records()
+        .map(|r| (r.rs_name.as_ref(), r.doc_comment.as_ref().unwrap().as_ref()))
+        .collect();
 
     assert_eq!(comments["DocCommentSlashes"], "Doc comment\n\n * with three slashes");
     assert_eq!(comments["DocCommentBang"], "Doc comment\n\n * with slashes and bang");
@@ -708,8 +710,8 @@
     let type_mapping: HashMap<_, _> = fields
         .map(|f| {
             (
-                f.type_.as_ref().unwrap().cc_type.name.as_ref().unwrap().as_str(),
-                f.type_.as_ref().unwrap().rs_type.name.as_ref().unwrap().as_str(),
+                f.type_.as_ref().unwrap().cc_type.name.as_ref().unwrap().as_ref(),
+                f.type_.as_ref().unwrap().rs_type.name.as_ref().unwrap().as_ref(),
             )
         })
         .collect();
@@ -2772,11 +2774,11 @@
     assert_eq!(&*func.return_type.rs_type.lifetime_args, &[a_id]);
 
     assert_eq!(func.params[0].identifier, ir_id("__this"));
-    assert_eq!(func.params[0].type_.rs_type.name, Some("&mut".to_string()));
+    assert_eq!(func.params[0].type_.rs_type.name.as_deref(), Some("&mut"));
     assert_eq!(&*func.params[0].type_.rs_type.lifetime_args, &[a_id]);
 
     assert_eq!(func.params[1].identifier, ir_id("i"));
-    assert_eq!(func.params[1].type_.rs_type.name, Some("&mut".to_string()));
+    assert_eq!(func.params[1].type_.rs_type.name.as_deref(), Some("&mut"));
     assert_eq!(&*func.params[1].type_.rs_type.lifetime_args, &[b_id]);
 }
 
@@ -2797,7 +2799,7 @@
     let t = &p.type_.rs_type;
     assert_eq!(t.lifetime_args.len(), 1);
     assert_eq!(t.lifetime_args[0], f.lifetime_params[0].id);
-    assert_eq!(t.name, Some("&mut".to_string()));
+    assert_eq!(t.name.as_deref(), Some("&mut"));
 }
 
 #[test]
diff --git a/rs_bindings_from_cc/src_code_gen.rs b/rs_bindings_from_cc/src_code_gen.rs
index a74f7d7..80b966a 100644
--- a/rs_bindings_from_cc/src_code_gen.rs
+++ b/rs_bindings_from_cc/src_code_gen.rs
@@ -1794,12 +1794,12 @@
     })
 }
 
-fn generate_doc_comment(comment: &Option<String>) -> TokenStream {
+fn generate_doc_comment(comment: &Option<Rc<str>>) -> TokenStream {
     match comment {
         Some(text) => {
             // token_stream_printer (and rustfmt) don't put a space between /// and the doc
             // comment, let's add it here so our comments are pretty.
-            let doc = format!(" {}", text.replace('\n', "\n "));
+            let doc = format!(" {}", text.as_ref()).replace('\n', "\n ");
             quote! {#[doc=#doc]}
         }
         None => quote! {},
@@ -2074,11 +2074,11 @@
                 Err(msg) => {
                     let supplemental_text =
                         format!("Reason for representing this field as a blob of bytes:\n{}", msg);
-                    let new_text = match field.doc_comment.as_ref() {
+                    let new_text = match &field.doc_comment {
                         None => supplemental_text,
-                        Some(old_text) => format!("{}\n\n{}", old_text, supplemental_text),
+                        Some(old_text) => format!("{}\n\n{}", old_text.as_ref(), supplemental_text),
                     };
-                    generate_doc_comment(&Some(new_text))
+                    generate_doc_comment(&Some(new_text.into()))
                 }
             };
             let access = if field.access == AccessSpecifier::Public
@@ -3423,7 +3423,7 @@
         quote! {}
     };
     if let Some(ref name) = ty.name {
-        match name.as_str() {
+        match name.as_ref() {
             mut name @ ("*" | "&" | "&&") => {
                 if ty.type_args.len() != 1 {
                     bail!("Invalid pointer type (need exactly 1 type argument): {:?}", ty);