Skip to content

False "missing_const_in_fn" for a function that consumes self #8874

Open
@ppentchev

Description

@ppentchev

Summary

Hi,

First of all, thanks a lot for working on Rust and the related tools and crates!

Clippy seems to report a "missing_const_in_fn" for a function that replaces a field in a struct. If I add "const" to the function, rustc says "constant functions cannot evaluate destructors". It is quite possible that, just like e.g. #4041, this is actually a bug in rustc's parser, AST builder, code analyzer, etc; apologies if it has been reported already.

Since the source file is a bit on the large side, I have put the mini-"crate" up in a Git repository at https://gitlab.com/ppentchev/rust-bug-missing-const

Lint Name

clippy::missing_const_for_fn

Reproducer

I tried this code (it uses expect-exit 0.4.2):

/*
 * Copyright (c) 2022  Peter Pentchev <roam@ringlet.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */
//! Demonstrate a false `clippy::missing_const_for_fn` positive.

#![deny(missing_docs)]
// Activate most of the clippy::restriction lints that we've encountered...
#![warn(clippy::pattern_type_mismatch)]
#![warn(clippy::missing_docs_in_private_items)]
#![warn(clippy::print_stdout)]
// ...except for these ones.
#![allow(clippy::implicit_return)]
// Activate some of the clippy::nursery lints...
#![warn(clippy::missing_const_for_fn)]

use std::env;

/// Runtime configuration for the bug-missing-const tool.
#[derive(Debug, PartialEq)]
#[non_exhaustive]
struct Config {
    /// The current program name.
    program: String,
}

impl Default for Config {
    fn default() -> Self {
        Self {
            program: "(unspecified)".to_owned(),
        }
    }
}

impl Config {
    /// Specify the program name.
    fn with_program(self, program: String) -> Self {
        Self { program, ..self }
    }
}

/// Parse the command-line arguments into a configuration structure.
fn parse_args() -> Config {
    let args: Vec<String> = env::args().collect();
    match *args {
        [] => expect_exit::exit("Not even a program name?"),
        [ref program] => Config::default().with_program(program.clone()),
        _ => expect_exit::exit("Usage: bug-missing-const"),
    }
}

#[cfg(test)]
mod tests {
    use super::Config;

    #[test]
    fn test_config_default() {
        assert!(
            Config::default()
                == Config {
                    program: "(unspecified)".to_owned()
                }
        );
    }

    #[test]
    fn test_config_with_program() {
        assert!(
            Config::default().with_program("616".to_owned())
                == Config {
                    program: "616".to_owned()
                }
        );
    }
}

#[allow(clippy::print_stdout)]
fn main() {
    let cfg = parse_args();
    println!("Program name: {}", cfg.program);
}

I saw this happen:

    Checking bug-missing-const v0.1.0 (/home/roam/lang/rust/misc/bug-missing-const)
warning: this could be a `const fn`
  --> src/main.rs:58:5
   |
58 | /     fn with_program(self, program: String) -> Self {
59 | |         Self { program, ..self }
60 | |     }
   | |_____^

I expected to see no warnings at all.

Version

rustc 1.61.0 (fe5b13d68 2022-05-18)
binary: rustc
commit-hash: fe5b13d681f25ee6474be29d748c65adcd91f69e
commit-date: 2022-05-18
host: x86_64-unknown-linux-gnu
release: 1.61.0
LLVM version: 14.0.0

Additional Labels

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-bugCategory: Clippy is not doing the correct thingI-false-positiveIssue: The lint was triggered on code it shouldn't haveL-nurseryLint: Currently in the nursery group

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions