stevearc / conform.nvim

Lightweight yet powerful formatter plugin for Neovim
MIT License
2.89k stars 150 forks source link

bug: rustfmt errors out with `Unrecognized option: 'manifest-path'` when called in the presence of a Cargo.toml file #330

Closed nwj closed 5 months ago

nwj commented 6 months ago

Neovim version (nvim -v)

0.9.5

Operating system/version

MacOS Sonoma 14.2.1

Add the debug logs

Log file

Log file: /Users/nwj/.local/state/nvim/conform.log                                                                               

          error: `async move` blocks are only allowed in Rust 2018 or later                                                      
            --> <stdin>:11:23                                                                                                    
             |                                                                                                                   
          11 |         tokio::spawn( async move {                                                                                
             |                       ^^^^^^^^^^                                                                                  

          error[E0670]: `async fn` is not permitted in Rust 2015                                                                 
            --> <stdin>:17:1                                                                                                     
             |                                                                                                                   
          17 | async fn process(socket: TcpStream) {                                                                             
             | ^^^^^ to use `async fn`, switch to Rust 2018 or later                                                             
             |                                                                                                                   
             = help: pass `--edition 2021` to `rustc`                                                                            
             = note: for more on editions, read https://doc.rust-lang.org/edition-guide                                          

          13:21:09[ERROR] Formatter 'rustfmt' error: Unrecognized option: 'manifest-path'                                        

          13:21:24[ERROR] Formatter 'rustfmt' error: Unrecognized option: 'manifest-path'                                        

          13:22:40[ERROR] Formatter 'rustfmt' error: Unrecognized option: 'manifest-path'                                        

          13:27:48[ERROR] Formatter 'rustfmt' error: Unrecognized option: 'manifest-path'                                        

          13:27:52[ERROR] Formatter 'rustfmt' error: Unrecognized option: 'manifest-path'                                        

          13:31:43[ERROR] Formatter 'rustfmt' error: Unrecognized option: 'manifest-path'                                        

Formatters for this buffer:                                                                                                      
LSP: rust_analyzer                                                                                                               
rustfmt ready (rust) /Users/nwj/.config/cargo/bin/rustfmt                                                                        

Other formatters:                                                                                                                
gofmt unavailable: Command not found                                                                                             
prettier ready (json, css, html, javascript, javascriptreact, markdown, typescript, typescriptreact) /opt/homebrew/bin/prettier  
rubocop unavailable: Command not found                                                                                           
stylua ready (lua) /opt/homebrew/bin/stylua                                                                                      

Describe the bug

Attempts to run Rustfmt via Conform on Rust files that use async functions error out and no formatting occurs.

What is the severity of this bug?

breaking (some functionality is broken)

Steps To Reproduce

  1. Setup repro filesystem by creating tmp/Cargo.toml and tmp/src/main.rs as specified.
  2. Make sure you have rustfmt installed and up to date.
  3. nvim -u repro.lua
  4. :e src/main.rs
  5. Invoke Conform on the file (my repro.lua binds the format command to space + shift + f)
  6. :ConformInfo to witness error.

Expected Behavior

In file paths that include a Cargo.toml, Conform is able to invoke rustfmt on Rust files containing async syntax in a way that successfully formats the file without errors.

Minimal example file

tmp/src/main.rs

#[tokio::main]
async fn main() {
    println!("Hello world");
}

tmp/Cargo.toml

[package]
name = "tmp"
version = "0.1.0"
edition = "2021"

[dependencies]
tokio = { version = "1", features = ["full"]}

Minimal init.lua

-- DO NOT change the paths and don't remove the colorscheme
local root = vim.fn.fnamemodify("./.repro", ":p")

-- set stdpaths to use .repro
for _, name in ipairs({ "config", "data", "state", "cache" }) do
  vim.env[("XDG_%s_HOME"):format(name:upper())] = root .. "/" .. name
end

-- bootstrap lazy
local lazypath = root .. "/plugins/lazy.nvim"
if not vim.loop.fs_stat(lazypath) then
  vim.fn.system({
    "git",
    "clone",
    "--filter=blob:none",
    "--single-branch",
    "https://github.com/folke/lazy.nvim.git",
    lazypath,
  })
end
vim.opt.runtimepath:prepend(lazypath)

vim.g.mapleader = " "

-- install plugins
local plugins = {
  "folke/tokyonight.nvim",
  {
    "stevearc/conform.nvim",
    config = function()
      require("conform").setup({
        log_level = vim.log.levels.DEBUG,
        -- add your config here
        formatters_by_ft = { rust = { "rustfmt" }}
      })
    end,
    keys = {
        {
            "<leader>F",
            function()
                require("conform").format({ async = true})
            end,
            mode = "",
            desc = "Run auto-formatter",
        },
    },
  },
  -- add any other plugins here
}
require("lazy").setup(plugins, {
  root = root .. "/plugins",
})

vim.cmd.colorscheme("tokyonight")
-- add anything else here

Additional context

I believe this is happening because Conform is not setting the appropriate edition parameter when it calls rustfmt. https://github.com/stevearc/conform.nvim/pull/328 attempted to fix this, but fails when Conform is invoked in a filesystem path that includes a Cargo.toml file.

I believe the reason for this failure is that when Conform finds a Cargo.toml file, it attempts to pass the path to that file to rustfmt using the --manifest-path parameter. This fails because rustfmt does not support such a parameter (cargo fmt does, but I don't think Conform ever invokes cargo fmt?).

Potential fixes seem to me like:

stevearc commented 5 months ago

Did some research and it seems like there's no good way to get cargo fmt to operate on stdin. It does not seem to be built for the purpose of integrating with an editor. I don't love it, but I think the better approach is to parse the edition (hackily, because we don't have a toml parser) from the Cargo.toml file.