code: private Environment checkLogicalDisjunction(Expr.LogicalOr expr, boolean sign, Environment environment) {
  		Tuple<Expr> operands = expr.getOperands();
  		if (sign) {
  			Environment[] refinements = new Environment[operands.size()];
  			for (int i = 0; i != operands.size(); ++i) {
  				refinements[i] = checkCondition(operands.get(i), sign, environment);
  				// The clever bit. Recalculate assuming opposite sign.
  				environment = checkCondition(operands.get(i), !sign, environment);
  			}
  			// Done.
  			return FlowTypeUtils.union(refinements);
  		} else {
  			for (int i = 0; i != operands.size(); ++i) {
  				environment = checkCondition(operands.get(i), sign, environment);
  			}
  			return environment;
  		}
  	}
docs: In this case, we are assuming the environments are exclusive from each other
  (i.e. this is the opposite of threading them through). For example, consider
  this case:
  
  <pre>
  function f(int|null x) -> (bool r):
  return (x is null) || (x >= 0)
  </pre>
  
  The environment produced by the left condition is <code>{x->null}</code>. We
  cannot thread this environment into the right condition as, clearly, it's not
  correct. Instead, we want to thread through the environment which arises on
  the assumption the fist case is false. That would be <code>{x->!null}</code>.
  Finally, the resulting environment is simply the union of the two
  environments from each case.
  
  @param operands
  @param sign
  @param environment
  
  @return