Skip to main content

EagerSessionLinalgExt

Trait EagerSessionLinalgExt 

Source
pub trait EagerSessionLinalgExt {
Show 25 methods // Required methods fn cholesky(&mut self, input: &EagerTensor) -> Result<EagerTensor>; fn svd( &mut self, input: &EagerTensor, ) -> Result<(EagerTensor, EagerTensor, EagerTensor)>; fn svd_with_options( &mut self, input: &EagerTensor, options: SvdOptions, ) -> Result<(EagerTensor, EagerTensor, EagerTensor)>; fn svd_full( &mut self, input: &EagerTensor, ) -> Result<(EagerTensor, EagerTensor, EagerTensor)>; fn qr(&mut self, input: &EagerTensor) -> Result<(EagerTensor, EagerTensor)>; fn qr_with_options( &mut self, input: &EagerTensor, options: QrOptions, ) -> Result<(EagerTensor, EagerTensor)>; fn triangular_solve( &mut self, matrix: &EagerTensor, rhs: &EagerTensor, left_side: bool, lower: bool, transpose_a: bool, unit_diagonal: bool, ) -> Result<EagerTensor>; fn solve( &mut self, matrix: &EagerTensor, rhs: &EagerTensor, ) -> Result<EagerTensor>; fn lstsq( &mut self, matrix: &EagerTensor, rhs: &EagerTensor, ) -> Result<EagerTensor>; fn lu( &mut self, input: &EagerTensor, ) -> Result<(EagerTensor, EagerTensor, EagerTensor, EagerTensor)>; fn slogdet( &mut self, input: &EagerTensor, ) -> Result<(EagerTensor, EagerTensor)>; fn det(&mut self, input: &EagerTensor) -> Result<EagerTensor>; fn inv(&mut self, input: &EagerTensor) -> Result<EagerTensor>; fn eigvalsh(&mut self, input: &EagerTensor) -> Result<EagerTensor>; fn eigvals(&mut self, input: &EagerTensor) -> Result<EagerTensor>; fn eigh( &mut self, input: &EagerTensor, ) -> Result<(EagerTensor, EagerTensor)>; fn eigh_with_options( &mut self, input: &EagerTensor, options: EighOptions, ) -> Result<(EagerTensor, EagerTensor)>; fn eig(&mut self, input: &EagerTensor) -> Result<(EagerTensor, EagerTensor)>; fn pinv(&mut self, input: &EagerTensor) -> Result<EagerTensor>; fn pinv_with_rtol( &mut self, input: &EagerTensor, rtol: f64, ) -> Result<EagerTensor>; fn norm( &mut self, input: &EagerTensor, ord: Option<f64>, dim: Option<&[usize]>, keepdim: bool, ) -> Result<EagerTensor>; fn full_piv_lu( &mut self, input: &EagerTensor, ) -> Result<(EagerTensor, EagerTensor, EagerTensor, EagerTensor, EagerTensor)>; fn full_piv_lu_solve( &mut self, matrix: &EagerTensor, rhs: &EagerTensor, ) -> Result<EagerTensor>; fn rank_revealing_qr( &mut self, input: &EagerTensor, options: RankRevealingQrOptions, ) -> Result<RankRevealingQrResult<EagerTensor>>; fn householder_qr( &mut self, input: &EagerTensor, ) -> Result<HouseholderQr<EagerTensor>>;
}
Expand description

Linear algebra operations on a runtime-bound borrowed eager session.

§Examples

use tenferro_ad::{EagerRuntime, Tensor};
use tenferro_linalg::EagerSessionLinalgExt;
let ctx = EagerRuntime::new()?;
let factor = ctx.with_eager_session(|session| {
    let input = session.constant_from(Tensor::from_vec_col_major(vec![1, 1], vec![4.0_f64])?)?;
    session.cholesky(&input)
})?;
assert_eq!(factor.value()?.as_slice::<f64>()?, &[2.0]);

Required Methods§

Source

fn cholesky(&mut self, input: &EagerTensor) -> Result<EagerTensor>

Compute the lower Cholesky factor without reopening the eager backend.

§Examples
use tenferro_ad::{EagerRuntime, Tensor};
use tenferro_linalg::EagerSessionLinalgExt;
let ctx = EagerRuntime::new()?;
let factor = ctx.with_eager_session(|session| {
    let input = session.constant_from(Tensor::from_vec_col_major(vec![1, 1], vec![9.0_f64])?)?;
    session.cholesky(&input)
})?;
assert_eq!(factor.value()?.as_slice::<f64>()?, &[3.0]);
§Errors

Returns typed validation, extension, backend, module or unsupported-executor errors.

Source

fn svd( &mut self, input: &EagerTensor, ) -> Result<(EagerTensor, EagerTensor, EagerTensor)>

Compute a thin singular value decomposition in this borrowed session.

§Examples
use tenferro_ad::{EagerRuntime, Tensor};
use tenferro_linalg::EagerSessionLinalgExt;
let ctx = EagerRuntime::new()?;
let (_u, values, _vt) = ctx.with_eager_session(|s| {
    let a = s.constant_from(Tensor::from_vec_col_major([1, 1], vec![3.0_f64])?)?;
    s.svd(&a)
})?;
assert_eq!(values.value()?.as_slice::<f64>()?, &[3.0]);
§Errors

Returns typed validation, extension, backend, or unsupported-executor errors.

Source

fn svd_with_options( &mut self, input: &EagerTensor, options: SvdOptions, ) -> Result<(EagerTensor, EagerTensor, EagerTensor)>

Compute thin SVD with an explicit gauge, driver, and derivative regularizer.

§Examples
use tenferro_ad::{EagerRuntime, Tensor};
use tenferro_linalg::{EagerSessionLinalgExt, SvdOptions};
let ctx = EagerRuntime::new()?;
let (_u, values, _vt) = ctx.with_eager_session(|s| {
    let a = s.constant_from(Tensor::from_vec_col_major([1, 1], vec![3.0_f64])?)?;
    s.svd_with_options(&a, SvdOptions::default())
})?;
assert_eq!(values.value()?.as_slice::<f64>()?, &[3.0]);
§Errors

Returns typed invalid-tolerance, extension, backend, or unsupported errors.

Source

fn svd_full( &mut self, input: &EagerTensor, ) -> Result<(EagerTensor, EagerTensor, EagerTensor)>

Compute full-matrices SVD, including the right nullspace.

§Examples
use tenferro_ad::{EagerRuntime, Tensor};
use tenferro_linalg::EagerSessionLinalgExt;
let ctx = EagerRuntime::new()?;
let (u, values, vh) = ctx.with_eager_session(|s| {
    let a = s.constant_from(Tensor::from_vec_col_major([1, 2], vec![1.0_f64, 1.0])?)?;
    s.svd_full(&a)
})?;
assert_eq!(u.shape(), &[1, 1]);
assert_eq!(values.shape(), &[1]);
assert_eq!(vh.shape(), &[2, 2]);
§Errors

Returns Error::Validation with ValidationError::RankMismatch when the input is not a (batched) matrix, Error::UnsupportedAdRule when a traced input needs a derivative this decomposition does not provide, Error::Extension carrying the linalg failure (for example Error::NonConvergence or an unsupported dtype), or Error::TensorRuntime for a backend failure.

Source

fn qr(&mut self, input: &EagerTensor) -> Result<(EagerTensor, EagerTensor)>

Compute a thin QR decomposition in this borrowed session.

§Examples
use tenferro_ad::{EagerRuntime, Tensor};
use tenferro_linalg::EagerSessionLinalgExt;
let ctx = EagerRuntime::new()?;
let (q, r) = ctx.with_eager_session(|s| {
    let a = s.constant_from(Tensor::from_vec_col_major([1, 1], vec![3.0_f64])?)?;
    s.qr(&a)
})?;
assert_eq!(q.shape(), &[1, 1]);
assert_eq!(r.shape(), &[1, 1]);
§Errors

Returns typed validation, extension, backend, or unsupported-executor errors.

Source

fn qr_with_options( &mut self, input: &EagerTensor, options: QrOptions, ) -> Result<(EagerTensor, EagerTensor)>

Compute QR with an explicit post-processing gauge.

§Examples
use tenferro_ad::{EagerRuntime, Tensor};
use tenferro_linalg::{EagerSessionLinalgExt, QrOptions};
let ctx = EagerRuntime::new()?;
let (q, r) = ctx.with_eager_session(|s| {
    let a = s.constant_from(Tensor::from_vec_col_major([1, 1], vec![3.0_f64])?)?;
    s.qr_with_options(&a, QrOptions::default())
})?;
assert_eq!(q.shape(), &[1, 1]);
assert_eq!(r.shape(), &[1, 1]);
§Errors

Returns typed validation, extension, backend, or unsupported errors.

Source

fn triangular_solve( &mut self, matrix: &EagerTensor, rhs: &EagerTensor, left_side: bool, lower: bool, transpose_a: bool, unit_diagonal: bool, ) -> Result<EagerTensor>

Solve a triangular system in this borrowed session.

§Examples
use tenferro_ad::{EagerRuntime, Tensor};
use tenferro_linalg::EagerSessionLinalgExt;
let ctx = EagerRuntime::new()?;
let x = ctx.with_eager_session(|s| {
    let a = s.constant_from(Tensor::from_vec_col_major([1, 1], vec![2.0_f64])?)?;
    let b = s.constant_from(Tensor::from_vec_col_major([1, 1], vec![4.0_f64])?)?;
    s.triangular_solve(&a, &b, true, true, false, false)
})?;
assert_eq!(x.value()?.as_slice::<f64>()?, &[2.0]);
§Errors

Returns typed validation, extension, backend, or unsupported-executor errors.

Source

fn solve( &mut self, matrix: &EagerTensor, rhs: &EagerTensor, ) -> Result<EagerTensor>

Solve a square linear system in this borrowed session.

§Examples
use tenferro_ad::{EagerRuntime, Tensor};
use tenferro_linalg::EagerSessionLinalgExt;
let ctx = EagerRuntime::new()?;
let x = ctx.with_eager_session(|s| {
    let a = s.constant_from(Tensor::from_vec_col_major([1, 1], vec![2.0_f64])?)?;
    let b = s.constant_from(Tensor::from_vec_col_major([1, 1], vec![4.0_f64])?)?;
    s.solve(&a, &b)
})?;
assert_eq!(x.value()?.as_slice::<f64>()?, &[2.0]);
§Errors

Returns typed validation, extension, backend, or unsupported-executor errors.

Source

fn lstsq( &mut self, matrix: &EagerTensor, rhs: &EagerTensor, ) -> Result<EagerTensor>

Solve a full-column-rank least-squares problem inside this session.

§Examples
use tenferro_ad::{EagerRuntime, Tensor};
use tenferro_linalg::EagerSessionLinalgExt;
let ctx = EagerRuntime::new()?;
let x = ctx.with_eager_session(|s| {
    let a = s.constant_from(Tensor::from_vec_col_major([2, 1], vec![1.0_f64, 2.0])?)?;
    let b = s.constant_from(Tensor::from_vec_col_major([2, 1], vec![2.0_f64, 4.0])?)?;
    s.lstsq(&a, &b)
})?;
assert!((x.value()?.as_slice::<f64>()?[0] - 2.0).abs() < 1e-12);
§Errors

Returns typed rank/shape/dtype validation, extension, backend, or unsupported errors.

Source

fn lu( &mut self, input: &EagerTensor, ) -> Result<(EagerTensor, EagerTensor, EagerTensor, EagerTensor)>

Factor a matrix without leaving this borrowed session.

§Examples
use tenferro_ad::{EagerRuntime, Tensor};
use tenferro_linalg::EagerSessionLinalgExt;
let ctx = EagerRuntime::new()?;
let (_p, _l, u, _parity) = ctx.with_eager_session(|s| {
    let a = s.constant_from(Tensor::from_vec_col_major([1, 1], vec![2.0_f64])?)?;
    s.lu(&a)
})?;
assert_eq!(u.value()?.as_slice::<f64>()?, &[2.0]);
§Errors

Returns typed validation, extension, backend, or unsupported-executor errors.

Source

fn slogdet(&mut self, input: &EagerTensor) -> Result<(EagerTensor, EagerTensor)>

Compute determinant sign and logarithm of its absolute value in this session.

§Examples
use tenferro_ad::{EagerRuntime, Tensor};
use tenferro_linalg::EagerSessionLinalgExt;
let ctx = EagerRuntime::new()?;
let (sign, logabs) = ctx.with_eager_session(|s| {
    let a = s.constant_from(Tensor::from_vec_col_major([1, 1], vec![2.0_f64])?)?;
    s.slogdet(&a)
})?;
assert_eq!(sign.value()?.as_slice::<f64>()?, &[1.0]);
assert!((logabs.value()?.as_slice::<f64>()?[0] - 2.0_f64.ln()).abs() < 1e-12);
§Errors

Returns typed validation, extension, backend, or unsupported-executor errors.

Source

fn det(&mut self, input: &EagerTensor) -> Result<EagerTensor>

Compute a determinant inside the borrowed session.

§Examples
use tenferro_ad::{EagerRuntime, Tensor};
use tenferro_linalg::EagerSessionLinalgExt;
let ctx = EagerRuntime::new()?;
let det = ctx.with_eager_session(|s| {
    let a = s.constant_from(Tensor::from_vec_col_major([1, 1], vec![2.0_f64])?)?;
    s.det(&a)
})?;
assert_eq!(det.value()?.as_slice::<f64>()?, &[2.0]);
§Errors

Returns typed validation, extension, backend, or unsupported-executor errors.

Source

fn inv(&mut self, input: &EagerTensor) -> Result<EagerTensor>

Invert a square matrix inside this borrowed session.

§Examples
use tenferro_ad::{EagerRuntime, Tensor};
use tenferro_linalg::EagerSessionLinalgExt;
let ctx = EagerRuntime::new()?;
let inverse = ctx.with_eager_session(|s| {
    let a = s.constant_from(Tensor::from_vec_col_major([1, 1], vec![2.0_f64])?)?;
    s.inv(&a)
})?;
assert_eq!(inverse.value()?.as_slice::<f64>()?, &[0.5]);
§Errors

Returns typed rank/shape/dtype validation, extension, backend, or unsupported errors.

Source

fn eigvalsh(&mut self, input: &EagerTensor) -> Result<EagerTensor>

Compute eigenvalues of a Hermitian matrix in this borrowed session.

§Examples
use tenferro_ad::{EagerRuntime, Tensor};
use tenferro_linalg::EagerSessionLinalgExt;
let ctx = EagerRuntime::new()?;
let values = ctx.with_eager_session(|s| {
    let a = s.constant_from(Tensor::from_vec_col_major([1, 1], vec![4.0_f64])?)?;
    s.eigvalsh(&a)
})?;
assert_eq!(values.value()?.as_slice::<f64>()?, &[4.0]);
§Errors

Returns typed validation, extension, backend, or unsupported-executor errors.

Source

fn eigvals(&mut self, input: &EagerTensor) -> Result<EagerTensor>

Compute general eigenvalues in this borrowed session.

§Examples
use tenferro_ad::{EagerRuntime, Tensor};
use tenferro_linalg::EagerSessionLinalgExt;
let ctx = EagerRuntime::new()?;
let values = ctx.with_eager_session(|s| {
    let a = s.constant_from(Tensor::from_vec_col_major([1, 1], vec![4.0_f64])?)?;
    s.eigvals(&a)
})?;
assert_eq!(values.value()?.as_slice::<num_complex::Complex64>()?, &[num_complex::Complex64::new(4.0, 0.0)]);
§Errors

Returns typed validation, extension, backend, or unsupported-executor errors.

Source

fn eigh(&mut self, input: &EagerTensor) -> Result<(EagerTensor, EagerTensor)>

Compute eigenvalues and vectors of a Hermitian matrix in this session.

§Examples
use tenferro_ad::{EagerRuntime, Tensor};
use tenferro_linalg::EagerSessionLinalgExt;
let ctx = EagerRuntime::new()?;
let (values, vectors) = ctx.with_eager_session(|s| {
    let a = s.constant_from(Tensor::from_vec_col_major([1, 1], vec![4.0_f64])?)?;
    s.eigh(&a)
})?;
assert_eq!(values.value()?.as_slice::<f64>()?, &[4.0]);
assert_eq!(vectors.shape(), &[1, 1]);
§Errors

Returns typed validation, unsupported-dtype, extension, or backend errors.

Source

fn eigh_with_options( &mut self, input: &EagerTensor, options: EighOptions, ) -> Result<(EagerTensor, EagerTensor)>

Compute Hermitian eigendecomposition with explicit gauge and tolerance.

§Examples
use tenferro_ad::{EagerRuntime, Tensor};
use tenferro_linalg::{EagerSessionLinalgExt, EighOptions};
let ctx = EagerRuntime::new()?;
let (values, _vectors) = ctx.with_eager_session(|s| {
    let a = s.constant_from(Tensor::from_vec_col_major([1, 1], vec![4.0_f64])?)?;
    s.eigh_with_options(&a, EighOptions::default())
})?;
assert_eq!(values.value()?.as_slice::<f64>()?, &[4.0]);
§Errors

Returns Error::Validation with ValidationError::InvalidArgument for an invalid tolerance or with ValidationError::ShapeMismatch for a non-square input, Error::Extension carrying the linalg failure (for example Error::NonConvergence or an unsupported dtype), or Error::TensorRuntime for a backend failure.

Source

fn eig(&mut self, input: &EagerTensor) -> Result<(EagerTensor, EagerTensor)>

Compute general eigenvalues and eigenvectors inside this session.

§Examples
use tenferro_ad::{EagerRuntime, Tensor};
use tenferro_linalg::EagerSessionLinalgExt;
let ctx = EagerRuntime::new()?;
let (values, vectors) = ctx.with_eager_session(|s| {
    let a = s.constant_from(Tensor::from_vec_col_major([1, 1], vec![4.0_f64])?)?;
    s.eig(&a)
})?;
assert_eq!(values.value()?.as_slice::<num_complex::Complex64>()?, &[num_complex::Complex64::new(4.0, 0.0)]);
assert_eq!(vectors.shape(), &[1, 1]);
§Errors

Returns Error::Validation with ValidationError::RankMismatch or ValidationError::ShapeMismatch for a non-square (batched) matrix, Error::Extension carrying the linalg failure (for example Error::NonConvergence or an unsupported dtype), or Error::TensorRuntime for a backend failure.

Source

fn pinv(&mut self, input: &EagerTensor) -> Result<EagerTensor>

Compute the Moore-Penrose pseudoinverse using the default tolerance.

§Examples
use tenferro_ad::{EagerRuntime, Tensor};
use tenferro_linalg::EagerSessionLinalgExt;
let ctx = EagerRuntime::new()?;
let inverse = ctx.with_eager_session(|s| {
    let a = s.constant_from(Tensor::from_vec_col_major([1, 1], vec![2.0_f64])?)?;
    s.pinv(&a)
})?;
assert_eq!(inverse.value()?.as_slice::<f64>()?, &[0.5]);
§Errors

Returns Error::Validation with ValidationError::RankMismatch when the input is not a (batched) matrix, Error::Extension carrying the linalg failure (for example Error::NonConvergence or an unsupported dtype) from the underlying SVD, or Error::TensorRuntime for a backend failure.

Source

fn pinv_with_rtol( &mut self, input: &EagerTensor, rtol: f64, ) -> Result<EagerTensor>

Compute the pseudoinverse with an explicit relative tolerance.

§Examples
use tenferro_ad::{EagerRuntime, Tensor};
use tenferro_linalg::EagerSessionLinalgExt;
let ctx = EagerRuntime::new()?;
let inverse = ctx.with_eager_session(|s| {
    let a = s.constant_from(Tensor::from_vec_col_major([1, 1], vec![2.0_f64])?)?;
    s.pinv_with_rtol(&a, 1.0e-12)
})?;
assert_eq!(inverse.value()?.as_slice::<f64>()?, &[0.5]);
§Errors

Returns Error::Validation with ValidationError::RankMismatch when the input is not a (batched) matrix, ValidationError::InvalidArgument for a negative or non-finite tolerance, Error::Extension carrying the linalg failure (for example Error::NonConvergence or an unsupported dtype) from the underlying SVD, or Error::TensorRuntime for a backend failure.

Source

fn norm( &mut self, input: &EagerTensor, ord: Option<f64>, dim: Option<&[usize]>, keepdim: bool, ) -> Result<EagerTensor>

Compute a vector, matrix, or tensor norm in this session. An empty axis list is a no-op and clones the input without dispatch.

§Examples
use tenferro_ad::{EagerRuntime, Tensor};
use tenferro_linalg::EagerSessionLinalgExt;
let ctx = EagerRuntime::new()?;
let result = ctx.with_eager_session(|s| {
    let a = s.constant_from(Tensor::from_vec_col_major([2], vec![3.0_f64, 4.0])?)?;
    s.norm(&a, Some(2.0), Some(&[0]), false)
})?;
assert_eq!(result.value()?.as_slice::<f64>()?, &[5.0]);
§Errors

