Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Resolve fully-qualified associated types #905

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
15 changes: 15 additions & 0 deletions src/bindgen/builder.rs
Original file line number Diff line number Diff line change
@@ -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,
@@ -407,6 +421,7 @@ impl Builder {
result.functions,
result.source_files,
result.package_version,
assoc_types,
)
.generate()
}
34 changes: 32 additions & 2 deletions src/bindgen/ir/constant.rs
Original file line number Diff line number Diff line change
@@ -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;
@@ -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.values_mut() {
literal.resolve_assoc_types(resolver);
}
}
Literal::Cast { ty, value } => {
value.resolve_assoc_types(resolver);
ty.resolve_assoc_types(resolver);
}
_ => {}
}
}
}

impl Literal {
@@ -603,6 +628,11 @@ impl Item for Constant {
fn generic_params(&self) -> &GenericParams {
GenericParams::empty()
}

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

impl Constant {
19 changes: 16 additions & 3 deletions src/bindgen/ir/enumeration.rs
Original file line number Diff line number Diff line change
@@ -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;
@@ -639,6 +639,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 {
12 changes: 11 additions & 1 deletion src/bindgen/ir/function.rs
Original file line number Diff line number Diff line change
@@ -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};
@@ -217,6 +219,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 {
59 changes: 56 additions & 3 deletions src/bindgen/ir/generic_path.rs
Original file line number Diff line number Diff line change
@@ -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,
@@ -184,6 +216,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 {
@@ -240,6 +280,7 @@ pub struct GenericPath {
export_name: String,
generics: Vec<GenericArgument>,
ctype: Option<DeclarationType>,
assoc: Option<AssocTypeId>,
}

impl GenericPath {
@@ -250,6 +291,7 @@ impl GenericPath {
export_name,
generics,
ctype: None,
assoc: None,
}
}

@@ -288,6 +330,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()
}
@@ -305,7 +351,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",
@@ -314,6 +360,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 {
@@ -338,6 +388,9 @@ impl GenericPath {
_ => Vec::new(),
};

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

Ok(ret)
}
}
7 changes: 6 additions & 1 deletion src/bindgen/ir/global.rs
Original file line number Diff line number Diff line change
@@ -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, GenericParams, Item, ItemContainer, Path, Type,
AnnotationSet, AssocTypeResolver, Cfg, Documentation, GenericParams, Item, ItemContainer, Path,
Type,
};
use crate::bindgen::library::Library;

@@ -112,4 +113,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
Original file line number Diff line number Diff line change
@@ -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, Documentation, Enum, GenericArgument, GenericParams, OpaqueItem,
Path, Static, Struct, Typedef, Union,
AnnotationSet, AssocTypeResolver, Cfg, Constant, Documentation, Enum, GenericArgument,
GenericParams, OpaqueItem, Path, Static, Struct, Typedef, Union,
};
use crate::bindgen::library::Library;
use crate::bindgen::monomorph::Monomorphs;
@@ -53,6 +53,7 @@ pub trait Item {
) {
unreachable!("Cannot instantiate {} as a generic.", self.name())
}
fn resolve_assoc_types(&mut self, resolver: &AssocTypeResolver);
}

#[derive(Debug, Clone)]
7 changes: 6 additions & 1 deletion src/bindgen/ir/opaque.rs
Original file line number Diff line number Diff line change
@@ -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;
@@ -135,4 +136,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
Original file line number Diff line number Diff line change
@@ -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, Typedef,
AnnotationSet, AssocTypeResolver, Cfg, Constant, Documentation, Field, GenericArgument,
GenericParams, Item, ItemContainer, Path, Repr, ReprAlign, ReprStyle, Type, Typedef,
};
use crate::bindgen::library::Library;
use crate::bindgen::mangle;
@@ -401,4 +401,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);
}
}
}
Loading