Skip to content

Commit 599f2ab

Browse files
Googlercopybara-github
authored andcommitted
Disable bindings for ADTs with non-'static lifetimes in cc_bindings_from_rs.
PiperOrigin-RevId: 910588993
1 parent 6babde5 commit 599f2ab

3 files changed

Lines changed: 63 additions & 3 deletions

File tree

cc_bindings_from_rs/generate_bindings/format_type.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,10 @@ pub fn format_ty_for_cc<'tcx>(
273273
let def_id = adt.did();
274274
let mut prereqs = CcPrerequisites::default();
275275

276+
if has_non_static_lifetime_in_adt(tcx, ty) {
277+
bail!("Types with non-'static lifetimes are not supported yet (b/500486197)");
278+
}
279+
276280
if location.is_bridgeable() && is_c_abi_compatible_by_value(tcx, ty) {
277281
ensure!(
278282
db.has_move_ctor_and_assignment_operator(
@@ -608,6 +612,35 @@ pub fn region_is_elided<'tcx>(tcx: TyCtxt<'tcx>, region: ty::Region<'tcx>) -> bo
608612
}
609613
}
610614

615+
pub(crate) fn has_non_static_lifetime_in_adt<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool {
616+
use core::ops::ControlFlow;
617+
use rustc_middle::ty::{Ty, TyCtxt, TypeVisitor};
618+
use ty::TypeSuperVisitable;
619+
620+
struct HasNonStaticLifetimeInAdt;
621+
struct Searcher<'tcx> {
622+
tcx: TyCtxt<'tcx>,
623+
}
624+
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for Searcher<'tcx> {
625+
type Result = ControlFlow<HasNonStaticLifetimeInAdt>;
626+
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<HasNonStaticLifetimeInAdt> {
627+
if let ty::TyKind::Adt(adt, substs) = ty.kind() {
628+
if self.tcx.item_name(adt.did()).as_str() == "LossyFormatter" {
629+
return ty.super_visit_with(self);
630+
}
631+
if substs.iter().any(|subst| subst.as_region().is_some_and(|r| !r.is_static())) {
632+
return ControlFlow::Break(HasNonStaticLifetimeInAdt);
633+
}
634+
}
635+
ty.super_visit_with(self)
636+
}
637+
}
638+
match (Searcher { tcx }).visit_ty(ty) {
639+
ControlFlow::Break(HasNonStaticLifetimeInAdt) => true,
640+
ControlFlow::Continue(()) => false,
641+
}
642+
}
643+
611644
#[derive(Debug, Clone)]
612645
pub struct CcParamTy<'tcx> {
613646
pub snippet: CcSnippet<'tcx>,

cc_bindings_from_rs/generate_bindings/format_type_test.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,12 @@ fn test_format_ty_for_cc_successes() {
304304
cc: "::rs::core::cmp::Ordering",
305305
includes: ["\"fake_bindings_for_unittests/core_cc_api.h\""]
306306
),
307+
case!(
308+
rs: "LifetimeGenericStruct<'static>",
309+
cc: "::rust_out::LifetimeGenericStruct",
310+
includes: [],
311+
prereq_def: "LifetimeGenericStruct"
312+
),
307313
];
308314
let preamble = quote! {
309315
#![allow(unused_parens)]
@@ -323,6 +329,10 @@ fn test_format_ty_for_cc_successes() {
323329
pub y: i32,
324330
}
325331

332+
pub struct LifetimeGenericStruct<'a> {
333+
pub reference: &'a u8,
334+
}
335+
326336
#[allow(unused)]
327337
type Identity<T> = T;
328338
};
@@ -466,6 +476,14 @@ fn test_format_ty_for_cc_failures() {
466476
"Failed to format type for the definition of `std::alloc::LayoutError`: \
467477
Zero-sized types (ZSTs) are not supported (b/258259459)",
468478
),
479+
(
480+
"LifetimeGenericStruct<'_>",
481+
"Types with non-'static lifetimes are not supported yet (b/500486197)",
482+
),
483+
(
484+
"Option<LifetimeGenericStruct<'_>>",
485+
"Types with non-'static lifetimes are not supported yet (b/500486197)",
486+
),
469487
];
470488
let preamble = quote! {
471489
#![feature(never_type)]
@@ -483,6 +501,10 @@ fn test_format_ty_for_cc_failures() {
483501
pub struct TypeGenericStruct<T = u8> {
484502
pub t: T,
485503
}
504+
505+
pub struct LifetimeGenericStruct<'a> {
506+
pub reference: &'a u8,
507+
}
486508
};
487509
test_ty(
488510
TypeLocation::FnParam { is_self_param: false, elided_is_output: false },

cc_bindings_from_rs/generate_bindings/generate_struct_and_union.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1001,10 +1001,15 @@ pub fn generate_adt_core<'tcx>(
10011001
// present. We want to generate bindings for functions regardless of their lifetime bounds, as
10021002
// C++ cannot special-case the availability of a function based on lifetimes.
10031003
#[rustversion::before(2026-04-19)]
1004-
let self_ty = erase_regions(tcx, tcx.type_of(def_id).instantiate_identity());
1004+
let original_self_ty = tcx.type_of(def_id).instantiate_identity();
10051005
#[rustversion::since(2026-04-19)]
1006-
let self_ty =
1007-
erase_regions(tcx, crate::normalize_ty(tcx, tcx.type_of(def_id).instantiate_identity()));
1006+
let original_self_ty = crate::normalize_ty(tcx, tcx.type_of(def_id).instantiate_identity());
1007+
1008+
if crate::format_type::has_non_static_lifetime_in_adt(tcx, original_self_ty) {
1009+
bail!("Types with non-'static lifetimes are not supported yet (b/500486197)");
1010+
}
1011+
1012+
let self_ty = erase_regions(tcx, original_self_ty);
10081013
assert!(self_ty.is_adt());
10091014
assert!(db.symbol_canonical_name(def_id).is_some(), "Caller should verify");
10101015

0 commit comments

Comments
 (0)