Continuing the discussion from [RFC] Tensors with unknown element types:
MLIR’s type system is currently quite a bit more limited than its op system in that many of the built-in (“standard”) types provide functionality that cannot be duplicated by dialect types. I’ve run into this issue multiple times with the ShapedType hierarchy (tensors, vectors, memrefs), and Chris above mentioned similar issues with the integer types.
The issue rarely comes up as a request for a more generic/open type system, but in my experience, the lack of such a thing is what causes us to have protracted discussions on the specific constraints that various standard types enforce (i.e. should tensor allow unknown element types, how do we represent bounded ranges of dims, etc). In the abstract, there is little reason that such things should need to be resolved to a single, global answer. I think the fact that it does today is a by-product of there being only one ShapedType hierarchy and it is impossible to extend it with dialect types without them being completely disjoint and existing on an island all their own.
When I look at ShapedType, isInteger(width), isSignlessInteger(), etc, I see what may be more appropriate to think of as type traits (or type interfaces) with an open system of concrete types that can conform to the trait. For ShapedType it is probably a number of traits, considering the complexity and diversity of real types in the wild that represent such things (i.e. RankedShapedType, StaticDimsShapedType, etc). Even if we grandfathered the ShapedType methods into a ShapedTypeTrait, we’d be better off than we are today, because arbitrary dialects could define their own, possibly adding other domain-specific traits (such as ShapedLayoutTrait, etc). It would be really nice if ODS predicates existed that predicated on a set of such type traits instead of a specific concrete type (for ops that are generic in this way).
I’d like to bring the topic up and get feedback on:
a. Does anyone agree/disagree with the concept in general or have further state on this?
b. If implementing such a thing, do people think it is necessary to model it how operations do (with an optional AbstractOperation that can resolve its traits/interfaces) or could we just build such a thing into TypeStorage (at the cost of an additional pointer)?
c. Thoughts on naming? “Type trait” is more aligned with C++ terminology (vs “Type interface”, “Metatype”, etc).