Scope

A scope (e.g. a module or function) is a block or section of code that can contain items and/or variable bindings. Scopes can be nested; things declared within a scope are only accessible within the same scope, unless they are exported.

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 (types, traits, modules, functions, ...) 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
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. Macros can't be invoked before they are defined:

If multiple macros with the same name are defined in the same file, they 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 variables (e.g.  bindings, but not static 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 items and expressions 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:

Moreover, 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:

Name resolution
When there are multiple items/variables with the same name in scope (e.g. a, a , a macro  and a local variable  ), Rust resolves the name by looking at how it is used:


 * 1) If it is followed by an exclamation mark, 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.

A call expression can be a function, a tuple struct or a tuple-like enum variant, but also another type that implements the trait, like a closure.

In the third case, if both an item 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 in parentheses:

When importing items, different namespaces aren't differentiated; instead, items from all three namespaces are imported: