Rust (programming language)

from Wikipedia, the free encyclopedia
Rust
Rust programming language black logo.svg
Basic data
Paradigms : Multiparadigms ( generic , concurrent , functional , imperative , structured )
Publishing year: 2010; first stable version 2015
Designer: Graydon Hoare
Developer: Formerly Graydon Hoare, now Rust Project Developers
Current  version 1.46.0   (August 27, 2020)
Typing : strong , static , affine , type inference
Influenced by: Alef , C ++ , C # , Cyclone , Erlang , Haskell , Limbo , Newsqueak , Objective CAML , Scheme , Standard ML , Swift
Operating system : Linux , macOS , Windows , FreeBSD , Android , iOS and more
License : Apache License 2.0 and MIT License
rust-lang.org

Rust is a multi paradigms - system programming language used by Mozilla was developed Research. It was developed with the aim of being safe, concurrent and practical. Security refers in particular to the avoidance of program errors that lead to memory access errors or buffer overflows and thus possibly also to security gaps , especially in concurrent processes. In contrast to other programming languages ​​with automatic memory management , Rust does not use garbage collection for this , but relies on a special type system .

Rust combines approaches from different programming paradigms , including functional , object-oriented and concurrent programming, and thus allows a high level of abstraction . For example, Rust has algebraic data types, pattern matching , traits (similar to the type classes in Haskell ), closures , and support for RAII . The language was designed in such a way that the costs of the abstractions at runtime can remain as low as possible ( zero-cost abstractions ) in order to achieve an efficiency comparable to that of C ++ .

The language emerged from a personal project by Mozilla employee Graydon Hoare. Mozilla began sponsoring the project in 2009. It was first announced in 2010. In the same year the change from a first compiler (still written in OCaml ) to a new compiler, which is itself written in Rust, began. This compiler, called rustc , uses LLVM as a back-end and has been able to successfully compile itself since 2011. A first stable version of the compiler and standard library , Rust 1.0, was released on May 15, 2015.

Language design

Syntax, language constructs

The language of syntactically C ajar. Several consecutive statements are separated by a semicolon , blocks are in curly brackets. However, the syntax differs in many details, for example no brackets are required around the conditions of if- and whilestatements, but instead curly brackets are forced around the block behind, even if there is only one statement there. The keyword foralways initiates a foreach loop in Rust , which enables iterating over any (including user-defined) containers and objects. Instead of the switchstatement, there are the much more powerful matchexpressions that not only deal with numbers and strings, but can also perform pattern matching on any nested structures.

Variables are usually written in lowercase ( snake_case), data types with the exception of the primitive with an uppercase letter ( CamelCase). Type parameters of generic types and functions are enclosed in angle brackets. Two colons indicate that the identifier on the right should come from the namespace of the identifier on the left. The binding of an identifier xto a value is made

let x: Typ = Wert;

written, whereby the specification of the type can also be omitted if the type can be derived . A variable declaration for the variable vhas the form:

let mut v: Typ = Initialwert;

or more generally:

let mut v: Typ;
v = Wert;

The compiler uses a data flow analysis to check whether all bindings and variables have been initialized before being read out. The use of uninitialized memory is only possible via a special command, which unsafemust be marked with.

Type system

User-defined data types can be defined either as struct( structure as in C) or as enum( tagged union ). Methods can be defined for both types of data types using the implkeyword . The otherwise for object-oriented programming customary inheritance does not exist in Rust however, polymorphism instead by traits and generic programming allows. A trait defines a set of functions and methods, which are then implemented together by data types and can serve as a restriction for the permitted types in the case of type parameters . This is also used for operators so that, for example, the operator can be used with any data type that implements the trait . All function, method and operator calls are statically bound, which enables the compiler to make some optimizations , but trait methods can also be accessed via so-called trait objects using dynamic binding . It is permitted to implement both existing traits from external code for user-defined types and new, user-defined traits for existing types. +Add

Pointer, memory management

In addition to the so-called raw pointers , which correspond to pointers in C and can only be unsafedereferenced in explicitly marked code, Rust also knows references . These always point to valid memory and must never assume the value zero . There are two different types differentiated from references: common references ( shared references ), initiated by &, and variable references ( mutable references ), initiated by &mut. The Rust compiler statically guarantees that no reference "survives" the object it refers to , that the referenced object is not changed while a reference (regardless of whether it is shared or changeable) exists, and that a changeable reference - if one exists - is always the only reference to an object, so changes can be made to the object without invalidating references to the same object elsewhere in the code or even in other threads .

