presto-main/src/main/java/io/prestosql/sql/planner/EqualityInference.java/EqualityInference/newInstance
class EqualityInference:    public static EqualityInference newInstance(Metadata metadata, Collection<Expression> expressions)
    {
        DisjointSet<Expression> equalities = new DisjointSet<>();
        List<Expression> candidates = expressions.stream()
                .flatMap(expression -> extractConjuncts(expression).stream())
                .filter(expression -> isInferenceCandidate(metadata, expression))
                .collect(Collectors.toList());

        for (Expression expression : candidates) {
            ComparisonExpression comparison = (ComparisonExpression) expression;
            Expression expression1 = comparison.getLeft();
            Expression expression2 = comparison.getRight();

            equalities.findAndUnion(expression1, expression2);
        }

        Collection<Set<Expression>> equivalentClasses = equalities.getEquivalentClasses();

        // Map every expression to the set of equivalent expressions
        Map<Expression, Set<Expression>> byExpression = new HashMap<>();
        for (Set<Expression> equivalence : equivalentClasses) {
            equivalence.forEach(expression -> byExpression.put(expression, equivalence));
        }

        // For every non-derived expression, extract the sub-expressions and see if they can be rewritten as other expressions. If so,
        // use this new information to update the known equalities.
        Set<Expression> derivedExpressions = new LinkedHashSet<>();
        for (Expression expression : byExpression.keySet()) {
            if (derivedExpressions.contains(expression)) {
                continue;
            }

            List<Expression> subExpressions = SubExpressionExtractor.extract(expression).stream()
                    .filter(e -> !e.equals(expression))
                    .collect(Collectors.toList());

            for (Expression subExpression : subExpressions) {
                Set<Expression> equivalences = byExpression.getOrDefault(subExpression, ImmutableSet.of()).stream()
                        .filter(e -> !e.equals(subExpression))
                        .collect(Collectors.toSet());

                for (Expression equivalentSubExpression : equivalences) {
                    Expression rewritten = replaceExpression(expression, ImmutableMap.of(subExpression, equivalentSubExpression));
                    equalities.findAndUnion(expression, rewritten);
                    derivedExpressions.add(rewritten);
                }
            }
        }

        Multimap<Expression, Expression> equalitySets = makeEqualitySets(equalities);

        ImmutableMap.Builder<Expression, Expression> canonicalMappings = ImmutableMap.builder();
        for (Map.Entry<Expression, Expression> entry : equalitySets.entries()) {
            Expression canonical = entry.getKey();
            Expression expression = entry.getValue();
            canonicalMappings.put(expression, canonical);
        }

        return new EqualityInference(equalitySets, canonicalMappings.build(), derivedExpressions);
    }