diff --git a/config/src/main/java/com/typesafe/config/impl/ConfigConcatenation.java b/config/src/main/java/com/typesafe/config/impl/ConfigConcatenation.java
index 1a561def..806e57b8 100644
--- a/config/src/main/java/com/typesafe/config/impl/ConfigConcatenation.java
+++ b/config/src/main/java/com/typesafe/config/impl/ConfigConcatenation.java
@@ -68,33 +68,26 @@ final class ConfigConcatenation extends AbstractConfigValue implements Unmergeab
     @Override
     AbstractConfigValue resolveSubstitutions(ResolveContext context) throws NotPossibleToResolve {
         List<AbstractConfigValue> resolved = new ArrayList<AbstractConfigValue>(pieces.size());
-        // if you have "foo = ${?foo}bar" then we will
-        // self-referentially look up foo and we need to
-        // get undefined, rather than "bar"
-        context.source().replace(this, ResolveReplacer.cycleResolveReplacer);
-        try {
-            for (AbstractConfigValue p : pieces) {
-                // to concat into a string we have to do a full resolve,
-                // so unrestrict the context
-                AbstractConfigValue r = context.unrestricted().resolve(p);
-                if (r == null) {
-                    // it was optional... omit
-                } else {
-                    switch (r.valueType()) {
-                    case LIST:
-                    case OBJECT:
-                        // cannot substitute lists and objects into strings
-                        // we know p was a ConfigReference since it wasn't
-                        // a ConfigString
-                        String pathString = ((ConfigReference) p).expression().toString();
-                        throw new ConfigException.WrongType(r.origin(), pathString, "not a list or object", r.valueType().name());
-                    default:
-                        resolved.add(r);
-                    }
+        for (AbstractConfigValue p : pieces) {
+            // to concat into a string we have to do a full resolve,
+            // so unrestrict the context
+            AbstractConfigValue r = context.unrestricted().resolve(p);
+            if (r == null) {
+                // it was optional... omit
+            } else {
+                switch (r.valueType()) {
+                case LIST:
+                case OBJECT:
+                    // cannot substitute lists and objects into strings
+                    // we know p was a ConfigReference since it wasn't
+                    // a ConfigString
+                    String pathString = ((ConfigReference) p).expression().toString();
+                    throw new ConfigException.WrongType(r.origin(), pathString,
+                            "not a list or object", r.valueType().name());
+                default:
+                    resolved.add(r);
                 }
             }
-        } finally {
-            context.source().unreplace(this);
         }
 
         // now need to concat everything
diff --git a/config/src/test/scala/com/typesafe/config/impl/ConfigSubstitutionTest.scala b/config/src/test/scala/com/typesafe/config/impl/ConfigSubstitutionTest.scala
index 026c0338..7c88994c 100644
--- a/config/src/test/scala/com/typesafe/config/impl/ConfigSubstitutionTest.scala
+++ b/config/src/test/scala/com/typesafe/config/impl/ConfigSubstitutionTest.scala
@@ -1053,6 +1053,19 @@ class ConfigSubstitutionTest extends TestUtils {
         assertEquals(1, resolved.getInt("a.b.c"))
     }
 
+    @Test
+    def substSelfReferenceAlongPathMoreComplex() {
+        // this is an example from the spec
+        val obj = parseObject("""
+    foo : { a : { c : 1 } }
+    foo : ${foo.a}
+    foo : { a : 2 }
+                """)
+        val resolved = resolve(obj)
+        assertEquals(1, resolved.getInt("foo.c"))
+        assertEquals(2, resolved.getInt("foo.a"))
+    }
+
     @Test
     def substSelfReferenceIndirect() {
         val obj = parseObject("""a=1, b=${a}, a=${b}""")
@@ -1131,6 +1144,27 @@ class ConfigSubstitutionTest extends TestUtils {
         assertEquals("foo", resolved.getString("a"))
     }
 
+    @Test
+    def substOptionalIndirectSelfReferenceInConcat() {
+        val obj = parseObject("""a=${?b}foo,b=${a}""")
+        val resolved = resolve(obj)
+        assertEquals("foo", resolved.getString("a"))
+    }
+
+    @Test
+    def substTwoOptionalSelfReferencesInConcat() {
+        val obj = parseObject("""a=${?a}foo${?a}""")
+        val resolved = resolve(obj)
+        assertEquals("foo", resolved.getString("a"))
+    }
+
+    @Test
+    def substTwoOptionalSelfReferencesInConcatWithPriorValue() {
+        val obj = parseObject("""a=1,a=${?a}foo${?a}""")
+        val resolved = resolve(obj)
+        assertEquals("1foo1", resolved.getString("a"))
+    }
+
     @Test
     def substSelfReferenceMiddleOfStack() {
         val obj = parseObject("""a=1, a=${a}, a=2""")