6

The Rust Reference presently says the following about the as operator:

7.2.12.5 Type cast expressions

A type cast expression is denoted with the binary operator as.

Executing an as expression casts the value on the left-hand side to the type on the right-hand side.

An example of an as expression:

fn average(values: &[f64]) -> f64 {
  let sum: f64 = sum(values);
  let size: f64 = len(values) as f64;
  sum / size
}

(Also, since it will be relevant:

7.2.12.8 Operator precedence

The precedence of Rust binary operators is ordered as follows, going from strong to weak:

as
* / %
+ -
<< >>

)

Naïvely using this as an operator doesn't seem to work:

fn main() {
    let x = 100 as u16 << 8;
}

Doesn't actually compile:

% rustc testing.rs
testing.rs:2:24: 2:25 error: expected type, found `8`
testing.rs:2    let x = 100 as u16 << 8;

With parentheses — let x = (100 as u16) << 8; — it compiles. The parens aren't required in the example in the reference, but seem to be here. What's the exact syntax here? Are parentheses required unless this is the only thing right of an =? Or am I just doing something wrong?

It is a bit weird that this is called an operator, as the RHS would seem to need to be a type, and typically, I think of an operator as taking two expressions…

Thanatos
  • 42,585
  • 14
  • 91
  • 146
  • The only surprising thing here is that the Operator Precedence seems off in light of your experiment. Otherwise, I don't see the issue with `as` being an operator. – Matthieu M. Aug 19 '15 at 18:22

1 Answers1

14

The trick here is as takes a type on its right hand side, i.e. the grammar of as looks something like: is expression 'as' type. The expression after the as looks a bit like (the start of) a type, it's trying to parse u16<<... as if u16 had a type parameter (an example of a type with a prefix like that would be Foo<<T>::Bar>).

This is basically just behaviour particular to << because it looks like the type parameter delimiters. If one uses an operator that can't appear after the leading identifier in a type, it works fine:

fn main() {
    let x = 100 as u16 - 8;
}
huon
  • 94,605
  • 21
  • 231
  • 225
  • 1
    Out of curiosity, what's the meaning of `` in your example? I.e., how is `` not preceded by an identifier, like `Foo::Bar>`? – Thanatos Aug 19 '15 at 21:40
  • 1
    It's part of "fully qualified paths", e.g. to refer to the asociated type `Bar` in the implementation of a trait `Trait` for a type `T`, one can write `::Bar` which can (sometimes) be abbreviated as `::Bar`. (Either the abbreviation or the full form is enough for this purpose: there's valid types with leading `<`.) – huon Aug 19 '15 at 22:25