Merge pull request #412 from dtolnay/sort

Perform topological sort of structs earlier during type checking
diff --git a/gen/src/mod.rs b/gen/src/mod.rs
index d19dea0..3d12c71 100644
--- a/gen/src/mod.rs
+++ b/gen/src/mod.rs
@@ -12,7 +12,6 @@
 mod namespace;
 mod nested;
 pub(super) mod out;
-mod toposort;
 mod write;
 
 pub(super) use self::error::Error;
diff --git a/gen/src/write.rs b/gen/src/write.rs
index 414ea46..fd2a815 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -1,7 +1,7 @@
 use crate::gen::block::Block;
 use crate::gen::nested::NamespaceEntries;
 use crate::gen::out::OutFile;
-use crate::gen::{builtin, include, toposort, Opt};
+use crate::gen::{builtin, include, Opt};
 use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::symbol::Symbol;
 use crate::syntax::{
@@ -96,7 +96,7 @@
         }
     }
 
-    for strct in toposort::sort(apis, out.types) {
+    for strct in &out.types.toposorted_structs {
         out.next_section();
         if !out.types.cxx.contains(&strct.name.rust) {
             write_struct(out, strct);
diff --git a/syntax/mod.rs b/syntax/mod.rs
index b742e37..33ed31c 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -20,6 +20,7 @@
 pub mod set;
 pub mod symbol;
 mod tokens;
+mod toposort;
 pub mod types;
 
 use self::discriminant::Discriminant;
diff --git a/gen/src/toposort.rs b/syntax/toposort.rs
similarity index 100%
rename from gen/src/toposort.rs
rename to syntax/toposort.rs
diff --git a/syntax/types.rs b/syntax/types.rs
index 5d6d582..ef2e5e6 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -3,7 +3,8 @@
 use crate::syntax::report::Errors;
 use crate::syntax::set::OrderedSet as Set;
 use crate::syntax::{
-    Api, Derive, Enum, ExternFn, ExternType, Impl, Pair, ResolvableName, Struct, Type, TypeAlias,
+    toposort, Api, Derive, Enum, ExternFn, ExternType, Impl, Pair, ResolvableName, Struct, Type,
+    TypeAlias,
 };
 use proc_macro2::Ident;
 use quote::ToTokens;
@@ -21,6 +22,7 @@
     pub explicit_impls: Set<&'a Impl>,
     pub resolutions: Map<&'a Ident, &'a Pair>,
     pub struct_improper_ctypes: UnorderedSet<&'a Ident>,
+    pub toposorted_structs: Vec<&'a Struct>,
 }
 
 impl<'a> Types<'a> {
@@ -35,6 +37,7 @@
         let mut explicit_impls = Set::new();
         let mut resolutions = Map::new();
         let struct_improper_ctypes = UnorderedSet::new();
+        let toposorted_structs = Vec::new();
 
         fn visit<'a>(all: &mut Set<&'a Type>, ty: &'a Type) {
             all.insert(ty);
@@ -205,8 +208,11 @@
             explicit_impls,
             resolutions,
             struct_improper_ctypes,
+            toposorted_structs,
         };
 
+        types.toposorted_structs = toposort::sort(apis, &types);
+
         let mut unresolved_structs: Vec<&Ident> = types.structs.keys().copied().collect();
         let mut new_information = true;
         while new_information {