anchor.diff:      _toProcess.add(initial);
   
       while (!_toProcess.isEmpty) {
  -      // Note: every fact needs to check against its own type first and bail
  -      // early if it's redundant. This helps ensure that we don't get circular.
  +      _fromCurrent.clear();
  +
         var fact = _toProcess.removeFirst();
         if (fact is Required) {
           fact = _requiredIntoRequired(fact);
           if (fact == null) continue;
   
  -        if (!_requiredIntoDisallowed(fact)) continue;
  +        fact = _requiredIntoDisallowed(fact);
  +        if (fact == null) continue;
  +
           _requiredIntoDependencies(fact);
           _requiredIntoIncompatibilities(fact);
  +
  +        _required[fact.name] = fact;
         } else if (fact is Disallowed) {
  -        if (!_disallowedIntoDisallowed(fact)) continue;
  +        fact = _disallowedIntoDisallowed(fact);
  +        if (fact == null) continue;
  +
           if (!_disallowedIntoRequired(fact)) continue;
           _disallowedIntoDependencies(fact);
           _disallowedIntoIncompatibilities(fact);
  +
  +        _disallowed[fact.dep.toRef()] = fact;
         } else if (fact is Dependency) {
           fact = _dependencyIntoDependency(fact);
           if (fact == null) continue;
   
  -        if (!_dependencyIntoReqired(fact)) continue;
  -      }
  +        fact = _dependencyIntoReqired(fact);
  +        if (fact == null) continue;
  +
  +        _dependenciesByDepender
  +            .putIfAbsent(fact.depender.toRef(), () => new Set())
  +            .add(fact);
  +        _dependenciesByAllowed
  +            .putIfAbsent(fact.allowed.toRef(), () => new Set())
  +            .add(fact);
  +      }
  +
  +      _toProcess.addAll(_fromCurrent);
       }
     }
   
  
positive.code:       if (trimmed == dependency.allowed.constraint) continue;
  
        // If [fact] covers some of [dependency.allowed], trim the dependency so
        // that its constraint doesn't include disallowed versions. If this would
        // produce an empty constraint, mark the depender as disallowed.
        _removeDependency(dependency);
  
        if (trimmed.isEmpty) {
          _toProcess.add(new Disallowed(dependency.depender, [dependency, fact]));
        } else {
          _toProcess.add(new Dependency(
              dependency.depender,
              dependency.allowed.withConstraint(trimmed),
              [dependency, fact]));
  
negative.code:       var allowed = _transitiveAllowed(fact.allowed, relevant);
        if (allowed == null) continue;
  
        _fromCurrent.add(new Dependency(
            dependency.depender, allowed, [dependency].addAll(relevant)));
      }
  
      return fact;
    }
  
    Dependency _dependencyIntoRequired(Dependency fact) {
      var required = _required[fact.depender.name];
      if (required != null) {
        if (required.toRef() != fact.depender.toRef()) return null;
  
        // Trim [fact] or throw it away if it's irrelevant. For example, if
        //
        // * a [0, 2) depends on b [0, 1) (fact)
        // * a [1, 3) is required (required)
        //
        // we can remove [fact] and add
        //
        // * a [1, 2) depends on b [0, 1)
        //
        // If this would produce an empty depender, we instead remove [dependency]
        // entirely.
        var intersection = required.dep.constraint
            .intersect(fact.depender.constraint);
        if (intersection.isEmpty) return null;
        if (intersection != fact.depender.constraint) {
          fact = new Dependency(
              fact.depender.withConstraint(intersection),
              fact.allowed,
              [required, fact]);
        }
  
        // If [fact]'s depender is required, see if we can come up with a merged
        // requirement based on all its dependers' dependencies. For example, if
        //
        // * a [0, 1) depends on b [0, 1) (fact)
        // * a [1, 2) depends on b [1, 2) (in siblings)
        // * a [0, 2) is required (required)
        //
        // we can add
        //
        // * b [0, 2) is required
        var allowedRef = fact.allowed.toRef();
        var siblings = _dependenciesByDepender[fact.depender.toRef()]
            .where((dependency) => dependency.allowed.toRef() == allowedRef)
            .toList()..add(fact);
        var allowed = _transitiveAllowed(fact.dep, sibilngs);
        if (allowed != null) {
          var newRequired = new Required(allowed, [required].addAll(siblings));
  
          // If [fact] entirely covered [required], [fact] is now redundant and
          // can be discarded. For example, if
          //
          // * a [0, 1) depends on b [0, 1) (fact)
          // * a [0, 1) is required (required)
          //
          // we can remove [fact] and add
          //
          // * b [0, 1) is required
          if (siblings.length == 1) {
            // Add to [_toProcess] because [_fromCurrent] will get discarded when
            // we return `null`.
            _toProcess.add(newRequired);
            return null;
          } else {
            _fromCurrent.add(newRequired);
          }
        }
      }
  
      required = _required[fact.allowed.name];
      if (required != null) {
        if (required.toRef() != fact.allowed.toRef()) return null;
  
        var intersection = required.dep.constraint
            .intersect(fact.allowed.constraint);
        if (intersection == fact.allowed.constraint) return null;
  
        // TODO: stuff
      }
    }
  
    // Resolves [required] and [disallowed], which should refer to the same
    // package.
    //
    // Returns a trimmed copy of [required], or `null` if it had no overlap with
    // [disallowed].
    Required _requiredAndDisallowed(Required required, Disallowed disallowed) {
      assert(required.dep.toRef() == disallowed.dep.toRef());
  
      var difference = required.dep.constraint.difference(
          disallowed.dep.constraint);
      if (difference.isEmpty) throw "Incompatible constriants!";
      if (difference == required.dep.constraint) return null;
  
      return new Required(
          required.dep.withConstraint(difference), [required, disallowed]);
    }
  
    void _removeDependency(Dependency dependency);
  