Skip to content

Remove noexcept from functions that can throw - #2950

Open
gouarin wants to merge 1 commit into
xtensor-stack:masterfrom
gouarin:fix-noexcept-throw
Open

gouarin wants to merge 1 commit into
xtensor-stack:masterfrom
gouarin:fix-noexcept-throw

Conversation

@gouarin

@gouarin gouarin commented Oct 29, 2026

Copy link
Copy Markdown
Member

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 (no public API changes).

Description

Several functions are noexcept but can throw an exception xtensor raises on purpose, so the caller gets std::terminate. Most cases fail without XTENSOR_ENABLE_ASSERT:

xt::xarray<double> a = {1., 2., 3.}, b = {1., 2.};
xt::allclose(a, b);        // broadcast_error, then std::terminate
xt::filter(a, a > b);      // same
xt::norm_l1(a, {3});       // axis check, then std::terminate
(a + b).begin();           // begin() computes the broadcast shape

noexcept is removed where an exception can escape:

  • shape of an xfunction: xconst_iterable/xiterable iterators, allclose, has_shape, transpose, imag, meshgrid, filter
  • library checks: in1d, norms on expressions, xgenerator::assign_to, xscalar::operator() (dimension checks)
  • allocation: xkeep_slice/xdrop_slice conversions

Forwarding functions (xshared_expression iterators, xfunctor_applier_base::size/shape, xconst_accessible::dimension, the xfunction constructor) are now noexcept only when the forwarded call is. isin now moves an rvalue test container instead of copying it.

Functions whose only failure is std::bad_alloc on shape-sized buffers (iterators, steppers, view constructors) keep noexcept, following C++ Core Guidelines E.12.

The new tests terminate on master and pass with the fix.

Several functions declared noexcept can throw an exception that xtensor
raises on purpose, so the caller gets std::terminate instead of an
exception it can catch:

- in1d asserts that its arguments are 1D.
- allclose, has_shape, transpose, imag of a real expression, meshgrid
  and filter read the shape of their argument. For an xfunction, the
  shape is computed on first use and throws broadcast_error when the
  operand shapes are incompatible.
- begin, end and the other iterator functions of xconst_iterable and
  xiterable read the shape the same way. xcontiguous_iterable is now
  noexcept only for the layout that uses the linear iterators.
- The norm functions on expressions check the reduction axes.
- xgenerator::assign_to resizes the destination, and a fixed-size
  container asserts when the shape differs.
- xscalar::operator() runs XTENSOR_CHECK_DIMENSION when dimension checks
  are enabled.
- The xkeep_slice and xdrop_slice conversions allocate.

Functions that only forward to another expression are now noexcept when
the forwarded call is: xshared_expression iterators,
xfunctor_applier_base::size and shape, and xconst_accessible::dimension.
The xfunction constructor is noexcept when building its operands and
functor cannot throw, and the converting constructor, which copies them,
is no longer noexcept. The xfunction shape cache is value-initialized
instead of going through make_sequence.

isin captured an rvalue test container by copy. It is now moved into the
lambda.
@codspeed

codspeed Bot commented Oct 29, 2026

Copy link
Copy Markdown
Contributor

Merging this PR will regress 1 benchmark

1 warning

⚠️ Unable to measure the execution of 1 benchmark

This benchmark measured no execution time, so its result is not comparable and counts as unchanged. This usually happens when the compiler removes the code under test.

Prevent compiler optimizations

See affected benchmarks

⚡ 1 improved benchmark
❌ 1 regressed benchmark
✅ 253 untouched benchmarks

Warning

Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Benchmark BASE HEAD Efficiency
❌ xshape_initializer[std\:\:array<std\:\:size_t, 4>] 151.7 ns 180.8 ns -16.13%
⚡ xshape_access[std\:\:array<std\:\:size_t, 4>] 154.4 ns 125.3 ns +23.28%

Tip

Investigate this regression by commenting @codspeedbot fix this regression on this PR, or directly use the CodSpeed MCP with your agent.


Comparing gouarin:fix-noexcept-throw (9b42019) with master (57f3d07)

Open in CodSpeed

This branch has not been deployed

No deployments
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.

1 participant