Introduce UnorderedSet newtype
diff --git a/syntax/set.rs b/syntax/set.rs
index ee490e9..6508f55 100644
--- a/syntax/set.rs
+++ b/syntax/set.rs
@@ -2,15 +2,15 @@
 use std::slice;
 
 pub use self::ordered::OrderedSet;
+pub use self::unordered::UnorderedSet;
 
 mod ordered {
-    use super::Iter;
+    use super::{Iter, UnorderedSet};
     use std::borrow::Borrow;
-    use std::collections::HashSet;
     use std::hash::Hash;
 
     pub struct OrderedSet<T> {
-        set: HashSet<T>,
+        set: UnorderedSet<T>,
         vec: Vec<T>,
     }
 
@@ -20,7 +20,7 @@
     {
         pub fn new() -> Self {
             OrderedSet {
-                set: HashSet::new(),
+                set: UnorderedSet::new(),
                 vec: Vec::new(),
             }
         }
@@ -59,6 +59,45 @@
     }
 }
 
+mod unordered {
+    use std::borrow::Borrow;
+    use std::collections::HashSet;
+    use std::hash::Hash;
+
+    // Wrapper prohibits accidentally introducing iteration over the set, which
+    // could lead to nondeterministic generated code.
+    pub struct UnorderedSet<T>(HashSet<T>);
+
+    impl<T> UnorderedSet<T>
+    where
+        T: Hash + Eq,
+    {
+        pub fn new() -> Self {
+            UnorderedSet(HashSet::new())
+        }
+
+        pub fn insert(&mut self, value: T) -> bool {
+            self.0.insert(value)
+        }
+
+        pub fn contains<Q>(&self, value: &Q) -> bool
+        where
+            T: Borrow<Q>,
+            Q: ?Sized + Hash + Eq,
+        {
+            self.0.contains(value)
+        }
+
+        pub fn get<Q>(&self, value: &Q) -> Option<&T>
+        where
+            T: Borrow<Q>,
+            Q: ?Sized + Hash + Eq,
+        {
+            self.0.get(value)
+        }
+    }
+}
+
 pub struct Iter<'s, 'a, T>(slice::Iter<'s, &'a T>);
 
 impl<'s, 'a, T> Iterator for Iter<'s, 'a, T> {
diff --git a/syntax/types.rs b/syntax/types.rs
index 50325d6..90a8221 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -1,14 +1,14 @@
 use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::improper::ImproperCtype;
 use crate::syntax::report::Errors;
-use crate::syntax::set::OrderedSet as Set;
+use crate::syntax::set::{OrderedSet as Set, UnorderedSet};
 use crate::syntax::{
     toposort, Api, Derive, Enum, ExternFn, ExternType, Impl, Pair, ResolvableName, Struct, Type,
     TypeAlias,
 };
 use proc_macro2::Ident;
 use quote::ToTokens;
-use std::collections::{BTreeMap as Map, HashSet as UnorderedSet};
+use std::collections::BTreeMap as Map;
 
 pub struct Types<'a> {
     pub all: Set<&'a Type>,