Drop `forward_declare`'s dependency on `extern type`

Upstream is improving `extern type`-- now, if you pass `Incomplete` to e.g. size_of_val, you get a compile-time error instead of a crash. However, it isn't easily possible to bridge across this change, so we temporarily revert to using `type Unsized = ()` rather than a proper `extern type`.

In the future, `type Unsized` should be returned to `extern "C"`, and
`pub unsafe trait CppType` should grow a `: PointeeSized` supertrait.

PiperOrigin-RevId: 773107157
Change-Id: Icb40b725fd422ab8c4a78d349e3306fc6db9da07
diff --git a/docs/overview/unstable_features.md b/docs/overview/unstable_features.md
index 2e8efd4..3b107c7 100644
--- a/docs/overview/unstable_features.md
+++ b/docs/overview/unstable_features.md
@@ -48,6 +48,14 @@
     where it relies on forward declarations for build performance or
     cycle-breaking reasons.
 
+### `sized_hierarchy`
+
+*   **Crubit feature:** `experimental`
+
+*   **Use case:** Used for forward declarations, which have an unknown size.
+
+*   **Exit strategy:** Same as `extern_types`.
+
 ### `arbitrary_self_types`
 
 *   **Crubit feature:** `experimental`
diff --git a/rs_bindings_from_cc/generate_bindings/database/rs_snippet.rs b/rs_bindings_from_cc/generate_bindings/database/rs_snippet.rs
index cf322af..ea718c6 100644
--- a/rs_bindings_from_cc/generate_bindings/database/rs_snippet.rs
+++ b/rs_bindings_from_cc/generate_bindings/database/rs_snippet.rs
@@ -797,6 +797,12 @@
         match self.unalias() {
             RsTypeKind::Error { error, .. } => bail!("Cannot use an error type by value: {error}"),
             RsTypeKind::Record { record, .. } => check_by_value(record),
+            RsTypeKind::IncompleteRecord { incomplete_record, .. } => {
+                bail!(
+                    "Attempted to pass incomplete record type `{}` by-value",
+                    incomplete_record.cc_name
+                )
+            }
             _ => Ok(()),
         }
     }
diff --git a/rs_bindings_from_cc/generate_bindings/generate_function.rs b/rs_bindings_from_cc/generate_bindings/generate_function.rs
index 61b2018..f268ada 100644
--- a/rs_bindings_from_cc/generate_bindings/generate_function.rs
+++ b/rs_bindings_from_cc/generate_bindings/generate_function.rs
@@ -1143,7 +1143,10 @@
         db.rs_type_kind(func.return_type.clone()).with_context(|| "Failed to format return type"),
     )?;
     if let Err(err) = return_type.check_by_value() {
+        // If the return type is not valid, we can't generate even a fake thunk, so we must return
+        // immediately.
         errors.add(err);
+        errors.consolidate()?;
     }
     let param_idents =
         func.params.iter().map(|p| make_rs_ident(&p.identifier.identifier)).collect_vec();
diff --git a/rs_bindings_from_cc/generate_bindings/generate_function_thunk.rs b/rs_bindings_from_cc/generate_bindings/generate_function_thunk.rs
index d2c81db..87035cf 100644
--- a/rs_bindings_from_cc/generate_bindings/generate_function_thunk.rs
+++ b/rs_bindings_from_cc/generate_bindings/generate_function_thunk.rs
@@ -194,7 +194,7 @@
 // The escaping scheme is not collision-free, i.e. two different inputs may map to the same output.
 // In practice, though, collisions are extremely unlikely, and other aspects of the way we create
 // thunk names may also cause (very unlikely) collisions.
