docs: @Override
      ResolveResult<? extends AbstractConfigValue> resolveSubstitutions(ResolveContext context, ResolveSource source) {
          ResolveContext newContext = context.addCycleMarker(this);
          AbstractConfigValue v;
          try {
              ResolveSource.ResultWithPath resultWithPath = source.lookupSubst(newContext, expr, prefixLength);
              newContext = resultWithPath.result.context;
  
              if (resultWithPath.result.value != null) {
                  if (ConfigImpl.traceSubstitutionsEnabled())
                      ConfigImpl.trace(newContext.depth(), "recursively resolving " + resultWithPath
                              + " which was the resolution of " + expr + " against " + source);
  
                  ResolveSource recursiveResolveSource = (new ResolveSource(
                          (AbstractConfigObject) resultWithPath.pathFromRoot.last(), resultWithPath.pathFromRoot));
  
                  if (ConfigImpl.traceSubstitutionsEnabled())
                      ConfigImpl.trace(newContext.depth(), "will recursively resolve against " + recursiveResolveSource);
  
                  ResolveResult<? extends AbstractConfigValue> result = newContext.resolve(resultWithPath.result.value,
                          recursiveResolveSource);
                  v = result.value;
                  newContext = result.context;
              } else {
                  ConfigValue fallback = context.options().getResolver().lookup(expr.path().render());
                  v = (AbstractConfigValue) fallback;
              }
          } catch (NotPossibleToResolve e) {
              if (ConfigImpl.traceSubstitutionsEnabled())
                  ConfigImpl.trace(newContext.depth(),
                          "not possible to resolve " + expr + ", cycle involved: " + e.traceString());
              if (expr.optional())
                  v = null;
              else
                  throw new ConfigException.UnresolvedSubstitution(origin(), expr
                          + " was part of a cycle of substitutions involving " + e.traceString(), e);
          }
  
          if (v == null && !expr.optional()) {
              if (newContext.options().getAllowUnresolved())
                  return ResolveResult.make(newContext.removeCycleMarker(this), this);
              else
                  throw new ConfigException.UnresolvedSubstitution(origin(), expr.toString());
          } else {
              return ResolveResult.make(newContext.removeCycleMarker(this), v);
          }
      }