docs: function objectTypeRelatedTo(source, originalSource, target, reportErrors) {
                  if (overflow) {
                      return 0 /* False */;
                  }
                  var id = relation !== identityRelation || source.id < target.id ? source.id + "," + target.id : target.id + "," + source.id;
                  var related = relation[id];
                  if (related !== undefined) {
                      if (reportErrors && related === 2 /* Failed */) {
                          // We are elaborating errors and the cached result is an unreported failure. Record the result as a reported
                          // failure and continue computing the relation such that errors get reported.
                          relation[id] = 3 /* FailedAndReported */;
                      }
                      else {
                          return related === 1 /* Succeeded */ ? -1 /* True */ : 0 /* False */;
                      }
                  }
                  if (depth > 0) {
                      for (var i = 0; i < depth; i++) {
                          // If source and target are already being compared, consider them related with assumptions
                          if (maybeStack[i][id]) {
                              return 1 /* Maybe */;
                          }
                      }
                      if (depth === 100) {
                          overflow = true;
                          return 0 /* False */;
                      }
                  }
                  else {
                      sourceStack = [];
                      targetStack = [];
                      maybeStack = [];
                      expandingFlags = 0;
                  }
                  sourceStack[depth] = source;
                  targetStack[depth] = target;
                  maybeStack[depth] = ts.createMap();
                  maybeStack[depth][id] = 1 /* Succeeded */;
                  depth++;
                  var saveExpandingFlags = expandingFlags;
                  if (!(expandingFlags & 1) && isDeeplyNestedGeneric(source, sourceStack, depth))
                      expandingFlags |= 1;
                  if (!(expandingFlags & 2) && isDeeplyNestedGeneric(target, targetStack, depth))
                      expandingFlags |= 2;
                  var result;
                  if (expandingFlags === 3) {
                      result = 1 /* Maybe */;
                  }
                  else {
                      result = propertiesRelatedTo(source, target, reportErrors);
                      if (result) {
                          result &= signaturesRelatedTo(source, target, 0 /* Call */, reportErrors);
                          if (result) {
                              result &= signaturesRelatedTo(source, target, 1 /* Construct */, reportErrors);
                              if (result) {
                                  result &= indexTypesRelatedTo(source, originalSource, target, 0 /* String */, reportErrors);
                                  if (result) {
                                      result &= indexTypesRelatedTo(source, originalSource, target, 1 /* Number */, reportErrors);
                                  }
                              }
                          }
                      }
                  }
                  expandingFlags = saveExpandingFlags;
                  depth--;
                  if (result) {
                      var maybeCache = maybeStack[depth];
                      // If result is definitely true, copy assumptions to global cache, else copy to next level up
                      var destinationCache = (result === -1 /* True */ || depth === 0) ? relation : maybeStack[depth - 1];
                      ts.copyProperties(maybeCache, destinationCache);
                  }
                  else {
                      // A false result goes straight into global cache (when something is false under assumptions it
                      // will also be false without assumptions)
                      relation[id] = reportErrors ? 3 /* FailedAndReported */ : 2 /* Failed */;
                  }
                  return result;
              }