Scope modes
This topic is not available in the selected language or version. Showing the start of this section.
This chapter starts the advanced path. You have built a program using default behavior and the standard library. Now choose features for individual functions or blocks to control changes to original values and the extent of optimization. The next chapter, copies, moves, and references, develops the borrowing rules.
Scope modes enable features in a particular function or block. explc and opt serve different purposes.
Choose the annotation and its location
Section titled “Choose the annotation and its location”| Annotation | Location | Purpose |
|---|---|---|
#![explc] | Immediately before a function | Use explicit references in that function. |
#scope[explc] { ... } | A block inside a function | Use explicit references within that block. |
#scope[opt] { ... } | A block inside a function | Mark code for the selected optimization option. |
let mut allows a variable to change. explc allows explicit references. Neither replaces the other.
Change an original value inside a block
Section titled “Change an original value inside a block”Save this as scope_modes.xen. append_shared declares a reference parameter, so it has #![explc]. In main, only the part that creates and passes the reference is enclosed in #scope[explc].
#![explc]fn append_shared(values: &mut Vec<Int>) { values.push(3);}fn main() { let mut values = [1, 2]; #scope[explc] { append_shared(&mut values); } println(values); let mut total = 0; #scope[opt] { for value in 1..5 { total = total + value; } } println(total);}xen check scope_modes.xenxen run scope_modes.xen[1, 2, 3]10The caller’s vector now contains 3. Unlike passing a value and changing an independent copy, &mut values refers to the caller’s original. The sum calculation is marked separately with opt.
When explicit references are used throughout a function, you can also put #![explc] immediately before main. Choose the function or block boundary to match where references are needed.
A callee’s annotation does not annotate its caller
Section titled “A callee’s annotation does not annotate its caller”This program deliberately fails. Run xen check scope_error.xen:
#![explc]fn append_shared(values: &mut Vec<Int>) { values.push(3); }fn main() { let mut values = [1, 2]; append_shared(&mut values);}passing references requires #![explc]Annotating append_shared does not enable &mut values inside main. Enclose the call in #scope[explc], as in the working program, or annotate main with #![explc]. Check both the function declaring reference parameters and the caller creating references.
explc preserves borrowing restrictions. You cannot change or move an original while shared references remain in use, or access it through another path while a mutable reference remains in use. Borrowing a temporary directly, returning references, and storing references in struct fields are unavailable.
Run opt blocks with different options
Section titled “Run opt blocks with different options”Run the same program with optimization disabled and enabled:
xen run scope_modes.xen --opt=offxen run scope_modes.xen --opt=basicxen run scope_modes.xen --opt=basic --opt-reportxen build scope_modes.xen --opt=basic --opt-cache=.xen-opt-cache -o scope-modesThe first two commands produce the standard output shown above. --opt-report writes application information separately to stderr. Do not use report line counts or internal identifiers as part of your program’s output contract.
build, run, and test default to --opt=basic. Optimization applies to code marked with #scope[opt]; unmarked code is unaffected. --opt-report and --opt-cache require basic and are unavailable for check. Checking does not execute the program or measure performance.
This small example teaches annotation placement and the execution workflow. Marking a block does not by itself establish a speed improvement.
bb and its detailed reference
Section titled “bb and its detailed reference”bb enables raw memory, volatile and atomic operations, syscalls, external C calls, and inline assembly. The low-level reference documents its APIs, target support, and caller responsibilities. Use the standard library for ordinary files, I/O, and paths.
Look up rules in the scope modes reference and options in the CLI reference.