private static Set<DimensionBindingForPath> wildcardExpanded(Set<DimensionBindingForPath> variants) {
        Set<DimensionBindingForPath> expanded = new HashSet<>();

        PathTree trie = new PathTree();
        for (var variant : variants)
            trie.add(variant);

        // Visit all variant prefixes, grouped on path, and all their unique child bindings.
        trie.forEachPrefixAndChildren((prefixes, childBindings) -> {
            Set<DimensionBinding> processed = new HashSet<>();
            for (DimensionBindingForPath prefix : prefixes)
                if (processed.add(prefix.binding())) // Only compute once for similar bindings, since path is equal.
                    if (hasWildcardBeforeEnd(prefix.binding()))
                        for (DimensionBinding childBinding : childBindings)
                            if (childBinding != prefix.binding()) {
                                DimensionBinding combined = prefix.binding().combineWith(childBinding);
                                if ( ! combined.isInvalid())
                                    expanded.add(new DimensionBindingForPath(combined, prefix.path()));
                            }
        });

        return expanded;
    }
For variants which are underspecified we must explicitly resolve each possible combination
of actual left-side values.

I.e if we have the variants [-,b=b1], [a=a1,-], [a=a2,-],
this returns the variants [a=a1,b=b1], [a=a2,b=b1]

This is necessary because left-specified values takes precedence, and resolving [a=a1,b=b1] would
otherwise lead us to the compiled profile [a=a1,-], which may contain default values for properties where
we should have preferred variant values in [-,b=b1].
container-search/src/main/java/com/yahoo/search/query/profile/QueryProfileCompiler.java