Use an `ImmutableSet` to represent the configuration hierarchy ImmutableSets are ordered and optimized for lookups. We happen to call `contains` a lot on hierarchies, so using a `Set` should optimize things a little.
Normalize `ModuleIdentifier` This commit reworks the `ComponentModuleIdentifier`/`ComponentModuleSelector`/`ModuleVersionSelector` classes to use `ModuleIdentifier` under the hood, instead of storing denormalized strings. This has the advantage that we can reduce the use of the module identifier factory, which is called very often during dependency resolution. Sharing instances reduces the need for conversions, and makes comparisons faster.