Repository: intellij-rust/intellij-rust
Issue: java.lang.IllegalStateException while file renaming

## Environment

* **Intellij-Rust plugin version:** 0.2.93.2117-191
* **Rust toolchain version:** rust 1.33
* **IDE name and version:** CL-191.5849.15
* **Operating system:** macOS 10.13.6

## Problem description

<details><summary>java.lang.IllegalStateException</summary>
<p>

```
java.lang.IllegalStateException: event.newChild must not be null
	at org.rust.lang.core.psi.RsPsiTreeChangeAdapter.beforeChildReplacement(RsPsiTreeChangeListener.kt:150)
	at com.intellij.psi.impl.PsiManagerImpl.fireEvent(PsiManagerImpl.java:380)
	at com.intellij.psi.impl.PsiManagerImpl.beforeChildReplacement(PsiManagerImpl.java:228)
	at com.intellij.psi.impl.file.impl.PsiVFSListener.lambda$beforePropertyChange$5(PsiVFSListener.java:260)
	at com.intellij.openapi.application.impl.ApplicationImpl.runWriteAction(ApplicationImpl.java:1054)
	at com.intellij.psi.impl.file.impl.PsiVFSListener.beforePropertyChange(PsiVFSListener.java:217)
	at com.intellij.psi.impl.file.impl.PsiVFSListener.before(PsiVFSListener.java:663)
	at com.intellij.psi.impl.file.impl.PsiVFSListener$2.before(PsiVFSListener.java:89)
	at sun.reflect.GeneratedMethodAccessor482.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at com.intellij.util.messages.impl.MessageBusConnectionImpl.deliverMessage(MessageBusConnectionImpl.java:114)
	at com.intellij.util.messages.impl.MessageBusImpl.doPumpMessages(MessageBusImpl.java:393)
	at com.intellij.util.messages.impl.MessageBusImpl.pumpWaitingBuses(MessageBusImpl.java:354)
	at com.intellij.util.messages.impl.MessageBusImpl.pumpMessages(MessageBusImpl.java:343)
	at com.intellij.util.messages.impl.MessageBusImpl.sendMessage(MessageBusImpl.java:320)
	at com.intellij.util.messages.impl.MessageBusImpl.access$100(MessageBusImpl.java:29)
	at com.intellij.util.messages.impl.MessageBusImpl$1.invoke(MessageBusImpl.java:192)
	at com.sun.proxy.$Proxy23.before(Unknown Source)
	at com.intellij.util.FileContentUtilCore.lambda$reparseFiles$0(FileContentUtilCore.java:64)
	at com.intellij.openapi.application.impl.ApplicationImpl.runWriteAction(ApplicationImpl.java:1054)
	at com.intellij.util.FileContentUtilCore.reparseFiles(FileContentUtilCore.java:55)
	at com.intellij.util.FileContentUtilCore.reparseFiles(FileContentUtilCore.java:46)
	at com.intellij.openapi.file.exclude.EnforcedPlainTextFileTypeManager.lambda$setPlainTextStatus$0(EnforcedPlainTextFileTypeManager.java:77)
	at com.intellij.openapi.application.impl.ApplicationImpl.runWriteAction(ApplicationImpl.java:1054)
	at com.intellij.openapi.file.exclude.EnforcedPlainTextFileTypeManager.setPlainTextStatus(EnforcedPlainTextFileTypeManager.java:64)
	at com.intellij.openapi.file.exclude.EnforcedPlainTextFileTypeManager.resetOriginalFileType(EnforcedPlainTextFileTypeManager.java:60)
	at com.intellij.openapi.file.exclude.ui.MarkAsOriginalTypeAction.actionPerformed(MarkAsOriginalTypeAction.java:34)
	at com.intellij.openapi.actionSystem.ex.ActionUtil$1.run(ActionUtil.java:260)
	at com.intellij.openapi.actionSystem.ex.ActionUtil.performActionDumbAware(ActionUtil.java:277)
	at com.intellij.openapi.actionSystem.impl.ActionMenuItem$ActionTransmitter.lambda$actionPerformed$0(ActionMenuItem.java:292)
	at com.intellij.openapi.wm.impl.FocusManagerImpl.runOnOwnContext(FocusManagerImpl.java:283)
	at com.intellij.openapi.wm.impl.IdeFocusManagerImpl.runOnOwnContext(IdeFocusManagerImpl.java:107)
	at com.intellij.openapi.actionSystem.impl.ActionMenuItem$ActionTransmitter.actionPerformed(ActionMenuItem.java:282)
	at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2022)
	at com.intellij.openapi.actionSystem.impl.ActionMenuItem.lambda$fireActionPerformed$0(ActionMenuItem.java:111)
	at com.intellij.openapi.application.TransactionGuardImpl.runSyncTransaction(TransactionGuardImpl.java:88)
	at com.intellij.openapi.application.TransactionGuardImpl.lambda$submitTransaction$1(TransactionGuardImpl.java:111)
	at com.intellij.openapi.application.TransactionGuardImpl.submitTransaction(TransactionGuardImpl.java:120)
	at com.intellij.openapi.application.TransactionGuard.submitTransaction(TransactionGuard.java:121)
	at com.intellij.openapi.actionSystem.impl.ActionMenuItem.fireActionPerformed(ActionMenuItem.java:111)
	at com.intellij.ui.plaf.beg.BegMenuItemUI.doClick(BegMenuItemUI.java:524)
	at com.intellij.ui.plaf.beg.BegMenuItemUI.access$300(BegMenuItemUI.java:35)
	at com.intellij.ui.plaf.beg.BegMenuItemUI$MyMouseInputHandler.mouseReleased(BegMenuItemUI.java:546)
	at java.awt.Component.processMouseEvent(Component.java:6550)
	at javax.swing.JComponent.processMouseEvent(JComponent.java:3325)
	at java.awt.Component.processEvent(Component.java:6315)
	at java.awt.Container.processEvent(Container.java:2239)
	at java.awt.Component.dispatchEventImpl(Component.java:4899)
	at java.awt.Container.dispatchEventImpl(Container.java:2297)
	at java.awt.Component.dispatchEvent(Component.java:4721)
	at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4904)
	at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4535)
	at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4476)
	at java.awt.Container.dispatchEventImpl(Container.java:2283)
	at java.awt.Window.dispatchEventImpl(Window.java:2746)
	at java.awt.Component.dispatchEvent(Component.java:4721)
	at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:766)
	at java.awt.EventQueue.access$500(EventQueue.java:98)
	at java.awt.EventQueue$3.run(EventQueue.java:715)
	at java.awt.EventQueue$3.run(EventQueue.java:709)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:74)
	at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:84)
	at java.awt.EventQueue$4.run(EventQueue.java:739)
	at java.awt.EventQueue$4.run(EventQueue.java:737)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:74)
	at java.awt.EventQueue.dispatchEvent(EventQueue.java:736)
	at com.intellij.ide.IdeEventQueue.defaultDispatchEvent(IdeEventQueue.java:723)
	at com.intellij.ide.IdeEventQueue._dispatchEvent(IdeEventQueue.java:668)
	at com.intellij.ide.IdeEventQueue.dispatchEvent(IdeEventQueue.java:367)
	at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:205)
	at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
	at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
	at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)
```

