Reapply r215966, r215965, r215964, r215963, r215960, r215959, r215958, and r215957

This reverts commit r215981, which reverted the above commits because
MSVC std::equal asserts on nullptr iterators, and thes commits
introduced an `ArrayRef::equals()` on empty ArrayRefs.

ArrayRef was changed not to use std::equal in r215986.