First of all, apologies: the part "it can have a different
element type" is actually forbidden by the spec.
Still, look at this example:
CL-USER> (defvar *a* (make-array 5 :initial-contents '(1 2 3 4 5)
:element-type '(unsigned-byte 8)))
*A*
CL-USER> (defvar *b* (make-array 5 :displaced-to *a*
:element-type '(unsigned-byte 8)))
*B*
CL-USER> (eq (array-displacement *b*) *a*)
T
CL-USER> (defvar *c* (make-array 5 :displaced-to *a*
:element-type '(unsigned-byte 8)))
*C*
CL-USER> (adjust-array *b* 5 :displaced-to *c*)
#<(VECTOR (UNSIGNED-BYTE 8) 5) {1011F11FEF}>
CL-USER> (eq * *b*)
T
CL-USER> (eq (array-displacement *b*) *c*)
T
Here, ADJUST-ARRAY is used to
destructively (see the EQ calls) mutate *B*, so that it is
displaced to a displaced array *C*, rather than the simple array
*A*. This means that we now have two layers of indirection (B
-> C -> A) rather than just one (B -> A), at which point
your code that was compiled with just one layer of indirection in
mind is going to fail.
(The destructive behavior is not
mandated by the spec, but it's made possible, and SBCL makes use
of this to avoid copying.)
I assume that changing this behavior
would require new specialized types for displaced arrays,
including their expected indirection level, so that the compiler
can get the information it needs to try and emit optimized code...
---------------------------
...but it gets worse, possibly
preventing the above optimization. There is no guarantee that this
indirection won't change during the course of a single function.
Think of the above example, but
multithreaded: one thread is accessing *B* in a loop while another
thread calls ADJUST-ARRAY on *B* (or *C*!) and effectively changes
the storage accessed by the first thread. The proper way to deal
with this would be to respect the indirection, which means that
this indirection needs to find its way into the final code for
each array access, and this is going to prevent optimizations.
The above can't easily get "fixed" by
the compiler. However, if you want to get a "static" hold on the
actual storage and not have it moved by other threads during your
loop, your function can probably call ARRAY-DISPLACEMENT itself
until it gets a non-displaced array, and then it can access that
instead.