Skip to content

Commit

Permalink
Squashed commits. Added functionality to resolve fully-qualified trai…
Browse files Browse the repository at this point in the history
…t associated types in cbindgen

Parsed associated types to map

Parsed associated type on function signature. Replaced assoc type with concrete type

Fixed unwraps. Changed storage of AssocTypeId in function

Fixed unwraps in Parse::load_syn_impl()

Moved AssocTypeId into GenericPath (Type::Path(GenericPath))

Minor changes

Moved assoc type translation to Library. Added for consts and structs

Added 1 test for assoc_types

Automatic output from tests

Minor fixes

Fixed things from feedback

Added recursive associated type replacements. Added test for array

Added test for nested associated types in func ptr and raw ptr

Added assoc type replacement for all types in Library. Added tests for each

Minor fixes + cargo fmt

WIP: Resolving nested associated types

Added GenericParam parsing. Fixed nested associated types.

Added fn for generic_params. Added OpaqueItem processing in library

Added resolve_assoc for Literal. Moved resolve_assoc to individual ir types

Moved resolve_assoc_types to Item trait. Added type alias for AssocTypeResolver

Add docs for no-export
  • Loading branch information
orangeng authored and mversic committed Dec 7, 2023
1 parent 6bfc217 commit cda3c70
Show file tree
Hide file tree
Showing 31 changed files with 1,317 additions and 29 deletions.
15 changes: 15 additions & 0 deletions src/bindgen/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,20 @@ impl Builder {

result.source_files.extend_from_slice(self.srcs.as_slice());

let assoc_types = result
.assoc_types
.into_iter()
.filter_map(
|(id, (ty_, count))| {
if count == 0 {
Some((id, ty_))
} else {
None
}
},
)
.collect();

Library::new(
self.config,
result.constants,
Expand All @@ -405,6 +419,7 @@ impl Builder {
result.typedefs,
result.functions,
result.source_files,
assoc_types,
)
.generate()
}
Expand Down
34 changes: 32 additions & 2 deletions src/bindgen/ir/constant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ use crate::bindgen::config::{Config, Language};
use crate::bindgen::declarationtyperesolver::DeclarationTypeResolver;
use crate::bindgen::dependencies::Dependencies;
use crate::bindgen::ir::{
AnnotationSet, Cfg, ConditionWrite, Documentation, GenericParams, Item, ItemContainer, Path,
Struct, ToCondition, Type,
AnnotationSet, AssocTypeResolver, Cfg, ConditionWrite, Documentation, GenericParams, Item,
ItemContainer, Path, Struct, ToCondition, Type,
};
use crate::bindgen::library::Library;
use crate::bindgen::writer::{Source, SourceWriter};
Expand Down Expand Up @@ -237,6 +237,31 @@ impl Literal {
});
uses_only_primitive_types
}

pub fn resolve_assoc_types(&mut self, resolver: &AssocTypeResolver) {
match self {
Literal::PostfixUnaryOp { value, .. } => {
value.resolve_assoc_types(resolver);
}
Literal::BinOp { left, right, .. } => {
left.resolve_assoc_types(resolver);
right.resolve_assoc_types(resolver);
}
Literal::FieldAccess { base, .. } => {
base.resolve_assoc_types(resolver);
}
Literal::Struct { fields, .. } => {
for (_, literal) in fields {
literal.resolve_assoc_types(resolver);
}
}
Literal::Cast { ty, value } => {
value.resolve_assoc_types(resolver);
ty.resolve_assoc_types(resolver);
}
_ => {}
}
}
}

