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
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
15 changes: 15 additions & 0 deletions src/bindgen/builder.rs
Original file line number Diff line number Diff line change
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
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::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.values_mut() {
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 @@ -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 {
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::language_backend::LanguageBackend;
use crate::bindgen::library::Library;
Expand Down Expand Up @@ -636,6 +636,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
Original file line number Diff line number Diff line change
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 @@ -219,6 +221,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
Original file line number Diff line number Diff line change
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 @@ -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 {
Expand Down Expand Up @@ -240,6 +280,7 @@ pub struct GenericPath {
export_name: String,
generics: Vec<GenericArgument>,
ctype: Option<DeclarationType>,
assoc: Option<AssocTypeId>,
}

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

Expand Down Expand Up @@ -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()
}
Expand All @@ -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",
Expand All @@ -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 {
Expand All @@ -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
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, GenericParams, Item, ItemContainer, Path, Type,
AnnotationSet, AssocTypeResolver, Cfg, Documentation, GenericParams, Item, ItemContainer, Path,
Type,
};
use crate::bindgen::library::Library;

Expand Down Expand Up @@ -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
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, 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;
Expand Down Expand Up @@ -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)]
Expand Down
7 changes: 6 additions & 1 deletion src/bindgen/ir/opaque.rs
Original file line number Diff line number Diff line change
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 @@ -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
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 @@ -377,4 +377,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);
}
}
}