How type conversions work in Rust
Tags: rust
Published: 2021-08-12 10:23:33

---
title: How type conversions work in Rust 
published: true
description: This series details how to how to convert between Rust’s data types and how to navigate some of the edge cases.
tags: rust
//cover_image: https://direct_url_to_image.jpg
series:  Rust Type Conversion
canonical_url: https://tim.mcnamara.nz/post/659305450250141696/rust-type-conversions
---

## Background

Rust is a strongly-typed programming language with static typing. It’s also quite pedantic. For example, it’s impossible to compare two integers with each other if they are of the different types. To avoid any extra work at runtime, such as [reflection](https://href.li/?https://en.wikipedia.org/wiki/Reflective_programming), Rust requires us to be precise with the types that our programs use.

This small program won't compile:

```rust
// https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=4a0ad78e651e74bc52d986037eb21b0c
fn main() {
    let a: i32 = 10;
    let b: u32 = 10;
    println!("{}", a + b);
}
```

Instead creating a program that prints 20  to the console, we receive an error message with two error codes:

```
error[E0308]: mismatched types
 --> src/main.rs:4:22
  |
4 |   println!("{}", a + b); 
  |                      ^ expected `i32`, found `u32`

error[E0277]: cannot add `u32` to `i32`
 --> src/main.rs:4:20
  |
4 |   println!("{}", a + b); 
  |                    ^ no implementation for `i32 + u32`
  |
  = help: the trait `Add<u32>` is not implemented for `i32`
```

For the curious, here is some information about how to interpret those error codes. The first ([E0308](https://href.li/?https://doc.rust-lang.org/stable/error-index.html#E0308)) is caused because the addition operator (+) expects the same type for both of its operands. The second error ([E0277](https://href.li/?https://doc.rust-lang.org/stable/error-index.html#E0277)) is subtly different. It’s saying that the trait bounds (the interface) are not satisfied. Addition is provided by the std::ops::Add  trait and has been implicitly parameterized to i32 type by its left operand.

## Explicitly changing types with the as keyword

The most common method you’ll encounter to convert one type to another is via the as  keyword. It’s particularly common when converting between usize (which may be 32 or 64 bits wide, depending on CPU architecture) and fixed-width integers, such as `u32`.

One option that's available to us for fixing the earlier example is to promote both values to the type `i64`, which can represent all possible values within the `u32` and `i32` types:

```rust
// https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=b55bd9b4447b9b01d4f98649ed54edf6
fn main() {
    let a: i32 = 10;
    let b: u32 = 10;
    println!("{}", a as i64 + b as i64);
}
```

If the value cannot fit within the bounds of the type being converted to — a negative number cannot be represented by an unsigned integer type, for example — then the program will exhibit very strange behaviour (see the "Rustnomicon" reference at the bottom of the article for details). We'll work through other options for handling cases where type conversions might fail later in the series.   

The `as` keyword asks Rust to do the minimal amount of work possible to treat a value of one type as a value of another. Very often, such as converting between integer types of equal width, the internal representation does not change. This efficiency comes at a cost.

As is only available for primitive types. When you require conversions of types that you’ve designed yourself, you need to use the `std::convert::{From,Into}` traits.


_The Rust reference provides a good overview of the details in the [type cast expression](https://href.li/?https://doc.rust-lang.org/stable/reference/expressions/operator-expr.html#type-cast-expressions) page. The Rustnomicon also has a detailed section about [casting between data types](https://doc.rust-lang.org/nomicon/casts.html)._

----

Posts to come in this series. Please follow me to get notified when they are posted!

*   Using the `From` and `Into` traits
*   Using the `From` and `Into` traits
*   Hidden type conversion via the `Deref` trait
*   Trait objects
*   Downcasting

----

Thanks to @vorfeedcanal for comments on a previous version of this post.