Skip to content

False positive for break_with_label_and_loop lint & incorrect suggestion #137414

Closed
@wmmc88

Description

@wmmc88

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)

Activity

added
needs-triageThis issue may need triage. Remove it if it has been sufficiently triaged.
on Feb 22, 2025
wmmc88

wmmc88 commented on Feb 22, 2025

@wmmc88
Author

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

workingjubilee commented on Feb 22, 2025

@workingjubilee
Member

this apparently was introduced between 1.83 and 1.84

added
A-lintsArea: Lints (warnings about flaws in source code) such as unused_mut.
L-false-positiveLint: False positive (should not have fired).
T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
C-bugCategory: This is a bug.
and removed
C-bugCategory: This is a bug.
needs-triageThis issue may need triage. Remove it if it has been sufficiently triaged.
on Feb 22, 2025
added 2 commits that reference this issue on Apr 18, 2025

Rollup merge of rust-lang#137454 - mu001999-contrib:fix-137414, r=wes…

ad10d18

Rollup merge of rust-lang#137454 - mu001999-contrib:fix-137414, r=wes…

b31aff5
added a commit that references this issue on Apr 19, 2025

Rollup merge of rust-lang#137454 - mu001999-contrib:fix-137414, r=wes…

9455414

3 remaining items

Loading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-lintsArea: Lints (warnings about flaws in source code) such as unused_mut.C-bugCategory: This is a bug.L-break_with_label_and_loopLint: break_with_label_and_loopL-false-positiveLint: False positive (should not have fired).T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      Participants

      @wmmc88@jieyouxu@workingjubilee@rustbot

      Issue actions

        False positive for `break_with_label_and_loop` lint & incorrect suggestion · Issue #137414 · rust-lang/rust