Skip to content

Commit

Permalink
Resolve fully-qualified associated types
Browse files Browse the repository at this point in the history
  • Loading branch information
orangeng authored and mversic committed Apr 23, 2024
1 parent ca78140 commit 68e66bd
Show file tree
Hide file tree
Showing 30 changed files with 1,294 additions and 25 deletions.
15 changes: 15 additions & 0 deletions src/bindgen/builder.rs
Expand Up @@ -395,6 +395,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 @@ -407,6 +421,7 @@ impl Builder {
result.functions,
result.source_files,
result.package_version,
assoc_types,
)
.generate()
}
Expand Down
34 changes: 32 additions & 2 deletions src/bindgen/ir/constant.rs
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::language_backend::LanguageBackend;
use crate::bindgen::library::Library;
Expand Down Expand Up @@ -238,6 +238,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 @@ -589,6 +614,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
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::language_backend::LanguageBackend;
use crate::bindgen::library::Library;
Expand Down Expand Up @@ -628,6 +628,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 Enum {
Expand Down
12 changes: 11 additions & 1 deletion src/bindgen/ir/function.rs
Expand Up @@ -9,7 +9,9 @@ use syn::ext::IdentExt;
use crate::bindgen::config::{Config, Language};
use crate::bindgen::declarationtyperesolver::DeclarationTypeResolver;
use crate::bindgen::dependencies::Dependencies;
use crate::bindgen::ir::{AnnotationSet, Cfg, Documentation, GenericPath, Path, Type};
use crate::bindgen::ir::{
AnnotationSet, AssocTypeResolver, Cfg, Documentation, GenericPath, Path, Type,
};
use crate::bindgen::library::Library;
use crate::bindgen::monomorph::Monomorphs;
use crate::bindgen::rename::{IdentifierType, RenameRule};
Expand Down Expand Up @@ -212,6 +214,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);
}
}
}

trait SynFnArgHelpers {
Expand Down
59 changes: 56 additions & 3 deletions src/bindgen/ir/generic_path.rs
Expand Up @@ -6,11 +6,43 @@ 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::language_backend::LanguageBackend;
use crate::bindgen::utilities::IterHelpers;
use crate::bindgen::writer::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: &syn::QSelf) -> Result<Self, String> {
let self_type = &qself.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 @@ -136,6 +168,14 @@ impl GenericParams {
) {
self.write_internal(language_backend, 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_) = &mut generic_param.ty {
ty_.resolve_assoc_types(resolver);
}
}
}
}

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

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

Expand Down Expand Up @@ -240,6 +282,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 @@ -257,7 +303,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 @@ -266,6 +312,10 @@ impl GenericPath {
let last_segment = path.segments.last().unwrap();
let name = last_segment.ident.unraw().to_string();

let assoc = qself
.map(|qself| AssocTypeId::load(path, qself))
.transpose()?;

let path = Path::new(name);
let phantom_data_path = Path::new("PhantomData");
if path == phantom_data_path {
Expand All @@ -290,6 +340,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
Expand Up @@ -5,7 +5,9 @@
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;

#[derive(Debug, Clone)]
Expand Down Expand Up @@ -102,4 +104,8 @@ 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);
}
}
5 changes: 3 additions & 2 deletions src/bindgen/ir/item.rs
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
7 changes: 6 additions & 1 deletion src/bindgen/ir/opaque.rs
Expand Up @@ -6,7 +6,8 @@ use crate::bindgen::config::Config;
use crate::bindgen::declarationtyperesolver::DeclarationTypeResolver;
use crate::bindgen::dependencies::Dependencies;
use crate::bindgen::ir::{
AnnotationSet, Cfg, Documentation, GenericArgument, GenericParams, Item, ItemContainer, Path,
AnnotationSet, AssocTypeResolver, Cfg, Documentation, GenericArgument, GenericParams, Item,
ItemContainer, Path,
};
use crate::bindgen::library::Library;
use crate::bindgen::mangle;
Expand Down Expand Up @@ -131,4 +132,8 @@ 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);
}
}
14 changes: 12 additions & 2 deletions src/bindgen/ir/structure.rs
Expand Up @@ -10,8 +10,8 @@ use crate::bindgen::config::{Config, Language, LayoutConfig};
use crate::bindgen::declarationtyperesolver::DeclarationTypeResolver;
use crate::bindgen::dependencies::Dependencies;
use crate::bindgen::ir::{
AnnotationSet, Cfg, Constant, Documentation, Field, GenericArgument, GenericParams, Item,
ItemContainer, Path, Repr, ReprAlign, ReprStyle, Type,
AnnotationSet, AssocTypeResolver, Cfg, Constant, Documentation, Field, GenericArgument,
GenericParams, Item, ItemContainer, Path, Repr, ReprAlign, ReprStyle, Type,
};
use crate::bindgen::library::Library;
use crate::bindgen::mangle;
Expand Down Expand Up @@ -373,4 +373,14 @@ 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.ty.resolve_assoc_types(resolver);
}
for const_ in self.associated_constants.iter_mut() {
const_.resolve_assoc_types(resolver);
}
}
}

0 comments on commit 68e66bd

Please sign in to comment.