Description
Since the constructor of `ExpressionSet` is protected, callers can only modify the state of an `ExpressionSet` by calling `add` and `remove`, so it maintains the invariants of:
- Every expr `e` in `baseSet` satisfies `e.deterministic && e.canonicalized == e`
- Every deterministic expr `e` in `originals` satisfies that `e.canonicalized` is already accessed.
The current implementation ignores the invariant and unnecessarily calls `.canonicalized` in lots of places which can cause performance issues as `canonicalized` is a pretty expensive operation.