</p>
</details>

## Steps to reproduce
Just rename file `foo.txt` to `foo.rs`


Changed files:
src/test/kotlin/org/rust/ide/refactoring/RenameTest.kt, src/main/kotlin/org/rust/lang/core/psi/RsPsiTreeChangeListener.kt

diff --git a/src/main/kotlin/org/rust/lang/core/psi/RsPsiTreeChangeListener.kt b/src/main/kotlin/org/rust/lang/core/psi/RsPsiTreeChangeListener.kt
index 9d0e4c338..5e969fae1 100644
--- a/src/main/kotlin/org/rust/lang/core/psi/RsPsiTreeChangeListener.kt
+++ b/src/main/kotlin/org/rust/lang/core/psi/RsPsiTreeChangeListener.kt
@@ -58,15 +58,28 @@ sealed class RsPsiTreeChangeEvent {
         override val file: PsiFile?,
         val parent: PsiElement,
         /** Invalid in [ChildReplacement.After] */
-        val oldChild: PsiElement,
-        val newChild: PsiElement
+        val oldChild: PsiElement
     ) : RsPsiTreeChangeEvent() {
-        class Before(file: PsiFile?, parent: PsiElement, oldChild: PsiElement, newChild: PsiElement) : ChildReplacement(file, parent, oldChild, newChild)
-        class After(file: PsiFile?, parent: PsiElement, oldChild: PsiElement, newChild: PsiElement) : ChildReplacement(file, parent, oldChild, newChild)
+
+        abstract val newChild: PsiElement?
+
+        class Before(
+            file: PsiFile?,
+            parent: PsiElement,
+            oldChild: PsiElement,
+            override val newChild: PsiElement?
+        ) : ChildReplacement(file, parent, oldChild)
+
+        class After(
+            file: PsiFile?,
+            parent: PsiElement,
+            oldChild: PsiElement,
+            override val newChild: PsiElement
+        ) : ChildReplacement(file, parent, oldChild)
 
         override fun toString(): String =
             "ChildReplacement.${javaClass.simpleName}(file=$file, parent=`${parent.text}`, " +
-                "oldChild=`${oldChild.safeText}`, newChild=`${newChild.text}`)"
+                "oldChild=`${oldChild.safeText}`, newChild=`${newChild?.text}`)"
     }
 
     sealed class ChildMovement(
diff --git a/src/test/kotlin/org/rust/ide/refactoring/RenameTest.kt b/src/test/kotlin/org/rust/ide/refactoring/RenameTest.kt
index 7b27dbc67..ec9af0a7b 100644
--- a/src/test/kotlin/org/rust/ide/refactoring/RenameTest.kt
+++ b/src/test/kotlin/org/rust/ide/refactoring/RenameTest.kt
@@ -403,6 +403,18 @@ class RenameTest : RsTestBase() {
         }
     """)
 
+    // https://github.com/intellij-rust/intellij-rust/issues/3483
+    fun `test change file type`() = checkByDirectory("""
+    //- foo.txt
+        fn foo() {}
+    """, """
+    //- foo.rs
+        fn foo() {}
+    """) {
+        val file = myFixture.configureFromTempProjectFile("foo.txt")
+        myFixture.renameElement(file, "foo.rs")
+    }
+
     private fun doTest(
         newName: String,
         @Language("Rust") before: String,