diff --git a/config/src/main/java/com/typesafe/config/impl/ConfigSubstitution.java b/config/src/main/java/com/typesafe/config/impl/ConfigSubstitution.java index f74d3776..31b6102b 100644 --- a/config/src/main/java/com/typesafe/config/impl/ConfigSubstitution.java +++ b/config/src/main/java/com/typesafe/config/impl/ConfigSubstitution.java @@ -32,7 +32,10 @@ final class ConfigSubstitution extends AbstractConfigValue implements final private List<Object> pieces; // the length of any prefixes added with relativized() final private int prefixLength; - final private boolean ignoresFallbacks; + + // this is just here to avoid breaking serialization; + // it is always false at the moment. + final private boolean ignoresFallbacks = false; ConfigSubstitution(ConfigOrigin origin, List<Object> pieces) { this(origin, pieces, 0, false); @@ -43,11 +46,14 @@ final class ConfigSubstitution extends AbstractConfigValue implements super(origin); this.pieces = pieces; this.prefixLength = prefixLength; - this.ignoresFallbacks = ignoresFallbacks; + for (Object p : pieces) { if (p instanceof Path) throw new RuntimeException("broken here"); } + + if (ignoresFallbacks) + throw new ConfigException.BugOrBroken("ConfigSubstitution may never ignore fallbacks"); } @Override @@ -108,12 +114,15 @@ final class ConfigSubstitution extends AbstractConfigValue implements @Override protected AbstractConfigValue mergedWithNonObject(AbstractConfigValue fallback) { - // if the optional substitution ends up getting deleted (because it is - // not present), we'll have to use the fallback. So delay the merge. - if (pieces.size() == 1 && ((SubstitutionExpression) pieces.get(0)).optional()) - return mergedLater(fallback); - else - return super.mergedWithNonObject(fallback); + // We may need the fallback for two reasons: + // 1. if an optional substitution ends up getting deleted + // because it is not defined + // 2. if the substitution is self-referential + // + // we can't easily detect the self-referential case since the cycle + // may involve more than one step, so we have to wait and + // merge later when resolving. + return mergedLater(fallback); } @Override