Let me give some motivation for this code:
A could represent some mathematical structure. For example a vector space. F could be an implementation of a vector space that uses a simple type internally to represent vectors (Int in the code).
Now vectors from different vector spaces should not be mixed up, as that doesn’t make sense (even when the vector spaces are isomorphic). For example, two vectors from different vector spaces should not be added together. Hence the opaque type.
H could be implementing an extension of the mathematical structure; for example vector spaces with cross products. To that end, it needs to refine the return type of foo, which could, say, be a way to get a basis for the vector space.
I don’t think the math can be modeled satisfactorily without opaque on B. Creating a surrounding shared scope would work, although it makes the abstraction leaky within that scope, forces all the code to be in the same file, and makes importing harder, amongst others.
I think the best is still an ugly cast:
override def foo: G & E & I = (new G() with I).asInstanceOf[G & E & I]
I do feel there is something wrong with opaque semantics that is highlighted by this code, though. Perhaps the compiler should know that, in that context, G is a subtype of E? Or perhaps opaque scopes could sometimes be protected?