Source:
<code>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 { v = getFallbackSubst(context); } } catch (NotPossibleToResolve e) { if (ConfigImpl.traceSubstitutionsEnabled()) ConfigImpl.trace(newContext.depth(), "not possible to resolve " + expr + ", cycle involved: " + e.traceString()); if (expr.optional()) v = getFallbackSubst(context); else throw new ConfigException.UnresolvedSubstitution(origin(), expr + " was part of a cycle of substitutions involving " + e.traceString(), e); } if (v == null && !expr.optional()) { <START> throw new ConfigException.UnresolvedSubstitution(origin(), expr.toString()); <END> } else { return ResolveResult.make(newContext.removeCycleMarker(this), v); } }</code><technical_language>clear code for checking getAllowUnresolved removed; I part of is in getFallbackSubst removeCycleMarker</technical_language>

Target:
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); } }