impl Literal {
Expand Down Expand Up @@ -689,6 +714,11 @@ impl Item for Constant {
fn resolve_declaration_types(&mut self, resolver: &DeclarationTypeResolver) {
self.ty.resolve_declaration_types(resolver);
}

fn resolve_assoc_types(&mut self, resolver: &AssocTypeResolver) {
self.ty.resolve_assoc_types(resolver);
self.value.resolve_assoc_types(resolver);
}
}

impl Constant {
Expand Down
19 changes: 16 additions & 3 deletions src/bindgen/ir/enumeration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ use crate::bindgen::config::{Config, Language};
use crate::bindgen::declarationtyperesolver::DeclarationTypeResolver;
use crate::bindgen::dependencies::Dependencies;
use crate::bindgen::ir::{
AnnotationSet, AnnotationValue, Cfg, ConditionWrite, DeprecatedNoteKind, Documentation, Field,
GenericArgument, GenericParams, GenericPath, Item, ItemContainer, Literal, Path, Repr,
ReprStyle, Struct, ToCondition, Type,
AnnotationSet, AnnotationValue, AssocTypeResolver, Cfg, ConditionWrite, DeprecatedNoteKind,
Documentation, Field, GenericArgument, GenericParams, GenericPath, Item, ItemContainer,
Literal, Path, Repr, ReprStyle, Struct, ToCondition, Type,
};
use crate::bindgen::library::Library;
use crate::bindgen::mangle;
Expand Down Expand Up @@ -652,6 +652,19 @@ impl Item for Enum {
variant.add_dependencies(library, out);
}
}

fn resolve_assoc_types(&mut self, resolver: &AssocTypeResolver) {
for variant in self.variants.iter_mut() {
if let Some(literal) = variant.discriminant.as_mut() {
literal.resolve_assoc_types(resolver);
}
if let VariantBody::Body { body, .. } = &mut variant.body {
body.resolve_assoc_types(resolver);
}
}

self.generic_params.resolve_assoc_types(resolver);
}
}

impl Source for Enum {
Expand Down
6 changes: 5 additions & 1 deletion src/bindgen/ir/field.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use syn::ext::IdentExt;
use crate::bindgen::cdecl;
use crate::bindgen::config::{Config, Language};
use crate::bindgen::ir::{AnnotationSet, Cfg, ConditionWrite};
use crate::bindgen::ir::{Documentation, Path, ToCondition, Type};
use crate::bindgen::ir::{AssocTypeResolver, Documentation, Path, ToCondition, Type};
use crate::bindgen::writer::{Source, SourceWriter};

#[derive(Debug, Clone)]
Expand Down Expand Up @@ -47,6 +47,10 @@ impl Field {
None
})
}

pub fn resolve_assoc_types(&mut self, resolver: &AssocTypeResolver) {
self.ty.resolve_assoc_types(resolver);
}
}

impl Source for Field {
Expand Down
12 changes: 10 additions & 2 deletions src/bindgen/ir/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ use crate::bindgen::config::{Config, Language, Layout};
use crate::bindgen::declarationtyperesolver::DeclarationTypeResolver;
use crate::bindgen::dependencies::Dependencies;
use crate::bindgen::ir::{
AnnotationSet, Cfg, ConditionWrite, DeprecatedNoteKind, Documentation, GenericPath, Path,
ToCondition, Type,
AnnotationSet, AssocTypeResolver, Cfg, ConditionWrite, DeprecatedNoteKind, Documentation,
GenericPath, Path, ToCondition, Type,
};
use crate::bindgen::library::Library;
use crate::bindgen::monomorph::Monomorphs;
Expand Down Expand Up @@ -218,6 +218,14 @@ impl Function {
}
}
}

pub fn resolve_assoc_types(&mut self, resolver: &AssocTypeResolver) {
self.ret.resolve_assoc_types(resolver);

for arg in self.args.iter_mut() {
arg.ty.resolve_assoc_types(resolver);
}
}
}

impl Source for Function {
Expand Down
64 changes: 61 additions & 3 deletions src/bindgen/ir/generic_path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,45 @@ use syn::ext::IdentExt;
use crate::bindgen::cdecl;
use crate::bindgen::config::{Config, Language};
use crate::bindgen::declarationtyperesolver::{DeclarationType, DeclarationTypeResolver};
use crate::bindgen::ir::{ConstExpr, Path, Type};
use crate::bindgen::ir::{AssocTypeResolver, ConstExpr, Path, Type};
use crate::bindgen::utilities::IterHelpers;
use crate::bindgen::writer::{Source, SourceWriter};

// Struct that serves as key for resolving associated types
#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct AssocTypeId {
pub ty: Box<Type>,
pub trait_: Path,
pub ident: Path,
}

