Type annotation

Here is a line of code that calculate sum of square of first n integers:

(1..=n).sum::<u32>().pow(2)

Can any one explain, why we are using sum::?

What I know is "::" is used for name space, so what is the purpose of using this operator here? Why we can not write is like?

(1..=n).sum<u32>().pow(2)

FYI, it seems you wrote sum::<u32>(), but the <u32> was interpreted as an HTML tag and doesn't show up. Enclose your code in backticks so it'll display properly.

As to your question, ::<> is the "turbofish operator," here used to specify the type of the generic parameter to the sum<S>() method. Without it, Rust wouldn't be able to tell what type sum() should return, as there could be multiple S's that implement Sum<u32> (assuming that n has already been explicitly annotated as u32, that is, otherwise it gets even more ambiguous).

1 Like

thanks @jwodder, let me edit my post as well

But dnt we use type annotation like?:

(1..=n).sum<u32>().pow(2)

No, that's invalid. The :: are needed so that the compiler can tell the difference between a turbofish and a less-than operation chained with a greater-than.

1 Like

See this file for an example where the turbofish is required for syntax disambiguity:

https://github.com/rust-lang/rust/blob/master/tests/ui/parser/bastion-of-the-turbofish.rs#L42

5 Likes

Turbofish (leading ::) is used in expressions. In type specific context, it is not.

Given how the biggest push to allow eliding the colons in expressions went (follow the links in the bastion comment), the turbofish is unlikely to ever go away.

Some say the turbofish is Ferris' (:crab:) friend or sidekick.

Because that expression already has a meaning:

  • (1..=n).sum < u32 means: take sum field and u32 variable and compare them[1]
  • (1..=n).sum < u32 >() means: tale value that you have on previous step and compare it with ()[2]
  • (1..=n).sum < u32 >().pow(2) means: take that comparison result and call pow now[3]

You may say that it's not what you have meant, but then, if you would involve types in the syntax parsing, you get nasty surprises and it becomes literally impossible to answer the question: does that thing that I have is a syntactically valid Rust code or not (it may depend on target platform and even then it's impossible to answer that question 100% of time).

Rust uses turbofish to avoid all that insanity. And it also avoid proliferation of typename and template tags in generics (which are needed because even with full compiler on your hand you still couldn't parse sum<u32>() properly in C++ is sum nested class.

Instead of spending hundreds of man-years and making every user learn bazillion complicated rules to save couple of characters Rust decided to use turbofish operator instead.

This was, obviously, the right thing to do.


  1. And yes, variable named u32 is perfectly valid in Rust ↩︎

  2. Again: nothing illegal there. ↩︎

  3. Again: totally no problems there. ↩︎

3 Likes

That is beautiful!

All hail the turbofish :slight_smile:

https://turbo.fish/

We learn to love our turbofish, I'm glad it found a fun name.

1 Like