liveBook · Manning

Type safety

As explained in Rust in Action: Systems programming concepts and techniques

Type safety is the enforcement of rules that prevent values of incompatible types from being used together in invalid operations.

Type safety keeps values from being used in operations their types do not support. Rust favors compile-time checks: the compiler rejects an invalid operation before the program runs. Types also give meaning to data; the same bit pattern can represent different numbers when interpreted as signed or unsigned. section 1.6.3 section 5.1

Comparing two integer types

Suppose a is an i32 containing 10 and b is a u16 containing 100. Rust rejects a < b because the operands have different types. Writing a < (b as i32) makes the conversion explicit. Casting a smaller integer type to a larger one is generally safer than converting in the other direction: 300_i32 as i8 produces 44. section 2.3.3

When a conversion might fail, try_into() offers an alternative to as. It returns a Result rather than simply treating every conversion as successful. Comparison operators themselves are supported through traits; understanding their full machinery is not necessary to use these examples. section 2.3.3

Listing 2.5 The try_into() method converts between types
 use std::convert::TryInto;    #1
 
 fn main() {
   let a: i32 = 10;
   let b: u16 = 100;
 
   let b_ = b.try_into()
             .unwrap();        #2
 
   if a < b_ {
     println!("Ten is less than one hundred.");
   }
 }

Compare the explicit try_into() conversion with the earlier rejected comparison: both operands have the same type by the time < is evaluated. section 2.3.3

A type can also express what a value represents. Replacing bare satellite ID integers with a CubeSat struct makes that distinction explicit, but changes how the program handles the values. Passing a CubeSat to a function moves its ownership; using the same value again then fails to compile unless that ownership issue is addressed. section 4.1.1

Type safety has a deliberate escape hatch. std::mem::transmute() can reinterpret a value’s bits as another type inside an unsafe block, but it discards type-safety guarantees. Investigate alternatives first: unsafe makes the programmer responsible for maintaining the program’s integrity. section 5.1

How Rust in Action: Systems programming concepts and techniques covers it

How deep it goes
Works through casts, fallible conversion, and an ownership error while introducing traits and Result only briefly.
Examples
Uses i32–u16 comparisons, a CubeSat struct, and signed-versus-unsigned readings of one bit pattern.
What it assumes
Assumes basic Rust variables and function calls, but introduces traits and Result briefly rather than requiring prior mastery.
What you can do after
Diagnose/debug with compiler errors by identifying mismatched comparison types, choosing explicit conversions, and recognizing use-after-move errors.
How it connects
Connects type safety to compile-time checks, numeric types, traits, ownership, and unsafe code.

Also explained in

Compare how 8 books explain type safety →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Rust in Action: Systems programming concepts and techniques. The section links point to the parts of the book it draws on.