This is a slightly less ambitious version of the (now reverted) commit 377cef8d, which had a bunch of issues that I don't have time to resolve right now.