Skip to content
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -81,3 +81,26 @@ pub struct NoMoveOrAssign<'tcx> {
/// Snippets containing explicitly deleted declarations.
pub explicitly_deleted: ApiSnippets<'tcx>,
}

/// The style of copy constructor and assignment operator to generate for an ADT.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum CopyCtorStyle {
// The type is copy and can use the default C++ copy constructor and assignment operator.
Copy,
// The type is clone and needs to call a clone thunk in the copy constructor and assignment
// operator.
Clone,
}

// The style of move constructor and assignment operator to generate for an ADT.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum MoveCtorStyle {
// The type does not require drop glue and can be moved by the default C++ move constructor and
// assignment operator.
Default,
// The type is Default (and Unpin) and can be moved using MemSwap and std::move.
MemSwap,
// The type cannot be moved but has a copy constructor and assignment operator that are used in
// lieu of the move constructor and assignment operator.
Copy,
}
29 changes: 28 additions & 1 deletion cc_bindings_from_rs/generate_bindings/database/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ extern crate rustc_hir;
extern crate rustc_middle;
extern crate rustc_span;

use crate::adt_core_bindings::{AdtCoreBindings, NoMoveOrAssign};
use crate::adt_core_bindings::{AdtCoreBindings, CopyCtorStyle, MoveCtorStyle, NoMoveOrAssign};
use crate::code_snippet::{ApiSnippets, CcSnippet, CrubitAbiTypeWithCcPrereqs};
use crate::fully_qualified_name::{FullyQualifiedName, PublicPaths, UnqualifiedName};
use crate::include_guard::IncludeGuard;
Expand Down Expand Up @@ -194,6 +194,33 @@ memoized::query_group! {
ty: Ty<'tcx>
) -> Result<TokenStream>;

/// Returns true if the type has a default constructor.
///
/// Implementation: cc_bindings_from_rs/generate_bindings/lib.rs?q=function:has_default_ctor
fn has_default_ctor(&self, self_ty: Ty<'tcx>) -> bool;

/// Returns the style of copy constructor and assignment operator for the given type, if available.
///
/// `def_id` is used to determine the typing env of `self_ty`.
///
/// Implementation: cc_bindings_from_rs/generate_bindings/lib.rs?q=function:has_copy_ctor_and_assignment_operator
fn has_copy_ctor_and_assignment_operator(
&self,
def_id: DefId,
self_ty: Ty<'tcx>,
) -> Option<CopyCtorStyle>;

/// Returns the style of move constructor and assignment operator for the given type, if available.
///
/// `def_id` is used to determine the typing env of `self_ty`.
///
/// Implementation: cc_bindings_from_rs/generate_bindings/lib.rs?q=function:has_move_ctor_and_assignment_operator
fn has_move_ctor_and_assignment_operator(
&self,
def_id: DefId,
self_ty: Ty<'tcx>,
) -> Option<MoveCtorStyle>;

/// Generates a default constructor for an ADT if possible (i.e. if the `Default`
/// trait is implemented for the ADT). Returns an error otherwise (e.g. if
/// there is no `Default` impl, then the default constructor will be
Expand Down
2 changes: 1 addition & 1 deletion cc_bindings_from_rs/generate_bindings/database/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ extern crate rustc_middle;
pub mod code_snippet;

mod adt_core_bindings;
pub use adt_core_bindings::{AdtCoreBindings, NoMoveOrAssign};
pub use adt_core_bindings::{AdtCoreBindings, CopyCtorStyle, MoveCtorStyle, NoMoveOrAssign};
pub mod cpp_type;
mod db;
pub use db::BindingsGenerator;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,47 +34,22 @@ struct OptionApi<'a, 'tcx> {
}

impl<'tcx> OptionApi<'_, 'tcx> {
// Remove wrapper Option<T> indirection.
fn underlying_argument_ty(&self) -> Ty<'tcx> {
fn underlying_argument_ty<'tcx>(db: &BindingsGenerator<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
let ty::TyKind::Adt(adt, subst) = ty.kind() else {
return ty;
};
let Some(variant) = adt.variants().iter().next() else {
return ty;
};
use rustc_hir::LangItem;
match db.tcx().lang_items().from_def_id(variant.def_id) {
Some(LangItem::OptionSome | LangItem::OptionNone) => {
underlying_argument_ty(db, subst.type_at(0))
}
_ => ty,
}
}
underlying_argument_ty(self.db, self.arg_ty_rs)
}

fn has_move_ctor(&self) -> bool {
let underlying_argument_ty = self.underlying_argument_ty();

underlying_argument_ty
self.arg_ty_rs
.ty_adt_def()
.map(|adt| {
self.db
.generate_adt_core(adt.did())
.and_then(|core| {
self.db.generate_move_ctor_and_assignment_operator(core).map_err(|e| e.err)
})
.is_ok()
self.db.has_move_ctor_and_assignment_operator(adt.did(), self.arg_ty_rs).is_some()
})
.unwrap_or(false)
}

fn has_relocating_ctor(&self) -> bool {
let underlying_argument_ty = self.underlying_argument_ty();
underlying_argument_ty
self.arg_ty_rs
.ty_adt_def()
.map(|adt| self.db.adt_needs_bindings(adt.did()).is_ok())
.map(|adt| {
crate::BridgedBuiltin::new(self.db, adt).is_some()
|| self.db.adt_needs_bindings(adt.did()).is_ok()
})
.unwrap_or(false)
}

Expand Down
Loading