code: private Environment checkLogicalConjunction(Expr.LogicalAnd expr, boolean sign, Environment environment) {
  		Tuple<Expr> operands = expr.getOperands();
  		if (sign) {
  			for (int i = 0; i != operands.size(); ++i) {
  				environment = checkCondition(operands.get(i), sign, environment);
  			}
  			return environment;
  		} else {
  			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);
  		}
  	}
docs: In this case, we are threading each environment as is through to the next
  statement. For example, consider this example:
  
  <pre>
  function f(int|null x) -> (bool r):
  return (x is int) && (x >= 0)
  </pre>
  
  The environment going into <code>x is int</code> will be
  <code>{x->(int|null)}</code>. The environment coming out of this statement
  will be <code>{x-&gt;int}</code> and this is just threaded directly into the
  next statement <code>x &gt; 0</code>
  
  @param operands
  @param sign
  @param environment
  
  @return