We can't find the internet
Attempting to reconnect
Something went wrong!
Attempting to reconnect
← Modules, Visibility, Testing and Docs step 12 of 22
Conditional compilation with cfg and cfg_select!
Conditional compilation lets a Rust program include code only when a build condition holds. Practice the distinction between selecting code and testing a boolean by implementing these two functions:
pub fn eval_cfg(predicate: &str, active: Vec<String>) -> Result<bool, String>
pub fn pointer_class() -> &'static str
Evaluate a small predicate language
eval_cfg evaluates a predicate against the supplied active options,
independently of the compiler's own build settings.
| Form | Meaning |
|---|---|
unix |
Is this bare option active? |
target_os="linux" |
Is this exact key-value option active? |
all(p, q) |
Are all child predicates true? |
any(p, q) |
Is at least one child predicate true? |
not(p) |
Invert one child predicate |
true, false |
Boolean literals, regardless of active |
Calls can nest. all() is true and any() is false. A single trailing comma
is accepted after an argument, as in all(unix,); leading commas and missing
arguments between commas are invalid. not takes exactly one argument.
For this exercise, remove every character recognized by char::is_whitespace
from both the predicate and each active option before parsing or comparison.
This includes whitespace inside quoted values: label="a b" becomes
label="ab". Duplicate active options have no effect, and several values
for one key can be active at once.
Names use ASCII letters or _ first, followed by ASCII letters, digits or
_. A value is enclosed in double quotes and can contain any non-quote
characters, including commas and parentheses. Those characters inside a
value are data, not argument separators or grouping syntax. Backslashes
are literal characters; this grammar does not decode escape sequences or
support raw strings. Assume nesting and input sizes fit available resources.
These are deliberate simplifications. Real Rust preserves whitespace inside string values and supports Rust string literals and identifiers. This parser is an exercise in recursive structure, not a replacement for the compiler.
Report invalid input
Check an empty normalized input first, then check parentheses outside quoted
values. Evaluate child predicates from left to right, checking every child
even if the boolean result is already known. For example, any(true, 7) is
an error, not Ok(true).
| Situation | Exact error string |
|---|---|
| Empty normalized input | empty predicate |
| Unbalanced parentheses outside values | unbalanced parentheses |
not has zero or more than one argument |
not() takes exactly one predicate |
| Invalid leaf or balanced expression | bad predicate: <text> |
In the last row, <text> is the normalized expression being evaluated.
An empty argument produces bad predicate: with a space after the colon.
Check not's argument count before evaluating its children. Active options
are normalized strings used for membership checks; do not recursively
evaluate them or reject the whole request because one is malformed.
Select code with cfg, test a boolean with cfg!
#[cfg(...)] excludes the annotated item when its predicate is false.
Excluded function bodies do not need to resolve names or type-check, but
ordinary Rust source must still parse. A missing type in an excluded function
is different from a missing closing delimiter.
cfg!(...) produces a boolean. It does not remove either branch of an if,
so both branches must resolve and type-check for the build target:
#[cfg(any())]
fn excluded() -> MissingType {
missing_function()
}
fn main() {
let family = if cfg!(unix) { "unix" } else { "other" };
assert!(matches!(family, "unix" | "other"));
}
cfg_attr conditionally applies another attribute. For example, this type
gets a Debug implementation in builds with debug assertions enabled:
#[cfg_attr(debug_assertions, derive(Debug))]
struct Reading(i32);
fn main() {
let reading = Reading(7);
#[cfg(debug_assertions)]
assert_eq!(format!("{reading:?}"), "Reading(7)");
assert_eq!(reading.0, 7);
}
Select the first matching arm
cfg_select!, available since Rust 1.95, selects the first true predicate
and emits its code. It can produce items or an expression. Use it for
pointer_class, returning "64-bit", "32-bit", "16-bit" or "unknown"
according to target_pointer_width. The harness checks the result against
size_of::<usize>() on the machine compiling the submission.
fn main() {
let bits = cfg_select! {
target_pointer_width = "64" => 64,
target_pointer_width = "32" => 32,
target_pointer_width = "16" => 16,
_ => 0,
};
assert_eq!(bits, match size_of::<usize>() {
2 => 16,
4 => 32,
8 => 64,
_ => 0,
});
}
Put overlapping cases in the order you intend them to take precedence.
The starter puts _ first, making later arms unreachable; move the fallback
last. The compiler's unreachable_cfg_select_predicates lint reports this,
and the warnings-as-errors grading gate rejects it. If no predicate matches
and there is no fallback, the macro emits a compilation error.
Compiler options affect the real cfg set. The current runner builds an
optimized executable without --test; debug assertions are off by default
there. Its separate Clippy check does not use the same optimization flag,
so do not rely on both passes having identical cfg settings.
That has no effect on eval_cfg: if its supplied options include
test or debug_assertions, those options are active for that evaluation.
Clippy can flag redundant expressions such as all(unix) with
non_minimal_cfg. The compiler can catch unexpected cfg names or values
with unexpected_cfgs when cfg checking is enabled, for example through
Cargo or rustc's --check-cfg. Do not assume a bare rustc invocation checks
every misspelling. Submissions must compile, pass the tests and pass Clippy
with warnings treated as errors.
Your code, saved here
Sign in to access your accepted solutions and saved draft history. You can keep reading the lesson without an account.
Sign in to your accountStuck?
Rust reference solution
Sign in to track your attempts toward unlocking the reference solution.