impl AssocTypeId {
pub fn load(path: &syn::Path, qself: &Option<syn::QSelf>) -> Result<Self, String> {
let self_type = &qself
.as_ref()
.ok_or(String::from("Type is not fully-qualified."))?
.ty;

let ir_type_opt = Type::load(&self_type)?;
let ir_type = ir_type_opt.ok_or(String::from("Valid but empty type"))?;

let path_len = path.segments.len();
// Theoretically not possible if qself is present
if path_len < 2 {
return Err(String::from("Trait not found in type"));
}

let ident = path.segments.last().unwrap().ident.to_string();
let trait_ident = path.segments[path_len - 2].ident.to_string();

Ok(AssocTypeId {
ty: Box::new(ir_type),
trait_: Path::new(trait_ident),
ident: Path::new(ident),
})
}
}

#[derive(Debug, Clone)]
pub enum GenericParamType {
Type,
Expand Down Expand Up @@ -57,6 +92,10 @@ impl GenericParam {
pub fn name(&self) -> &Path {
&self.name
}

pub fn ty(&mut self) -> &mut GenericParamType {
&mut self.ty
}
}

#[derive(Default, Debug, Clone)]
Expand Down Expand Up @@ -129,6 +168,14 @@ impl GenericParams {
pub fn write_with_default<F: Write>(&self, config: &Config, out: &mut SourceWriter<F>) {
self.write_internal(config, out, true);
}

pub fn resolve_assoc_types(&mut self, resolver: &AssocTypeResolver) {
for generic_param in self.0.iter_mut() {
if let GenericParamType::Const(ty_) = generic_param.ty() {
ty_.resolve_assoc_types(resolver);
}
}
}
}

impl Deref for GenericParams {
Expand Down Expand Up @@ -200,6 +247,7 @@ pub struct GenericPath {
export_name: String,
generics: Vec<GenericArgument>,
ctype: Option<DeclarationType>,
assoc: Option<AssocTypeId>,
}

impl GenericPath {
Expand All @@ -210,6 +258,7 @@ impl GenericPath {
export_name,
generics,
ctype: None,
assoc: None,
}
}

Expand Down Expand Up @@ -248,6 +297,10 @@ impl GenericPath {
&self.export_name
}

pub fn assoc(&self) -> Option<&AssocTypeId> {
self.assoc.as_ref()
}

pub fn is_single_identifier(&self) -> bool {
self.generics.is_empty()
}
Expand All @@ -265,7 +318,7 @@ impl GenericPath {
self.ctype = resolver.type_for(&self.path);
}

pub fn load(path: &syn::Path) -> Result<Self, String> {
pub fn load(path: &syn::Path, qself: &Option<syn::QSelf>) -> Result<Self, String> {
assert!(
!path.segments.is_empty(),
"{:?} doesn't have any segments",
Expand All @@ -274,6 +327,8 @@ impl GenericPath {
let last_segment = path.segments.last().unwrap();
let name = last_segment.ident.unraw().to_string();

let assoc = AssocTypeId::load(path, qself).ok();

let path = Path::new(name);
let phantom_data_path = Path::new("PhantomData");
if path == phantom_data_path {
Expand All @@ -298,6 +353,9 @@ impl GenericPath {
_ => Vec::new(),
};

Ok(Self::new(path, generics))
let mut ret = Self::new(path, generics);
ret.assoc = assoc;

Ok(ret)
}
}
8 changes: 7 additions & 1 deletion src/bindgen/ir/global.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ use crate::bindgen::cdecl;
use crate::bindgen::config::Config;
use crate::bindgen::declarationtyperesolver::DeclarationTypeResolver;
use crate::bindgen::dependencies::Dependencies;
use crate::bindgen::ir::{AnnotationSet, Cfg, Documentation, Item, ItemContainer, Path, Type};
use crate::bindgen::ir::{
AnnotationSet, AssocTypeResolver, Cfg, Documentation, Item, ItemContainer, Path, Type,
};
use crate::bindgen::library::Library;
use crate::bindgen::writer::{Source, SourceWriter};

Expand Down Expand Up @@ -106,6 +108,10 @@ impl Item for Static {
fn add_dependencies(&self, library: &Library, out: &mut Dependencies) {
self.ty.add_dependencies(library, out);
}

fn resolve_assoc_types(&mut self, resolver: &AssocTypeResolver) {
self.ty.resolve_assoc_types(resolver);
}
}

impl Source for Static {
Expand Down
5 changes: 3 additions & 2 deletions src/bindgen/ir/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ use crate::bindgen::config::Config;
use crate::bindgen::declarationtyperesolver::DeclarationTypeResolver;
use crate::bindgen::dependencies::Dependencies;
use crate::bindgen::ir::{
AnnotationSet, Cfg, Constant, Enum, GenericArgument, OpaqueItem, Path, Static, Struct, Typedef,
Union,
AnnotationSet, AssocTypeResolver, Cfg, Constant, Enum, GenericArgument, OpaqueItem, Path,
Static, Struct, Typedef, Union,
};
use crate::bindgen::library::Library;
use crate::bindgen::monomorph::Monomorphs;
Expand Down Expand Up @@ -46,6 +46,7 @@ pub trait Item {
) {
unreachable!("Cannot instantiate {} as a generic.", self.name())
}
fn resolve_assoc_types(&mut self, resolver: &AssocTypeResolver);
}

#[derive(Debug, Clone)]
Expand Down
8 changes: 6 additions & 2 deletions src/bindgen/ir/opaque.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ use crate::bindgen::config::{Config, Language};
use crate::bindgen::declarationtyperesolver::DeclarationTypeResolver;
use crate::bindgen::dependencies::Dependencies;
use crate::bindgen::ir::{
AnnotationSet, Cfg, ConditionWrite, Documentation, GenericArgument, GenericParams, Item,
ItemContainer, Path, ToCondition,
AnnotationSet, AssocTypeResolver, Cfg, ConditionWrite, Documentation, GenericArgument,
GenericParams, Item, ItemContainer, Path, ToCondition,
};
use crate::bindgen::library::Library;
use crate::bindgen::mangle;
Expand Down Expand Up @@ -135,6 +135,10 @@ impl Item for OpaqueItem {

out.insert_opaque(self, monomorph, generic_values.to_owned());
}

fn resolve_assoc_types(&mut self, resolver: &AssocTypeResolver) {
self.generic_params.resolve_assoc_types(resolver);
}
}

impl Source for OpaqueItem {
Expand Down
16 changes: 13 additions & 3 deletions src/bindgen/ir/structure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ use crate::bindgen::config::{Config, Language, LayoutConfig};
use crate::bindgen::declarationtyperesolver::DeclarationTypeResolver;
use crate::bindgen::dependencies::Dependencies;
use crate::bindgen::ir::{
AnnotationSet, Cfg, ConditionWrite, Constant, DeprecatedNoteKind, Documentation, Field,
GenericArgument, GenericParams, Item, ItemContainer, Path, Repr, ReprAlign, ReprStyle,
ToCondition, Type, Typedef,
AnnotationSet, AssocTypeResolver, Cfg, ConditionWrite, Constant, DeprecatedNoteKind,
Documentation, Field, GenericArgument, GenericParams, Item, ItemContainer, Path, Repr,
ReprAlign, ReprStyle, ToCondition, Type, Typedef,
};
use crate::bindgen::library::Library;
use crate::bindgen::mangle;
Expand Down Expand Up @@ -374,6 +374,16 @@ impl Item for Struct {
let monomorph = self.specialize(generic_values, &mappings, library.get_config());
out.insert_struct(library, self, monomorph, generic_values.to_owned());
}

fn resolve_assoc_types(&mut self, resolver: &AssocTypeResolver) {
self.generic_params.resolve_assoc_types(resolver);
for field in self.fields.iter_mut() {
field.resolve_assoc_types(resolver);
}
for const_ in self.associated_constants.iter_mut() {
const_.resolve_assoc_types(resolver);
}
}
}

impl Source for Struct {
Expand Down
Loading

0 comments on commit cda3c70

Please sign in to comment.