Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions rs_bindings_from_cc/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ deps_for_bindings(
"//support:forward_declare",
"//support:oops",
"//support:bridge_rust",
"//support:cref",
"//support/rs_std:dyn_callable_rs",
"//support/rs_std:lossy_formatter",
# Required for `Copy` trait assertions added to the generated Rust
Expand Down
34 changes: 28 additions & 6 deletions rs_bindings_from_cc/generate_bindings/database/rs_snippet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -463,6 +463,7 @@ pub enum RsTypeKind {
referent: Rc<RsTypeKind>,
mutability: Mutability,
lifetime: Lifetime,
is_cref: bool,
},
RvalueReference {
referent: Rc<RsTypeKind>,
Expand Down Expand Up @@ -1260,7 +1261,10 @@ impl RsTypeKind {
"`self` has no lifetime. Use lifetime annotations to create bindings for this function."
)
}
RsTypeKind::Reference { referent, lifetime, mutability } => {
RsTypeKind::Reference { referent, lifetime, mutability, is_cref } => {
if *is_cref {
bail!("Internal error (crubit.rs-bug): `self` should not be CRef/CMut.");
};
let mut_ = mutability.format_for_reference();
let lifetime = lifetime.format_for_reference();
if mutability == &Mutability::Mut && !referent.is_unpin() {
Expand Down Expand Up @@ -1469,12 +1473,20 @@ impl RsTypeKind {
quote! {* #mutability #pointee_ }
}
}
RsTypeKind::Reference { referent, mutability, lifetime } => {
RsTypeKind::Reference { referent, mutability, lifetime, is_cref } => {
let mut_ = mutability.format_for_reference();
let lifetime = lifetime.format_for_reference();
let referent_ = referent.to_token_stream_replacing_by_self(db, self_record);
let mut tokens = quote! {& #lifetime #mut_ #referent_};
let mut tokens = if *is_cref {
match mutability {
Mutability::Mut => quote! {cref::CMut<#lifetime, #referent_> },
Mutability::Const => quote! { cref::CRef<#lifetime, #referent_> },
}
} else {
quote! {& #lifetime #mut_ #referent_ }
};
if mutability == &Mutability::Mut && !referent.is_unpin() {
// TODO(zarko): Is Pin right for cref here?
tokens = quote! {::core::pin::Pin< #tokens >};
}
tokens
Expand Down Expand Up @@ -1747,12 +1759,20 @@ impl RsTypeKind {
quote! {* #mutability #pointee_tokens }
}
}
RsTypeKind::Reference { referent, mutability, lifetime } => {
let mut_ = mutability.format_for_reference();
RsTypeKind::Reference { referent, mutability, lifetime, is_cref } => {
let lifetime = lifetime.format_for_reference();
let referent_tokens = referent.to_token_stream(db);
let mut tokens = quote! {& #lifetime #mut_ #referent_tokens};
let mut tokens = if *is_cref {
match mutability {
Mutability::Mut => quote! {cref::CMut<#lifetime, #referent_tokens> },
Mutability::Const => quote! { cref::CRef<#lifetime, #referent_tokens> },
}
} else {
let mut_ = mutability.format_for_reference();
quote! {& #lifetime #mut_ #referent_tokens}
};
if mutability == &Mutability::Mut && !referent.is_unpin() {
// TODO(zarko): Is this the right thing for CRef?
tokens = quote! { ::core::pin::Pin< #tokens > };
}
tokens
Expand Down Expand Up @@ -2119,6 +2139,7 @@ mod tests {
referent,
mutability: Mutability::Const,
lifetime: Lifetime::new("_"),
is_cref: false,
};
assert_rs_matches!(reference.to_token_stream(EmptyDatabase), quote! {&::T});
}
Expand Down Expand Up @@ -2177,6 +2198,7 @@ mod tests {
referent: Rc::new(int.clone()),
mutability: Mutability::Const,
lifetime: Lifetime::new("_"),
is_cref: false,
};
for func_ptr in [
RsTypeKind::FuncPtr {
Expand Down
2 changes: 2 additions & 0 deletions rs_bindings_from_cc/generate_bindings/generate_function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1054,6 +1054,8 @@ fn adjust_param_types_for_trait_impl(
referent: Rc::new(param_type.clone()),
mutability: Mutability::Const,
lifetime: Lifetime::new("_"),
// This is a parameter type, so we don't want to lower to CRef.
is_cref: false,
};
(quote! {&mut }, quote! {.clone()})
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1980,7 +1980,7 @@ fn test_simple_explicit_lifetime() -> Result<()> {
rs_api,
quote! {
#[inline(always)]
pub fn Add<'a>(x: &'a mut ::ffi_11::c_int) -> &'a mut ::ffi_11::c_int {
pub fn Add<'a>(x: &'a mut ::ffi_11::c_int) -> cref::CMut<'a, ::ffi_11::c_int> {
unsafe { crate::detail::__rust_thunk___Z3AddRi(x) }
}
}
Expand All @@ -1993,7 +1993,7 @@ fn test_simple_explicit_lifetime() -> Result<()> {
use super::*;
unsafe extern "C" {
#[link_name = "_Z3AddRi"]
pub(crate) unsafe fn __rust_thunk___Z3AddRi<'a>(x: &'a mut ::ffi_11::c_int) -> &'a mut ::ffi_11::c_int;
pub(crate) unsafe fn __rust_thunk___Z3AddRi<'a>(x: &'a mut ::ffi_11::c_int) -> cref::CMut<'a, ::ffi_11::c_int>;
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ fn lifetime_arity(db: &BindingsGenerator, ty: &CcType) -> Result<usize> {
}
}

fn record_lifetime_arity(db: &BindingsGenerator, rc: &Record) -> Result<usize, arc_anyhow::Error> {
fn record_lifetime_arity(_db: &BindingsGenerator, rc: &Record) -> Result<usize, arc_anyhow::Error> {
// TODO(zarko): Handle the effects of [[lifetimebound]] et al on arity.
Ok(rc.lifetime_inputs.len())
}
Expand Down Expand Up @@ -333,6 +333,7 @@ impl<'a, 'db> LifetimeDefaults<'a, 'db> {
/// assigned.
fn add_lifetime_to_output_type(
&mut self,
use_crefs: bool,
lifetime_hint: &Vec<Rc<str>>,
new_bindings: &mut Vec<Rc<str>>,
ty: &CcType,
Expand Down Expand Up @@ -374,22 +375,30 @@ impl<'a, 'db> LifetimeDefaults<'a, 'db> {
.get_or_push_new_binding(l, |name| new_bindings.push(name.clone()))
})
.collect();
// TODO(zarko): Recurse on pty.pointee_type.
new_ty.variant =
CcTypeVariant::Pointer(PointerType { is_cref: use_crefs, ..pty.clone() });
return Ok(new_ty);
}
// If there is no viable inferred lifetime, we need to downgrade this to a raw
// pointer. We can at least mark it non-null. (An argument could be made about
// doing this later on provided we have a fuller treatement of safe/unsafe types
// selected by the presence of lifetime inputs.)
let kind =
if lifetime_hint.is_empty() { PointerTypeKind::NonNull } else { pty.kind };
let (kind, is_cref) = if lifetime_hint.is_empty() {
(PointerTypeKind::NonNull, false)
} else {
(pty.kind, use_crefs && pty.kind == PointerTypeKind::LValueRef)
};
let pointee_type = self.add_lifetime_to_output_type(
use_crefs,
lifetime_hint,
new_bindings,
&pty.pointee_type,
)?;
new_ty.variant = CcTypeVariant::Pointer(PointerType {
pointee_type: pointee_type.into(),
kind,
is_cref,
..pty.clone()
});
new_ty.explicit_lifetimes = lifetime_hint.clone();
Expand Down Expand Up @@ -498,6 +507,7 @@ impl<'a, 'db> LifetimeDefaults<'a, 'db> {
let mut this_state = LifetimeState::Unseen;
let mut had_this = false;
new_func.lifetime_inputs.clear();
let is_operator = matches!(func.cc_name, ir::UnqualifiedIdentifier::Operator(_));
// Note that we generate a new LifetimeDefaults per Item that we're importing, so we don't
// need to pop these bindings. (We *do* need to worry about unbinding names for internal
// binders, like function types.)
Expand Down Expand Up @@ -530,6 +540,7 @@ impl<'a, 'db> LifetimeDefaults<'a, 'db> {
_ => self.get_lifetime_for_state(&this_state),
};
new_func.return_type = self.add_lifetime_to_output_type(
!is_operator,
&lifetime,
&mut new_func.lifetime_inputs,
&new_func.return_type,
Expand Down
9 changes: 6 additions & 3 deletions rs_bindings_from_cc/generate_bindings/rs_type_kind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,12 @@ pub fn rs_type_kind_with_lifetime_elision(
}
};
Ok(match pointer.kind {
PointerTypeKind::LValueRef => {
RsTypeKind::Reference { referent: pointee, mutability, lifetime }
}
PointerTypeKind::LValueRef => RsTypeKind::Reference {
referent: pointee,
mutability,
lifetime,
is_cref: pointer.is_cref,
},
PointerTypeKind::RValueRef => {
RsTypeKind::RvalueReference { referent: pointee, mutability, lifetime }
}
Expand Down
34 changes: 34 additions & 0 deletions rs_bindings_from_cc/test/assume_lifetimes/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ crubit_rust_test(
":free_function",
],
deps = [
"//support:cref",
"@crate_index//:googletest",
],
)
Expand Down Expand Up @@ -67,6 +68,7 @@ crubit_rust_test(
":member_function",
],
deps = [
"//support:cref",
"@crate_index//:googletest",
],
)
Expand Down Expand Up @@ -102,6 +104,38 @@ crubit_rust_test(
],
)

crubit_test_cc_library(
name = "crefs",
srcs = ["crefs.cc"],
hdrs = ["crefs.h"],
aspect_hints = [
"//features:experimental",
],
deps = [
":test_annotations",
],
)

golden_test(
name = "crefs_golden_test",
basename = "crefs",
cc_library = "crefs",
golden_cc = "crefs_api_impl.cc",
golden_rs = "crefs_rs_api.rs",
)

crubit_rust_test(
name = "crefs_test",
srcs = ["crefs_test.rs"],
cc_deps = [
":crefs",
],
deps = [
"//support:cref",
"@crate_index//:googletest",
],
)

crubit_test_cc_library(
name = "string_view",
srcs = ["string_view.cc"],
Expand Down
8 changes: 8 additions & 0 deletions rs_bindings_from_cc/test/assume_lifetimes/crefs.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// Part of the Crubit project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#include "rs_bindings_from_cc/test/assume_lifetimes/crefs.h"

int& id_cmut(int& x) { return x; }
const int& id_cref(const int& x) { return x; }
11 changes: 11 additions & 0 deletions rs_bindings_from_cc/test/assume_lifetimes/crefs.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Part of the Crubit project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#ifndef THIRD_PARTY_CRUBIT_RS_BINDINGS_FROM_CC_TEST_ASSUME_LIFETIMES_CREF_H_
#define THIRD_PARTY_CRUBIT_RS_BINDINGS_FROM_CC_TEST_ASSUME_LIFETIMES_CREF_H_

int& id_cmut(int& x);
const int& id_cref(const int& x);

#endif // THIRD_PARTY_CRUBIT_RS_BINDINGS_FROM_CC_TEST_ASSUME_LIFETIMES_CREF_H_
24 changes: 24 additions & 0 deletions rs_bindings_from_cc/test/assume_lifetimes/crefs_api_impl.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Part of the Crubit project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

// Automatically @generated Rust bindings for the following C++ target:
// //rs_bindings_from_cc/test/assume_lifetimes:crefs
// Features: assume_lifetimes, assume_this_lifetimes, callables, check_default_initialized, experimental, fmt, supported, types, unsafe_view, wrapper

#include "support/internal/cxx20_backports.h"
#include "support/internal/offsetof.h"

#include <memory>

// Public headers of the C++ library being wrapped.
#include "rs_bindings_from_cc/test/assume_lifetimes/crefs.h"

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wthread-safety-analysis"

static_assert((int& (*)(int&)) & ::id_cmut);

static_assert((int const& (*)(int const&)) & ::id_cref);

#pragma clang diagnostic pop
42 changes: 42 additions & 0 deletions rs_bindings_from_cc/test/assume_lifetimes/crefs_rs_api.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// Part of the Crubit project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

// Automatically @generated Rust bindings for the following C++ target:
// //rs_bindings_from_cc/test/assume_lifetimes:crefs
// Features: assume_lifetimes, assume_this_lifetimes, callables, check_default_initialized, experimental, fmt, supported, types, unsafe_view, wrapper

#![rustfmt::skip]
#![feature(custom_inner_attributes)]
#![allow(stable_features)]
#![allow(improper_ctypes)]
#![allow(nonstandard_style)]
#![allow(unused)]
#![deny(warnings)]

/// Generated from: rs_bindings_from_cc/test/assume_lifetimes/crefs.h;l=8
#[inline(always)]
pub fn id_cmut<'x>(x: &'x mut ::ffi_11::c_int) -> cref::CMut<'x, ::ffi_11::c_int> {
unsafe { crate::detail::__rust_thunk___Z7id_cmutRi(x) }
}

/// Generated from: rs_bindings_from_cc/test/assume_lifetimes/crefs.h;l=9
#[inline(always)]
pub fn id_cref<'x>(x: &'x ::ffi_11::c_int) -> cref::CRef<'x, ::ffi_11::c_int> {
unsafe { crate::detail::__rust_thunk___Z7id_crefRKi(x) }
}

mod detail {
#[allow(unused_imports)]
use super::*;
unsafe extern "C" {
#[link_name = "_Z7id_cmutRi"]
pub(crate) unsafe fn __rust_thunk___Z7id_cmutRi<'x>(
x: &'x mut ::ffi_11::c_int,
) -> cref::CMut<'x, ::ffi_11::c_int>;
#[link_name = "_Z7id_crefRKi"]
pub(crate) unsafe fn __rust_thunk___Z7id_crefRKi<'x>(
x: &'x ::ffi_11::c_int,
) -> cref::CRef<'x, ::ffi_11::c_int>;
}
}
15 changes: 15 additions & 0 deletions rs_bindings_from_cc/test/assume_lifetimes/crefs_test.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Part of the Crubit project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

use cref::*;
use googletest::prelude::*;

#[gtest]
fn int_test() {
let x = 1;
let _xref: CRef<'_, i32> = crefs::id_cref(&x);

let mut y = 2;
let _ymut: CMut<'_, i32> = crefs::id_cmut(&mut y);
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

/// Generated from: rs_bindings_from_cc/test/assume_lifetimes/free_function.h;l=8
#[inline(always)]
pub fn increment_int_ref<'a>(a: &'a mut ::ffi_11::c_int) -> &'a mut ::ffi_11::c_int {
pub fn increment_int_ref<'a>(a: &'a mut ::ffi_11::c_int) -> cref::CMut<'a, ::ffi_11::c_int> {
unsafe { crate::detail::__rust_thunk___Z17increment_int_refRi(a) }
}

Expand All @@ -27,6 +27,6 @@ mod detail {
#[link_name = "_Z17increment_int_refRi"]
pub(crate) unsafe fn __rust_thunk___Z17increment_int_refRi<'a>(
a: &'a mut ::ffi_11::c_int,
) -> &'a mut ::ffi_11::c_int;
) -> cref::CMut<'a, ::ffi_11::c_int>;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

use cref::*;
use googletest::prelude::*;

#[gtest]
fn increment_int_ref_test() {
let mut x = 1;
let y = free_function::increment_int_ref(&mut x);
expect_eq!(*y, 2);
unsafe {
expect_eq!(*CMut::as_ptr(y), 2);
}
expect_eq!(x, 2);
}
Loading