What is Rust Programming Language?
Rust Programming Language is an open-source systems programming language that focuses on speed, memory safety and parallelism. Developers are using Rust to create a wide range of new software applications, such as game engines, operating systems, file systems, browser components and simulation engines for virtual reality.
An active community of volunteer coders maintains the Rust code base and continues to add new enhancements. Mozilla sponsors the Rust open source project.
Rust Programming language is a modern systems programming language developed by the Mozilla Corporation. It is intended to be a language for highly concurrent and highly secure systems. It compiles to native code; hence, it is blazingly fast like C and C++.
Rust programming language is a multi-paradigm programming language designed for performance and memory safety, especially safe concurrency. Rust is syntactically similar to C++, but can guarantee memory safety by using a borrow checker to validate references. Rust achieves memory safety without garbage collection, and reference counting is optional.
Rust was originally designed by Graydon Hoare at Mozilla Research, with contributions from others members. The designers refined the language while writing the Servo layout or browser engine and the Rust compiler. It has gained increasing use in industry, and Microsoft has been experimenting with the language for secure and safety-critical software components. Rust Programming Language is the only language that actually introduces genuinely new features. Namely the whole idea of safety of memory usage in a compiled, real systems programming language with no garbage collection or complicated run-time system.
How is Rust different?
Rust was built from scratch and incorporates elements from tried-and-true systems programming languages and modern programming language design. It fuses the expressive and intuitive syntax of high-level languages with the control and performance of a low-level language. It also prevents segmentation faults and guarantees thread safety. This empowers developers to write code that is ambitious, fast and correct.
Rust makes systems programming accessible by combining power with ergonomics. Using it, programmers can make software that is less prone to bugs and security exploits. Under the hood, it includes powerful features such as zero-cost abstractions, safe memory management, fearless concurrency and more. Visit the Rust open-source project website for a list of Rust features.
Why Rust?
Performance
Rust is blazingly fast and memory-efficient, with no runtime or garbage collector, it can power performance-critical services, run on embedded devices, and easily integrate with other languages.
Reliability
Rust’s rich type system and ownership model guarantee memory-safety and thread-safety, enabling you to eliminate many classes of bugs at compile-time.
Productivity
Rust has great documentation, a friendly compiler with useful error messages, and top-notch tooling, an integrated package manager and build tool, smart multi-editor support with auto-completion and type inspections, an auto-formatter, and more.
Features
Memory safety
Rust is designed to be memory safe, and it does not permit null pointers, dangling pointers, or data races in safe code. Data values can be initialized only through a fixed set of forms, all of which require their inputs to be already initialized. To replicate the function in other languages of pointers being either valid or ‘NULL’, such as in linked list or binary tree data structures, the Rust core library provides an option type, which can be used to test whether a pointer has ‘Some’ value or ‘None’. Rust also introduces added syntax to manage lifetimes, and the compiler reasons about these through its borrow checker. Unsafe code which can subvert some of these restrictions may be written using the language’s ‘unsafe’ keyword.
Memory management
Rust does not use an automated garbage collection system. Instead, memory and other resources are managed through the resource acquisition is initialization (RAII) convention, with optional reference counting. Rust provides deterministic management of resources, with very low overhead. Rust also favors stack allocation of values and does not perform implicit boxing.
There is the concept of references (using the ‘&’ symbol), which does not involve run-time reference counting. The safety of using such pointers is verified at compile time by the borrow checker, preventing dangling pointers and other forms of undefined behavior. Additionally, Rust’s type system separates shared, immutable pointers of the form ‘&T’ from unique, mutable pointers of the form ‘&mut T’. However, a mutable pointer can be coerced to an immutable pointer, but not vice versa.
Ownership
Rust has an ownership system where all values have a unique owner, and the scope of the value is the same as the scope of the owner. Values can be passed by immutable reference, using ‘&T’, by mutable reference, using ‘&mut T’, or by value, using ‘T’. At all times, there can either be multiple immutable references or one mutable reference (an implicit readers-writer lock). The Rust compiler enforces these rules at compile time and also checks that all references are valid.
Types and polymorphism
The type system supports a mechanism similar to type classes, called “traits”, inspired directly by the Haskell language. This is a facility for ad hoc polymorphism, achieved by adding constraints to type variable declarations. Other features from Haskell, such as higher-kinded polymorphism, are not yet supported.
Rust features type inference for variables declared with the keyword ‘let’. Such variables do not require a value to be initially assigned to determine their type. A compile-time error results if any branch of code fails to assign a value to the variable. Variables assigned multiple times must be marked with the keyword ‘mut’.
Functions can be given generic parameters, which usually require the generic type to implement a certain trait or traits. Within such a function, the generic value can only be used through those traits. This means that a generic function can be type-checked as soon as it is defined. This is in contrast to C++ templates, which are fundamentally duck typed and cannot be checked until instantiated with concrete types. C++ concepts address the same issue and are part of C++20, though they still don’t allow the C++ compiler to typecheck a template without concrete instantiation.
However, the implementation of Rust generics is similar to the typical implementation of C++ templates: a separate copy of the code is generated for each instantiation. This is called monomorphization and contrasts with the type erasure scheme typically used in Java and Haskell. The benefit of monomorphization is optimized code for each specific use case; the drawback is increased compile time and size of the resulting binaries.
The object system within Rust is based around implementations, traits and structured types. Implementations fulfill a role similar to that of classes within other languages and are defined with the keyword ‘impl’. Inheritance and polymorphism are provided by traits; they allow methods to be defined and mixed in to implementations. Structured types are used to define fields. Implementations and traits cannot define fields themselves, and only traits can provide inheritance. Among other benefits, this prevents the diamond problem of multiple inheritance, as in C++. In other words, Rust supports interface inheritance, but replaces implementation inheritance with composition; see composition over inheritance.
Performance
Performance of idiomatic Rust is comparable to the performance of idiomatic C++.
Rust in production
Hundreds of companies around the world are using Rust in production for fast, low-resource, cross-platform solutions. Companies like AWS, Firefox, Dropbox, and Cloudflare use Rust Programming Language their solutions.
From startups to large corporations, from embedded devices to scalable web services, Rust is a great fit.
Adoption
Web browser
A Web browser and several related components are being written in Rust, including:
- Firefox
Operating systems
Operating systems and OS-level components written in Rust include:
Other
- exa: a “modern replacement for ls“
- Microsoft Azure IoT Edge: a platform used to run Azure services and artificial intelligence on IoT devices has components implemented in Rust
- OpenDNS: used in two of its components
- Tor: an anonymity network, written in C originally, is experimenting with porting to Rust for its security features
- Deno: a secure runtime for JavaScript and TypeScript built with V8, Rust, and Tokio.
- Discord — chat service targeted towards gamers that uses Rust for portions of its backend, as well as client-side video encoding.
Genuinely new and well considered features
While some languages just add polish and ease to existing concepts, several users feel that Rust is actually doing new things with a programming language. And it’s not doing new things just to be showy; they feel these design choices solve hard problems with modern programming.
Beyond safety and performance, we have:
- generics;
- traits;
- algebraic types;
- functional and imperative paradigms;
- perhaps the world’s best dependency management and build tool, which has practically solved the ‘dependency hell’ problem;
- fantastic support for inline documentation, tests, and benchmarks;
- a large and growing ecosystem of libraries, abstractions, and tools;
- procedural macros;
- FFI interoperability with existing code;
- support for dozens of platforms (with more on the way!);
- and a developer experience that is just wholesome and unquestionably satisfying.
Rust is the only language that ticks all the boxes:
- Memory safe
- Type safe
- Data race-free
- Ahead-of-time compiled
- Built on and encourages zero-cost abstractions
- Minimal runtime (no stop-the-world garbage collection, no JIT compiler, no VM)
- Low memory footprint (programs run in resource constrained-environments like small microcontrollers)
- Targets bare-metal (e.g. write an OS kernel or device driver; use Rust as a ‘high level assembler’)”
Compile time guarantees: When I think of a “statically typed language”, I think of Java, or C#, or something like TypeScript. They give compile-time assurances that your code has the correct types, and move a set of errors from runtime to compile time. Rust goes one magnitude further in this! Compile time checking extends to thread safety, to ownership semantics, to validation.
Enums mean that, at compile time, I can declare the set of variants my data can exist as, and when accessing that data I’m forced to consider all possibilities. Traits mean that when my code is templated/generic, I have exact capabilities I can require.
Rust is extremely backwards compatible. I can run code written for Rust 1.0. Equally, I can write code which I know I won’t have to update next time I update Rust.
And it’s not just Rust itself – the language enables libraries to have the same guarantees. Consider two facts:
- In type checking, only the signature of functions are considered. There’s no relying on the implementation for determining if callers are correct (like you can do in Scala, or Haskell)
- The extensive type system means incorrect usages of interfaces become type errors, not runtime errors.
Because of these two things, libraries can be 100% sure that they maintain backwards compatibility when releasing a new interface. In Python, or Java, or Javascript, or even Scala or Haskell, you need to pay extra attention to implementations of things if you want to ensure you maintain backwards compatibility. In Rust, it’s free: if you haven’t changed the function signature, it remains the same.
Rust found a sweet spot: it is just as low-level as C or C++ with all the advantages of these (e.g. control, size, speed, etc.) At the same time, it is as high-level as Haskell with an amazing amount of functional heritage. It is still imperative, so quite accessible to most people, and it is just as flexible as Python. For example, concepts like “duck-typing” are happening at compile time (i.e. trait bounds), yet it does not have the dated, object-oriented programming model and all of its well known problems.
Last but not least, the batteries which are included: the small and concise syntax, the small number of features the language provides, the integrity of the standard library as well as its consistency and the quality of its documentation, including the learning materials for both beginners and advanced users are all contributing factors.
With Rust/cargo I can focus on the actual code rather than the build system. No need to spend whole days reading up on Yet Another Build System. Cross-compilation with Rust is so incredibly simple and painless that when you read up on how to do it, you can’t help but think “Wait, I must be missing something.”
When you’re outside of Rust, there are things that sound like empty slogans, but when you start using it you’ll become pleasantly surprised to realize there’s a lot of truth to:
- While you spend time fighting to compile your code, you save that time in not having to debug your code.
- You’re no longer afraid of major refactoring. Once your refactored code compiles, it works as intended.
- It really does force you to do proper multithreading (well, you can still deadlock, but the crashy types of bugs are far more difficult to do).
I find myself doing far less boilerplate code. And what boilerplate code I do need, I can often hide in a different module so it doesn’t get in the way of the actual application logic code. (Most common example of this is the error type conversions).
Safety and speed at scale
Many current programming discussions revolve around whether to use a fast, low-level language that lets you handle memory management or a higher-level language with greater safety precautions. For fans of Rust, they like that it does both.
Rust provides automatic memory management like any other high level language, but it’s done at compile time so there’s no hidden cost or behavior to account for.
Rust has always been designed for what we expect in modern hardware. Thread safety and data races, which can be a common footgun in other languages, were accounted for at the language level. As a result it can be incredibly easy to take full advantage of your workstation’s capabilities without a lot of changes or headaches. It’s always been impressive to me how rayon
(a popular library in Rust) can parallelize your entire workload by changing just a single line of code.
As a result there’s been a lot of high quality and fast implementations being written in Rust, and thanks to cargo and crates.io (Rust’s package manager and community run package registry), it’s never been easier to reuse and share that code both internally and with the world at large.
Cargo handles a large repository with several to dozens of packages just as well as it handles one, you don’t need to spend days writing a build file to have the configuration you want.
Not only is it easy to manage and update your Rust dependencies, Rust itself is incredibly easy to upgrade and switch between different versions of the language with Rustup; a toolchain version manager that is included by default.
Any of the above points would be enough for somebody to like Rust, but taken altogether it makes Rust an incredibly compelling language that feels refreshing to write and create your projects in.
Web: Rust Website
Learn Rust Programming Language
Rust Tutorials by TutorialsPoint
Books:
https://nnethercote.github.io/perf-book/
https://rustc-dev-guide.rust-lang.org/
https://doc.rust-lang.org/book/title-page.html