Just for the record, this is by design according to the docs.
It would be nice if hasElaborateDestructor didn't compile for reference types. I don't know if the breakage is acceptable, but at least it would enforce correct usage.
Comment #3 by petar.p.kirov — 2016-04-05T12:04:06Z
But what about generic code that already (wrongly) relies on hasElaborateDestructor (such as std.experimental.allocator)? Should we add hasElaborateDestructor2 that handles both classes and structs and errors on unions?