Skip to content

Commit

Permalink
Better error messages for tagged unions
Browse files Browse the repository at this point in the history
  • Loading branch information
Patrick Urbanke committed Apr 15, 2024
1 parent b38f12e commit 62619d4
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 4 deletions.
6 changes: 4 additions & 2 deletions include/rfl/TaggedUnion.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ struct TaggedUnion {
/// The type of the underlying variant.
using VariantType = std::variant<Ts...>;

/// A literal containing all the tags that are possible
using PossibleTags = define_literal_t<internal::tag_t<_discriminator, Ts>...>;

TaggedUnion(const VariantType& _variant) : variant_(_variant) {}

TaggedUnion(VariantType&& _variant) noexcept
Expand Down Expand Up @@ -85,8 +88,7 @@ struct TaggedUnion {
/// Returns the underlying variant.
const VariantType& variant() const { return variant_; }

static_assert(!define_literal_t<
internal::tag_t<_discriminator, Ts>...>::has_duplicates(),
static_assert(!PossibleTags::has_duplicates(),
"Duplicate tags are not allowed inside tagged unions.");

/// The underlying variant - a TaggedUnion is a thin wrapper
Expand Down
11 changes: 9 additions & 2 deletions include/rfl/parsing/Parser_tagged_union.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "../Result.hpp"
#include "../TaggedUnion.hpp"
#include "../always_false.hpp"
#include "../internal/strings/join.hpp"
#include "Parser_base.hpp"
#include "TaggedUnionWrapper.hpp"
#include "schema/Type.hpp"
Expand Down Expand Up @@ -64,8 +65,13 @@ struct Parser<R, W, TaggedUnion<_discriminator, AlternativeTypes...>> {
const R& _r, const std::string& _disc_value,
const InputVarType& _var) noexcept {
if constexpr (_i == sizeof...(AlternativeTypes)) {
const auto names =
TaggedUnion<_discriminator,
AlternativeTypes...>::PossibleTags::names();
return Error("Could not parse tagged union, could not match " +
_discriminator.str() + " '" + _disc_value + "'.");
_discriminator.str() + " '" + _disc_value +
"'. The following tags are allowed: " +
internal::strings::join(",", names));
} else {
using AlternativeType = std::remove_cvref_t<
std::variant_alternative_t<_i, std::variant<AlternativeTypes...>>>;
Expand Down Expand Up @@ -132,7 +138,8 @@ struct Parser<R, W, TaggedUnion<_discriminator, AlternativeTypes...>> {
/// tag, if the object doesn't already contain the wrap.
template <class T>
static auto wrap_if_necessary(const T& _val) noexcept {
if constexpr (named_tuple_t<T>::Names::template contains<_discriminator>()) {
if constexpr (named_tuple_t<T>::Names::template contains<
_discriminator>()) {
return _val;
} else {
const auto tag = internal::make_tag<_discriminator, T>(_val);
Expand Down

0 comments on commit 62619d4

Please sign in to comment.