Newbie here. Sorry if it's a dumb question.
Personally I would not worry about idiomatic. I like to see types on variable declarations. It shows my intention, maybe I really want u8's rather than some other type of integer, and may raise an error if I use the thing wrongly later. But sometimes it's convenient not to have to. I end up treating this on a case by case basis.
Here are a couple situations where I will sometimes annotate a variable's type even when not strictly necessary:
- When the expression is large so it can be difficult to quickly see what is actually being returned
let x: MyType = match {
Some(_) => {
// some
// stuff
}
None => {
// more
// stuff
}
};
- Late assignment. This is pretty niche but has come in handy sometimes.
let x: String;
// some stuff
x = "hello".to_string();
Usually, you don't specify the full type of every single variable. Local type annotations can generally be left out, except for when they serve a useful purpose, including but not limited to:
- in
unsafe
code, it's generally advisable to be very explicit, specifically around pointers and lifetimes; - to guide type inference with partial types, when code is highly generic (e.g.
let container: Vec<_> = iter.collect()
) or involves coercions (e.g. trait objects of different base types in different arms of a conditional); - or to disambiguate identically-named items e.g. the same method on different traits on a type implementing both traits.
I would say that typing every single local variable with its full type can become somewhat noisy and is definitely not the norm, especially when you use long, fully-qualified names in deeply nested generics.
However, do err on the side of being more explicit than shorter/more clever if you feel the need for some reason.
Note that rust-analyzer has the rust-analyzer.inlayHints.typeHints.enable
setting to have it show hints for the type of a variable. This means that if you do leave the type unspecified, you can still have an IDE show you what type has been inferred.
Definitely not a dumb question. Rust has documentation for naming.
Nothing directly relevant in it; you could take the last entry and over emphasize consistent. or the second to last and misconstrue free-of-placeholder.
Personally prefer to avoid showing types. It is down to what I prefer to read.
With type declared the information is only there at that point. If you name your variables well, you see it in later code (that makes use of the variable.)
I would likely decide this question on a case-by-case basis. Add explicit types where it improves readability, but skip them (where possible) where the extra verbosity makes it harder to read.
Also note that it's possible to annotate the type partially, e.g. omit lifetimes or type parameters (of generic types). Also here, a case-by-case decision may be useful.
Remember that the compiler does require that you give full and complete types on function parameters and returns.
So because of that I would generally suggest that you default to not writing types on immutable let
s yourself. Then, if you find that the types are getting complicated or you're not sure what's happening, consider trying to extract part of it out into a separate function -- then the name of that function will serve as documentation, and because the function will have types specified, it'll make the types clearer too.
As some others said, though, in other cases it can be helpful to annotate types. For something mutable, I'll often prefer let mut x = 0_usize;
because the interesting part will happen later in the code, so setting expectations that you can see at the declaration can help the reader. And in unsafe
code, where the compiler trusts you more, it's often better to be explicit about what you're doing -- in normal code all the checks will tend to keep wrong types from compiling, but invisibly getting something you didn't expect is more hazardous in code that's doing unchecked things.
TL/DR: Like how variable names can be short for small-scope things (like |x| x + 1
) but should be longer for long-lasting things, you should prefer fewer type annotations for simple local stuff and more type annotations for complicated long-lasting things.