[RFC] Cleaning up type-related concepts in ODS

While working on type verifiers in the LLVM dialect, I noticed that we have pairwise-redundant concepts in ODS for types:

  • TypeConstraint that contains a predicate checking if a type instance satisfies the constraint and a description;
  • Type that derives from TypeConstraint and only defines a duplicate field for the description and provides an empty field for builder (see below);
  • BuildableType that defines the same builder field as Type without being connected to Type or TypeConstraint. It has been intended for types one can construct given a context and the information present in the ODS description, e.g. standard f32 (only context) or standard integer (context + bitwidth available in the ODS description).

I remember introducing TypeConstraint and can repeat the rationale: conceptually many ODS definitions are not types but constraints. For example, “AnyInteger” or “AnyMemref” do not identify a specific type but rather a condition a given type must satisfy. Yet both inherit from Type rather than TypeConstraint. Many core ODS pieces use Type when they should be actually using TypeConstraint. BuildableType was intended for constructing types in ODS-generated code, i.e. BuildableType actually is a specific type. Declarative assembly relies on this for results.

I propose to (1) replace all uses of Type that don’t define a concrete type with TypeConstraint; (2) merge BuildableType and Type to denote a concrete type, with an optional field for builder code. Type will keep inheriting from TypeConstraint and remain usable anywhere a TypeConstraint is expected.

Ping @antiagainst @River707 and @jpienaar for visibility.

+1

Why? Meaning, if merging but making optional we need to do two checks (is type, has builder) to know if buildable. Why not keep it two and require buildable type to have a builder? The builder field is then on the “subclass”. When does one have a concrete type that isn’t buildable? General memrefs come to mind where we had the discussion about allowing to specify the layout in textual form and then parsing it, sure there are others where it is cumbersome too, but in which cases should that just then be a type constraint instead. So effectively when do we have a non-buildable type where it is beneficial to not just express as type constraint instead?

We can have concrete types without ever needing to build them in ODS. But I was mostly thinking about reducing the transition burden downstream.