diff options
author | David Tolnay <dtolnay@gmail.com> | 2020-11-02 12:57:57 -0800 |
---|---|---|
committer | David Tolnay <dtolnay@gmail.com> | 2020-11-02 18:20:08 -0800 |
commit | 7953a11d0c9466103344c15a56569a0aa7f45c9d (patch) | |
tree | eba74278e6771d72510e621d123edfc5e15b4536 /syntax/improper.rs | |
parent | fa1f15b2d700af64980747a0824725965056123b (diff) | |
download | cxx-7953a11d0c9466103344c15a56569a0aa7f45c9d.tar.gz |
Implement improper ctypes check without infinite loop on cyclic structs
Diffstat (limited to 'syntax/improper.rs')
-rw-r--r-- | syntax/improper.rs | 36 |
1 files changed, 36 insertions, 0 deletions
diff --git a/syntax/improper.rs b/syntax/improper.rs new file mode 100644 index 00000000..6fd31629 --- /dev/null +++ b/syntax/improper.rs @@ -0,0 +1,36 @@ +use self::ImproperCtype::*; +use crate::syntax::atom::Atom::{self, *}; +use crate::syntax::{Type, Types}; +use proc_macro2::Ident; + +pub enum ImproperCtype<'a> { + Definite(bool), + Depends(&'a Ident), +} + +impl<'a> Types<'a> { + // yes, no, maybe + pub fn determine_improper_ctype(&self, ty: &Type) -> ImproperCtype<'a> { + match ty { + Type::Ident(ident) => { + let ident = &ident.rust; + if let Some(atom) = Atom::from(ident) { + Definite(atom == RustString) + } else if let Some(strct) = self.structs.get(ident) { + Depends(&strct.name.rust) // iterate to fixed-point + } else { + Definite(self.rust.contains(ident)) + } + } + Type::RustBox(_) + | Type::RustVec(_) + | Type::Str(_) + | Type::Fn(_) + | Type::Void(_) + | Type::Slice(_) + | Type::SliceRefU8(_) => Definite(true), + Type::UniquePtr(_) | Type::CxxVector(_) => Definite(false), + Type::Ref(ty) => self.determine_improper_ctype(&ty.inner), + } + } +} |