refactored to avoid gcc ICEs