Skip to content

Conversation

@yosh-matsuda
Copy link
Contributor

Checklist

  • The title and commit message(s) are descriptive.
  • Small commits made to fix your PR have been squashed to avoid history pollution.
  • Tests have been added for new features or bug fixes.
  • API of new functions and classes are documented.

Description

I found xt::broadcast_error is not caught and std::terminate is called for assign operators with xt::xarray_adaptor.

To reproduce:

void test()
{
    using namespace xt;
    using vec_type = std::vector<int>;
    using xarray_adaptor_type = xarray_adaptor<vec_type, layout_type::dynamic>;

    auto v1 = vec_type{1, 2, 3, 4};
    auto xa1 = xarray_adaptor_type(v1, {4});

    auto v2 = vec_type{10, 20, 30, 40};
    auto xa2 = xarray_adaptor_type(v2, {2, 2});

    try
    {
        // expect broadcast error
        xa1 += xa2;
    }
    catch (const xt::broadcast_error& e)
    {
        // xt::broadcast_error will NOT be caught
        // std::terminate called from compiler-generated code
        std::println("broadcast error: {}\n", e.what());
    }
}

It seems that this is because xt::broadcast_error exception is thrown within noexcept specified function.
Here:

    template <class D>
    inline auto xconst_accessible<D>::size() const noexcept -> size_type
    {
        return compute_size(derived_cast().shape());
    }

    inline void xfunction<F, CT...>::compute_cached_shape() const
    {
        static_assert(!detail::is_fixed<shape_type>::value, "Calling compute_cached_shape on fixed!");

        m_cache.shape = uninitialized_shape<xindex_type_t<inner_shape_type>>(compute_dimension());
        m_cache.is_trivial = broadcast_shape(m_cache.shape, false);
        m_cache.is_initialized = true;
    }

    template <class F, class... CT>
    inline auto xfunction<F, CT...>::shape() const -> const inner_shape_type& 
    {
        if constexpr (!detail::is_fixed<inner_shape_type>::value)
        {
            if (!m_cache.is_initialized)
            {
                compute_cached_shape();
            }
        }
        return m_cache.shape;
    }

derived_cast().shape() possibly throw exception and noexcept should be replaced by noexcept(noexcept(...)) to fix it.

@JohanMabille
Copy link
Member

JohanMabille commented Oct 21, 2025

Thanks! The error in te CI is due to a well-known concurrency issue.

@JohanMabille JohanMabille merged commit abe7b0f into xtensor-stack:master Oct 21, 2025
19 of 20 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants