I do not understand why defining the Add operator for AD (in the code below) leads to an overflow evaluting requirements in a statement that I think is in no way using AD:
/*
If I execute 'cargo run', I get:
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.01s
Running `target/debug/package`
Hello World
If I execut 'cargo test', I get:
Compiling package v0.1.0 (/home/bradbell/trash/rust/package)
error[E0275]: overflow evaluating the requirement `for<'a> &'a Simd<_, _>: Add`
--> src/main.rs:65:24
|
65 | forward_0 : add_fun,
| ^^^^^^^
|
= help: consider increasing the recursion limit by adding
*/
// -------------------------------------------------------------------------
// AD
pub struct AD<F> {
pub value : F,
}
//
#[cfg(test)]
impl<F> std::ops::Add< &AD<F> > for &AD<F>
where
for<'a> &'a F: std::ops::Add<&'a F, Output=F>,
F : Clone
{ type Output = AD<F>;
//
fn add(self , rhs : &AD<F> ) -> AD<F>
{
AD{ value : rhs.value.clone() }
}
}
// AD is not used below here
// -------------------------------------------------------------------------
//
// LazyLock
use std::sync::LazyLock;
//
// FunType
pub type FunType<V> = fn(
_var_zero : &mut Vec<V> ,
);
//
// add_fun
fn add_fun<V> ( var_zero : &mut Vec<V> )
where for<'a> &'a V : std::ops::Add< &'a V, Output = V>,
{
var_zero[2] = &var_zero[0] + &var_zero[1];
}
//
// FunInfo
#[derive(Clone)]
pub struct FunInfo<V> {
pub forward_0 : FunType<V>,
}
//
// fun_init
pub fn fun_init<V>() -> FunInfo<V>
where for<'a> &'a V : std::ops::Add< &'a V, Output = V>,
{
FunInfo {
forward_0 : add_fun,
}
}
//
// GlobalData
pub trait GlobalData
where Self : Sized + 'static,
{
fn get() -> &'static std::sync::LazyLock< FunInfo<Self> >;
}
impl GlobalData for f32 {
fn get() -> &'static LazyLock< FunInfo<f32> > {
pub static GLOBAL_DATA :
LazyLock< FunInfo<f32> > = LazyLock::new( || fun_init() );
&GLOBAL_DATA
}
}
//
// main()
fn main() {
println!("Hello World");
}
the snippet compiles with -Znext-solver. (godbolt link)
possibly related:
I'm not an expert on the trait solver, I can't explain the error, but for this particular example, on stable rust, you can "help" type inference with some type annotation (godbolt link):
I am once again stuck trying to fix the where clauses in my code. I have isolated the problem I am currently having in the file main.rs bleow. If I execute cargo run, the program runs correctly.
If I execute cargo test, I get the error message below the program, which does not help me know what to do to fix it (Note the #[cfg(test)] int main.rs below ) ?
main.rs
// AD
#[derive(Debug)]
pub struct AD<V> {
pub value : V,
}
//
impl<V> std::ops::Add< &AD<V> > for &AD<V>
where
for<'a> &'a V : std::ops::Add< &'a V, Output = V>,
{ type Output = AD<V>;
//
fn add(self , rhs : &AD<V> ) -> AD<V>
{ AD { value : &self.value + &rhs.value } }
}
//
// ---------------------------------------------------------------------------
// FunType
pub type FunType<V> = fn( _var_zero : &mut Vec< AD<V> > );
// hello_world
/// default [FunType] function will panic
fn hello_world<V> (
_var_zero : &mut Vec< AD<V> > ,
) { println!("Hello World"); }
// ---------------------------------------------------------------------------
/// Information for one operator
#[derive(Clone)]
pub struct FunInfo<V> {
pub fun : FunType<V>,
}
// ---------------------------------------------------------------------------
// get_op_info
pub fn get_op_info<V>() -> Vec< FunInfo<V> >
where
for<'a> &'a V : std::ops::Add<&'a V, Output = V> ,
{
let hello = FunInfo { fun : hello_world::<V> };
let op_info : Vec< FunInfo<V> > = vec![hello ];
#[cfg(test)]
set_op_info(&mut op_info);
op_info
}
// --------------------------------------------------------------------------
// add_fun
fn add_fun<V> ( var_zero : &mut Vec< AD<V> > )
where for<'a> &'a V : std::ops::Add< &'a V, Output = V>,
{ var_zero[2] = &var_zero[0] + &var_zero[1]; }
// ---------------------------------------------------------------------------
// set_op_info
pub fn set_op_info<V>( op_info : &mut Vec< FunInfo::<V> > )
where
for<'a> &'a V : std::ops::Add<&'a V, Output = V> ,
{
op_info[0] = FunInfo{ fun : add_fun::<V> };
}
// ---------------------------------------------------------------------------
// main()
fn main() {
let info = get_op_info::<f32>();
let fun = info[0].fun;
let mut var_zero : Vec< AD<f32> > = Vec::new();
var_zero.push( AD{ value : 2f32 } );
var_zero.push( AD{ value : 3f32 } );
var_zero.push( AD{ value : f32::NAN } );
println!("var_zero = {:?}", var_zero);
fun(&mut var_zero);
println!("var_zero = {:?}", var_zero);
}
Error message:
= help: consider increasing the recursion limit by adding a #![recursion_limit = "256"] attribute to your crate (package)
note: required for &'a AD<Simd<_, _>> to implement for<'a> Add
--> src/main.rs:7:9
|
7 | impl std::ops::Add< &AD > for &AD
| ^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^
8 | where
9 | for<'a> &'a V : std::ops::Add< &'a V, Output = V>,
| ---------- unsatisfied trait bound introduced here
= note: 126 redundant requirements hidden
= note: required for &AD<AD<AD<AD<AD<AD<AD<AD<AD<AD<AD<AD<AD<AD<AD<AD<...>>>>>>>>>>>>>>>> to implement for<'a> Add
note: required by a bound in set_op_info
--> src/main.rs:52:21
|
50 | pub fn set_op_info( op_info : &mut Vec< FunInfo:: > )
| ----------- required by a bound in this function
51 | where
52 | for<'a> &'a V : std::ops::Add<&'a V, Output = V> ,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in set_op_info
= note: the full name for the type has been written to '/home/bradbell/trash/rust/package/target/debug/deps/package-2e9b0110440db6ae.long-type-16883548437017512517.txt'
= note: consider using --verbose to print the full type name to the console
For more information about this error, try rustc --explain E0275.
since it's the same issue cause by the bad interaction between the trait solver and type inference, the same workaround should work for this too, turbofish to the rescue.