The creation of references is also known as borrowing and, together with the concept of ownership, forms the basis for secure memory management without garbage collection. Ownership here means that every object in memory is owned by the variable to which it was assigned when it was created. At the end of the life of this variable, the memory is automatically released. For most of the more complex data types, Rust uses the so-called move semantics, so that when an object is assigned to another variable, the object is "moved" and access to the old variable is then no longer possible. When objects are passed as value parameters to functions ( call by value ), such objects are "pushed into" the function and can no longer be accessed from the outside if they are not returned by the function. Primitive data types do not use move semantics, but the usual copy semantics (assignments create a copy), and with user-defined data types the copy trait can be used to decide whether move or copy semantics should be used.

For dynamic memory management are the smart pointer types Box , Rcand the auxiliary type RefCellavailable, which are firstly subjected to the system ownership borrowing lifetime Move, on the other hand apply this system to the term dynamics. The type Box<T>describes an owning pointer to a value of the type Tin dynamically allocated memory. The type Rc<T>uses reference counting to describe common property at an unchangeable value. An immutable value can, however, have variable internal data of the type RefCell<T>, with a reference counter for access analogous to &and &mutenabling secure dynamic borrowing by checking at runtime.

RcDynamics of cyclical data structures is not possible with alone. This can be RefCellused again, whereby the cycles have to be broken manually so that there is no memory leak . As an alternative concept, there is the type of Weak<T>pointer in which the pointers are analogous to Rc, but have no ownership of the value. To implement Weakis Rcimplemented a second reference count. A pointer of the type Weakdoes not prevent the destructor call when all pointers of the type disappear Rc, but the deallocation of the unused node then only happens when the last pointer of the type disappears Weak. The destructor calls ensure that the cycles are automatically broken.

For concurrent programming, an exchange of Rcfor Arcand RefCellagainst the analog concepts Mutexor is RwLocknecessary.

There are no null pointers in Rust. The absence of a value is instead Option<T>modeled by the type , which makes it enumpossible to distinguish between Some(T)(presence) and None(absence). The use of options is not limited to pointers. Would you like B. structleave a large part of an uninitialized first, then you can structhide this as an inner one behind an option and Noneinitialize it with .

Error handling

Rust differs (between unrecoverable unrecoverable ) and unrecoverable ( recoverable ) errors. If an unrecoverable error occurs, a message is output, the stack is unwinding and the thread concerned is terminated. If this is not the main thread, the program continues. An immediate program termination via abort()can also be configured. For recoverable errors, the exception handling with automatic stack unwinding that is available in many languages ​​is not available in Rust. Instead, recoverable errors are modeled as normal return values ​​from functions. The types Result<T,E>and are used for strict typing Option<T>. Both types are enumformulated as, Resultdifferentiating between Ok(T)(normal values) and Err(E)(error values), but Optiondefined Some(T)(normal values) and None(no value).

There is no runtime disadvantage when returning from, enumor structin many cases, since the compiler is able to automatically generate pointers for larger objects and to perform null pointer optimizations.

Examples

Hello world function

fn main() {
    println!("Hello, world!");
}

The above example outputs the text Hello, world!on the output medium. println!()is not an ordinary function here , but a macro . The function declaration is made in Rust with the keyword fn .

Factorial function

For the calculation of the factorial of a number , that is , there are different approaches, in particular a recursive and an iterative one. Both can be implemented in Rust.

Iterative

fn fakultaet(i: u64) -> u64 {
    let mut acc = 1;
    for num in 2..=i {
        acc *= num;
    }
    acc
}

Since the factorial is defined for all natural numbersu64 , an unsigned 64-bit integer can be used as the data type . In this variant, the faculty is implemented according to the above definition. Striking is the keyword mutin line 2, that in the declaration of the variable acc is common to these as a variable ( mut to identify viable), since a renewed in the loop body in line 4 value assignment is performed. An explicit returnstatement is not required in Rust, because the last expression (which is not a statement due to the missing semicolon) is used as the return value. This expression must match the return type from the function header.

Alternatively, Rust allows the problem to be approached in terms of functional programming. So-called iterators offer a way of processing iterable objects. The faculty can be represented with the help of the iterator (1..=i)and its method product()as follows:

fn fakultaet(i: u64) -> u64 {
    (1..=i).product()
}

Recursive

fn fakultaet(i: u64) -> u64 {
    match i {
        0 => 1,
        n => n * fakultaet(n - 1)
    }
}

In this variant, the core lies in a case distinction with which the faculty can also be defined:

This expression can be implemented in Rust using pattern matching and recursive function calls.

Treatment of overflow

With the 64-bit integer data type used here, the factorial can only be calculated up to 20, until an overflow occurs, which only delivers incorrect results. This often happens unnoticed. Depending on the compilation method, this overflow would be noted as an unrecoverable error in the above examples, so that the program would terminate, or the overflow would be used for further calculations.

