docs: public void infer() {
      scopes = StaticAnalysis.getScopes(expression);
      expressionTypes = Maps.newHashMap();
      constraints = ConstraintSet.empty();
      for (Scope scope : scopes.getScopes()) {
        for (String variable : scope.getBoundVariables()) {
          int location = scope.getBindingIndex(variable);
          if (!expressionTypes.containsKey(location)) {
            expressionTypes.put(location, constraints.getFreshTypeVar());
          }
        }
      }
  
      populateExpressionTypes(0);
      // TODO: root type.
      solved = constraints.solve(typeDeclaration);
  
      for (int k : expressionTypes.keySet()) {
        expressionTypes.put(k, expressionTypes.get(k).substitute(solved.getBindings()));
      }
    }