You are trying to confine an array with an integer constraint. That doesn’t make sense indeed . The error could be improved but at that level the C++ types involved and rules regarding them is not trivial to deduce (I see this less as a footgun and more as inconsistent). Wouldn’t you need an all of constraint that would verify for all in the container that the elementwise constraint holds?
I have been always bothered by the name ArrayAttr because I am used to associating “array” with a container of identically-typed objects, yet ArrayAttr can have elements of different types. IMO, it is more of a TupleAttr given that it is also immutable, whereas the Dense*ArrayAttr is actually an ArrayAttr. I can’t even start imagining the amount of churn caused by a rename .
A stupid solution is to update ArrayMinCount to emit code that dispatches based on type (attr.isa<ArrayAttr>() ? attr.cast<ArrayAttr>().size() : attr.cast<DenseArrayBaseAttr>().size()), which is not exactly elegant or efficient.
Preventing such footguns may require some work at the tablegen level where we could, for example, extend AttributeConstraint to keep track of the supported base attribute classes and check that is it only applied to those or their subclasses at tablegen level.
ArrayAttr has historically been abused to behave like a true “array”, in which all elements are the same kind. I wouldn’t be surprised if every attribute constrained by ArrayMinCount today would make more sense as a dense array or a custom attribute.