PyUnicode_Append() now works in-place when it's possible
diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c
index 2303634..3eec75a 100644
--- a/Objects/unicodeobject.c
+++ b/Objects/unicodeobject.c
@@ -9775,19 +9775,80 @@
 }
 
 void
-PyUnicode_Append(PyObject **pleft, PyObject *right)
+PyUnicode_Append(PyObject **p_left, PyObject *right)
 {
-    PyObject *new;
-    if (*pleft == NULL)
-        return;
-    if (right == NULL || !PyUnicode_Check(*pleft)) {
-        Py_DECREF(*pleft);
-        *pleft = NULL;
+    PyObject *left, *res;
+
+    if (p_left == NULL) {
+        if (!PyErr_Occurred())
+            PyErr_BadInternalCall();
         return;
     }
-    new = PyUnicode_Concat(*pleft, right);
-    Py_DECREF(*pleft);
-    *pleft = new;
+    left = *p_left;
+    if (right == NULL || !PyUnicode_Check(left)) {
+        if (!PyErr_Occurred())
+            PyErr_BadInternalCall();
+        goto error;
+    }
+
+    if (PyUnicode_CheckExact(left) && left != unicode_empty
+        && PyUnicode_CheckExact(right) && right != unicode_empty
+        && unicode_resizable(left)
+        && (_PyUnicode_KIND(right) <= _PyUnicode_KIND(left)
+            || _PyUnicode_WSTR(left) != NULL))
+    {
+        Py_ssize_t u_len, v_len, new_len, copied;
+
+        /* FIXME: don't make wstr string ready */
+        if (PyUnicode_READY(left))
+            goto error;
+        if (PyUnicode_READY(right))
+            goto error;
+
+        /* FIXME: support ascii+latin1, PyASCIIObject => PyCompactUnicodeObject */
+        if (PyUnicode_MAX_CHAR_VALUE(right) <= PyUnicode_MAX_CHAR_VALUE(left))
+        {
+            u_len = PyUnicode_GET_LENGTH(left);
+            v_len = PyUnicode_GET_LENGTH(right);
+            if (u_len > PY_SSIZE_T_MAX - v_len) {
+                PyErr_SetString(PyExc_OverflowError,
+                                "strings are too large to concat");
+                goto error;
+            }
+            new_len = u_len + v_len;
+
+            /* Now we own the last reference to 'left', so we can resize it
+             * in-place.
+             */
+            if (unicode_resize(&left, new_len) != 0) {
+                /* XXX if _PyUnicode_Resize() fails, 'left' has been
+                 * deallocated so it cannot be put back into
+                 * 'variable'.  The MemoryError is raised when there
+                 * is no value in 'variable', which might (very
+                 * remotely) be a cause of incompatibilities.
+                 */
+                goto error;
+            }
+            /* copy 'right' into the newly allocated area of 'left' */
+            copied = PyUnicode_CopyCharacters(left, u_len,
+                                              right, 0,
+                                              v_len);
+            assert(0 <= copied);
+            *p_left = left;
+            return;
+        }
+    }
+
+    res = PyUnicode_Concat(left, right);
+    if (res == NULL)
+        goto error;
+    Py_DECREF(left);
+    *p_left = res;
+    return;
+
+error:
+    Py_DECREF(*p_left);
+    *p_left = NULL;
 }
 
 void