Skip to content

False positive for break_with_label_and_loop lint & incorrect suggestion #137414

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wmmc88 opened this issue Feb 22, 2025 · 2 comments · May be fixed by #137454
Open

False positive for break_with_label_and_loop lint & incorrect suggestion #137414

wmmc88 opened this issue Feb 22, 2025 · 2 comments · May be fixed by #137454
Labels
A-lints Area: Lints (warnings about flaws in source code) such as unused_mut. C-bug Category: This is a bug. L-break_with_label_and_loop Lint: break_with_label_and_loop L-false-positive Lint: False positive (should not have fired). T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@wmmc88
Copy link

wmmc88 commented Feb 22, 2025

I tried this code:

use std::mem::MaybeUninit;

#[derive(Debug)]
pub struct Foo {
    pub field_1: u32,
    pub field_2: u64,
}

const SUCCESS: u32 = 0;

unsafe fn ffi_init_foo(foo: *mut Foo) -> u32 {
    (*foo).field_1 = 1;
    (*foo).field_2 = 2;
    SUCCESS
}

fn func_1() -> Result<Foo, u32>{
    let mut foo = MaybeUninit::<Foo>::uninit();

    let foo = 'block: {
        let ret_val = unsafe {
            ffi_init_foo(foo.as_mut_ptr())
        };
        if ret_val == SUCCESS {
            break 'block unsafe { foo.assume_init() };
        }
        eprintln!("ERROR: {ret_val}");
        return Err(ret_val);
    };
    
    Ok(foo)
}

// uses compiler suggestion!
fn func_2() -> Result<Foo, u32>{
    let mut foo = MaybeUninit::<Foo>::uninit();

    let foo = 'block: {
        let ret_val = unsafe {
            ffi_init_foo(foo.as_mut_ptr())
        };
        if ret_val == SUCCESS {
            break 'block (unsafe { foo.assume_init() });
        }
        eprintln!("ERROR: {ret_val}");
        return Err(ret_val);
    };
    
    Ok(foo)
}

// this works without warnings
fn func_3() -> Result<Foo, u32>{
    let mut foo = MaybeUninit::<Foo>::uninit();

    let foo = 'block: {
        let ret_val = unsafe {
            ffi_init_foo(foo.as_mut_ptr())
        };
        if ret_val == SUCCESS {
            let foo = unsafe { foo.assume_init() };
            break 'block foo;
        }
        eprintln!("ERROR: {ret_val}");
        return Err(ret_val);
    };
    
    Ok(foo)
}

fn main() {
    let _ = dbg!(func_1());
    let _ = dbg!(func_2());
    let _ = dbg!(func_3());
}

I expected func_1 to compile without warning but it produced:

warning: this labeled break expression is easy to confuse with an unlabeled break with a labeled value expression
  --> src/main.rs:25:13
   |
25 |             break 'block unsafe { foo.assume_init() };
   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
   = note: `#[warn(break_with_label_and_loop)]` on by default
help: wrap this expression in parentheses
   |
25 |             break 'block (unsafe { foo.assume_init() });
   |                          +                            +

func_2 is the same as func_1, but it follows the compilers suggestion and produces this warning:

warning: unnecessary parentheses around `break` value
  --> src/main.rs:43:26
   |
43 |             break 'block (unsafe { foo.assume_init() });
   |                          ^                            ^
   |
   = note: `#[warn(unused_parens)]` on by default
help: remove these parentheses
   |
43 -             break 'block (unsafe { foo.assume_init() });
43 +             break 'block unsafe { foo.assume_init() };
   |

func_3 compiles without warnings, but it adds a needless assignment.

Meta

rustc --version --verbose:

1.87.0-nightly

(2025-02-21 794c12416b2138064af1)

The issue is also present on latest stable (1.85)

@wmmc88 wmmc88 added the C-bug Category: This is a bug. label Feb 22, 2025
@rustbot rustbot added the needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. label Feb 22, 2025
@wmmc88
Copy link
Author

wmmc88 commented Feb 22, 2025

From reading the break_with_label_and_loop lint, I'm guessing that it might be confusing the unsafe expression with a loop.

'label: loop {
    break 'label unsafe { foo.assume_init() };
};

looks a lot like

'label: loop {
    break 'label loop { break 42; };
};

where the latter is the example for the lint.

@workingjubilee
Copy link
Member

this apparently was introduced between 1.83 and 1.84

@jieyouxu jieyouxu added A-lints Area: Lints (warnings about flaws in source code) such as unused_mut. L-false-positive Lint: False positive (should not have fired). L-break_with_label_and_loop Lint: break_with_label_and_loop T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. C-bug Category: This is a bug. and removed C-bug Category: This is a bug. needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. labels Feb 22, 2025
@mu001999 mu001999 linked a pull request Feb 23, 2025 that will close this issue
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this issue Apr 18, 2025
…leywiser

not lint break with label and unsafe block

fixes rust-lang#137414

we can't label unsafe blocks, so that we can do not lint them
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this issue Apr 18, 2025
…leywiser

not lint break with label and unsafe block

fixes rust-lang#137414

we can't label unsafe blocks, so that we can do not lint them
jhpratt added a commit to jhpratt/rust that referenced this issue Apr 19, 2025
…leywiser

not lint break with label and unsafe block

fixes rust-lang#137414

we can't label unsafe blocks, so that we can do not lint them
ChrisDenton added a commit to ChrisDenton/rust that referenced this issue Apr 19, 2025
…leywiser

not lint break with label and unsafe block

fixes rust-lang#137414

we can't label unsafe blocks, so that we can do not lint them
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-lints Area: Lints (warnings about flaws in source code) such as unused_mut. C-bug Category: This is a bug. L-break_with_label_and_loop Lint: break_with_label_and_loop L-false-positive Lint: False positive (should not have fired). T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants