Skip to content
Snippets Groups Projects
Select Git revision
  • c1b35ca4d5df2b2052224274c26bea7a8eee8ac5
  • develop default protected
  • feature/advection
  • feature/composite-scheme-other-fluxes
  • origin/stage/bouguettaia
  • save_clemence
  • feature/local-dt-fsi
  • feature/variational-hydro
  • feature/gmsh-reader
  • feature/reconstruction
  • feature/kinetic-schemes
  • feature/composite-scheme-sources
  • feature/serraille
  • feature/composite-scheme
  • hyperplastic
  • feature/polynomials
  • feature/gks
  • feature/implicit-solver-o2
  • feature/coupling_module
  • feature/implicit-solver
  • feature/merge-local-dt-fsi
  • v0.5.0 protected
  • v0.4.1 protected
  • v0.4.0 protected
  • v0.3.0 protected
  • v0.2.0 protected
  • v0.1.0 protected
  • Kidder
  • v0.0.4 protected
  • v0.0.3 protected
  • v0.0.2 protected
  • v0 protected
  • v0.0.1 protected
33 results

test_IntegrateCellArray.cpp

Blame
  • test_ASTNodeNaturalConversionChecker.cpp 90.67 KiB
    #include <catch2/catch.hpp>
    
    #include <language/PEGGrammar.hpp>
    #include <language/ast/ASTNode.hpp>
    #include <language/utils/ASTNodeNaturalConversionChecker.hpp>
    
    namespace language
    {
    struct integer;
    }
    
    // clazy:excludeall=non-pod-global-static
    
    TEST_CASE("ASTNodeNaturalConversionChecker", "[language]")
    {
      const ASTNodeDataType undefined_dt        = ASTNodeDataType{};
      const ASTNodeDataType bool_dt             = ASTNodeDataType::build<ASTNodeDataType::bool_t>();
      const ASTNodeDataType unsigned_int_dt     = ASTNodeDataType::build<ASTNodeDataType::unsigned_int_t>();
      const ASTNodeDataType int_dt              = ASTNodeDataType::build<ASTNodeDataType::int_t>();
      const ASTNodeDataType double_dt           = ASTNodeDataType::build<ASTNodeDataType::double_t>();
      const ASTNodeDataType string_dt           = ASTNodeDataType::build<ASTNodeDataType::string_t>();
      const ASTNodeDataType void_dt             = ASTNodeDataType::build<ASTNodeDataType::void_t>();
      const ASTNodeDataType function_dt         = ASTNodeDataType::build<ASTNodeDataType::function_t>();
      const ASTNodeDataType builtin_function_dt = ASTNodeDataType::build<ASTNodeDataType::builtin_function_t>();
    
      std::vector<std::shared_ptr<const ASTNodeDataType>> type_list;
      type_list.push_back(std::make_shared<const ASTNodeDataType>(double_dt));
      type_list.push_back(std::make_shared<const ASTNodeDataType>(int_dt));
    
      const ASTNodeDataType list_dt = ASTNodeDataType::build<ASTNodeDataType::list_t>(type_list);
    
      SECTION("Valid conversions")
      {
        std::unique_ptr data_node = std::make_unique<ASTNode>();
    
        SECTION("-> string")
        {
          SECTION("string -> string")
          {
            data_node->m_data_type = string_dt;
            REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, string_dt});
          }
    
          SECTION("R^d -> string")
          {
            data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::vector_t>(5);
            REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, string_dt});
          }
    
          SECTION("R -> string")
          {
            data_node->m_data_type = double_dt;
            REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, string_dt});
          }
    
          SECTION("Z -> string")
          {
            data_node->m_data_type = int_dt;
            REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, string_dt});
          }
    
          SECTION("N -> string")
          {
            data_node->m_data_type = unsigned_int_dt;
            REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, string_dt});
          }
    
          SECTION("B -> string")
          {
            data_node->m_data_type = bool_dt;
            REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, string_dt});
          }
    
          SECTION("list -> string")
          {
            data_node->m_data_type = list_dt;
            REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, string_dt});
          }
    
          SECTION("tuple -> string")
          {
            data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(double_dt);
            REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, string_dt});
          }
        }
    
        SECTION("-> R^dxd")
        {
          SECTION("R^1x1 -> R^1x1")
          {
            data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::matrix_t>(1, 1);
            REQUIRE_NOTHROW(
              ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::build<ASTNodeDataType::matrix_t>(1, 1)});
          }
    
          SECTION("list -> R^1x1")
          {
            data_node->m_data_type =
              ASTNodeDataType::build<ASTNodeDataType::list_t>({std::make_shared<const ASTNodeDataType>(double_dt)});
            {
              std::unique_ptr list0_node = std::make_unique<ASTNode>();
              list0_node->m_data_type    = double_dt;
              data_node->emplace_back(std::move(list0_node));
            }
            REQUIRE_NOTHROW(
              ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::build<ASTNodeDataType::matrix_t>(1, 1)});
          }
    
          SECTION("'0' -> R^dxd")
          {
            data_node->m_data_type = int_dt;
            data_node->set_type<language::integer>();
            data_node->source  = "0";
            auto& source       = data_node->source;
            data_node->m_begin = TAO_PEGTL_NAMESPACE::internal::iterator{&source[0]};
            data_node->m_end   = TAO_PEGTL_NAMESPACE::internal::iterator{&source[source.size()]};
    
            SECTION("d = 1")
            {
              REQUIRE_NOTHROW(
                ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::build<ASTNodeDataType::matrix_t>(1, 1)});
            }
            SECTION("d = 2")
            {
              REQUIRE_NOTHROW(
                ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::build<ASTNodeDataType::matrix_t>(2, 2)});
            }
            SECTION("d = 3")
            {
              REQUIRE_NOTHROW(
                ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::build<ASTNodeDataType::matrix_t>(3, 3)});
            }
          }
    
          SECTION("R^2x2 -> R^2x2")
          {
            data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::matrix_t>(2, 2);
            REQUIRE_NOTHROW(
              ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::build<ASTNodeDataType::matrix_t>(2, 2)});
          }
    
          SECTION("list -> R^2x2")
          {
            data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::list_t>(
              {std::make_shared<const ASTNodeDataType>(double_dt), std::make_shared<const ASTNodeDataType>(unsigned_int_dt),
               std::make_shared<const ASTNodeDataType>(unsigned_int_dt),
               std::make_shared<const ASTNodeDataType>(unsigned_int_dt)});
            {
              std::unique_ptr list0_node = std::make_unique<ASTNode>();
              list0_node->m_data_type    = double_dt;
              data_node->emplace_back(std::move(list0_node));
    
              std::unique_ptr list1_node = std::make_unique<ASTNode>();
              list1_node->m_data_type    = unsigned_int_dt;
              data_node->emplace_back(std::move(list1_node));
    
              std::unique_ptr list2_node = std::make_unique<ASTNode>();
              list2_node->m_data_type    = unsigned_int_dt;
              data_node->emplace_back(std::move(list2_node));
    
              std::unique_ptr list3_node = std::make_unique<ASTNode>();
              list3_node->m_data_type    = unsigned_int_dt;
              data_node->emplace_back(std::move(list3_node));
            }
            REQUIRE_NOTHROW(
              ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::build<ASTNodeDataType::matrix_t>(2, 2)});
          }
    
          SECTION("R^3x3 -> R^3x3")
          {
            data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::matrix_t>(3, 3);
            REQUIRE_NOTHROW(
              ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::build<ASTNodeDataType::matrix_t>(3, 3)});
          }
    
          SECTION("list -> R^3x3")
          {
            data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::list_t>(
              {std::make_shared<const ASTNodeDataType>(double_dt), std::make_shared<const ASTNodeDataType>(unsigned_int_dt),
               std::make_shared<const ASTNodeDataType>(int_dt), std::make_shared<const ASTNodeDataType>(double_dt),
               std::make_shared<const ASTNodeDataType>(unsigned_int_dt), std::make_shared<const ASTNodeDataType>(int_dt),
               std::make_shared<const ASTNodeDataType>(double_dt), std::make_shared<const ASTNodeDataType>(unsigned_int_dt),
               std::make_shared<const ASTNodeDataType>(int_dt)});
            {
              std::unique_ptr list0_node = std::make_unique<ASTNode>();
              list0_node->m_data_type    = double_dt;
              data_node->emplace_back(std::move(list0_node));
    
              std::unique_ptr list1_node = std::make_unique<ASTNode>();
              list1_node->m_data_type    = unsigned_int_dt;
              data_node->emplace_back(std::move(list1_node));
    
              std::unique_ptr list2_node = std::make_unique<ASTNode>();
              list2_node->m_data_type    = int_dt;
              data_node->emplace_back(std::move(list2_node));
    
              std::unique_ptr list3_node = std::make_unique<ASTNode>();
              list3_node->m_data_type    = double_dt;
              data_node->emplace_back(std::move(list3_node));
    
              std::unique_ptr list4_node = std::make_unique<ASTNode>();
              list4_node->m_data_type    = unsigned_int_dt;
              data_node->emplace_back(std::move(list4_node));
    
              std::unique_ptr list5_node = std::make_unique<ASTNode>();
              list5_node->m_data_type    = int_dt;
              data_node->emplace_back(std::move(list5_node));
    
              std::unique_ptr list6_node = std::make_unique<ASTNode>();
              list6_node->m_data_type    = double_dt;
              data_node->emplace_back(std::move(list6_node));
    
              std::unique_ptr list7_node = std::make_unique<ASTNode>();
              list7_node->m_data_type    = unsigned_int_dt;
              data_node->emplace_back(std::move(list7_node));
    
              std::unique_ptr list8_node = std::make_unique<ASTNode>();
              list8_node->m_data_type    = int_dt;
              data_node->emplace_back(std::move(list8_node));
            }
            REQUIRE_NOTHROW(
              ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::build<ASTNodeDataType::matrix_t>(3, 3)});
          }
        }
    
        SECTION("-> R^d")
        {
          SECTION("R^1 -> R^1")
          {
            data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::vector_t>(1);
            REQUIRE_NOTHROW(
              ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::build<ASTNodeDataType::vector_t>(1)});
          }
    
          SECTION("list -> R^1")
          {
            data_node->m_data_type =
              ASTNodeDataType::build<ASTNodeDataType::list_t>({std::make_shared<const ASTNodeDataType>(double_dt)});
            {
              std::unique_ptr list0_node = std::make_unique<ASTNode>();
              list0_node->m_data_type    = double_dt;
              data_node->emplace_back(std::move(list0_node));
            }
            REQUIRE_NOTHROW(
              ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::build<ASTNodeDataType::vector_t>(1)});
          }
    
          SECTION("'0' -> R^d")
          {
            data_node->m_data_type = int_dt;
            data_node->set_type<language::integer>();
            data_node->source  = "0";
            auto& source       = data_node->source;
            data_node->m_begin = TAO_PEGTL_NAMESPACE::internal::iterator{&source[0]};
            data_node->m_end   = TAO_PEGTL_NAMESPACE::internal::iterator{&source[source.size()]};
    
            SECTION("d = 1")
            {
              REQUIRE_NOTHROW(
                ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::build<ASTNodeDataType::vector_t>(1)});
            }
            SECTION("d = 2")
            {
              REQUIRE_NOTHROW(
                ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::build<ASTNodeDataType::vector_t>(2)});
            }
            SECTION("d = 3")
            {
              REQUIRE_NOTHROW(
                ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::build<ASTNodeDataType::vector_t>(3)});
            }
          }
    
          SECTION("R^2 -> R^2")
          {
            data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::vector_t>(2);
            REQUIRE_NOTHROW(
              ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::build<ASTNodeDataType::vector_t>(2)});
          }
    
          SECTION("list -> R^2")
          {
            data_node->m_data_type =
              ASTNodeDataType::build<ASTNodeDataType::list_t>({std::make_shared<const ASTNodeDataType>(double_dt),
                                                               std::make_shared<const ASTNodeDataType>(unsigned_int_dt)});
            {
              std::unique_ptr list0_node = std::make_unique<ASTNode>();
              list0_node->m_data_type    = double_dt;
              data_node->emplace_back(std::move(list0_node));
    
              std::unique_ptr list1_node = std::make_unique<ASTNode>();
              list1_node->m_data_type    = unsigned_int_dt;
              data_node->emplace_back(std::move(list1_node));
            }
            REQUIRE_NOTHROW(
              ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::build<ASTNodeDataType::vector_t>(2)});
          }
    
          SECTION("R^3 -> R^3")
          {
            data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::vector_t>(3);
            REQUIRE_NOTHROW(
              ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::build<ASTNodeDataType::vector_t>(3)});
          }
    
          SECTION("list -> R^3")
          {
            data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::list_t>(
              {std::make_shared<const ASTNodeDataType>(double_dt), std::make_shared<const ASTNodeDataType>(unsigned_int_dt),
               std::make_shared<const ASTNodeDataType>(int_dt)});
            {
              std::unique_ptr list0_node = std::make_unique<ASTNode>();
              list0_node->m_data_type    = double_dt;
              data_node->emplace_back(std::move(list0_node));
    
              std::unique_ptr list1_node = std::make_unique<ASTNode>();
              list1_node->m_data_type    = unsigned_int_dt;
              data_node->emplace_back(std::move(list1_node));
    
              std::unique_ptr list2_node = std::make_unique<ASTNode>();
              list2_node->m_data_type    = int_dt;
              data_node->emplace_back(std::move(list2_node));
            }
            REQUIRE_NOTHROW(
              ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::build<ASTNodeDataType::vector_t>(3)});
          }
        }
    
        SECTION("-> R")
        {
          SECTION("R -> R")
          {
            data_node->m_data_type = double_dt;
            REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, double_dt});
          }
    
          SECTION("Z -> R")
          {
            data_node->m_data_type = int_dt;
            REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, double_dt});
          }
    
          SECTION("N -> R")
          {
            data_node->m_data_type = unsigned_int_dt;
            REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, double_dt});
          }
    
          SECTION("B -> R")
          {
            data_node->m_data_type = bool_dt;
            REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, double_dt});
          }
        }
    
        SECTION("-> Z")
        {
          SECTION("Z -> Z")
          {
            data_node->m_data_type = int_dt;
            REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, int_dt});
          }
    
          SECTION("N -> Z")
          {
            data_node->m_data_type = unsigned_int_dt;
            REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, int_dt});
          }
    
          SECTION("B -> Z")
          {
            data_node->m_data_type = bool_dt;
            REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, int_dt});
          }
        }
    
        SECTION("-> N")
        {
          SECTION("Z -> N")
          {
            data_node->m_data_type = int_dt;
            REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, unsigned_int_dt});
          }
    
          SECTION("N -> N")
          {
            data_node->m_data_type = unsigned_int_dt;
            REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, unsigned_int_dt});
          }
    
          SECTION("B -> N")
          {
            data_node->m_data_type = bool_dt;
            REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, unsigned_int_dt});
          }
        }
    
        SECTION("-> B")
        {
          SECTION("B -> B")
          {
            data_node->m_data_type = bool_dt;
            REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, bool_dt});
          }
        }
    
        SECTION("-> tuple")
        {
          SECTION("B -> tuple(B)")
          {
            data_node->m_data_type = bool_dt;
            REQUIRE_NOTHROW(
              ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::build<ASTNodeDataType::tuple_t>(bool_dt)});
          }
    
          SECTION("B -> tuple(N)")
          {
            data_node->m_data_type = bool_dt;
            REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::build<ASTNodeDataType::tuple_t>(
                                                                          unsigned_int_dt)});
          }
    
          SECTION("N -> tuple(N)")
          {
            data_node->m_data_type = unsigned_int_dt;
            REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::build<ASTNodeDataType::tuple_t>(
                                                                          unsigned_int_dt)});
          }
    
          SECTION("Z -> tuple(N)")
          {
            data_node->m_data_type = int_dt;
            REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::build<ASTNodeDataType::tuple_t>(
                                                                          unsigned_int_dt)});
          }
    
          SECTION("B -> tuple(Z)")
          {
            data_node->m_data_type = bool_dt;
            REQUIRE_NOTHROW(
              ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::build<ASTNodeDataType::tuple_t>(int_dt)});
          }
    
          SECTION("N -> tuple(Z)")
          {
            data_node->m_data_type = unsigned_int_dt;
            REQUIRE_NOTHROW(
              ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::build<ASTNodeDataType::tuple_t>(int_dt)});
          }
    
          SECTION("Z -> tuple(Z)")
          {
            data_node->m_data_type = int_dt;
            REQUIRE_NOTHROW(
              ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::build<ASTNodeDataType::tuple_t>(int_dt)});
          }
    
          SECTION("B -> tuple(R)")
          {
            data_node->m_data_type = bool_dt;
            REQUIRE_NOTHROW(
              ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::build<ASTNodeDataType::tuple_t>(double_dt)});
          }
    
          SECTION("N -> tuple(R)")
          {
            data_node->m_data_type = unsigned_int_dt;
            REQUIRE_NOTHROW(
              ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::build<ASTNodeDataType::tuple_t>(double_dt)});
          }
    
          SECTION("Z -> tuple(R)")
          {
            data_node->m_data_type = int_dt;
            REQUIRE_NOTHROW(
              ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::build<ASTNodeDataType::tuple_t>(double_dt)});
          }
    
          SECTION("R -> tuple(R)")
          {
            data_node->m_data_type = double_dt;
            REQUIRE_NOTHROW(
              ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::build<ASTNodeDataType::tuple_t>(double_dt)});
          }
    
          SECTION("R^1 -> tuple(R^1)")
          {
            auto R1                = ASTNodeDataType::build<ASTNodeDataType::vector_t>(1);
            data_node->m_data_type = R1;
            REQUIRE_NOTHROW(
              ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::build<ASTNodeDataType::tuple_t>(R1)});
          }
    
          SECTION("R^2 -> tuple(R^2)")
          {
            auto R2                = ASTNodeDataType::build<ASTNodeDataType::vector_t>(2);
            data_node->m_data_type = R2;
            REQUIRE_NOTHROW(
              ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::build<ASTNodeDataType::tuple_t>(R2)});
          }
    
          SECTION("R^3 -> tuple(R^3)")
          {
            auto R3                = ASTNodeDataType::build<ASTNodeDataType::vector_t>(3);
            data_node->m_data_type = R3;
            REQUIRE_NOTHROW(
              ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::build<ASTNodeDataType::tuple_t>(R3)});
          }
    
          SECTION("string -> tuple(string)")
          {
            data_node->m_data_type = string_dt;
            REQUIRE_NOTHROW(
              ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::build<ASTNodeDataType::tuple_t>(string_dt)});
          }
    
          SECTION("type_id_t -> tuple(type_id_t)")
          {
            auto type_id           = ASTNodeDataType::build<ASTNodeDataType::type_id_t>("foo");
            data_node->m_data_type = type_id;
            REQUIRE_NOTHROW(
              ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::build<ASTNodeDataType::tuple_t>(type_id)});
          }
    
          SECTION("(B, B, B) -> tuple(B)")
          {
            data_node->m_data_type = list_dt;
            {
              std::unique_ptr list0_node = std::make_unique<ASTNode>();
              list0_node->m_data_type    = bool_dt;
              data_node->emplace_back(std::move(list0_node));
    
              std::unique_ptr list1_node = std::make_unique<ASTNode>();
              list1_node->m_data_type    = bool_dt;
              data_node->emplace_back(std::move(list1_node));
    
              std::unique_ptr list2_node = std::make_unique<ASTNode>();
              list2_node->m_data_type    = bool_dt;
              data_node->emplace_back(std::move(list2_node));
            }
            auto tuple_t = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(bool_dt);
            REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, tuple_t});
          }
    
          SECTION("(B, N, Z) -> tuple(N)")
          {
            data_node->m_data_type = list_dt;
            {
              std::unique_ptr list0_node = std::make_unique<ASTNode>();
              list0_node->m_data_type    = bool_dt;
              data_node->emplace_back(std::move(list0_node));
    
              std::unique_ptr list1_node = std::make_unique<ASTNode>();
              list1_node->m_data_type    = unsigned_int_dt;
              data_node->emplace_back(std::move(list1_node));
    
              std::unique_ptr list2_node = std::make_unique<ASTNode>();
              list2_node->m_data_type    = int_dt;
              data_node->emplace_back(std::move(list2_node));
            }
            auto tuple_t = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(unsigned_int_dt);
            REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, tuple_t});
          }
    
          SECTION("(B, N, Z) -> tuple(Z)")
          {
            data_node->m_data_type = list_dt;
            {
              std::unique_ptr list0_node = std::make_unique<ASTNode>();
              list0_node->m_data_type    = bool_dt;
              data_node->emplace_back(std::move(list0_node));
    
              std::unique_ptr list1_node = std::make_unique<ASTNode>();
              list1_node->m_data_type    = unsigned_int_dt;
              data_node->emplace_back(std::move(list1_node));
    
              std::unique_ptr list2_node = std::make_unique<ASTNode>();
              list2_node->m_data_type    = int_dt;
              data_node->emplace_back(std::move(list2_node));
            }
            auto tuple_t = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(int_dt);
            REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, tuple_t});
          }
    
          SECTION("(R, N, Z) -> tuple(R)")
          {
            data_node->m_data_type = list_dt;
            {
              std::unique_ptr list0_node = std::make_unique<ASTNode>();
              list0_node->m_data_type    = double_dt;
              data_node->emplace_back(std::move(list0_node));
    
              std::unique_ptr list1_node = std::make_unique<ASTNode>();
              list1_node->m_data_type    = unsigned_int_dt;
              data_node->emplace_back(std::move(list1_node));
    
              std::unique_ptr list2_node = std::make_unique<ASTNode>();
              list2_node->m_data_type    = int_dt;
              data_node->emplace_back(std::move(list2_node));
            }
            auto tuple_t = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(double_dt);
            REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, tuple_t});
          }
    
          SECTION("(R^1, R^1) -> tuple(R^1)")
          {
            auto R1                = ASTNodeDataType::build<ASTNodeDataType::vector_t>(1);
            data_node->m_data_type = list_dt;
            {
              std::unique_ptr list0_node = std::make_unique<ASTNode>();
              list0_node->m_data_type    = R1;
              data_node->emplace_back(std::move(list0_node));
    
              std::unique_ptr list1_node = std::make_unique<ASTNode>();
              list1_node->m_data_type    = R1;
              data_node->emplace_back(std::move(list1_node));
            }
            auto tuple_t = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(R1);
            REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, tuple_t});
          }
    
          SECTION("(R^2, R^2, R^2) -> tuple(R^2)")
          {
            auto R2                = ASTNodeDataType::build<ASTNodeDataType::vector_t>(2);
            data_node->m_data_type = list_dt;
            {
              std::unique_ptr list0_node = std::make_unique<ASTNode>();
              list0_node->m_data_type    = R2;
              data_node->emplace_back(std::move(list0_node));
    
              std::unique_ptr list1_node = std::make_unique<ASTNode>();
              list1_node->m_data_type    = R2;
              data_node->emplace_back(std::move(list1_node));
    
              std::unique_ptr list2_node = std::make_unique<ASTNode>();
              list2_node->m_data_type    = R2;
              data_node->emplace_back(std::move(list2_node));
            }
            auto tuple_t = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(R2);
            REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, tuple_t});
          }
    
          SECTION("(R^3, R^3) -> tuple(R^3)")
          {
            auto R3                = ASTNodeDataType::build<ASTNodeDataType::vector_t>(2);
            data_node->m_data_type = list_dt;
            {
              std::unique_ptr list0_node = std::make_unique<ASTNode>();
              list0_node->m_data_type    = R3;
              data_node->emplace_back(std::move(list0_node));
    
              std::unique_ptr list1_node = std::make_unique<ASTNode>();
              list1_node->m_data_type    = R3;
              data_node->emplace_back(std::move(list1_node));
            }
            auto tuple_t = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(R3);
            REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, tuple_t});
          }
    
          SECTION("(string, string) -> tuple(string)")
          {
            auto str_t             = string_dt;
            data_node->m_data_type = list_dt;
            {
              std::unique_ptr list0_node = std::make_unique<ASTNode>();
              list0_node->m_data_type    = str_t;
              data_node->emplace_back(std::move(list0_node));
    
              std::unique_ptr list1_node = std::make_unique<ASTNode>();
              list1_node->m_data_type    = str_t;
              data_node->emplace_back(std::move(list1_node));
            }
            auto tuple_t = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(str_t);
            REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, tuple_t});
          }
    
          SECTION("(type_id_t, type_id_t) -> tuple(type_id_t)")
          {
            auto type_id           = ASTNodeDataType::build<ASTNodeDataType::type_id_t>("foo");
            data_node->m_data_type = list_dt;
            {
              std::unique_ptr list0_node = std::make_unique<ASTNode>();
              list0_node->m_data_type    = type_id;
              data_node->emplace_back(std::move(list0_node));
    
              std::unique_ptr list1_node = std::make_unique<ASTNode>();
              list1_node->m_data_type    = type_id;
              data_node->emplace_back(std::move(list1_node));
            }
            auto tuple_t = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(type_id);
            REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, tuple_t});
          }
    
          SECTION("tuple(B) -> tuple(B)")
          {
            data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(bool_dt);
            auto tuple_t           = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(bool_dt);
    
            REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, tuple_t});
          }
    
          SECTION("tuple(B) -> tuple(N)")
          {
            data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(bool_dt);
            auto tuple_t           = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(unsigned_int_dt);
    
            REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, tuple_t});
          }
    
          SECTION("tuple(Z) -> tuple(N)")
          {
            data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(int_dt);
            auto tuple_t           = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(unsigned_int_dt);
    
            REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, tuple_t});
          }
    
          SECTION("tuple(N) -> tuple(N)")
          {
            data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(unsigned_int_dt);
            auto tuple_t           = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(unsigned_int_dt);
    
            REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, tuple_t});
          }
    
          SECTION("tuple(B) -> tuple(Z)")
          {
            data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(bool_dt);
            auto tuple_t           = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(int_dt);
    
            REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, tuple_t});
          }
    
          SECTION("tuple(N) -> tuple(Z)")
          {
            data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(unsigned_int_dt);
            auto tuple_t           = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(int_dt);
    
            REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, tuple_t});
          }
    
          SECTION("tuple(Z) -> tuple(Z)")
          {
            data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(int_dt);
            auto tuple_t           = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(int_dt);
    
            REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, tuple_t});
          }
    
          SECTION("tuple(B) -> tuple(R)")
          {
            data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(bool_dt);
            auto tuple_t           = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(double_dt);
    
            REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, tuple_t});
          }
    
          SECTION("tuple(Z) -> tuple(R)")
          {
            data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(int_dt);
            auto tuple_t           = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(double_dt);
    
            REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, tuple_t});
          }
    
          SECTION("tuple(N) -> tuple(R)")
          {
            data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(unsigned_int_dt);
            auto tuple_t           = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(double_dt);
    
            REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, tuple_t});
          }
    
          SECTION("tuple(R) -> tuple(R)")
          {
            data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(double_dt);
            auto tuple_t           = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(double_dt);
    
            REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, tuple_t});
          }
    
          SECTION("tuple(B) -> tuple(string)")
          {
            data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(bool_dt);
            auto tuple_t           = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(string_dt);
    
            REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, tuple_t});
          }
    
          SECTION("tuple(Z) -> tuple(string)")
          {
            data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(int_dt);
            auto tuple_t           = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(string_dt);
    
            REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, tuple_t});
          }
    
          SECTION("tuple(N) -> tuple(string)")
          {
            data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(unsigned_int_dt);
            auto tuple_t           = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(string_dt);
    
            REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, tuple_t});
          }
    
          SECTION("tuple(R) -> tuple(string)")
          {
            data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(double_dt);
            auto tuple_t           = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(string_dt);
    
            REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, tuple_t});
          }
    
          SECTION("tuple(string) -> tuple(string)")
          {
            data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(string_dt);
            auto tuple_t           = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(string_dt);
    
            REQUIRE_NOTHROW(ASTNodeNaturalConversionChecker{*data_node, tuple_t});
          }
    
          SECTION("tuple(R^1) -> tuple(R^1)")
          {
            auto R1                = ASTNodeDataType::build<ASTNodeDataType::vector_t>(1);
            data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(R1);
            REQUIRE_NOTHROW(
              ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::build<ASTNodeDataType::tuple_t>(R1)});
          }
    
          SECTION("tuple(R^2) -> tuple(R^2)")
          {
            auto R2                = ASTNodeDataType::build<ASTNodeDataType::vector_t>(2);
            data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(R2);
            REQUIRE_NOTHROW(
              ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::build<ASTNodeDataType::tuple_t>(R2)});
          }
    
          SECTION("tuple(R^3) -> tuple(R^3)")
          {
            auto R3                = ASTNodeDataType::build<ASTNodeDataType::vector_t>(3);
            data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(R3);
            REQUIRE_NOTHROW(
              ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::build<ASTNodeDataType::tuple_t>(R3)});
          }
    
          SECTION("tuple(type_id_t) -> tuple(type_id_t)")
          {
            auto type_id           = ASTNodeDataType::build<ASTNodeDataType::type_id_t>("foo");
            data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(type_id);
            REQUIRE_NOTHROW(
              ASTNodeNaturalConversionChecker{*data_node, ASTNodeDataType::build<ASTNodeDataType::tuple_t>(type_id)});
          }
        }
      }
    
      SECTION("Invalid conversions")
      {
        std::unique_ptr data_node = std::make_unique<ASTNode>();
    
        SECTION("-> R^dxd")
        {
          SECTION("R^2x2 -> R^1x2")
          {
            data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::matrix_t>(2, 2);
            REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                 ASTNodeDataType::build<ASTNodeDataType::matrix_t>(1, 1)}),
                                "invalid implicit conversion: R^2x2 -> R^1x1");
          }
    
          SECTION("R^3x3 -> R^1x1")
          {
            data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::matrix_t>(3, 3);
            REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                 ASTNodeDataType::build<ASTNodeDataType::matrix_t>(1, 1)}),
                                "invalid implicit conversion: R^3x3 -> R^1x1");
          }
    
          SECTION("R^1x1 -> R^2x2")
          {
            data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::matrix_t>(1, 1);
            REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                 ASTNodeDataType::build<ASTNodeDataType::matrix_t>(2, 2)}),
                                "invalid implicit conversion: R^1x1 -> R^2x2");
          }
    
          SECTION("R^3x3 -> R^2x2")
          {
            data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::matrix_t>(3, 3);
            REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                 ASTNodeDataType::build<ASTNodeDataType::matrix_t>(2, 2)}),
                                "invalid implicit conversion: R^3x3 -> R^2x2");
          }
    
          SECTION("R^1x1 -> R^3x3")
          {
            data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::matrix_t>(1, 1);
            REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                 ASTNodeDataType::build<ASTNodeDataType::matrix_t>(3, 3)}),
                                "invalid implicit conversion: R^1x1 -> R^3x3");
          }
    
          SECTION("R^2x2 -> R^3x3")
          {
            data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::matrix_t>(2, 2);
            REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                 ASTNodeDataType::build<ASTNodeDataType::matrix_t>(3, 3)}),
                                "invalid implicit conversion: R^2x2 -> R^3x3");
          }
    
          SECTION("list1 -> R^dxd")
          {
            data_node->m_data_type =
              ASTNodeDataType::build<ASTNodeDataType::list_t>({std::make_shared<const ASTNodeDataType>(double_dt)});
            {
              std::unique_ptr list0_node = std::make_unique<ASTNode>();
              list0_node->m_data_type    = double_dt;
              data_node->emplace_back(std::move(list0_node));
            }
    
            SECTION("d=2")
            {
              REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                   ASTNodeDataType::build<ASTNodeDataType::matrix_t>(2,
                                                                                                                     2)}),
                                  "incompatible dimensions in affectation: expecting 4, but provided 1");
            }
    
            SECTION("d=3")
            {
              REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                   ASTNodeDataType::build<ASTNodeDataType::matrix_t>(3,
                                                                                                                     3)}),
                                  "incompatible dimensions in affectation: expecting 9, but provided 1");
            }
          }
    
          SECTION("list2 -> R^dxd")
          {
            data_node->m_data_type = list_dt;
            {
              std::unique_ptr list0_node = std::make_unique<ASTNode>();
              list0_node->m_data_type    = double_dt;
              data_node->emplace_back(std::move(list0_node));
    
              std::unique_ptr list1_node = std::make_unique<ASTNode>();
              list1_node->m_data_type    = unsigned_int_dt;
              data_node->emplace_back(std::move(list1_node));
            }
    
            SECTION("d=1")
            {
              REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                   ASTNodeDataType::build<ASTNodeDataType::matrix_t>(1,
                                                                                                                     1)}),
                                  "incompatible dimensions in affectation: expecting 1, but provided 2");
            }
    
            SECTION("d=3")
            {
              REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                   ASTNodeDataType::build<ASTNodeDataType::matrix_t>(3,
                                                                                                                     3)}),
                                  "incompatible dimensions in affectation: expecting 9, but provided 2");
            }
          }
    
          SECTION("list3 -> R^dxd")
          {
            data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::list_t>(
              {std::make_shared<const ASTNodeDataType>(double_dt), std::make_shared<const ASTNodeDataType>(unsigned_int_dt),
               std::make_shared<const ASTNodeDataType>(int_dt)});
            {
              std::unique_ptr list0_node = std::make_unique<ASTNode>();
              list0_node->m_data_type    = double_dt;
              data_node->emplace_back(std::move(list0_node));
    
              std::unique_ptr list1_node = std::make_unique<ASTNode>();
              list1_node->m_data_type    = unsigned_int_dt;
              data_node->emplace_back(std::move(list1_node));
    
              std::unique_ptr list2_node = std::make_unique<ASTNode>();
              list2_node->m_data_type    = int_dt;
              data_node->emplace_back(std::move(list2_node));
            }
    
            SECTION("d=1")
            {
              REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                   ASTNodeDataType::build<ASTNodeDataType::matrix_t>(1,
                                                                                                                     1)}),
                                  "incompatible dimensions in affectation: expecting 1, but provided 3");
            }
    
            SECTION("d=2")
            {
              REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                   ASTNodeDataType::build<ASTNodeDataType::matrix_t>(2,
                                                                                                                     2)}),
                                  "incompatible dimensions in affectation: expecting 4, but provided 3");
            }
          }
    
          SECTION("tuple -> R^dxd")
          {
            SECTION("tuple(N) -> R^1x1")
            {
              data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(unsigned_int_dt);
              REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                   ASTNodeDataType::build<ASTNodeDataType::matrix_t>(1,
                                                                                                                     1)}),
                                  "invalid implicit conversion: tuple(N) -> R^1x1");
            }
    
            SECTION("tuple(R) -> R^1x1")
            {
              data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(double_dt);
              REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                   ASTNodeDataType::build<ASTNodeDataType::matrix_t>(1,
                                                                                                                     1)}),
                                  "invalid implicit conversion: tuple(R) -> R^1x1");
            }
    
            SECTION("tuple(R) -> R^2x2")
            {
              data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(double_dt);
              REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                   ASTNodeDataType::build<ASTNodeDataType::matrix_t>(2,
                                                                                                                     2)}),
                                  "invalid implicit conversion: tuple(R) -> R^2x2");
            }
    
            SECTION("tuple(B) -> R^2x2")
            {
              data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(bool_dt);
              REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                   ASTNodeDataType::build<ASTNodeDataType::matrix_t>(2,
                                                                                                                     2)}),
                                  "invalid implicit conversion: tuple(B) -> R^2x2");
            }
    
            SECTION("tuple(Z) -> R^3x2")
            {
              data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(int_dt);
              REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                   ASTNodeDataType::build<ASTNodeDataType::matrix_t>(3,
                                                                                                                     3)}),
                                  "invalid implicit conversion: tuple(Z) -> R^3x3");
            }
    
            SECTION("tuple(R) -> R^3x3")
            {
              data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(double_dt);
              REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                   ASTNodeDataType::build<ASTNodeDataType::matrix_t>(3,
                                                                                                                     3)}),
                                  "invalid implicit conversion: tuple(R) -> R^3x3");
            }
    
            SECTION("tuple(R^1) -> tuple(R^3x3)")
            {
              auto tuple_R1 =
                ASTNodeDataType::build<ASTNodeDataType::tuple_t>(ASTNodeDataType::build<ASTNodeDataType::vector_t>(1));
              auto tuple_R3x3 =
                ASTNodeDataType::build<ASTNodeDataType::tuple_t>(ASTNodeDataType::build<ASTNodeDataType::matrix_t>(3, 3));
              data_node->m_data_type = tuple_R1;
              REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, tuple_R3x3}),
                                  "invalid implicit conversion: R^1 -> R^3x3");
            }
    
            SECTION("tuple(R^2) -> tuple(R^3x3)")
            {
              auto tuple_R2 =
                ASTNodeDataType::build<ASTNodeDataType::tuple_t>(ASTNodeDataType::build<ASTNodeDataType::vector_t>(2));
              auto tuple_R3x3 =
                ASTNodeDataType::build<ASTNodeDataType::tuple_t>(ASTNodeDataType::build<ASTNodeDataType::matrix_t>(3, 3));
              data_node->m_data_type = tuple_R2;
              REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, tuple_R3x3}),
                                  "invalid implicit conversion: R^2 -> R^3x3");
            }
    
            SECTION("tuple(R^2) -> tuple(R^1x1)")
            {
              auto tuple_R1x1 =
                ASTNodeDataType::build<ASTNodeDataType::tuple_t>(ASTNodeDataType::build<ASTNodeDataType::matrix_t>(1, 1));
              auto tuple_R2 =
                ASTNodeDataType::build<ASTNodeDataType::tuple_t>(ASTNodeDataType::build<ASTNodeDataType::vector_t>(2));
              data_node->m_data_type = tuple_R2;
              REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, tuple_R1x1}),
                                  "invalid implicit conversion: R^2 -> R^1x1");
            }
    
            SECTION("tuple(R^1x1) -> tuple(R^3x3)")
            {
              auto tuple_R1x1 =
                ASTNodeDataType::build<ASTNodeDataType::tuple_t>(ASTNodeDataType::build<ASTNodeDataType::matrix_t>(1, 1));
              auto tuple_R3x3 =
                ASTNodeDataType::build<ASTNodeDataType::tuple_t>(ASTNodeDataType::build<ASTNodeDataType::matrix_t>(3, 3));
              data_node->m_data_type = tuple_R1x1;
              REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, tuple_R3x3}),
                                  "invalid implicit conversion: R^1x1 -> R^3x3");
            }
    
            SECTION("tuple(R^2x2) -> tuple(R^3x3)")
            {
              auto tuple_R2x2 =
                ASTNodeDataType::build<ASTNodeDataType::tuple_t>(ASTNodeDataType::build<ASTNodeDataType::matrix_t>(2, 2));
              auto tuple_R3x3 =
                ASTNodeDataType::build<ASTNodeDataType::tuple_t>(ASTNodeDataType::build<ASTNodeDataType::matrix_t>(3, 3));
              data_node->m_data_type = tuple_R2x2;
              REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, tuple_R3x3}),
                                  "invalid implicit conversion: R^2x2 -> R^3x3");
            }
    
            SECTION("tuple(R^2x2) -> tuple(R^1x1)")
            {
              auto tuple_R1x1 =
                ASTNodeDataType::build<ASTNodeDataType::tuple_t>(ASTNodeDataType::build<ASTNodeDataType::matrix_t>(1, 1));
              auto tuple_R2x2 =
                ASTNodeDataType::build<ASTNodeDataType::tuple_t>(ASTNodeDataType::build<ASTNodeDataType::matrix_t>(2, 2));
              data_node->m_data_type = tuple_R2x2;
              REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, tuple_R1x1}),
                                  "invalid implicit conversion: R^2x2 -> R^1x1");
            }
          }
    
          SECTION("R -> R^dxd")
          {
            data_node->m_data_type = double_dt;
    
            SECTION("d=1")
            {
              REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                   ASTNodeDataType::build<ASTNodeDataType::matrix_t>(1,
                                                                                                                     1)}),
                                  "invalid implicit conversion: R -> R^1x1");
            }
    
            SECTION("d=2")
            {
              REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                   ASTNodeDataType::build<ASTNodeDataType::matrix_t>(2,
                                                                                                                     2)}),
                                  "invalid implicit conversion: R -> R^2x2");
            }
    
            SECTION("d=3")
            {
              REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                   ASTNodeDataType::build<ASTNodeDataType::matrix_t>(3,
                                                                                                                     3)}),
                                  "invalid implicit conversion: R -> R^3x3");
            }
          }
    
          SECTION("Z -> R^dxd (non-zero)")
          {
            data_node->m_data_type = int_dt;
            data_node->set_type<language::integer>();
            data_node->source  = "1";
            auto& source       = data_node->source;
            data_node->m_begin = TAO_PEGTL_NAMESPACE::internal::iterator{&source[0]};
            data_node->m_end   = TAO_PEGTL_NAMESPACE::internal::iterator{&source[source.size()]};
    
            SECTION("d=1")
            {
              REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                   ASTNodeDataType::build<ASTNodeDataType::matrix_t>(1,
                                                                                                                     1)}),
                                  "invalid implicit conversion: Z -> R^1x1");
            }
    
            SECTION("d=2")
            {
              REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                   ASTNodeDataType::build<ASTNodeDataType::matrix_t>(2,
                                                                                                                     2)}),
                                  "invalid implicit conversion: Z -> R^2x2");
            }
    
            SECTION("d=3")
            {
              REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                   ASTNodeDataType::build<ASTNodeDataType::matrix_t>(3,
                                                                                                                     3)}),
                                  "invalid implicit conversion: Z -> R^3x3");
            }
          }
    
          SECTION("N -> R^dxd")
          {
            data_node->m_data_type = unsigned_int_dt;
    
            SECTION("d=1")
            {
              REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                   ASTNodeDataType::build<ASTNodeDataType::matrix_t>(1,
                                                                                                                     1)}),
                                  "invalid implicit conversion: N -> R^1x1");
            }
    
            SECTION("d=2")
            {
              REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                   ASTNodeDataType::build<ASTNodeDataType::matrix_t>(2,
                                                                                                                     2)}),
                                  "invalid implicit conversion: N -> R^2x2");
            }
    
            SECTION("d=3")
            {
              REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                   ASTNodeDataType::build<ASTNodeDataType::matrix_t>(3,
                                                                                                                     3)}),
                                  "invalid implicit conversion: N -> R^3x3");
            }
          }
    
          SECTION("B -> R^dxd")
          {
            data_node->m_data_type = bool_dt;
    
            SECTION("d=1")
            {
              REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                   ASTNodeDataType::build<ASTNodeDataType::matrix_t>(1,
                                                                                                                     1)}),
                                  "invalid implicit conversion: B -> R^1x1");
            }
    
            SECTION("d=2")
            {
              REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                   ASTNodeDataType::build<ASTNodeDataType::matrix_t>(2,
                                                                                                                     2)}),
                                  "invalid implicit conversion: B -> R^2x2");
            }
    
            SECTION("d=3")
            {
              REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                   ASTNodeDataType::build<ASTNodeDataType::matrix_t>(3,
                                                                                                                     3)}),
                                  "invalid implicit conversion: B -> R^3x3");
            }
          }
    
          SECTION("string -> R^dxd")
          {
            data_node->m_data_type = string_dt;
    
            SECTION("d=1")
            {
              REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                   ASTNodeDataType::build<ASTNodeDataType::matrix_t>(1,
                                                                                                                     1)}),
                                  "invalid implicit conversion: string -> R^1x1");
            }
    
            SECTION("d=2")
            {
              REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                   ASTNodeDataType::build<ASTNodeDataType::matrix_t>(2,
                                                                                                                     2)}),
                                  "invalid implicit conversion: string -> R^2x2");
            }
    
            SECTION("d=3")
            {
              REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                   ASTNodeDataType::build<ASTNodeDataType::matrix_t>(3,
                                                                                                                     3)}),
                                  "invalid implicit conversion: string -> R^3x3");
            }
          }
        }
    
        SECTION("-> R^d")
        {
          SECTION("R^2 -> R^1")
          {
            data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::vector_t>(2);
            REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                 ASTNodeDataType::build<ASTNodeDataType::vector_t>(1)}),
                                "invalid implicit conversion: R^2 -> R^1");
          }
    
          SECTION("R^3 -> R^1")
          {
            data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::vector_t>(3);
            REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                 ASTNodeDataType::build<ASTNodeDataType::vector_t>(1)}),
                                "invalid implicit conversion: R^3 -> R^1");
          }
    
          SECTION("R^1 -> R^2")
          {
            data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::vector_t>(1);
            REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                 ASTNodeDataType::build<ASTNodeDataType::vector_t>(2)}),
                                "invalid implicit conversion: R^1 -> R^2");
          }
    
          SECTION("R^3 -> R^2")
          {
            data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::vector_t>(3);
            REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                 ASTNodeDataType::build<ASTNodeDataType::vector_t>(2)}),
                                "invalid implicit conversion: R^3 -> R^2");
          }
    
          SECTION("R^1 -> R^3")
          {
            data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::vector_t>(1);
            REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                 ASTNodeDataType::build<ASTNodeDataType::vector_t>(3)}),
                                "invalid implicit conversion: R^1 -> R^3");
          }
    
          SECTION("R^2 -> R^3")
          {
            data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::vector_t>(2);
            REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                 ASTNodeDataType::build<ASTNodeDataType::vector_t>(3)}),
                                "invalid implicit conversion: R^2 -> R^3");
          }
    
          SECTION("list1 -> R^d")
          {
            data_node->m_data_type =
              ASTNodeDataType::build<ASTNodeDataType::list_t>({std::make_shared<const ASTNodeDataType>(double_dt)});
            {
              std::unique_ptr list0_node = std::make_unique<ASTNode>();
              list0_node->m_data_type    = double_dt;
              data_node->emplace_back(std::move(list0_node));
            }
    
            SECTION("d=2")
            {
              REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                   ASTNodeDataType::build<ASTNodeDataType::vector_t>(2)}),
                                  "incompatible dimensions in affectation: expecting 2, but provided 1");
            }
    
            SECTION("d=3")
            {
              REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                   ASTNodeDataType::build<ASTNodeDataType::vector_t>(3)}),
                                  "incompatible dimensions in affectation: expecting 3, but provided 1");
            }
          }
    
          SECTION("list2 -> R^d")
          {
            data_node->m_data_type = list_dt;
            {
              std::unique_ptr list0_node = std::make_unique<ASTNode>();
              list0_node->m_data_type    = double_dt;
              data_node->emplace_back(std::move(list0_node));
    
              std::unique_ptr list1_node = std::make_unique<ASTNode>();
              list1_node->m_data_type    = unsigned_int_dt;
              data_node->emplace_back(std::move(list1_node));
            }
    
            SECTION("d=1")
            {
              REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                   ASTNodeDataType::build<ASTNodeDataType::vector_t>(1)}),
                                  "incompatible dimensions in affectation: expecting 1, but provided 2");
            }
    
            SECTION("d=3")
            {
              REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                   ASTNodeDataType::build<ASTNodeDataType::vector_t>(3)}),
                                  "incompatible dimensions in affectation: expecting 3, but provided 2");
            }
          }
    
          SECTION("list3 -> R^d")
          {
            data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::list_t>(
              {std::make_shared<const ASTNodeDataType>(double_dt), std::make_shared<const ASTNodeDataType>(unsigned_int_dt),
               std::make_shared<const ASTNodeDataType>(int_dt)});
            {
              std::unique_ptr list0_node = std::make_unique<ASTNode>();
              list0_node->m_data_type    = double_dt;
              data_node->emplace_back(std::move(list0_node));
    
              std::unique_ptr list1_node = std::make_unique<ASTNode>();
              list1_node->m_data_type    = unsigned_int_dt;
              data_node->emplace_back(std::move(list1_node));
    
              std::unique_ptr list2_node = std::make_unique<ASTNode>();
              list2_node->m_data_type    = int_dt;
              data_node->emplace_back(std::move(list2_node));
            }
    
            SECTION("d=1")
            {
              REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                   ASTNodeDataType::build<ASTNodeDataType::vector_t>(1)}),
                                  "incompatible dimensions in affectation: expecting 1, but provided 3");
            }
    
            SECTION("d=2")
            {
              REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                   ASTNodeDataType::build<ASTNodeDataType::vector_t>(2)}),
                                  "incompatible dimensions in affectation: expecting 2, but provided 3");
            }
          }
    
          SECTION("tuple -> R^d")
          {
            SECTION("tuple(N) -> R^1")
            {
              data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(unsigned_int_dt);
              REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                   ASTNodeDataType::build<ASTNodeDataType::vector_t>(1)}),
                                  "invalid implicit conversion: tuple(N) -> R^1");
            }
    
            SECTION("tuple(R) -> R^1")
            {
              data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(double_dt);
              REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                   ASTNodeDataType::build<ASTNodeDataType::vector_t>(1)}),
                                  "invalid implicit conversion: tuple(R) -> R^1");
            }
    
            SECTION("tuple(R) -> R^2")
            {
              data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(double_dt);
              REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                   ASTNodeDataType::build<ASTNodeDataType::vector_t>(2)}),
                                  "invalid implicit conversion: tuple(R) -> R^2");
            }
    
            SECTION("tuple(B) -> R^2")
            {
              data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(bool_dt);
              REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                   ASTNodeDataType::build<ASTNodeDataType::vector_t>(2)}),
                                  "invalid implicit conversion: tuple(B) -> R^2");
            }
    
            SECTION("tuple(Z) -> R^3")
            {
              data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(int_dt);
              REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                   ASTNodeDataType::build<ASTNodeDataType::vector_t>(3)}),
                                  "invalid implicit conversion: tuple(Z) -> R^3");
            }
    
            SECTION("tuple(R) -> R^3")
            {
              data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(double_dt);
              REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                   ASTNodeDataType::build<ASTNodeDataType::vector_t>(3)}),
                                  "invalid implicit conversion: tuple(R) -> R^3");
            }
    
            SECTION("tuple(R^1x1) -> tuple(R^3)")
            {
              auto tuple_R1x1 =
                ASTNodeDataType::build<ASTNodeDataType::tuple_t>(ASTNodeDataType::build<ASTNodeDataType::matrix_t>(1, 1));
              auto tuple_R3 =
                ASTNodeDataType::build<ASTNodeDataType::tuple_t>(ASTNodeDataType::build<ASTNodeDataType::vector_t>(3));
              data_node->m_data_type = tuple_R1x1;
              REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, tuple_R3}),
                                  "invalid implicit conversion: R^1x1 -> R^3");
            }
    
            SECTION("tuple(R^2x2) -> tuple(R^3)")
            {
              auto tuple_R2x2 =
                ASTNodeDataType::build<ASTNodeDataType::tuple_t>(ASTNodeDataType::build<ASTNodeDataType::matrix_t>(2, 2));
              auto tuple_R3 =
                ASTNodeDataType::build<ASTNodeDataType::tuple_t>(ASTNodeDataType::build<ASTNodeDataType::vector_t>(3));
              data_node->m_data_type = tuple_R2x2;
              REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, tuple_R3}),
                                  "invalid implicit conversion: R^2x2 -> R^3");
            }
    
            SECTION("tuple(R^2x2) -> tuple(R^1)")
            {
              auto tuple_R1 =
                ASTNodeDataType::build<ASTNodeDataType::tuple_t>(ASTNodeDataType::build<ASTNodeDataType::vector_t>(1));
              auto tuple_R2x2 =
                ASTNodeDataType::build<ASTNodeDataType::tuple_t>(ASTNodeDataType::build<ASTNodeDataType::matrix_t>(2, 2));
              data_node->m_data_type = tuple_R2x2;
              REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, tuple_R1}),
                                  "invalid implicit conversion: R^2x2 -> R^1");
            }
    
            SECTION("tuple(R^1) -> tuple(R^3)")
            {
              auto tuple_R1 =
                ASTNodeDataType::build<ASTNodeDataType::tuple_t>(ASTNodeDataType::build<ASTNodeDataType::vector_t>(1));
              auto tuple_R3 =
                ASTNodeDataType::build<ASTNodeDataType::tuple_t>(ASTNodeDataType::build<ASTNodeDataType::vector_t>(3));
              data_node->m_data_type = tuple_R1;
              REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, tuple_R3}),
                                  "invalid implicit conversion: R^1 -> R^3");
            }
    
            SECTION("tuple(R^2) -> tuple(R^3)")
            {
              auto tuple_R2 =
                ASTNodeDataType::build<ASTNodeDataType::tuple_t>(ASTNodeDataType::build<ASTNodeDataType::vector_t>(2));
              auto tuple_R3 =
                ASTNodeDataType::build<ASTNodeDataType::tuple_t>(ASTNodeDataType::build<ASTNodeDataType::vector_t>(3));
              data_node->m_data_type = tuple_R2;
              REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, tuple_R3}),
                                  "invalid implicit conversion: R^2 -> R^3");
            }
    
            SECTION("tuple(R^2) -> tuple(R^1)")
            {
              auto tuple_R1 =
                ASTNodeDataType::build<ASTNodeDataType::tuple_t>(ASTNodeDataType::build<ASTNodeDataType::vector_t>(1));
              auto tuple_R2 =
                ASTNodeDataType::build<ASTNodeDataType::tuple_t>(ASTNodeDataType::build<ASTNodeDataType::vector_t>(2));
              data_node->m_data_type = tuple_R2;
              REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, tuple_R1}),
                                  "invalid implicit conversion: R^2 -> R^1");
            }
    
            SECTION("tuple(R) -> tuple(Z)")
            {
              auto tuple_R           = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(double_dt);
              auto tuple_Z           = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(int_dt);
              data_node->m_data_type = tuple_R;
              REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, tuple_Z}),
                                  "invalid implicit conversion: R -> Z");
            }
    
            SECTION("tuple(R) -> tuple(R^1)")
            {
              auto tuple_R = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(double_dt);
              auto tuple_R1 =
                ASTNodeDataType::build<ASTNodeDataType::tuple_t>(ASTNodeDataType::build<ASTNodeDataType::vector_t>(1));
              data_node->m_data_type = tuple_R;
              REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, tuple_R1}),
                                  "invalid implicit conversion: R -> R^1");
            }
    
            SECTION("tuple(string) -> tuple(R)")
            {
              auto tuple_string      = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(string_dt);
              auto tuple_R           = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(double_dt);
              data_node->m_data_type = tuple_string;
              REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, tuple_R}),
                                  "invalid implicit conversion: string -> R");
            }
    
            SECTION("tuple(type_id) -> tuple(R)")
            {
              auto type_id = ASTNodeDataType::build<ASTNodeDataType::type_id_t>("foo");
    
              auto tuple_type_id     = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(type_id);
              auto tuple_R           = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(double_dt);
              data_node->m_data_type = tuple_type_id;
              REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, tuple_R}),
                                  "invalid implicit conversion: foo -> R");
            }
    
            SECTION("tuple(type_id) -> tuple(R)")
            {
              auto type_id0 = ASTNodeDataType::build<ASTNodeDataType::type_id_t>("foo");
              auto type_id1 = ASTNodeDataType::build<ASTNodeDataType::type_id_t>("bar");
    
              auto tuple_type_id0    = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(type_id0);
              auto tuple_type_id1    = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(type_id1);
              data_node->m_data_type = tuple_type_id0;
              REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, tuple_type_id1}),
                                  "invalid implicit conversion: foo -> bar");
            }
          }
    
          SECTION("R -> R^d")
          {
            data_node->m_data_type = double_dt;
    
            SECTION("d=1")
            {
              REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                   ASTNodeDataType::build<ASTNodeDataType::vector_t>(1)}),
                                  "invalid implicit conversion: R -> R^1");
            }
    
            SECTION("d=2")
            {
              REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                   ASTNodeDataType::build<ASTNodeDataType::vector_t>(2)}),
                                  "invalid implicit conversion: R -> R^2");
            }
    
            SECTION("d=3")
            {
              REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                   ASTNodeDataType::build<ASTNodeDataType::vector_t>(3)}),
                                  "invalid implicit conversion: R -> R^3");
            }
          }
    
          SECTION("Z -> R^d (non-zero)")
          {
            data_node->m_data_type = int_dt;
            data_node->set_type<language::integer>();
            data_node->source  = "1";
            auto& source       = data_node->source;
            data_node->m_begin = TAO_PEGTL_NAMESPACE::internal::iterator{&source[0]};
            data_node->m_end   = TAO_PEGTL_NAMESPACE::internal::iterator{&source[source.size()]};
    
            SECTION("d=1")
            {
              REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                   ASTNodeDataType::build<ASTNodeDataType::vector_t>(1)}),
                                  "invalid implicit conversion: Z -> R^1");
            }
    
            SECTION("d=2")
            {
              REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                   ASTNodeDataType::build<ASTNodeDataType::vector_t>(2)}),
                                  "invalid implicit conversion: Z -> R^2");
            }
    
            SECTION("d=3")
            {
              REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                   ASTNodeDataType::build<ASTNodeDataType::vector_t>(3)}),
                                  "invalid implicit conversion: Z -> R^3");
            }
          }
    
          SECTION("N -> R^d")
          {
            data_node->m_data_type = unsigned_int_dt;
    
            SECTION("d=1")
            {
              REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                   ASTNodeDataType::build<ASTNodeDataType::vector_t>(1)}),
                                  "invalid implicit conversion: N -> R^1");
            }
    
            SECTION("d=2")
            {
              REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                   ASTNodeDataType::build<ASTNodeDataType::vector_t>(2)}),
                                  "invalid implicit conversion: N -> R^2");
            }
    
            SECTION("d=3")
            {
              REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                   ASTNodeDataType::build<ASTNodeDataType::vector_t>(3)}),
                                  "invalid implicit conversion: N -> R^3");
            }
          }
    
          SECTION("B -> R^d")
          {
            data_node->m_data_type = bool_dt;
    
            SECTION("d=1")
            {
              REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                   ASTNodeDataType::build<ASTNodeDataType::vector_t>(1)}),
                                  "invalid implicit conversion: B -> R^1");
            }
    
            SECTION("d=2")
            {
              REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                   ASTNodeDataType::build<ASTNodeDataType::vector_t>(2)}),
                                  "invalid implicit conversion: B -> R^2");
            }
    
            SECTION("d=3")
            {
              REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                   ASTNodeDataType::build<ASTNodeDataType::vector_t>(3)}),
                                  "invalid implicit conversion: B -> R^3");
            }
          }
    
          SECTION("string -> R^d")
          {
            data_node->m_data_type = string_dt;
    
            SECTION("d=1")
            {
              REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                   ASTNodeDataType::build<ASTNodeDataType::vector_t>(1)}),
                                  "invalid implicit conversion: string -> R^1");
            }
    
            SECTION("d=2")
            {
              REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                   ASTNodeDataType::build<ASTNodeDataType::vector_t>(2)}),
                                  "invalid implicit conversion: string -> R^2");
            }
    
            SECTION("d=3")
            {
              REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                   ASTNodeDataType::build<ASTNodeDataType::vector_t>(3)}),
                                  "invalid implicit conversion: string -> R^3");
            }
          }
        }
    
        SECTION("-> R")
        {
          SECTION("string -> R")
          {
            data_node->m_data_type = string_dt;
            REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, double_dt}),
                                "invalid implicit conversion: string -> R");
          }
    
          SECTION("R^1 -> R")
          {
            data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::vector_t>(1);
            REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, double_dt}),
                                "invalid implicit conversion: R^1 -> R");
          }
    
          SECTION("R^2 -> R")
          {
            data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::vector_t>(2);
            REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, double_dt}),
                                "invalid implicit conversion: R^2 -> R");
          }
    
          SECTION("R^3 -> R")
          {
            data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::vector_t>(3);
            REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, double_dt}),
                                "invalid implicit conversion: R^3 -> R");
          }
    
          SECTION("tuple(N) -> R")
          {
            data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(unsigned_int_dt);
            REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, double_dt}),
                                "invalid implicit conversion: tuple(N) -> R");
          }
    
          SECTION("tuple(R) -> R")
          {
            data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(double_dt);
            REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, double_dt}),
                                "invalid implicit conversion: tuple(R) -> R");
          }
        }
    
        SECTION("-> Z")
        {
          SECTION("string -> Z")
          {
            data_node->m_data_type = string_dt;
            REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, int_dt}),
                                "invalid implicit conversion: string -> Z");
          }
    
          SECTION("R^1 -> Z")
          {
            data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::vector_t>(1);
            REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, int_dt}),
                                "invalid implicit conversion: R^1 -> Z");
          }
    
          SECTION("R^2 -> Z")
          {
            data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::vector_t>(2);
            REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, int_dt}),
                                "invalid implicit conversion: R^2 -> Z");
          }
    
          SECTION("R^3 -> Z")
          {
            data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::vector_t>(3);
            REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, int_dt}),
                                "invalid implicit conversion: R^3 -> Z");
          }
    
          SECTION("R -> Z")
          {
            data_node->m_data_type = double_dt;
            REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, int_dt}),
                                "invalid implicit conversion: R -> Z");
          }
    
          SECTION("tuple(N) -> Z")
          {
            data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(unsigned_int_dt);
            REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, int_dt}),
                                "invalid implicit conversion: tuple(N) -> Z");
          }
    
          SECTION("tuple(Z) -> Z")
          {
            data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(int_dt);
            REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, int_dt}),
                                "invalid implicit conversion: tuple(Z) -> Z");
          }
        }
    
        SECTION("-> N")
        {
          SECTION("string -> N")
          {
            data_node->m_data_type = string_dt;
            REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, unsigned_int_dt}),
                                "invalid implicit conversion: string -> N");
          }
    
          SECTION("R^1 -> N")
          {
            data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::vector_t>(1);
            REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, unsigned_int_dt}),
                                "invalid implicit conversion: R^1 -> N");
          }
    
          SECTION("R^2 -> N")
          {
            data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::vector_t>(2);
            REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, unsigned_int_dt}),
                                "invalid implicit conversion: R^2 -> N");
          }
    
          SECTION("R^3 -> N")
          {
            data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::vector_t>(3);
            REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, unsigned_int_dt}),
                                "invalid implicit conversion: R^3 -> N");
          }
    
          SECTION("R -> N")
          {
            data_node->m_data_type = double_dt;
            REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, unsigned_int_dt}),
                                "invalid implicit conversion: R -> N");
          }
    
          SECTION("tuple(Z) -> N")
          {
            data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(int_dt);
            REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, unsigned_int_dt}),
                                "invalid implicit conversion: tuple(Z) -> N");
          }
    
          SECTION("tuple(N) -> N")
          {
            data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(unsigned_int_dt);
            REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, unsigned_int_dt}),
                                "invalid implicit conversion: tuple(N) -> N");
          }
        }
    
        SECTION("-> B")
        {
          SECTION("string -> B")
          {
            data_node->m_data_type = string_dt;
            REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, bool_dt}),
                                "invalid implicit conversion: string -> B");
          }
    
          SECTION("R^1 -> B")
          {
            data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::vector_t>(1);
            REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, bool_dt}),
                                "invalid implicit conversion: R^1 -> B");
          }
    
          SECTION("R^2 -> B")
          {
            data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::vector_t>(2);
            REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, bool_dt}),
                                "invalid implicit conversion: R^2 -> B");
          }
    
          SECTION("R^3 -> B")
          {
            data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::vector_t>(3);
            REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, bool_dt}),
                                "invalid implicit conversion: R^3 -> B");
          }
    
          SECTION("R -> B")
          {
            data_node->m_data_type = double_dt;
            REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, bool_dt}),
                                "invalid implicit conversion: R -> B");
          }
    
          SECTION("Z -> B")
          {
            data_node->m_data_type = int_dt;
            REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, bool_dt}),
                                "invalid implicit conversion: Z -> B");
          }
    
          SECTION("N -> B")
          {
            data_node->m_data_type = unsigned_int_dt;
            REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, bool_dt}),
                                "invalid implicit conversion: N -> B");
          }
    
          SECTION("tuple(Z) -> B")
          {
            data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(int_dt);
            REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, bool_dt}),
                                "invalid implicit conversion: tuple(Z) -> B");
          }
    
          SECTION("tuple(B) -> B")
          {
            data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(bool_dt);
            REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, bool_dt}),
                                "invalid implicit conversion: tuple(B) -> B");
          }
        }
    
        SECTION("-> tuple")
        {
          SECTION("N -> tuple(B)")
          {
            data_node->m_data_type = unsigned_int_dt;
            REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                 ASTNodeDataType::build<ASTNodeDataType::tuple_t>(
                                                                   bool_dt)}),
                                "invalid implicit conversion: N -> B");
          }
    
          SECTION("Z -> tuple(B)")
          {
            data_node->m_data_type = int_dt;
            REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                 ASTNodeDataType::build<ASTNodeDataType::tuple_t>(
                                                                   bool_dt)}),
                                "invalid implicit conversion: Z -> B");
          }
    
          SECTION("R -> tuple(B)")
          {
            data_node->m_data_type = double_dt;
            REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                 ASTNodeDataType::build<ASTNodeDataType::tuple_t>(
                                                                   bool_dt)}),
                                "invalid implicit conversion: R -> B");
          }
    
          SECTION("string -> tuple(B)")
          {
            data_node->m_data_type = string_dt;
            REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                 ASTNodeDataType::build<ASTNodeDataType::tuple_t>(
                                                                   bool_dt)}),
                                "invalid implicit conversion: string -> B");
          }
    
          SECTION("R^1 -> tuple(B)")
          {
            data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::vector_t>(1);
            REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                 ASTNodeDataType::build<ASTNodeDataType::tuple_t>(
                                                                   bool_dt)}),
                                "invalid implicit conversion: R^1 -> B");
          }
    
          SECTION("R^2 -> tuple(B)")
          {
            data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::vector_t>(2);
            REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                 ASTNodeDataType::build<ASTNodeDataType::tuple_t>(
                                                                   bool_dt)}),
                                "invalid implicit conversion: R^2 -> B");
          }
    
          SECTION("R^3 -> tuple(B)")
          {
            data_node->m_data_type = ASTNodeDataType::build<ASTNodeDataType::vector_t>(3);
            REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                 ASTNodeDataType::build<ASTNodeDataType::tuple_t>(
                                                                   bool_dt)}),
                                "invalid implicit conversion: R^3 -> B");
          }
    
          SECTION("R -> tuple(N)")
          {
            data_node->m_data_type = double_dt;
            REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                 ASTNodeDataType::build<ASTNodeDataType::tuple_t>(
                                                                   unsigned_int_dt)}),
                                "invalid implicit conversion: R -> N");
          }
    
          SECTION("R^1x1 -> tuple(R^2x2)")
          {
            auto R1x1              = ASTNodeDataType::build<ASTNodeDataType::matrix_t>(1, 1);
            auto R2x2              = ASTNodeDataType::build<ASTNodeDataType::matrix_t>(2, 2);
            data_node->m_data_type = R1x1;
            REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                 ASTNodeDataType::build<ASTNodeDataType::tuple_t>(R2x2)}),
                                "invalid implicit conversion: R^1x1 -> R^2x2");
          }
    
          SECTION("R^2x2 -> tuple(R^3x3)")
          {
            auto R2x2              = ASTNodeDataType::build<ASTNodeDataType::matrix_t>(2, 2);
            auto R3x3              = ASTNodeDataType::build<ASTNodeDataType::matrix_t>(3, 3);
            data_node->m_data_type = R2x2;
            REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                 ASTNodeDataType::build<ASTNodeDataType::tuple_t>(R3x3)}),
                                "invalid implicit conversion: R^2x2 -> R^3x3");
          }
    
          SECTION("R^3x3 -> tuple(R^2x2)")
          {
            auto R3x3              = ASTNodeDataType::build<ASTNodeDataType::matrix_t>(3, 3);
            auto R2x2              = ASTNodeDataType::build<ASTNodeDataType::matrix_t>(2, 2);
            data_node->m_data_type = R3x3;
            REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                 ASTNodeDataType::build<ASTNodeDataType::tuple_t>(R2x2)}),
                                "invalid implicit conversion: R^3x3 -> R^2x2");
          }
    
          SECTION("R^1 -> tuple(R^2)")
          {
            auto R1                = ASTNodeDataType::build<ASTNodeDataType::vector_t>(1);
            auto R2                = ASTNodeDataType::build<ASTNodeDataType::vector_t>(2);
            data_node->m_data_type = R1;
            REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                 ASTNodeDataType::build<ASTNodeDataType::tuple_t>(R2)}),
                                "invalid implicit conversion: R^1 -> R^2");
          }
    
          SECTION("R^2 -> tuple(R^3)")
          {
            auto R2                = ASTNodeDataType::build<ASTNodeDataType::vector_t>(2);
            auto R3                = ASTNodeDataType::build<ASTNodeDataType::vector_t>(3);
            data_node->m_data_type = R2;
            REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                 ASTNodeDataType::build<ASTNodeDataType::tuple_t>(R3)}),
                                "invalid implicit conversion: R^2 -> R^3");
          }
    
          SECTION("R^3 -> tuple(R^2)")
          {
            auto R3                = ASTNodeDataType::build<ASTNodeDataType::vector_t>(3);
            auto R2                = ASTNodeDataType::build<ASTNodeDataType::vector_t>(2);
            data_node->m_data_type = R3;
            REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node,
                                                                 ASTNodeDataType::build<ASTNodeDataType::tuple_t>(R2)}),
                                "invalid implicit conversion: R^3 -> R^2");
          }
    
          SECTION("(B, R, Z) -> tuple(N)")
          {
            data_node->m_data_type = list_dt;
            {
              std::unique_ptr list0_node = std::make_unique<ASTNode>();
              list0_node->m_data_type    = bool_dt;
              data_node->emplace_back(std::move(list0_node));
    
              std::unique_ptr list1_node = std::make_unique<ASTNode>();
              list1_node->m_data_type    = double_dt;
              data_node->emplace_back(std::move(list1_node));
    
              std::unique_ptr list2_node = std::make_unique<ASTNode>();
              list2_node->m_data_type    = int_dt;
              data_node->emplace_back(std::move(list2_node));
            }
            auto tuple_t = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(unsigned_int_dt);
            REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, tuple_t}),
                                "invalid implicit conversion: R -> N");
          }
    
          SECTION("(R, N, Z) -> tuple(Z)")
          {
            data_node->m_data_type = list_dt;
            {
              std::unique_ptr list0_node = std::make_unique<ASTNode>();
              list0_node->m_data_type    = double_dt;
              data_node->emplace_back(std::move(list0_node));
    
              std::unique_ptr list1_node = std::make_unique<ASTNode>();
              list1_node->m_data_type    = unsigned_int_dt;
              data_node->emplace_back(std::move(list1_node));
    
              std::unique_ptr list2_node = std::make_unique<ASTNode>();
              list2_node->m_data_type    = int_dt;
              data_node->emplace_back(std::move(list2_node));
            }
            auto tuple_t = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(int_dt);
            REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, tuple_t}),
                                "invalid implicit conversion: R -> Z");
          }
    
          SECTION("(B, N, R) -> tuple(N)")
          {
            data_node->m_data_type = list_dt;
            {
              std::unique_ptr list0_node = std::make_unique<ASTNode>();
              list0_node->m_data_type    = bool_dt;
              data_node->emplace_back(std::move(list0_node));
    
              std::unique_ptr list1_node = std::make_unique<ASTNode>();
              list1_node->m_data_type    = unsigned_int_dt;
              data_node->emplace_back(std::move(list1_node));
    
              std::unique_ptr list2_node = std::make_unique<ASTNode>();
              list2_node->m_data_type    = double_dt;
              data_node->emplace_back(std::move(list2_node));
            }
            auto tuple_t = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(unsigned_int_dt);
            REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, tuple_t}),
                                "invalid implicit conversion: R -> N");
          }
        }
    
        SECTION("(type_id_t, type_id_t) -> tuple(type_id_t)")
        {
          auto type_id1          = ASTNodeDataType::build<ASTNodeDataType::type_id_t>("foo");
          auto type_id2          = ASTNodeDataType::build<ASTNodeDataType::type_id_t>("bar");
          data_node->m_data_type = list_dt;
          {
            std::unique_ptr list0_node = std::make_unique<ASTNode>();
            list0_node->m_data_type    = type_id1;
            data_node->emplace_back(std::move(list0_node));
    
            std::unique_ptr list1_node = std::make_unique<ASTNode>();
            list1_node->m_data_type    = type_id2;
            data_node->emplace_back(std::move(list1_node));
          }
          auto tuple_t = ASTNodeDataType::build<ASTNodeDataType::tuple_t>(type_id2);
          REQUIRE_THROWS_WITH((ASTNodeNaturalConversionChecker{*data_node, tuple_t}),
                              "invalid implicit conversion: foo -> bar");
        }
      }
    }