Add hb_assign(obj, value)
diff --git a/src/hb-machinery.hh b/src/hb-machinery.hh
index 1205b1f..2070fd8 100644
--- a/src/hb-machinery.hh
+++ b/src/hb-machinery.hh
@@ -390,7 +390,7 @@
   {
     if (this->may_edit (obj, hb_static_size (Type)))
     {
-      const_cast<Type *> (obj)->set (v);
+      hb_assign (* const_cast<Type *> (obj), v);
       return true;
     }
     return false;
diff --git a/src/hb-null.hh b/src/hb-null.hh
index 7ea2bab..8a3e0d4 100644
--- a/src/hb-null.hh
+++ b/src/hb-null.hh
@@ -59,7 +59,10 @@
 { enum { value = _hb_null_size<T, _hb_bool_type<true> >::value }; };
 #define hb_null_size(T) hb_null_size<T>::value
 
-/* This doesn't belong here, but since is copy/paste from above, put it here. */
+/* These doesn't belong here, but since is copy/paste from above, put it here. */
+
+/* hb_static_size (T)
+ * Returns T::static_size if T::min_size is defined, or sizeof (T) otherwise. */
 
 template <typename T, typename B>
 struct _hb_static_size
@@ -74,6 +77,25 @@
 #define hb_static_size(T) hb_static_size<T>::value
 
 
+/* hb_assign (obj, value)
+ * Calls obj.set (value) if obj.min_size is defined and value has different type
+ * from obj, or obj = v otherwise. */
+
+template <typename T, typename V, typename B>
+struct _hb_assign
+{ static inline void value (T &o, const V v) { o = v; } };
+template <typename T, typename V>
+struct _hb_assign<T, V, _hb_bool_type<(bool) (1 + (unsigned int) T::min_size)> >
+{ static inline void value (T &o, const V v) { o.set (v); } };
+template <typename T>
+struct _hb_assign<T, T, _hb_bool_type<(bool) (1 + (unsigned int) T::min_size)> >
+{ static inline void value (T &o, const T v) { o = v; } };
+
+template <typename T, typename V>
+static inline void hb_assign (T &o, const V v)
+{ _hb_assign<T, V, _hb_bool_type<true> >::value (o, v); };
+
+
 /*
  * Null()
  */
diff --git a/src/hb-open-type.hh b/src/hb-open-type.hh
index 6517c6b..7f88279 100644
--- a/src/hb-open-type.hh
+++ b/src/hb-open-type.hh
@@ -553,12 +553,13 @@
     if (unlikely (!c->extend (*this))) return_trace (false);
     return_trace (true);
   }
-  bool serialize (hb_serialize_context_t *c, hb_array_t<const Type> items)
+  template <typename T>
+  bool serialize (hb_serialize_context_t *c, hb_array_t<const T> items)
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!serialize (c, items.len))) return_trace (false);
     for (unsigned int i = 0; i < items.len; i++)
-      arrayZ[i] = items[i];
+      hb_assign (arrayZ[i], items[i]);
     return_trace (true);
   }