Skip to content

Missed unconditional recursion warning in Default trait implementation. #83534

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

Closed
a2aaron opened this issue Mar 26, 2021 · 2 comments
Closed
Labels
A-lints Area: Lints (warnings about flaws in source code) such as unused_mut. C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@a2aaron
Copy link
Contributor

a2aaron commented Mar 26, 2021

Given the following code: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=97f86e28bd7cd07f59f1507f35a9c7a3

pub struct Foo {
    pub x: f32,
    pub y: f32,
}

impl Default for Foo {
    fn default() -> Self {
        Foo {
            x: 1.0f32.floor(),
            ..Default::default()
        }
    }
}

The current output is:

   Compiling playground v0.0.1 (/playground)
    Finished dev [unoptimized + debuginfo] target(s) in 0.83s

Ideally the output should look like:

   Compiling playground v0.0.1 (/playground)
warning: function cannot return without recursing
  --> src/lib.rs:7:5
   |
7  |     fn default() -> Self {
   |     ^^^^^^^^^^^^^^^^^^^^ cannot return without recursing
...
10 |             ..Default::default()
   |               ------------------ recursive call site
   |
   = note: `#[warn(unconditional_recursion)]` on by default
   = help: a `loop` may express intention better if this is on purpose

The above code should produce a warning because it is impossible for Foo::default() to return without recursing. This likely occurs because the compiler is conservative when it comes to function calls (ex: it's possible that 1.0f32.floor() could panic and hence never return) but this should still be rejected because any path that actually would return would require unconditional recursion.

Note that this does not occur if x doesn't make a function or method call. For example, this code properly warns about unconditional recursion.

impl Default for Foo {
    fn default() -> Self {
        Foo {
            x: 1.0,
            ..Default::default()
        }
    }
}

I ran into this accidentally when implementing default.

@a2aaron a2aaron added A-diagnostics Area: Messages for errors, warnings, and lints T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Mar 26, 2021
@jonas-schievink jonas-schievink added A-lints Area: Lints (warnings about flaws in source code) such as unused_mut. C-bug Category: This is a bug. and removed A-diagnostics Area: Messages for errors, warnings, and lints labels Mar 26, 2021
@ShikChen
Copy link

It's a common trap... #78474 was also for this issue.

@ehuss
Copy link
Contributor

ehuss commented Jan 4, 2022

Closing as a duplicate of #78474.

@ehuss ehuss closed this as completed Jan 4, 2022
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. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

4 participants