diff --git a/include/qapi/visitor-impl.h b/include/qapi/visitor-impl.h
index ed2934b..4557e99 100644
--- a/include/qapi/visitor-impl.h
+++ b/include/qapi/visitor-impl.h
@@ -81,11 +81,6 @@ struct Visitor

     /* May be NULL; most useful for input visitors. */
     void (*optional)(Visitor *v, const char *name, bool *present);
-
-    /* FIXME - needs to be removed */
-    bool (*start_union)(Visitor *v, bool data_present, Error **errp);
-    /* FIXME - needs to be removed */
-    void (*end_union)(Visitor *v, bool data_present, Error **errp);
 };

 /**
diff --git a/include/qapi/visitor.h b/include/qapi/visitor.h
index 6e49b51..d7a0110 100644
--- a/include/qapi/visitor.h
+++ b/include/qapi/visitor.h
@@ -274,16 +274,4 @@ void visit_type_any(Visitor *v, const char *name, QObject **obj, Error **errp);
  */
 void visit_type_null(Visitor *v, const char *name, Error **errp);

-/**
- * Mark the start of visiting the branches of a union. Return true if
- * @data_present.
- * FIXME: Should not be needed
- */
-bool visit_start_union(Visitor *v, bool data_present, Error **errp);
-/**
- * Mark the end of union branches, after visit_start_union().
- * FIXME: Should not be needed
- */
-void visit_end_union(Visitor *v, bool data_present, Error **errp);
-
 #endif
diff --git a/qapi/qapi-dealloc-visitor.c b/qapi/qapi-dealloc-visitor.c
index ede1703..1a54864 100644
--- a/qapi/qapi-dealloc-visitor.c
+++ b/qapi/qapi-dealloc-visitor.c
@@ -171,31 +171,6 @@ static void qapi_dealloc_type_enum(Visitor *v, const char *name, int *obj,
 {
 }

-/* If there's no data present, the dealloc visitor has nothing to free.
- * Thus, indicate to visitor code that the subsequent union fields can
- * be skipped. This is not an error condition, since the cleanup of the
- * rest of an object can continue unhindered, so leave errp unset in
- * these cases.
- *
- * NOTE: In cases where we're attempting to deallocate an object that
- * may have missing fields, the field indicating the union type may
- * be missing. In such a case, it's possible we don't have enough
- * information to differentiate data_present == false from a case where
- * data *is* present but happens to be a scalar with a value of 0.
- * This is okay, since in the case of the dealloc visitor there's no
- * work that needs to done in either situation.
- *
- * The current inability in QAPI code to more thoroughly verify a union
- * type in such cases will likely need to be addressed if we wish to
- * implement this interface for other types of visitors in the future,
- * however.
- */
-static bool qapi_dealloc_start_union(Visitor *v, bool data_present,
-                                     Error **errp)
-{
-    return data_present;
-}
-
 Visitor *qapi_dealloc_get_visitor(QapiDeallocVisitor *v)
 {
     return &v->visitor;
@@ -227,7 +202,6 @@ QapiDeallocVisitor *qapi_dealloc_visitor_new(void)
     v->visitor.type_number = qapi_dealloc_type_number;
     v->visitor.type_any = qapi_dealloc_type_anything;
     v->visitor.type_null = qapi_dealloc_type_null;
-    v->visitor.start_union = qapi_dealloc_start_union;

     QTAILQ_INIT(&v->stack);

diff --git a/qapi/qapi-visit-core.c b/qapi/qapi-visit-core.c
index 399256b..3360cdf 100644
--- a/qapi/qapi-visit-core.c
+++ b/qapi/qapi-visit-core.c
@@ -76,21 +76,6 @@ void visit_end_list(Visitor *v)
     v->end_list(v);
 }

-bool visit_start_union(Visitor *v, bool data_present, Error **errp)
-{
-    if (v->start_union) {
-        return v->start_union(v, data_present, errp);
-    }
-    return true;
-}
-
-void visit_end_union(Visitor *v, bool data_present, Error **errp)
-{
-    if (v->end_union) {
-        v->end_union(v, data_present, errp);
-    }
-}
-
 bool visit_optional(Visitor *v, const char *name, bool *present)
 {
     if (v->optional) {
diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py
index feef17f..7a44c13 100644
--- a/scripts/qapi-visit.py
+++ b/scripts/qapi-visit.py
@@ -60,10 +60,16 @@ static void visit_type_implicit_%(c_type)s(Visitor *v, %(c_type)s **obj, Error *
     Error *err = NULL;

     visit_start_implicit_struct(v, (void **)obj, sizeof(%(c_type)s), &err);
-    if (!err) {
-        visit_type_%(c_type)s_fields(v, obj, errp);
-        visit_end_implicit_struct(v);
+    if (err) {
+        goto out;
     }
+    if (!*obj) {
+        goto out_obj;
+    }
+    visit_type_%(c_type)s_fields(v, obj, &err);
+out_obj:
+    visit_end_implicit_struct(v);
+out:
     error_propagate(errp, err);
 }
 ''',
@@ -254,9 +260,6 @@ void visit_type_%(c_name)s(Visitor *v, const char *name, %(c_name)s **obj, Error

     if variants:
         ret += mcgen('''
-    if (!visit_start_union(v, !!(*obj)->u.data, &err) || err) {
-        goto out_obj;
-    }
     switch ((*obj)->%(c_name)s) {
 ''',
                      c_name=c_name(variants.tag_member.name))
@@ -293,16 +296,6 @@ void visit_type_%(c_name)s(Visitor *v, const char *name, %(c_name)s **obj, Error

     ret += mcgen('''
 out_obj:
-''')
-    if variants:
-        ret += mcgen('''
-    error_propagate(errp, err);
-    err = NULL;
-    if (*obj) {
-        visit_end_union(v, !!(*obj)->u.data, &err);
-    }
-''')
-    ret += mcgen('''
     error_propagate(errp, err);
     err = NULL;
     visit_end_struct(v, &err);
