Are you a developer looking to learn Rust? To help you decide, this article presents some of the features of Rust, one of the most popular systems programming languages.

In this article, we’ll explore the Rust programming language, and its features, such as type system, memory safety, and ownership. We’ll also go over a list of resources that can help you learn Rust.

Let’s begin!

What Is Rust?

Rust is a systems programming language. It started as a personal project of Graydon Hoare, a developer, back in 2006. In less than a decade, it has grown into the go-to choice for systems programming and allied applications. The average salary of a Rust programmer is about $120K.

So if you’re looking to switch from C to Rust or are looking to pick up a new language, learning Rust can be a great choice! According to the StackOverflow Developer survey, Rust has been voted the most-loved programming language – for seven years in a row.

<img alt="image-96" data-src="https://kirelos.com/wp-content/uploads/2023/01/echo/image-96.png" decoding="async" height="401" src="data:image/svg xml,” width=”750″>
Image Source: StackOverflow

Rust offers the speed of low-level systems programming languages such as C and C and the safety of high-level programming languages such as Python.

From notable projects such as Dropbox and Firefox to WebAssembly and embedded programming, Rust is widely used in all areas of software development. Rust offers out-of-the-box package management support through Cargo.

Cargo: The Package Manager for Rust

Cargo is the package manager for Rust. You can use cargo to install packages from crates, the Rust package registry. In addition to being a package manager that lets you search for, install, and manage packages, cargo also serves as a test runner, a docs generator, and a build system.

Now that you have an overview of Rust, let’s take a closer look at some of the features of Rust that make it stand out as a systems programming language with wide adoption.

Helpful Error Messages

<img alt="Helpful-Error-Messages" data- data-src="https://kirelos.com/wp-content/uploads/2023/01/echo/Helpful-Error-Messages.png" data- decoding="async" height="547" src="data:image/svg xml,” width=”793″>

As a beginner programmer, you will run into errors and spend a significant amount of time debugging your code. You’ll use the error messages and warnings provided by the compiler to fix those issues. And helpful messages can help you debug faster.

An Example Error Message

When your code does not compile successfully, Rust provides helpful error messages which provide explanations of what needs to be fixed in your code and where.

In this example, the variable num2 is defined inside the function inner(). It is therefore limited to the scope of the function. If you try to access it outside the function, the compiler throws an error:

fn main() {
    let num1 = 10;
    fn inner(){
        let num2 = 9; 
    }
    println!("The value of num2 is: {}", num2);
}

And the error message gives info on what needs to be fixed.

error[E0425]: cannot find value `num2` in this scope
 --> src/main.rs:6:42
  |
6 |     println!("The value of num2 is: {}", num2);
  |                                          ^^^^ help: a local variable with a similar name exists: `num1`

Warnings During Compilation

The compiler also provides helpful warnings regarding issues in your code. When you define variables but never use them in the rest of the program, Rust gives you a warning message, as shown.

fn main() {
    let num1 = 10;
    let num2 = 9;
    println!("The value of num1 is: {}", num1);
}

Here, the variable num2 is declared but never used.

warning: unused variable: `num2`
 --> src/main.rs:3:9
  |
3 |     let num2 = 9;
  |         ^^^^ help: if this is intentional, prefix it with an underscore: `_num2`
  |

Strongly Typed Language

Another reason you should use Rust for your development projects is its type system. Rust is a strongly typed language, which means it does not support type coercion. Type coercion is when a language can implicitly convert a value in a data type to another.

For example, the Python code in the following code cell will run without errors. This is because in Python, a non-zero number has a truth value of True, and therefore, the if statement runs without errors—even though the number 10 is an integer—and not a Boolean.

num1 = 10
if num1:
    num2 = 9
print(f"num2 is {num2}")

# Output: num2 is 9

On the other hand, Rust does not coerce types. So the following code will throw an error:

fn main() {
    let num1 = 10;
    if num1{
        let num2 = 9; 
    }
}

The error reports a type mismatch, where a Boolean was expected and integer was found.

error[E0308]: mismatched types
 --> src/main.rs:3:8
  |
