code: private ImmutableList<Fact> description() {
      String description = null;
      boolean descriptionWasDerived = false;
      for (Step step : steps) {
        if (step.isCheckCall()) {
          checkState(description != null);
          if (step.descriptionUpdate == null) {
            description = null;
            descriptionWasDerived = false;
          } else {
            description = verifyNotNull(step.descriptionUpdate.apply(description));
            descriptionWasDerived = true;
          }
          continue;
        }
  
        if (description == null) {
          description =
              firstNonNull(step.subject.internalCustomName(), step.subject.typeDescription());
        }
      }
      return descriptionWasDerived
          ? ImmutableList.of(fact("value of", description))
          : ImmutableList.<Fact>of();
    }
docs: Returns a description of how the final actual value was derived from earlier actual values in
  the chain, if the chain ends with at least one derivation that we have a name for.
  
  <p>We don't want to say: "value of string: expected [foo] but was [bar]" (OK, we might still
  decide to say this, but for now, we don't.)
  
  <p>We do want to say: "value of throwable.getMessage(): expected [foo] but was [bar]"
  
  <p>To support that, {@code descriptionWasDerived} tracks whether we've been given context
  through {@code check} calls <i>that include names</i>.
  
  <p>If we're missing a naming function halfway through, we have to reset: We don't want to claim
  that the value is "foo.bar.baz" when it's "foo.bar.somethingelse.baz." We have to go back to
  "object.baz." (But note that {@link #rootUnlessThrowable} will still provide the value of the
  root foo to the user as long as we had at least one naming function: We might not know the
  root's exact relationship to the final object, but we know it's some object "different enough"
  to be worth displaying.)