Skip to content

← Errors Are Values step 21 of 24

Medium Framework

#[must_use] in depth

Repair a builder API's annotations and make its port updates take effect.

pub fn build(ops: Vec<String>) -> Vec<String>

Start with host localhost and port 80. Process operations in order:

Operation State change Output appended
port:N Set port from N None
host:H Set host to H exactly None
reset Restore localhost and 80 None
show None {host}:{port}
validate None ok {host}:{port} or err {message}
Anything else None unknown

Parse N with Rust's str::parse::<u16>(). Failed parsing, including empty, negative, out-of-range or whitespace-padded input, sets the port to zero. A leading + is accepted. Host text may be empty or contain colons; keep the entire suffix after host: without trimming.

Validation checks the host first. An empty host produces host must not be empty. Otherwise, a port below 1024 produces port {port} is privileged, using the current port. All other configurations pass. This is the exercise's validation policy; it does not test network connectivity, hostname syntax or operating-system permissions.

For example, ["show", "port:8080", "validate", "reset", "show"] returns ["localhost:80", "ok localhost:8080", "localhost:80"]. Empty input returns an empty vector. Validation leaves the current settings available for later operations.

Repair the discarded builder result

with_port and with_host consume a Config and return its replacement. Keep their #[must_use] attributes. The starter's port branch calls the method on a clone and discards the returned configuration, so the original cfg never changes.

Assign the returned value back to cfg, as the host branch already does. No clone is needed there because the old configuration is being replaced. The clone before validate serves a different purpose: validation consumes its receiver, while later operations still need the current configuration.

Remove two unnecessary function annotations

The starter has four annotated methods. Keep the annotations on the two builder methods and remove the bare attributes on validate and reset:

Method Reason
validate Its Result return type already warns when directly discarded; a bare function attribute triggers Clippy's double_must_use lint
reset It changes the existing configuration and returns unit; annotating that return triggers Clippy's must_use_unit lint

A custom #[must_use = "explanation"] message can add context to an API, but this exercise needs no extra function annotation on validate.

What the type annotation means

Keep #[must_use] on Validated. This asks the compiler to warn when a value of that type is directly discarded in an expression statement. The warning follows the type, so producers do not each need an annotation. A function annotation instead targets that function's returned value.

These are warnings about likely mistakes, not proof that a result was meaningfully handled. Binding a value or explicitly writing let _ = ... can suppress a must-use diagnostic without applying its contents. Silencing the warning in the broken port branch would not fix its output.

In particular, ignoring an error deliberately is different from handling it. For this task, match the validation result and append the required success or error message.

Attribute placement and lint limits

An attribute on a trait method declaration can apply to calls to its implementations. Putting #[must_use] only on the method inside a trait implementation has no effect. An attribute on a trait can also affect values returned through impl Trait or a trait object.

The unused_must_use lint does not recursively enforce use of everything stored inside every container. Do not rely on wrapping a result to communicate intentional error handling. Prefer code that makes the chosen action clear.

With warnings denied, applicable must-use and Clippy warnings fail the submission gate. Passing that gate still does not establish correct behavior; the operation results must also match the task.