There's nothing wrong doing what you're doing, just like there's nothing keeping you from overloading the Add() operator to do multiplication.
Your questions are entirely theoretical, and so it's hard to say anything one way or another. Yes, the constructs are "legal". So what?
It's like asking about walking on your hands vs. walking on your feet after you've discovered that you CAN walk on your hands.
The question in all cases is the same ... why would you want to do it?
Rather than asking about coding approaches that are "legal" but nobody uses, why don't you try showing an example where such uses would prove to be an advantage?
From a theoretical standpoint, you're trying to mash-up two different data aggregation mechanisms.
Arrays are a way of collecting items of the same type. Records and classes are a way of collecting related items of different types. They're both containers of sorts, but they have distinct qualities.
You usually declare an array as "array of " not "array of record ... end".
By convention, you define the record as a TYPE so you can "re-use" that type.
You obviously haven't got much experience with this, because you can't actually USE these constructs outside of a very narrow setting.
Let's say you want to define something like "array of integer"; you can define it as a specific type:
type
TIntArray = array of integer;
Why would you do this? Because at times you'll discover that declaring two different things both as "array of integer" makes them not type-compatible, which is counter-intuitive.
But if they're each declared as TIntArray, the compiler accepts that.
I don't know if this is the correct terminology or not, but as far as the compiler is concerned, there IS a difference between "myvar : " and "myvar : ". In this case, would be "TIntArray", and would be "array of integer".
var
myvar1 : array of integer;
myvar2 : TIntArray;
These two are NOT type compatible in all cases. Furthermore,
procedure myproc( AVar : array of integer )
will not accept myproc(myvar2) because myvar2 is not of type "array of integer". Really! It's of type TIntArray. See the difference?
Now replace that declaration with any sort of "record ... end", or even your "array of record ... end" thingie and you start to see the limitations of what you're asking. Yes, the compiler digests it just fine. It just won't let you pass anything in as an argument that matches that type! Even if they "look" exactly the same, believe it or not.
So, to answer your own question, I challenge you to construct a non-trivial example where the things you propose actually make sense and the compiler accepts them. Because while the compiler might accept the isolated examples you've created above, they're not likely to work very well in practice (if at all).
But you get an 'A' for Audacity in asking an insightful question!
var Matrix: array of array of record Re, Im: Real end;
Do you need complex scalar type or column vector type? Then extract particular component. Otherwise it's fine to leave as is. – Semivitreous