Suppress fields if their type isn't supported with these feature flags.

PiperOrigin-RevId: 660125121
Change-Id: I8e0838728f372d9d470b64b5a5f3be64c829d54b
diff --git a/rs_bindings_from_cc/generate_bindings/generate_record.rs b/rs_bindings_from_cc/generate_bindings/generate_record.rs
index f74573c..e1e8654 100644
--- a/rs_bindings_from_cc/generate_bindings/generate_record.rs
+++ b/rs_bindings_from_cc/generate_bindings/generate_record.rs
@@ -113,9 +113,9 @@
         // Both the template definition and its instantiation should enable experimental
         // features.
         for target in record.defining_target.iter().chain([&record.owning_target]) {
-            let required_features = db.ir().target_crubit_features(target);
+            let enabled_features = db.ir().target_crubit_features(target);
             ensure!(
-                required_features.contains(ir::CrubitFeature::Experimental),
+                enabled_features.contains(ir::CrubitFeature::Experimental),
                 "unknown field attributes are only supported with experimental features \
                 enabled on {target}\nUnknown attribute: {unknown_attr}`"
             );
@@ -125,6 +125,17 @@
         Ok(t) => db.rs_type_kind(t.rs_type.clone())?,
         Err(e) => bail!("{e}"),
     };
+
+    for target in record.defining_target.iter().chain([&record.owning_target]) {
+        let enabled_features = db.ir().target_crubit_features(target);
+        let (missing_features, reason) = type_kind.required_crubit_features(enabled_features);
+        ensure!(
+            missing_features.is_empty(),
+            "missing features: [{missing_features}]: {reason}",
+            missing_features = missing_features.into_iter().map(|f| f.aspect_hint()).join(", ")
+        );
+    }
+
     // In supported, we replace nontrivial fields with opaque blobs.
     // This is because we likely don't want the `ManuallyDrop<T>` solution to be the
     // one users get.
@@ -132,9 +143,9 @@
     // Users can still work around this with accessor functions.
     if should_implement_drop(record) && !record.is_union() && needs_manually_drop(&type_kind) {
         for target in record.defining_target.iter().chain([&record.owning_target]) {
-            let required_features = db.ir().target_crubit_features(target);
+            let enabled_features = db.ir().target_crubit_features(target);
             ensure!(
-                required_features.contains(ir::CrubitFeature::Experimental),
+                enabled_features.contains(ir::CrubitFeature::Experimental),
                 "nontrivial fields would be destroyed in the wrong order"
             );
         }
@@ -2597,6 +2608,13 @@
     /// This is hard to test any other way than token comparison!
     #[test]
     fn test_supported_suppressed_field_types() -> Result<()> {
+        // Ideally we'd use a cross-platform test, but it's hard to craft an unsupported
+        // type that is still returned successfully by db.rs_type_kind(), and so
+        // results in a secondary failure when we check afterwards for the
+        // required features for the type.
+        if multiplatform_testing::test_platform() != multiplatform_testing::Platform::X86Linux {
+            return Ok(()); // vectorcall only exists on x86_64, not e.g. aarch64
+        }
         let mut ir = ir_from_cc(
             r#"
             struct Nontrivial {
@@ -2605,6 +2623,9 @@
 
             struct Trivial {
                 Nontrivial* hidden_field;
+                // An example of a field which has a type that is not supported,
+                // but _is_ successfully retrieved by db.rs_type_kind().
+                void(*hidden_field_2)() [[clang::vectorcall]];
             };
         
         "#,
@@ -2618,6 +2639,9 @@
             struct Trivial {
                 ...
                 pub(crate) hidden_field: [::core::mem::MaybeUninit<u8>; 8],
+                ...
+                pub(crate) hidden_field_2: [::core::mem::MaybeUninit<u8>; 8],
+                ...
             }}
         );
         Ok(())
diff --git a/rs_bindings_from_cc/test/extern_c/no_bindings_test.rs b/rs_bindings_from_cc/test/extern_c/no_bindings_test.rs
index 750600e..9a720b3 100644
--- a/rs_bindings_from_cc/test/extern_c/no_bindings_test.rs
+++ b/rs_bindings_from_cc/test/extern_c/no_bindings_test.rs
@@ -103,3 +103,8 @@
     assert!(!type_exists!(no_bindings::UnknownTypeAttribute));
     assert!(!value_exists!(no_bindings::crubit_unknown_type_attribute));
 }
+
+#[test]
+fn test_incomplete_type() {
+    assert!(!value_exists!(no_bindings::crubit_incomplete_type));
+}