Ownership (Page 89)

Scope and Assigment

Can anyone help , I get an error when run this:

fn main(){
    let mut d = String::from("hello");
    d = String::from("ahoy");
        
    println!("{d}, world!");
}
warning: value assigned to `d` is never read
 --> ownership.rs:2:17
  |
2 |     let mut d = String::from("hello");
  |                 ^^^^^^^^^^^^^^^^^^^^^
  |
  = help: maybe it is overwritten before being read?
  = note: `#[warn(unused_assignments)]` (part of `#[warn(unused)]`) on by default

warning: 1 warning emitted

Welcome!

What you have showed is just a warning from the compiler, it's not an error :slightly_smiling_face: .

2 Likes

The warning is correct. If this was a real program, the unused string value "hello" being created in the first place might indicate a bug in the program. Assuming you're just learning Rust and trying to get an understanding of the hard rules of the language, you might be interested to know that you can turn off warnings. It’s most straightforward to do with attributes like the one the compiler message is mentioning to you.

When a "lint" (which is the general term in Rust used for optional kinds of checks, which can produce warnings or errors or nothing at all, controlled by a default lint-level, and user-controlled overrides) is turned on by default and that results in a warning, you can see the compiler mention it on the first warning of each kind of lint:

  = note: `#[warn(unused_assignments)]` (part of `#[warn(unused)]`) on by default

The main annotations for controlling lints are allow, warn and deny which sets the level to "do nothing" or "warn" or "produce an error", respectively.

The lint here is called “unused-assignments” and it’s part of the lint group “unused”.

You can thus turn of the warning by either doing #[allow(unused_assignments)] (which turns off warnings for this specific kind of case) or #[allow(unused)] (which turns off a lot more differerent warnings related to things being unused).

The other freedom that you have is control about where you want to disable the lint.

For example, if you have

fn other_function() {
    let mut value = String::from("test");

    value = String::new();
    drop(value);
}

fn main(){
    let mut d = String::from("hello");
    d = String::from("ahoy");
        
    println!("{d}, world!");

    other_function();
}

producing multiple warnings

warning: value assigned to `value` is never read
 --> src/main.rs:2:21
  |
2 |     let mut value = String::from("test");
  |                     ^^^^^^^^^^^^^^^^^^^^
  |
  = help: maybe it is overwritten before being read?
  = note: `#[warn(unused_assignments)]` (part of `#[warn(unused)]`) on by default

warning: value assigned to `d` is never read
 --> src/main.rs:9:17
  |
9 |     let mut d = String::from("hello");
  |                 ^^^^^^^^^^^^^^^^^^^^^
  |
  = help: maybe it is overwritten before being read?

then placing #[allow(unused_assignments)] before on one function

fn other_function() {
    let mut value = String::from("test");

    value = String::new();
    drop(value);
}

#[allow(unused_assignments)]
fn main(){
    let mut d = String::from("hello");
    d = String::from("ahoy");
        
    println!("{d}, world!");

    other_function();
}

would only remove one of the warnings: (playground

(this one stays)

warning: value assigned to `value` is never read
 --> src/main.rs:2:21
  |
2 |     let mut value = String::from("test");
  |                     ^^^^^^^^^^^^^^^^^^^^
  |
  = help: maybe it is overwritten before being read?
  = note: `#[warn(unused_assignments)]` (part of `#[warn(unused)]`) on by default

To apply to a whole module (or whole crate) you can also place an inner attribute at the beginning of your source file. The inner attribute syntax features an added ! to differentiate from outer-attributes ("outer" as in: outside the thing they apply to):sweat_smile:

#![allow(unused_assignments)] // applies to whole file, not just `other_function`

fn other_function() {
    let mut value = String::from("test");

    value = String::new();
    drop(value);
}

fn main(){
    let mut d = String::from("hello");
    d = String::from("ahoy");
        
    println!("{d}, world!");

    other_function();
}

(no more warnings).

Warnings about unused things relating to specific variables can also often be disabled by the convention of adding an underscore to the beginning of the variable name like this:

fn main(){
    let mut _d = String::from("hello");
    _d = String::from("ahoy");
        
    println!("{_d}, world!");
}

(no more warnings; try it out in the playground)

4 Likes

yeah, when I running on both rutsc and cargo I got:

cargo run:

 --> src/main.rs:2:17
  |
2 |     let mut a = String::from("hello");
  |                 ^^^^^^^^^^^^^^^^^^^^^
  |
  = help: maybe it is overwritten before being read?
  = note: `#[warn(unused_assignments)]` (part of `#[warn(unused)]`) on by default

warning: `hello_world` (bin "hello_world") generated 1 warning
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.01s
     Running `/home/adiq/rust/hello_world/target/debug/hello_world`
ahoy, world!

rustc ownership.rs:

warning: value assigned to `d` is never read
 --> ownership.rs:2:17
  |
2 |     let mut d = String::from("hello");
  |                 ^^^^^^^^^^^^^^^^^^^^^
  |
  = help: maybe it is overwritten before being read?
  = note: `#[warn(unused_assignments)]` (part of `#[warn(unused)]`) on by default

warning: 1 warning emitted


It might make sense to add some of that information to the lint itself, specially pointing at the place that go reassigned. Filed `unused_assignments` should provide more information for newcomers · Issue #154434 · rust-lang/rust · GitHub.

3 Likes