‹ BackHN Continuity

Thread

Why building a Rust LSP is hard

144 points · 77 comments · agluszak

  1. klodolph · · focus · HN ↗
    The particulars of Rust make this a little more difficult, I think. There’s a certain tension between making your language more concise and adding useful redundancies, and Rust has generally gone to the “concise” side, with some redundancies that can make the tooling a little more painful. Like with imports.

      impl std::fmt::Display for Blah {
      }
    
    If your language makes you qualify your imports (like above) then your LSP can, delightfully, still reliably do certain ops like renaming, even when chunks of your project aren’t parsing. But if you glob import std::fmt, and glob import something else, you are fucked. Display could come from anywhere (maybe from a module that has a parse error at the moment). I really appreciate languages where glob imports (or their equivalent) are either disallowed entirely or where typical code doesn’t use it.

    Meanwhile, if you add a new file, there’s this little dance where you say:

      mod mycoolmod;
    
    And then you create mycoolmod.rs. Or you do it the other way around. A little redundancy (the file exists and it is declared), that seems to just create a little friction in the LSP because mycoolmod doesn’t get a working LSP until it’s declared in the parent (you have to create both, and then you get a transient diagnostic that your module is unused for a while yet). A small issue, just another little bit of friction in the tooling of Rust that has nothing to do with the type system.
    1. verandaguy · · focus · HN ↗
      Having worked with rust for nearly two years now (granted, on one team with agreed-upon standards):

      - glob imports are rare in my experience, less for the LSP’s sake and more for code self-documentation

      - the `mod foo` line exists because omitting it cannot fall back to a reasonable default visibility level (`pub`/`pub(crate)`/<none> (private))

      1. yencabulator · · focus · HN ↗
        Of course it could just default to private, and if you wanted something you'd have to specify that.
        1. verandaguy · · focus · HN ↗
          At this point...

          - I don't think that private-default is a universally (or more importantly, widely) reasonable default

          - It adds another case where Rust is unopinionated and gives the user another way to do a basic function.

          I like Rust for its unopionation, generally, but I think that the returns for this kind of thing diminish as you get to really boilerplate stuff.

          1. yencabulator · · focus · HN ↗
            I'll argue the default already is private.

              mod foo
              pub mod foo
              pub(crate) mod foo
            
            clearly when you leave the visibility modifier out, the default is private.
    2. yencabulator · · focus · HN ↗
      Wildcard imports are a horrible idea.

      (And anyone pushing to have a "prelude" for their library is making it worse. Please don't.)

      Clippy `wildcard_imports = "warn"` is your friend.

Open on Hacker News to reply ↗

Unofficial Hacker News client; not affiliated with Y Combinator.