Scope

A scope is a block or section of code that is a namespace for items and/or variable bindings. Scopes can be nested; things declared within a scope are only accessible within the same scope.

Scopes play an important role for borrow checking: Values are dropped when they go out of scope.

The  sigil used in paths is called the “scope operator”, because it accesses items in a different scope.

Scoping models
Different things follow different scoping models. The biggest difference is between items and variables. Furthermore,  based macros behave differently than other items.

Scoping of items
Items (except macros) use path-based scoping. This means that items must have a name (mostly) unique within the scope, and the order in which items appear is irrelevant. Furthermore, child modules don't automatically inherit items from their parent module. Instead, the items must be imported:

Scoping of macros
See also: Reference – Macros By Example: Scoping, Exporting and Importing

Macros based on  default to textual scoping, which relies mostly on the order in which items appear in the source file. Macros can't be invoked in a sibling module of the macro definition, but they can be invoked in a child module. The macro must be invoked after it is was defined:

If multiple macros with the same name are defined in the same file, they overwrite/shadow the ones defined before:

Macros can be used across multiple files, as long as they are declared before the module where they are used:

If the macro invocation is a path containing a, e.g. , or if it can't be resolved using textual scoping, it is resolved with path-based scoping instead:

Scoping of variables
Scoping of local variables works very similar to textual scoping (see above), except that they can't appear directly in a module:

Types of scopes
Scopes are usually, but not always surrounded by curly braces. The following constructs create scopes that can contain statements and expressions:


 * Functions
 * Regular blocks
 * ,,  ,  ,   and   blocks
 * ,,  ,   branches
 * each match arm in a  block
 * blocks (these are still experimental)

Items can be declared anywhere where statements are allowed. They can also be declared in


 * Modules
 * Traits and  blocks (associated items only)
 * blocks (static variables, functions and extern types only)

Variables declared in a bindings have an implicit scope starting at the  binding and ending at the end of the enclosing scope. So this:

is semantically equivalent to

Namespaces
Every scope introduces not one, but three namespaces: One for functions, one for macros, and one for everything else. This means that a struct can't have the same name as a trait in the same module, but e.g. a function and a macro with the same name can coexist:

There are a few exceptions, however: A function can't be in the same scope as a unit struct, tuple struct, constant or static item with the same name:

The same also applies struct fields, methods and associated items. Since functions live in a separate namespace, a type can have a method with the same name as a field:

Furthermore, a trait or  block can have an associated item with the same name as as a function:

The namespaces of inherent s of the same type are combined:

Disambiguating things with the same name
When there are multiple items/variables with the same name in scope (e.g. a, a , a macro  and a local variable  ), Rust disambiguates them by looking at how they are used:


 * 1) If it is followed by an exclamation point, it's a macro
 * 2) If it is followed by an opening parenthesis, it's a call expression
 * 3) Otherwise, it can be a type, trait, module, variable, etc.

Call expressions are anything that can be called. This includes functions, tuple structs and tuple-like enum variants, but also other types that implement the trait, like closures.

In the third case, if both an item (type, trait, module, ...) and a local variable is in scope, the local variable is preferred:

When calling something that could be a field or a method, Rust always assumes that it is a method:

This can be fixed by wrapping {rs|f.field}} in parentheses:

Disambiguating call expressions
When Rust encounters a call expression and there are multiple applicable candidates, it uses the following strategy:


 * If there's a local variable with the right name, call the variable.
 * If