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`
///