3 |     if num1{
  |        ^^^^ expected `bool`, found integer

Memory Safety

Memory safety is another feature of Rust that makes it appealing to programmers. We’ll try to provide a cursory overview of how this works.

Variables Must Be Initialized Before They Are Used

In Rust, all variables must be initialized before they can be used. In languages such as C, the following code where num is not initialized will compile and run without errors. The value of the uninitialized variable is some garbage value.

#include 

int main(void) {
    int num;
	printf("The value of num is %d", num);
	return 0;
}
// Output: The value of num is 0

If you try doing something similar in Rust, you’ll run into a compile-time error. Rust, therefore, has no notion of garbage collection.

fn main() {
    let num:i32;
    println!("The value of num is: {}",num);
}
error[E0381]: used binding `num` isn't initialized
 --> src/main.rs:3:40
  |
2 |     let num:i32;
  |         --- binding declared here but left uninitialized
3 |     println!("The value of num is: {}",num);
  |                                        ^^^ `num` used here but it isn't initialized
  |

Memory Safety At Compile Time

Rust ensures memory safety at compile time. Let’s take a simple example. Here, even though the if conditional statement has a Boolean value of true, which means the value of num will always be 100, we get an error when we try to print out the value of num.

fn main() {
    let num:i32;
    if true{
        num = 100;
    }
    println!("The value of num is: {}", num);
}

This is because conditional evaluation occurs at run time, and the compiler will not be able to guarantee that num has a value at compile time.

error[E0381]: used binding `num` is possibly-uninitialized
 --> src/main.rs:6:41
  |
2 |     let num:i32;
  |         --- binding declared here but left uninitialized
3 |     if true{
  |        ---- if this `if` condition is `false`, `num` is not initialized
4 |         num = 100;
5 |     }
  |      - an `else` arm might be missing here, initializing `num`
6 |     println!("The value of num is: {}", num);
  |                                         ^^^ `num` used here but it is possibly-uninitialized

If you take a closer look at the error message, you’ll see that with an else statement, we can ensure that num will have a value. So the following code will run without errors. Because this way, the compiler can determine that num will have a value—at compile time—so there are no errors.

fn main() {
    let num:i32;
    if true{
        num = 100;
    }
    else{
        num = 50;
    }
    println!("The value of num is: {}", num);
}
The value of num is: 100

Immutability of Variables

It’s also helpful to note that variables in Rust are immutable by default. This means as a developer, you don’t have to worry about accidentally overwriting the value of a particular variable. Here’s an example:

fn main() {
    let num1 = 10;
    num1 = 5;
    println!("The value of num1 is: {}", num1);
}

As num1 is initialized to 10, when you try assigning it a value of 5, you get an error message that reads ‘cannot assign twice to immutable variable num1‘.

error[E0384]: cannot assign twice to immutable variable `num1`
 --> src/main.rs:3:5
  |
2 |     let num1 = 10;
  |         ----
  |         |
  |         first assignment to `num1`
  |         help: consider making this binding mutable: `mut num1`
3 |     num1 = 5;
  |     ^^^^^^^^ cannot assign twice to immutable variable

Ownership and Borrowing

Ownership ensures memory safety. Functionally, ownership in Rust can be summed up as follows:

Every object should have one and only one owner. If the owner goes out of scope, then the object is dropped.

Let’s take a simple example. Here, we initialize a string str1 and then move its value to str2. As any object can have only one owner, the str1 object is dropped as soon as its value is moved to str2.

fn main() {
    let str1 = String::from("Rust");
    let str2 = str1;
    println!("The value of str1 is: {}", str1);
}
error[E0382]: borrow of moved value: `str1`
 --> src/main.rs:4:42
  |
2 |     let str1 = String::from("Rust");
  |         ---- move occurs because `str1` has type `String`, which does not implement the `Copy` trait
3 |     let str2 = str1;
  |                ---- value moved here
4 |     println!("The value of str1 is: {}", str1);
  |                                          ^^^^ value borrowed here after move

While this seems intuitive, to better understand and appreciate how ownership works, it’s helpful to learn the concepts of borrowing and references.

Quick Development

So far, we’ve discussed several useful features of the Rust programming language. To review a few:

  • Rust is optimized for both speed and safety.
  • It comes with a built-in package management tool and builds a system.
  • It also has a rich standard library.

In essence, Rust offers everything a developer can ask for. Therefore, with Rust, you can develop applications quickly with minimal debugging and faster builds.

Cross-Platform Development

With Rust, you can choose to develop on a platform of your choice. Rust supports the most common platforms: Linux, MacOS, and Windows.

Application development is generally easy as you can compile the Rust source code into an executable without depending on other build tools and external compilers.

A supportive community goes a long way in simplifying your learning journey. Rust has a huge user base that is only growing with every passing year.

The popularity of Rust in the StackOverflow developers survey indicates that there is a large community of users, with a lot of experienced developers willing to share their knowledge and expertise.

In addition to the official documentation, there is also a user-generated documentation site and a discussion forum. You can also check the Rust subreddit and LinkedIn groups for relevant discussions.

Learning Resources to Get Started With Rust

<img alt="Learning-Resources-to-Get-Started-With-Rust" data- data-src="https://kirelos.com/wp-content/uploads/2023/01/echo/Learning-Resources-to-Get-Started-With-Rust.png" data- decoding="async" height="493" src="data:image/svg xml,” width=”740″>

This section lists a few helpful resources to help you get started with Rust. This is not an exhaustive list but includes some recommended tutorials, courses, and books to help you in your learning journey.

#1. Rust By Example

Rust By Example will teach you Rust fundamentals and standard libraries through a series of examples that you can code along in an online editor.

The topics covered include crates, cargo: the package management tool for Rust, generics, traits, error handling, and much more.

#2. Rustlings

Rustlings is another official learning resource for the Rust programming language. It is similar to Rust by example. However, it requires you to set up your local development environment, clone an example repo, and solve simple problems to learn these concepts.

#3. Exercism Rust Track

<img alt="rust" data- data-src="https://kirelos.com/wp-content/uploads/2023/01/echo/rust.png" data- decoding="async" height="290" src="data:image/svg xml,” width=”927″>

The Rust Track on Exercism has more than 100 exercises to help you learn and test your understanding of Rust. Exercism is a free platform where you can get mentored by experienced programmers in addition to coding your way through the exercises.

#4. Ultimate Rust Crash Course

<img alt="image-68" data-src="https://kirelos.com/wp-content/uploads/2023/01/echo/image-68.png" decoding="async" height="260" src="data:image/svg xml,” width=”750″>

The Ultimate Rust Crash Course taught by Nathan Stocks on Udemy covers the following:

  • Fundamentals of Rust programming 
  • Module system in Rust
  • Data types and control flow 
  • Reference and borrowing 
  • Structs, traits, and collections

#5. Ultimate Rust 2: Intermediate Concepts

<img alt="image-67" data-src="https://kirelos.com/wp-content/uploads/2023/01/echo/image-67.png" decoding="async" height="251" src="data:image/svg xml,” width=”750″>

Ultimate Rust 2 is a follow-up course to the Ultimate Rust Crash Course and covers the following topics:

  • Closures 
  • Iterators 
  • Error handling 
  • Unit and integration test 
  • Logging, multithreading, and channels

#6. Rust lang: The complete beginner’s guide 2023

<img alt="image-69" data-src="https://kirelos.com/wp-content/uploads/2023/01/echo/image-69.png" decoding="async" height="260" src="data:image/svg xml,” width=”751″>

This Udemy course taught by Catalin Stefan is a comprehensive course on Rust programming. Some of the topics covered include:

  • Rust fundamentals
  • Datatypes, control structures
  • Functions, traits
  • Memory management
  • Concurrency

#7. Programming Rust: Fast, Safe Systems Development

Programming Rust by O’Reilly is a popular Rust programming book that’ll teach you the following:

  • Fundamental data types
  • Ownership and borrowing
  • Asynchronous programming
  • Fast multithreading applications
  • Closures, iterators
  • Collections

#8. The Rust Programming Language, 2nd Edition

The Rust Programming Language is authored by renowned contributors of the Rust community. This book covers everything you need to know about Rust, including:

  • Ownership and borrowing
  • Generics, traits
  • Smart pointers, multithreading 
  • Testing and error handling

#9. The Complete Rust Programming Reference Guide

The Complete Rust Programming Reference Guide from Packt covers the following:

  • Implementing data structures in Rust
  • Writing reusable and testable components in Rust
  • Designing multithreaded applications algorithm design and
  • Applications of Rust in WebAssembly, networking, and command-line applications

#10. Creative Projects for Rust Programmers

If you are an experienced developer learning Rust, then building a few projects in your domain of interest will suffice to gain a good grasp of the language. Creative Projects for Rust Programmers from Packt is a book that teaches Rust by applying them to projects such as:

  • Building Restful web services
  • 2D games with
  • Web application development using the WebAssembly
  • Machine language emulators
  • and more!

Conclusion

This article presented an overview of Rust as a systems programming language, including features such as memory safety, improved package management, and more. We also enumerated learning resources to help you get up and running with Rust.

As a next step, you can choose one or more of the learning resources mentioned to pick up the basics of Rust. Happy Rust programming!

You may also explore some best Rust server hosting providers.