rust-lang / rust-analyzer

A Rust compiler front-end for IDEs
https://rust-analyzer.github.io/
Apache License 2.0
14.25k stars 1.61k forks source link

Autocomplete of generic functions that require turbofish #2890

Open JMS55 opened 4 years ago

JMS55 commented 4 years ago

Consider the following function signature:

fn get<T: Component>(&self, entity: Entity) -> Result<Ref<T>, ComponentError>

This has a type parameter T, that does not show up anywhere inside the parameters, requiring you to use turbo fish syntax (or explicitly label a variable with a type, if you're binding to a variable. Or if you are passing this value to a function, you don't really need to give a type at all).


Right now, autocomplete of this function looks like this:

ecs.get(CURSOR)

Instead, it would be helpful if it looked like this:

ecs.get::<CURSOR>(CURSOR_AFTER_TABBING)
flodiebold commented 2 years ago

Another example is std::mem::size_of::<T>(), which doesn't even have the type parameter in the return, so you always need the turbofish.

Keavon commented 2 years ago

Does this include autocompleting .collect() into .collect::<Vec<_>>()? It'd sure be nice not having to always write ::<Vec<_>> all the time. Or if this doesn't match the request described in this issue, is there another issue for this?

flodiebold commented 2 years ago

It would maybe include autocompleting .collect() as .collect::<>(). But for things like collect, the type parameter can still often be inferred, and many people prefer adding the type hint to the let binding instead of the turbofish, so in that case this would not be helpful. And in general, I think we try to err on the side of not adding things that the user doesn't want and needs to remove.

flodiebold commented 2 years ago

So I actually think we can't implement the original request, since it's the same situation as collect. There's no way to tell whether the user will need the turbofish or whether it will be possible to infer.

Keavon commented 2 years ago

Perhaps an option, at least? It seems sensible to not add things the user doesn't want, but some people (i.e. those who prefer the turbofish) have to otherwise write that cumbersome set of special characters many times a day, compared to the downside of occasionally removing it if it's wrong. I'd personally like to enable such a setting if it were to exist, even if it's not enabled by default.

lnicola commented 2 years ago

The thing is, in many (most?) cases you don't actually need the turbofish once you finish writing the code. For example,

impl TryFrom<&Row<'_>> for Share {
    type Error = Error;

    fn try_from(row: &Row) -> Result<Self, Self::Error> {
        let r = Self {
            id: row.get(0)?,
            name: row.get(1)?,
            path: row.get::<_, PathBufWrapper>(2)?.into_inner(),
            access_level: row.get(3)?,
            upload_allowed: row.get(4)?,
        };
        Ok(r)
    }
}
flodiebold commented 2 years ago

And for those cases where you do need it, a diagnostic with quickfix could be more appropriate.