Returns typed unsupported-dtype, invalid-axis/order, SVD, or backend errors.

Source

fn full_piv_lu( &mut self, input: &EagerTensor, ) -> Result<(EagerTensor, EagerTensor, EagerTensor, EagerTensor, EagerTensor)>

Compute complete-pivot LU factors (P, L, U, Q, parity) in this session. Reconstruction uses A = P^T * L * U * Q; scalar parity is real (F32 for F32/C32 inputs and F64 for F64/C64).

§Examples
use tenferro_ad::{EagerRuntime, Tensor};
use tenferro_linalg::EagerSessionLinalgExt;
let ctx = EagerRuntime::new()?;
let (p, _l, _u, q, parity) = ctx.with_eager_session(|s| {
    let a = s.constant_from(Tensor::from_vec_col_major([2, 2], vec![1.0_f64, 3.0, 2.0, 4.0])?)?;
    s.full_piv_lu(&a)
})?;
assert_eq!(p.shape(), &[2, 2]);
assert_eq!(q.shape(), &[2, 2]);
assert_eq!(parity.shape(), &[] as &[usize]);
§Errors

Returns typed rank/shape, unsupported-provider, numerical, or output-count errors.

Source

fn full_piv_lu_solve( &mut self, matrix: &EagerTensor, rhs: &EagerTensor, ) -> Result<EagerTensor>

Solve a linear system using complete-pivot LU in this session.

§Examples
use tenferro_ad::{EagerRuntime, Tensor};
use tenferro_linalg::EagerSessionLinalgExt;
let ctx = EagerRuntime::new()?;
let x = ctx.with_eager_session(|s| {
    let a = s.constant_from(Tensor::from_vec_col_major([1, 1], vec![2.0_f64])?)?;
    let b = s.constant_from(Tensor::from_vec_col_major([1, 1], vec![4.0_f64])?)?;
    s.full_piv_lu_solve(&a, &b)
})?;
assert_eq!(x.value()?.as_slice::<f64>()?, &[2.0]);
§Errors

Returns typed rank/shape, unsupported-provider, singularity, or backend errors.

Source

fn rank_revealing_qr( &mut self, input: &EagerTensor, options: RankRevealingQrOptions, ) -> Result<RankRevealingQrResult<EagerTensor>>

Compute column-pivoted rank-revealing QR in this session.

§Examples
use tenferro_ad::{EagerRuntime, Tensor};
use tenferro_linalg::{EagerSessionLinalgExt, RankRevealingQrOptions};
let ctx = EagerRuntime::new()?;
let result = ctx.with_eager_session(|s| {
    let a = s.constant_from(Tensor::from_vec_col_major([2, 2], vec![1.0_f64, 0.0, 0.0, 2.0])?)?;
    s.rank_revealing_qr(&a, RankRevealingQrOptions::default())
})?;
assert_eq!(result.column_permutation.shape(), &[2]);
assert_eq!(result.rank.value()?.as_slice::<i64>()?, &[2]);
§Errors

Returns Error::Validation with ValidationError::RankMismatch, ValidationError::DTypeMismatch or ValidationError::InvalidArgument for an invalid rank, dtype or tolerance, Error::Extension carrying the linalg failure (for example Error::NonConvergence or an unsupported dtype), or Error::TensorRuntime for a backend failure.

Source

fn householder_qr( &mut self, input: &EagerTensor, ) -> Result<HouseholderQr<EagerTensor>>

Initialize compact Householder QR state in this borrowed session.

§Examples
use tenferro_ad::{EagerRuntime, Tensor};
use tenferro_linalg::EagerSessionLinalgExt;
let ctx = EagerRuntime::new()?;
let state = ctx.with_eager_session(|s| {
    let a = s.constant_from(Tensor::from_vec_col_major([2, 1], vec![1.0_f64, 2.0])?)?;
    s.householder_qr(&a)
})?;
assert!(format!("{state:?}").starts_with("HouseholderQr"));
§Errors

Returns typed invalid metadata, unsupported executor, or backend errors.

Dyn Compatibility§

This trait is dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety".

Implementors§