Remove `SpecialMemberFunc::access` field.

The `SpecialMemberFunc::access` field was redundant - non-`public`
constructors/destructors could be expressed as
`SpecialMemberFunc::Definition::kDeleted` instead.

PiperOrigin-RevId: 452622261
diff --git a/rs_bindings_from_cc/ast_convert.cc b/rs_bindings_from_cc/ast_convert.cc
index 9c6ee21..ffdf43b 100644
--- a/rs_bindings_from_cc/ast_convert.cc
+++ b/rs_bindings_from_cc/ast_convert.cc
@@ -68,55 +68,44 @@
     const clang::RecordDecl& record_decl,
     absl::FunctionRef<const clang::CXXMethodDecl*(const clang::CXXRecordDecl*)>
         getter) {
-  SpecialMemberFunc smf = {
-      .definition = SpecialMemberFunc::Definition::kTrivial,
-      .access = kPublic,
-  };
-
   const auto* cxx_record_decl =
       clang::dyn_cast<clang::CXXRecordDecl>(&record_decl);
   if (cxx_record_decl == nullptr) {
-    return smf;
+    return SpecialMemberFunc::kTrivial;
   }
 
   const clang::CXXMethodDecl* decl = getter(cxx_record_decl);
   if (decl == nullptr) {
-    smf.definition = SpecialMemberFunc::Definition::kDeleted;
-    return smf;
+    return SpecialMemberFunc::kUnavailable;
   }
 
-  smf.access = TranslateAccessSpecifier(decl->getAccess());
-  if (decl->isDeleted()) {
-    smf.definition = SpecialMemberFunc::Definition::kDeleted;
-  } else if (decl->isTrivial()) {
-    smf.definition = SpecialMemberFunc::Definition::kTrivial;
-  } else if (HasNoUserProvidedSpecialMember(cxx_record_decl, getter)) {
-    smf.definition = SpecialMemberFunc::Definition::kNontrivialMembers;
-  } else {
-    smf.definition = SpecialMemberFunc::Definition::kNontrivialUserDefined;
-  }
-  return smf;
-}
-}  // namespace
-
-AccessSpecifier TranslateAccessSpecifier(clang::AccessSpecifier access) {
-  switch (access) {
+  switch (decl->getAccess()) {
     case clang::AS_public:
-      return kPublic;
+      break;
     case clang::AS_protected:
-      return kProtected;
     case clang::AS_private:
-      return kPrivate;
+      return SpecialMemberFunc::kUnavailable;
     case clang::AS_none:
       CRUBIT_CHECK(
           false &&
           "We should never be encoding a 'none' access specifier in IR.");
-      // We have to return something. Conservatively return private so we don't
-      // inadvertently make a private member variable accessible in Rust.
-      return kPrivate;
+      // We have to return something. kDeleted seems like a safe fallback.
+      return SpecialMemberFunc::kUnavailable;
+  }
+
+  if (decl->isDeleted()) {
+    return SpecialMemberFunc::kUnavailable;
+  } else if (decl->isTrivial()) {
+    return SpecialMemberFunc::kTrivial;
+  } else if (HasNoUserProvidedSpecialMember(cxx_record_decl, getter)) {
+    return SpecialMemberFunc::kNontrivialMembers;
+  } else {
+    return SpecialMemberFunc::kNontrivialUserDefined;
   }
 }
 
+}  // namespace
+
 SpecialMemberFunc GetCopyCtorSpecialMemberFunc(
     const clang::RecordDecl& record_decl) {
   return GetSpecialMemberFunc(record_decl, &GetCopyCtor);
diff --git a/rs_bindings_from_cc/ast_convert.h b/rs_bindings_from_cc/ast_convert.h
index 10bf8cf..c19ef58 100644
--- a/rs_bindings_from_cc/ast_convert.h
+++ b/rs_bindings_from_cc/ast_convert.h
@@ -12,12 +12,9 @@
 
 #include "rs_bindings_from_cc/ir.h"
 #include "clang/AST/Decl.h"
-#include "clang/Basic/Specifiers.h"
 
 namespace crubit {
 
-AccessSpecifier TranslateAccessSpecifier(clang::AccessSpecifier access);
-
 SpecialMemberFunc GetCopyCtorSpecialMemberFunc(
     const clang::RecordDecl& record_decl);
 
diff --git a/rs_bindings_from_cc/importer_test.cc b/rs_bindings_from_cc/importer_test.cc
index e4a406e..750ce04 100644
--- a/rs_bindings_from_cc/importer_test.cc
+++ b/rs_bindings_from_cc/importer_test.cc
@@ -276,12 +276,6 @@
 // Matches a Record which is trivial for calls.
 MATCHER(IsTrivialAbi, "") { return arg.is_trivial_abi; }
 
-// Matches a SpecialMemberFunc that has the given definition.
-MATCHER_P(DefinitionIs, definition, "") { return arg.definition == definition; }
-
-// Matches a Field that has the given access specifier.
-MATCHER_P(AccessIs, access, "") { return arg.access == access; }
-
 // Matches a Field that has the given offset.
 MATCHER_P(OffsetIs, offset, "") {
   if (arg.offset == offset) return true;
@@ -426,8 +420,8 @@
 
   std::vector<const Record*> records = ir.get_items_if<Record>();
   EXPECT_THAT(records, SizeIs(2));
-  EXPECT_THAT(records, Each(Pointee(CopyConstructor(DefinitionIs(
-                           SpecialMemberFunc::Definition::kTrivial)))));
+  EXPECT_THAT(records,
+              Each(Pointee(CopyConstructor(SpecialMemberFunc::kTrivial))));
 }
 
 TEST(ImporterTest, NontrivialUserDefinedCopyConstructor) {
@@ -449,9 +443,8 @@
 
   std::vector<const Record*> records = ir.get_items_if<Record>();
   EXPECT_THAT(records, SizeIs(3));
-  EXPECT_THAT(records,
-              Each(Pointee(CopyConstructor(DefinitionIs(
-                  SpecialMemberFunc::Definition::kNontrivialUserDefined)))));
+  EXPECT_THAT(records, Each(Pointee(CopyConstructor(
+                           SpecialMemberFunc::kNontrivialUserDefined))));
 }
 
 TEST(ImporterTest, NontrivialMembersCopyConstructor) {
@@ -476,8 +469,7 @@
       Each(Pointee(AnyOf(
           RsNameIs(
               "NontrivialUserDefined"),  // needed to create nontrivial members
-          CopyConstructor(DefinitionIs(
-              SpecialMemberFunc::Definition::kNontrivialMembers))))));
+          CopyConstructor(SpecialMemberFunc::kNontrivialMembers)))));
 }
 
 TEST(ImporterTest, DeletedCopyConstructor) {
@@ -495,8 +487,8 @@
   ASSERT_OK_AND_ASSIGN(IR ir, IrFromCc(file));
   std::vector<const Record*> records = ir.get_items_if<Record>();
   EXPECT_THAT(records, SizeIs(3));
-  EXPECT_THAT(records, Each(Pointee(CopyConstructor(DefinitionIs(
-                           SpecialMemberFunc::Definition::kDeleted)))));
+  EXPECT_THAT(records,
+              Each(Pointee(CopyConstructor(SpecialMemberFunc::kUnavailable))));
 }
 
 TEST(ImporterTest, PublicCopyConstructor) {
@@ -514,7 +506,8 @@
 
   std::vector<const Record*> records = ir.get_items_if<Record>();
   EXPECT_THAT(records, SizeIs(3));
-  EXPECT_THAT(records, Each(Pointee(CopyConstructor(AccessIs(kPublic)))));
+  EXPECT_THAT(records,
+              Each(Pointee(CopyConstructor(SpecialMemberFunc::kTrivial))));
 }
 
 TEST(ImporterTest, PrivateCopyConstructor) {
@@ -531,7 +524,8 @@
 
   std::vector<const Record*> records = ir.get_items_if<Record>();
   EXPECT_THAT(records, SizeIs(2));
-  EXPECT_THAT(records, Each(Pointee(CopyConstructor(AccessIs(kPrivate)))));
+  EXPECT_THAT(records,
+              Each(Pointee(CopyConstructor(SpecialMemberFunc::kUnavailable))));
 }
 
 TEST(ImporterTest, TrivialMoveConstructor) {
@@ -545,8 +539,8 @@
 
   std::vector<const Record*> records = ir.get_items_if<Record>();
   EXPECT_THAT(records, SizeIs(2));
-  EXPECT_THAT(records, Each(Pointee(MoveConstructor(DefinitionIs(
-                           SpecialMemberFunc::Definition::kTrivial)))));
+  EXPECT_THAT(records,
+              Each(Pointee(MoveConstructor(SpecialMemberFunc::kTrivial))));
 }
 
 TEST(ImporterTest, NontrivialUserDefinedMoveConstructor) {
@@ -567,9 +561,8 @@
   ASSERT_OK_AND_ASSIGN(IR ir, IrFromCc(file));
   std::vector<const Record*> records = ir.get_items_if<Record>();
   EXPECT_THAT(records, SizeIs(3));
-  EXPECT_THAT(records,
-              Each(Pointee(MoveConstructor(DefinitionIs(
-                  SpecialMemberFunc::Definition::kNontrivialUserDefined)))));
+  EXPECT_THAT(records, Each(Pointee(MoveConstructor(
+                           SpecialMemberFunc::kNontrivialUserDefined))));
 }
 
 TEST(ImporterTest, NontrivialMembersMoveConstructor) {
@@ -594,8 +587,7 @@
       Each(Pointee(AnyOf(
           RsNameIs(
               "NontrivialUserDefined"),  // needed to create nontrivial members
-          MoveConstructor(DefinitionIs(
-              SpecialMemberFunc::Definition::kNontrivialMembers))))));
+          MoveConstructor(SpecialMemberFunc::kNontrivialMembers)))));
 }
 
 TEST(ImporterTest, DeletedMoveConstructor) {
@@ -613,8 +605,8 @@
   ASSERT_OK_AND_ASSIGN(IR ir, IrFromCc(file));
   std::vector<const Record*> records = ir.get_items_if<Record>();
   EXPECT_THAT(records, SizeIs(3));
-  EXPECT_THAT(records, Each(Pointee(MoveConstructor(DefinitionIs(
-                           SpecialMemberFunc::Definition::kDeleted)))));
+  EXPECT_THAT(records,
+              Each(Pointee(MoveConstructor(SpecialMemberFunc::kUnavailable))));
 }
 
 TEST(ImporterTest, PublicMoveConstructor) {
@@ -632,7 +624,8 @@
 
   std::vector<const Record*> records = ir.get_items_if<Record>();
   EXPECT_THAT(records, SizeIs(3));
-  EXPECT_THAT(records, Each(Pointee(MoveConstructor(AccessIs(kPublic)))));
+  EXPECT_THAT(records,
+              Each(Pointee(MoveConstructor(SpecialMemberFunc::kTrivial))));
 }
 
 TEST(ImporterTest, PrivateMoveConstructor) {
@@ -649,7 +642,8 @@
 
   std::vector<const Record*> records = ir.get_items_if<Record>();
   EXPECT_THAT(records, SizeIs(2));
-  EXPECT_THAT(records, Each(Pointee(MoveConstructor(AccessIs(kPrivate)))));
+  EXPECT_THAT(records,
+              Each(Pointee(MoveConstructor(SpecialMemberFunc::kUnavailable))));
 }
 
 TEST(ImporterTest, TrivialDestructor) {
@@ -663,8 +657,7 @@
 
   std::vector<const Record*> records = ir.get_items_if<Record>();
   EXPECT_THAT(records, SizeIs(2));
-  EXPECT_THAT(records, Each(Pointee(Destructor(DefinitionIs(
-                           SpecialMemberFunc::Definition::kTrivial)))));
+  EXPECT_THAT(records, Each(Pointee(Destructor(SpecialMemberFunc::kTrivial))));
 }
 
 TEST(ImporterTest, NontrivialUserDefinedDestructor) {
@@ -691,9 +684,9 @@
   ASSERT_OK_AND_ASSIGN(IR ir, IrFromCc(file));
   std::vector<const Record*> records = ir.get_items_if<Record>();
   EXPECT_THAT(records, SizeIs(4));
-  EXPECT_THAT(records,
-              Each(Pointee(Destructor(DefinitionIs(
-                  SpecialMemberFunc::Definition::kNontrivialUserDefined)))));
+  EXPECT_THAT(
+      records,
+      Each(Pointee(Destructor(SpecialMemberFunc::kNontrivialUserDefined))));
 }
 
 TEST(ImporterTest, NontrivialMembersDestructor) {
@@ -718,8 +711,7 @@
       Each(Pointee(AnyOf(
           RsNameIs(
               "NontrivialUserDefined"),  // needed to create nontrivial members
-          Destructor(DefinitionIs(
-              SpecialMemberFunc::Definition::kNontrivialMembers))))));
+          Destructor(SpecialMemberFunc::kNontrivialMembers)))));
 }
 
 TEST(ImporterTest, DeletedDestructor) {
@@ -735,8 +727,8 @@
 
   std::vector<const Record*> records = ir.get_items_if<Record>();
   EXPECT_THAT(records, SizeIs(2));
-  EXPECT_THAT(records, Each(Pointee(Destructor(DefinitionIs(
-                           SpecialMemberFunc::Definition::kDeleted)))));
+  EXPECT_THAT(records,
+              Each(Pointee(Destructor(SpecialMemberFunc::kUnavailable))));
 }
 
 TEST(ImporterTest, PublicDestructor) {
@@ -754,7 +746,7 @@
 
   std::vector<const Record*> records = ir.get_items_if<Record>();
   EXPECT_THAT(records, SizeIs(3));
-  EXPECT_THAT(records, Each(Pointee(Destructor(AccessIs(kPublic)))));
+  EXPECT_THAT(records, Each(Pointee(Destructor(SpecialMemberFunc::kTrivial))));
 }
 
 TEST(ImporterTest, PrivateDestructor) {
@@ -771,7 +763,8 @@
 
   std::vector<const Record*> records = ir.get_items_if<Record>();
   EXPECT_THAT(records, SizeIs(2));
-  EXPECT_THAT(records, Each(Pointee(Destructor(AccessIs(kPrivate)))));
+  EXPECT_THAT(records,
+              Each(Pointee(Destructor(SpecialMemberFunc::kUnavailable))));
 }
 
 TEST(ImporterTest, TrivialAbi) {
diff --git a/rs_bindings_from_cc/importers/cxx_record.cc b/rs_bindings_from_cc/importers/cxx_record.cc
index 7225883..2e016e1 100644
--- a/rs_bindings_from_cc/importers/cxx_record.cc
+++ b/rs_bindings_from_cc/importers/cxx_record.cc
@@ -24,6 +24,24 @@
       .getAsString(policy);
 }
 