-fn ident_fragment_from_mangled_name(mangled_name: &str) -> Cow<str> {
+fn ident_fragment_from_mangled_name(mangled_name: &str) -> Cow<'_, str> {
     // LLVM identifiers use the `\01` prefix to suppress mangling:
     // https://llvm.org/docs/LangRef.html#identifiers
     // We won't be passing the name to LLVM anyway, so we simply strip the prefix if present.
diff --git a/rs_bindings_from_cc/generate_bindings/generate_struct_and_union_test.rs b/rs_bindings_from_cc/generate_bindings/generate_struct_and_union_test.rs
index 2192367..3e4b22d 100644
--- a/rs_bindings_from_cc/generate_bindings/generate_struct_and_union_test.rs
+++ b/rs_bindings_from_cc/generate_bindings/generate_struct_and_union_test.rs
@@ -437,7 +437,7 @@
     assert_rs_matches!(rs_api, quote! {impl<'error> Default});
     assert_rs_matches!(rs_api, quote! {impl<'error> From});
     assert_rs_matches!(rs_api, quote! {impl<'error> Clone});
-    assert_rs_matches!(rs_api, quote! {ReturnsValue<'error>});
+    assert_rs_not_matches!(rs_api, quote! {ReturnsValue});
     assert_rs_matches!(rs_api, quote! {TakesValue<'error>});
     // ... but it is otherwise available:
     assert_rs_matches!(rs_api, quote! {struct Indestructible});
@@ -467,7 +467,7 @@
     let rs_api = generate_bindings_tokens_for_test(ir)?.rs_api;
     // It isn't available by value:
     assert_rs_not_matches!(rs_api, quote! {CtorNew});
-    assert_rs_matches!(rs_api, quote! {ReturnsValue<'error>});
+    assert_rs_not_matches!(rs_api, quote! {ReturnsValue});
     assert_rs_matches!(rs_api, quote! {TakesValue<'error>});
     // ... but it is otherwise available:
     assert_rs_matches!(rs_api, quote! {struct Indestructible});
diff --git a/rs_bindings_from_cc/test/golden/enums_rs_api.rs b/rs_bindings_from_cc/test/golden/enums_rs_api.rs
index 9b05a2b..a50d124 100644
--- a/rs_bindings_from_cc/test/golden/enums_rs_api.rs
+++ b/rs_bindings_from_cc/test/golden/enums_rs_api.rs
@@ -6,13 +6,7 @@
 // //rs_bindings_from_cc/test/golden:enums_cc
 
 #![rustfmt::skip]
-#![feature(
-    allocator_api,
-    cfg_sanitize,
-    custom_inner_attributes,
-    impl_trait_in_assoc_type,
-    register_tool
-)]
+#![feature(allocator_api, cfg_sanitize, custom_inner_attributes, register_tool)]
 #![allow(stable_features)]
 #![no_std]
 #![allow(improper_ctypes)]
@@ -320,22 +314,5 @@
 // Error while generating bindings for item 'ForwardDeclared':
 // Can't generate bindings for ForwardDeclared, because it is unsupported: b/322391132: Forward-declared (opaque) enums are not implemented yet
 
-#[diagnostic::on_unimplemented(
-    message = "binding generation for function failed\nCannot use an error type by value: Can't generate bindings for ForwardDeclared, because it is unsupported"
-)]
-pub trait BindingFailedFor_Z31do_not_generate_bindings_for_mev {}
-#[inline(always)]
-pub(crate) fn do_not_generate_bindings_for_me<'error>() -> impl ::ctor::Ctor<
-    Output = ::forward_declare::Incomplete<::forward_declare::symbol!("ForwardDeclared"), ()>,
->
-where
-    &'error (): BindingFailedFor_Z31do_not_generate_bindings_for_mev,
-{
-    #![allow(unused_variables)]
-    unreachable!(
-        "This impl can never be instantiated. \
-                    If this message appears at runtime, please report a <internal link>."
-    );
-    #[allow(unreachable_code)]
-    ::ctor::UnreachableCtor::new()
-}
+// Error while generating bindings for item 'do_not_generate_bindings_for_me':
+// Cannot use an error type by value: Can't generate bindings for ForwardDeclared, because it is unsupported
diff --git a/support/BUILD b/support/BUILD
index b3ae589..e93f1c0 100644
--- a/support/BUILD
+++ b/support/BUILD
@@ -107,11 +107,11 @@
 rust_library(
     name = "forward_declare",
     srcs = ["forward_declare.rs"],
-    # LINT.ThenChange(//docs/overview/unstable_features.md)
     crate_features = ["unstable"],
     proc_macro_deps = [":forward_declare_proc_macros"],
     # LINT.IfChange
     rustc_flags = ["-Zallow-features=extern_types,negative_impls,vec_into_raw_parts,unsized_const_params"],
+    # LINT.ThenChange(//docs/overview/unstable_features.md)
     visibility = [
         "//:__subpackages__",
         "//google_internal/release:crubit_support_lib_visibility",
diff --git a/support/forward_declare.rs b/support/forward_declare.rs
index 952757e..bec7fe6 100644
--- a/support/forward_declare.rs
+++ b/support/forward_declare.rs
@@ -274,11 +274,15 @@
 
 use internal::*;
 
-extern "C" {
-    /// Adding an `Unsized` field to your type makes it completely unsized
-    /// (not just dynamically-sized).
-    type Unsized;
-}
+// TODO: cramertj - Move this to `extern "C"` type when extern types and the Sized heirarchy have
+// stabilized.
+//
+// extern "C" {
+//     /// Adding an `Unsized` field to your type makes it completely unsized
+//     /// (not just dynamically-sized).
+//     type Unsized;
+// }
+type Unsized = ();
 
 /// A struct representing an "Incomplete Type" for `Name`
 ///