We can't find the internet
Attempting to reconnect
Something went wrong!
Attempting to reconnect
← Shape Your Data: Structs, Enums, Pattern Matching step 2 of 26
Field init shorthand and struct update syntax
Start from a base configuration and apply a list of (key, value) overrides
in order, then render the result as "host:port".
pub fn apply_overrides(
base_host: String,
base_port: u32,
overrides: Vec<(String, String)>,
) -> String
Recognised keys are "host" and "port". Anything else is ignored. A
"port" value that does not parse as a u32 is ignored too. Later overrides
win over earlier ones. An empty override list gives back the base.
With base ("localhost", 8080) and overrides
[("host", "b.test"), ("port", "2"), ("host", "c.test")] the answer is
"c.test:2".
The two pieces of syntax
Field init shorthand. When the variable already has the field’s name, you write the name once:
let port = 443;
let cfg = Config { host, port }; // not `host: host, port: port`
This is not a style preference you can decline. redundant_field_names is on
by default, and under -D warnings it fails your build.
Struct update syntax. ..other fills in every field you did not list:
let tweaked = Config { port: 9000, ..base };
It must come last and takes no trailing comma.
..base is not a JavaScript spread
This is the whole reason the item exists. {...base, port: 9000} in
JavaScript copies — base is untouched and reusable. ..base in Rust
moves. It takes the remaining fields out of base and hands them to the
new value, and any field it takes that is not Copy is gone from base
afterwards.
The starter ships the demonstration: two configs built from one base. It does not compile. Read the message before you change anything —
error[E0382]: use of moved value: `base.host`
Note what rustc says and what it does not say. It does not complain about
base.port: u32 is Copy, so ..base copied it and left the original in
place. Only host, a String, actually moved. Rust tracks ownership
per field, which is why the error is about base.host and not about
base. This granularity is real and useful — you can move one field out of a
struct and keep using the others.
Three ways out, in rough order of how often you want them:
- Thread one value through. Build each successive config from the previous one, so nothing is used twice. That is what this problem wants.
-
Clone.
..base.clone()works and costs an allocation per use. - Borrow instead of own. Not available here — struct update always moves.
Another lint to know about
needless_update fires when you list every field and then also write
..base. At that point the base contributes nothing, and clippy tells you to
delete it. It is on by default.
Shape of a solution
You want a Config { host: String, port: u32 }, one value of it, and a loop
over the overrides that rebuilds it. Matching on key.as_str() gives you
&str arms, which is what string literals compare against — match key { "host" => ... }
on a String will not type-check.
Remember the grade is compile + tests + clippy -D warnings.
Loading visualization…
Stuck?
Rust reference solution
Sign in to attempt this problem and reveal the reference solution.