Repository: rust-lang/rust-mode (language: rust)

Issue:
Use `cargo fmt` instead of `rustfmt`
For Rust 2018, rustfmt does not work correctly (e.g. removes leading `::` from `use` statements. The fact that `rust-mode` runs it instead of `cargo fmt` makes it problematic for writing 2018 code...

It would be nice to have this mode use the recommended `cargo fmt` command instead of `rustfmt`.

Thanks in advance!


Discussion / hints:
Could you provide a code snippet that it's formatting incorrectly? I'm not experiencing this issue myself, but am wondering if using rustfmt is actually the issue here. While playing with replacing the rustfmt calls, I found that `cargo fmt` itself will pass arguments to `rustfmt` given the `--` argument.
I stumbled upon it as a part of the Rust 2018 changes - where rustfmt did not respect the "Edition" directive in cargo.toml. I guess this is no longer the case so the priority of this should not be that critical IMO
Certainly still seems to be the case for me. See https://github.com/rust-lang/rustfmt/issues/3724
rustfmt does not respect Cargo.toml because it is intended for a stand-alone tool, even without cargo. You could still pass `--edition 2018` to rustfmt to let it understand that the files being passed use edition 2018.

Fix patch:
diff --git a/rust-mode.el b/rust-mode.el
index b361749e..5c686409 100644
--- a/rust-mode.el
+++ b/rust-mode.el
@@ -165,6 +165,11 @@ to the function arguments.  When nil, `->' will be indented one level."
   :type 'string
   :group 'rust-mode)
 
+(defcustom rust-rustfmt-switches '("--edition" "2018")
+  "Arguments to pass when invoking the `rustfmt' executable."
+  :type '(repeat string)
+  :group 'rust-mode)
+
 (defcustom rust-cargo-bin "cargo"
   "Path to cargo executable."
   :type 'string
@@ -1354,8 +1359,14 @@ This is written mainly to be used as `end-of-defun-function' for Rust."
     (erase-buffer)
     (insert-buffer-substring buf)
     (let* ((tmpf (make-temp-file "rustfmt"))
-           (ret (call-process-region (point-min) (point-max) rust-rustfmt-bin
-                                     t `(t ,tmpf) nil)))
+           (ret (apply 'call-process-region
+                       (point-min)
+                       (point-max)
+                       rust-rustfmt-bin
+                       t
+                       `(t ,tmpf)
+                       nil
+                       rust-rustfmt-switches)))
       (unwind-protect
           (cond
            ((zerop ret)
@@ -1465,16 +1476,20 @@ Return the created process."
   (interactive)
   (unless (executable-find rust-rustfmt-bin)
     (error "Could not locate executable \%s\"" rust-rustfmt-bin))
-  (let ((proc
-         (start-process "rustfmt-diff"
-                        (with-current-buffer
-                            (get-buffer-create "*rustfmt-diff*")
-                          (let ((inhibit-read-only t))
-                            (erase-buffer))
-                          (current-buffer))
-                        rust-rustfmt-bin
-                        "--check"
-                        (buffer-file-name))))
+  (let* ((buffer
+          (with-current-buffer
+              (get-buffer-create "*rustfmt-diff*")
+            (let ((inhibit-read-only t))
+              (erase-buffer))
+            (current-buffer)))
+         (proc
+          (apply 'start-process
+                 "rustfmt-diff"
+                 buffer
+                 rust-rustfmt-bin
+                 "--check"
+                 (cons (buffer-file-name)
+                       rust-rustfmt-switches))))
     (set-process-sentinel proc 'rust-format-diff-buffer-sentinel)
     proc))
 


Test patch: