# Handling Associated Output Types in Generated Code

TLDR: When generating code for `...Assign` traits in `std::ops` with operands known to produce inconsistent-but-valid output types, how ought one to handle the output types to make it the least confusing?

### Background:

A nice macro generates a general representation of a number. This representation includes coefficients of some numeric type T corresponding to the defining elements of some vector basis:

``````struct Number<T>(Vec<T>);
``````

The macro also generates some Special utility types – essentially like sparse vectors on predetermined useful bases – like:

``````/// A special type with an a-coefficient
struct A<T>{ a: T }
/// A special type with a c-coefficient
struct C<T>{  c: T }
/// A special type with a d-coefficient
struct D<T>{  d: T }
/// A special type with a- and b-coefficients
struct AB<T>{  a: T, b: T }
/// A special type with a-, b- and c-coefficients
struct ABC<T>{   a: T, b: T, c: T }
// ..et. cetera
``````

The nice macro also generates `std::ops::Sub` and `std::ops::Add` trait implementations by determining the associated Output types according to two rules:

#### 1. When an in-basis coefficient is in the right-hand-side, the result is an instance of the left-hand-side specialized representation type:

``````AB<T> - A<T> = AB<T> // Basis: {a, b} + {a} = {a, b} ... can use same type
``````

#### 2. When an out-of-basis coefficient is in the right-hand-side, the result is a general representation type unless a known specialized type is exists matching the new basis:

``````AB<T> - C<T> = ABC<T>
// ^ Basis: {a,b} + {c} = {a,b,c} (basis matches another type)

AB<T> + D<T> = Number<T>
// ^ Basis: {a,b} + {d} = {a,b,c,d,...} (no basis-match, so use general type)
``````

## The Assign Problem

What should the nice macro do with the `AddAssign` and `SubAssign` traits?!

The solution above (using the general type for out-of-bounds basis operations) doesn't really work – obviously it can't change the type of the `self` being assigned to.

For now, it uses a `nan`-producing function to signify something wrong, but then, the basis behavior seems inconsistent:

``````AB<T> += D<T> -> AB::<T>::nan() // Basis: {a,b} += {d} ≠ {a,b}
``````

Would it be less confusing to just not generate the `...Assign` traits for these cases at all? I feel like this is a cop-out somehow. Or does this `nan` result help the user know they're writing code that attempts invalid operations?

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.