Separate return and data stacks anyone
I'm sure I remember working with processors that had separate code return and data stacks back in the 80s. All you would have to do is protect the return stack from all but call and return instructions.
Actually now I think about it the "shadow stack" is just like the old code return stack. They've just left a copy of the return address on the data stack as well so as not to upset compilers/debuggers that expect to see it there.