+AccessSpecifier TranslateAccessSpecifier(clang::AccessSpecifier access) {
+  switch (access) {
+    case clang::AS_public:
+      return kPublic;
+    case clang::AS_protected:
+      return kProtected;
+    case clang::AS_private:
+      return kPrivate;
+    case clang::AS_none:
+      CRUBIT_CHECK(
+          false &&
+          "We should never be encoding a 'none' access specifier in IR.");
+      // We have to return something. Conservatively return private so we don't
+      // inadvertently make a private member variable accessible in Rust.
+      return kPrivate;
+  }
+}
+
 }  // namespace
 
 std::optional<IR::Item> CXXRecordDeclImporter::Import(
diff --git a/rs_bindings_from_cc/ir.cc b/rs_bindings_from_cc/ir.cc
index d482cdd..97f3f2e 100644
--- a/rs_bindings_from_cc/ir.cc
+++ b/rs_bindings_from_cc/ir.cc
@@ -339,32 +339,19 @@
   };
 }
 
-static std::string SpecialMemberDefinitionToString(
-    SpecialMemberFunc::Definition def) {
-  switch (def) {
-    case SpecialMemberFunc::Definition::kTrivial:
+llvm::json::Value toJSON(const SpecialMemberFunc& f) {
+  switch (f) {
+    case SpecialMemberFunc::kTrivial:
       return "Trivial";
-    case SpecialMemberFunc::Definition::kNontrivialMembers:
+    case SpecialMemberFunc::kNontrivialMembers:
       return "NontrivialMembers";
-    case SpecialMemberFunc::Definition::kNontrivialUserDefined:
+    case SpecialMemberFunc::kNontrivialUserDefined:
       return "NontrivialUserDefined";
-    case SpecialMemberFunc::Definition::kDeleted:
-      return "Deleted";
+    case SpecialMemberFunc::kUnavailable:
+      return "Unavailable";
   }
 }
 
-std::ostream& operator<<(std::ostream& o,
-                         const SpecialMemberFunc::Definition& definition) {
-  return o << SpecialMemberDefinitionToString(definition);
-}
-
-llvm::json::Value SpecialMemberFunc::ToJson() const {
-  return llvm::json::Object{
-      {"definition", SpecialMemberDefinitionToString(definition)},
-      {"access", AccessToString(access)},
-  };
-}
-
 llvm::json::Value BaseClass::ToJson() const {
   return llvm::json::Object{
       {"base_record_id", base_record_id},
diff --git a/rs_bindings_from_cc/ir.h b/rs_bindings_from_cc/ir.h
index cc536ee..a5ec007 100644
--- a/rs_bindings_from_cc/ir.h
+++ b/rs_bindings_from_cc/ir.h
@@ -507,29 +507,22 @@
 // functions in narrow cases: even for a nontrivial special member function, if
 // it is kNontrivialMembers, we can directly implement it in Rust in terms of
 // the member variables.
-struct SpecialMemberFunc {
-  enum class Definition : char {
-    kTrivial,
-    // Nontrivial, but only because of a member variable with a nontrivial
-    // special member function.
-    kNontrivialMembers,
-    // Nontrivial because of a user-defined special member function in this or a
-    // base class. (May *also* be nontrivial due to member variables.)
-    kNontrivialUserDefined,
-    kDeleted,
-  };
-
-  llvm::json::Value ToJson() const;
-
-  Definition definition = Definition::kTrivial;
-  AccessSpecifier access = AccessSpecifier::kPublic;
+enum class SpecialMemberFunc : char {
+  kTrivial,
+  // Nontrivial, but only because of a member variable with a nontrivial
+  // special member function.
+  kNontrivialMembers,
+  // Nontrivial because of a user-defined special member function in this or a
+  // base class. (May *also* be nontrivial due to member variables.)
+  kNontrivialUserDefined,
+  // Deleted or non-public.
+  kUnavailable,
 };
 
-std::ostream& operator<<(std::ostream& o,
-                         const SpecialMemberFunc::Definition& definition);
+llvm::json::Value toJSON(const SpecialMemberFunc& f);
 
 inline std::ostream& operator<<(std::ostream& o, const SpecialMemberFunc& f) {
-  return o << std::string(llvm::formatv("{0:2}", f.ToJson()));
+  return o << std::string(llvm::formatv("{0:2}", toJSON(f)));
 }
 
 // A base class subobject of a struct or class.
@@ -580,9 +573,9 @@
   bool override_alignment = false;
 
   // Special member functions.
-  SpecialMemberFunc copy_constructor = {};
-  SpecialMemberFunc move_constructor = {};
-  SpecialMemberFunc destructor = {};
+  SpecialMemberFunc copy_constructor = SpecialMemberFunc::kUnavailable;
+  SpecialMemberFunc move_constructor = SpecialMemberFunc::kUnavailable;
+  SpecialMemberFunc destructor = SpecialMemberFunc::kUnavailable;
 
   // Whether this type is passed by value as if it were a trivial type (the same
   // as it would be if it were a struct in C).
diff --git a/rs_bindings_from_cc/ir.rs b/rs_bindings_from_cc/ir.rs
index 18f5831..802bbd9 100644
--- a/rs_bindings_from_cc/ir.rs
+++ b/rs_bindings_from_cc/ir.rs
@@ -363,11 +363,11 @@
 }
 
 #[derive(Debug, PartialEq, Eq, Hash, Clone, Deserialize)]
-pub enum SpecialMemberDefinition {
+pub enum SpecialMemberFunc {
     Trivial,
     NontrivialMembers,
     NontrivialUserDefined,
-    Deleted,
+    Unavailable,
 }
 
 #[derive(Debug, PartialEq, Eq, Hash, Clone, Deserialize)]
@@ -377,12 +377,6 @@
 }
 
 #[derive(Debug, PartialEq, Eq, Hash, Clone, Deserialize)]
-pub struct SpecialMemberFunc {
-    pub definition: SpecialMemberDefinition,
-    pub access: AccessSpecifier,
-}
-
-#[derive(Debug, PartialEq, Eq, Hash, Clone, Deserialize)]
 pub struct IncompleteRecord {
     pub cc_name: String,
     pub id: ItemId,
diff --git a/rs_bindings_from_cc/ir_from_cc_test.rs b/rs_bindings_from_cc/ir_from_cc_test.rs
index 69adc99..2e5eca9 100644
--- a/rs_bindings_from_cc/ir_from_cc_test.rs
+++ b/rs_bindings_from_cc/ir_from_cc_test.rs
@@ -429,9 +429,9 @@
         quote! {
             Record {
                 rs_name: "SomeStruct" ...
-                copy_constructor: SpecialMemberFunc { ... access: Private ... },
-                move_constructor: SpecialMemberFunc { ... access: Protected ... },
-                destructor: SpecialMemberFunc { ... access: Public ... } ...
+                copy_constructor: Unavailable,
+                move_constructor: Unavailable,
+                destructor: NontrivialUserDefined ...
             }
         }
     );
@@ -456,9 +456,9 @@
         quote! {
             Record {
                 rs_name: "SomeStruct" ...
-                copy_constructor: SpecialMemberFunc { definition: NontrivialUserDefined ... },
-                move_constructor: SpecialMemberFunc { definition: Deleted ... },
-                destructor: SpecialMemberFunc { definition: Trivial ... } ...
+                copy_constructor: Unavailable,
+                move_constructor: Unavailable,
+                destructor: Trivial ...
             }
         }
     );
diff --git a/rs_bindings_from_cc/src_code_gen.rs b/rs_bindings_from_cc/src_code_gen.rs
index bbde86f..2794f66 100644
--- a/rs_bindings_from_cc/src_code_gen.rs
+++ b/rs_bindings_from_cc/src_code_gen.rs
@@ -896,25 +896,25 @@
 }
 
 fn should_implement_drop(record: &Record) -> bool {
-    match record.destructor.definition {
+    match record.destructor {
         // TODO(b/202258760): Only omit destructor if `Copy` is specified.
-        SpecialMemberDefinition::Trivial => false,
+        SpecialMemberFunc::Trivial => false,
 
         // TODO(b/212690698): Avoid calling into the C++ destructor (e.g. let
         // Rust drive `drop`-ing) to avoid (somewhat unergonomic) ManuallyDrop
         // if we can ask Rust to preserve C++ field destruction order in
         // NontrivialMembers case.
-        SpecialMemberDefinition::NontrivialMembers => true,
+        SpecialMemberFunc::NontrivialMembers => true,
 
         // The `impl Drop` for NontrivialUserDefined needs to call into the
         // user-defined destructor on C++ side.
-        SpecialMemberDefinition::NontrivialUserDefined => true,
+        SpecialMemberFunc::NontrivialUserDefined => true,
 
         // TODO(b/213516512): Today the IR doesn't contain Func entries for
         // deleted functions/destructors/etc. But, maybe we should generate
         // `impl Drop` in this case? With `unreachable!`? With
         // `std::mem::forget`?
-        SpecialMemberDefinition::Deleted => false,
+        SpecialMemberFunc::Unavailable => false,
     }
 }
 
@@ -1160,7 +1160,7 @@
                         if needs_manually_drop(rs_type, ir)? {
                             // TODO(b/212690698): Avoid (somewhat unergonomic) ManuallyDrop
                             // if we can ask Rust to preserve field destruction order if the
-                            // destructor is the SpecialMemberDefinition::NontrivialMembers
+                            // destructor is the SpecialMemberFunc::NontrivialMembers
                             // case.
                             formatted = quote! { crate::rust_std::mem::ManuallyDrop<#formatted> }
                         } else {
@@ -1396,26 +1396,16 @@
         // `union`s (unlike `struct`s) should only derive `Clone` if they are `Copy`.
         should_derive_copy(record)
     } else {
-        // TODO(lukasza): Deduplicate the condition below against
-        // `should_derive_copy` (most likely by getting rid of
-        // `SpecialMemberDefinition::access` and mapping non-public copy
-        // constructors into `SpecialMemberDefinition::Deleted`).
         record.is_unpin()
-            && record.copy_constructor.access == ir::AccessSpecifier::Public
-            && record.copy_constructor.definition == SpecialMemberDefinition::Trivial
+            && record.copy_constructor == SpecialMemberFunc::Trivial
     }
 }
 
 fn should_derive_copy(record: &Record) -> bool {
     // TODO(b/202258760): Make `Copy` inclusion configurable.
-    // TODO(lukasza): Deduplicate part the condition below against
-    // `should_derive_copy` (most likely by getting rid of
-    // `SpecialMemberDefinition::access` and mapping non-public copy
-    // constructors into `SpecialMemberDefinition::Deleted`).
     record.is_unpin()
-        && record.copy_constructor.access == ir::AccessSpecifier::Public
-        && record.copy_constructor.definition == SpecialMemberDefinition::Trivial
-        && record.destructor.definition == ir::SpecialMemberDefinition::Trivial
+        && record.copy_constructor == SpecialMemberFunc::Trivial
+        && record.destructor == ir::SpecialMemberFunc::Trivial
 }
 
 fn generate_derives(record: &Record) -> Vec<Ident> {
@@ -3228,32 +3218,23 @@
     }
 
     #[test]
-    fn test_copy_derives_ctor_nonpublic() {
-        let mut record = ir_record("S");
-        for access in [ir::AccessSpecifier::Protected, ir::AccessSpecifier::Private] {
-            record.copy_constructor.access = access;
-            assert_eq!(generate_derives(&record), &[""; 0]);
-        }
-    }
-
-    #[test]
     fn test_copy_derives_ctor_deleted() {
         let mut record = ir_record("S");
-        record.copy_constructor.definition = ir::SpecialMemberDefinition::Deleted;
+        record.copy_constructor = ir::SpecialMemberFunc::Unavailable;
         assert_eq!(generate_derives(&record), &[""; 0]);
     }
 
     #[test]
     fn test_copy_derives_ctor_nontrivial_members() {
         let mut record = ir_record("S");
-        record.copy_constructor.definition = ir::SpecialMemberDefinition::NontrivialMembers;
+        record.copy_constructor = ir::SpecialMemberFunc::NontrivialMembers;
         assert_eq!(generate_derives(&record), &[""; 0]);
     }
 
     #[test]
     fn test_copy_derives_ctor_nontrivial_self() {
         let mut record = ir_record("S");
-        record.copy_constructor.definition = ir::SpecialMemberDefinition::NontrivialUserDefined;
+        record.copy_constructor = ir::SpecialMemberFunc::NontrivialUserDefined;
         assert_eq!(generate_derives(&record), &[""; 0]);
     }
 
@@ -3261,11 +3242,10 @@
     #[test]
     fn test_copy_derives_dtor_nontrivial_self() {
         let mut record = ir_record("S");
-        for definition in [
-            ir::SpecialMemberDefinition::NontrivialUserDefined,
-            ir::SpecialMemberDefinition::NontrivialMembers,
-        ] {
-            record.destructor.definition = definition;
+        for definition in
+            [ir::SpecialMemberFunc::NontrivialUserDefined, ir::SpecialMemberFunc::NontrivialMembers]
+        {
+            record.destructor = definition;
             assert_eq!(generate_derives(&record), &["Clone"]);
         }
     }