Instead, this error case can be handled as follows using the type system:

fn fakultaet(i: u64) -> Option<u64> {
    match i {
        0 => Some(1),
        n => match fakultaet(n - 1) {
            Some(m) => n.checked_mul(m),
            None => None
        }
    }
}

use

The Rust compiler is delivered as standard with Cargo , a package manager for Rust software, which automatically downloads the libraries used and resolves dependencies. Each package contains a configuration file in TOML format that is stored as Cargo.toml in the package directory. In addition to general information about the package (e.g. name, version and authors), it also specifies the required dependencies.

A large number of reusable open source components are available in the official package repository crates.io . From version 1.34.0 it is also possible to use other package repositories. This enables, for example, companies to create their own internal package repositories and use them for closed source components.

Rust is used in the following projects, among others:

Web links

Individual evidence

  1. Announcing Rust 1.46.0 .
  2. Alexis Beingessner: The Pain Of Real Linear Types in Rust . In Beingessner's blog, May 8, 2017, accessed October 10, 2019.
  3. Appendix: Influences - The Rust Reference . (accessed on January 28, 2018).
  4. ^ Doc building for ios . Retrieved January 4, 2015.
  5. Rust Platform Support ( English ) Retrieved on June 3 of 2019.
  6. Frequently Asked Questions ( English ) Retrieved June 3, 2019.
  7. COPYRIGHT . Rust compiler source repository. Retrieved December 17, 2012.
  8. ^ Rust . Mozilla Research. Retrieved May 3, 2019.
  9. ^ The Rust Programming Language . Retrieved October 21, 2012.
  10. The Rust Project Developers: The Rust Language FAQ: How fast is Rust? Accessed July 8, 2018 .
  11. Project FAQ . September 14, 2010. Retrieved January 11, 2012.
  12. ^ Future Tense . April 29, 2011. Accessed on February 6, 2012: "At Mozilla Summit 2010, we launched Rust, a new programming language motivated by safety and concurrency for parallel hardware, the" manycore "future which is upon us."
  13. ^ Graydon Hoare: Rust Progress. In: Graydon's work on Mozilla. October 2, 2010, archived from the original on March 19, 2012 ; accessed on April 3, 2016 .
  14. ^ Graydon Hoare: [rust-dev] stage1 / rustc builds . April 20, 2011. Retrieved April 20, 2011: “After that last change fixing the logging scope context bug, looks like stage1 / rustc builds. Just shy of midnight :) "
  15. ^ Announcing Rust 1.0
  16. Documentation of the “Add” trait
  17. Recoverable Errors with Result - The Rust Programming Language. Retrieved April 23, 2019 .
  18. u64 - Rust. Retrieved April 21, 2019 .
  19. ^ Functions - Rust By Example. Retrieved April 21, 2019 .
  20. std :: iter :: Product - Rust Documentation. Retrieved April 21, 2019 .
  21. ^ The Manifest Format - The Cargo Book. Retrieved April 19, 2019 .
  22. The Rust community's crate host. Retrieved April 3, 2017 .
  23. ^ Dave Herman: Shipping Rust in Firefox. In: Mozilla Hacks. July 12, 2016, accessed April 2, 2017 .
  24. Quantum. In: Mozilla Wiki. Retrieved April 3, 2017 .
  25. Rainald Menge-Sonnentag: Mozilla publishes first preview of the new browser engine Servo. In: Heise Newsticker . July 4, 2016, accessed July 4, 2016 .
  26. Rust's Redox OS could show Linux a few new tricks (English) , infoworld. Retrieved March 21, 2016. 
  27. Redox OS: If you don't rust, you rust - Golem.de . ( golem.de [accessed on February 12, 2018]).
  28. ^ Cade Metz: The Epic Story of Dropbox's Exodus From the Amazon Cloud Empire. Wired , March 14, 2016, accessed April 3, 2017 .
  29. Denis Frank: Using HyperLogLog to Detect Malware Faster Than Ever . Retrieved March 19, 2016.
  30. Frank Denis: ZeroMQ: Helping us Block Malicious Domains in Real Time . Retrieved March 19, 2016.
  31. MesaLink - A memory-safe and OpenSSL-compatible TLS library. Retrieved September 2, 2018 .
  32. Andrew Gallant: ripgrep is faster than {grep, ag, git grep, ucg, pt, sift}. In: Andrew Gallant's blog. September 23, 2016, accessed April 3, 2017 .
  33. Fuchsia - Rust. Retrieved March 5, 2019 .
  34. ^ Open wiki documentation for Grin and MimbleWimble. Contribute to mimblewimble / docs development by creating an account on GitHub. mimblewimble, April 5, 2019, accessed April 5, 2019 .