I tried using the
SameOperandAndResultTypes trait assuming it verified that the Op has the same number and types for its operands and results. So something like (f32, i32) → (f32, i32) would conform to the trait. However, looks like the trait checks that all operand and result types have the same uniform element type and compatible shapes. Looks like there is no trait that simply checks that operand and result counts are equal and their types are pair-wise identical.
Given what the
SameOperandAndResultTypes checks, would
UniformOperandAndResultTypes be a more appropriate name? From a cursory look, other traits like
SameOperandAndResultShapes also have similar behavior: they check uniformity of a particular property across all input and output types. And then
Same would perform pair-wise check and would always be something like
Other name for the simple trait I was looking for could be
PairwiseSameOperandAndResultXXX if we do not want to rename the Same* traits.
I ran into this recently too and support renaming this, as it is quite confusing. My initial thinking was to call it
CompatibleOperandAndResultTypes, but “uniform” sounds good too.
However, because shape compatibility is not transitive (
1x4 ~= 4x4 and
4x1 ~= 4x4 does not imply
1x4 ~= 4x1), the thing being checked right now is fairly nonintuitive. The code is really checking all operands and results are compatible with the first result. So the case of multiple result types doesn’t make much sense AFAICT.
I think that
SameOperandsAndResultTypes should do a literal type equality check (pointer equality) (which is transitive) across all operands (no notion of “compatibility”).
We can then use more fine-grained traits depending on the desired shape compatibility criterion. For example, many ops that are currently relying on the “compatible shape” aspect of today’s SameOperandsAndResultTypes probably should be using ResultsBroadcastableShape.
btw, for me “pairwise” implies checking each operand against each result, rather than “the range of result types is identical to the range of input types” (maybe
ResultTypeRangeEqualsOperandTypeRange for that behavior?)
The trait implies that executionally these should have the same type. This is about dynamic equality vs static. And for verification you don’t have sufficient information to reject an op as invalid if you don’t know the static shape until runtime. So you’d be rejecting without sufficient knowledge if this trait was just using static information.
Adding a StaticallySameOperandAndResult or just using AllTypesMatch gets you the static behavior.
Yeah that one is a little weird: it should consider the join of them really.
I guess there are really 2 dimensions here:
- Definition of ‘Same’: Static same or dynamic same or some other criteria (just element types match etc)
- The dimension/pattern across which this same-ness is checked. Current definition checks for sameness of say result(0) with all other results and all other inputs. This to me is a uniformity check (a certain same-ness property is uniformly true across all types considered). Other definition can be same-ness of result(i) and operand(i) for all i, or something else.
I agree Pairwise is not a good name to describe the result(i) vs operand(i) check. Other names that come to mind are ElementWise or PointWise.