Skip to content

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

Closed

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

Activity

  1. added
    C-bugCategory: Clippy is not doing the correct thing
    I-false-positiveIssue: The lint was triggered on code it shouldn't have
    on May 23, 2022
  2. BurntNail commented on Jul 14, 2022

    @BurntNail

    I'm also experiencing this issue - the code that triggers it follows:

    pub enum Either<A, B> {
        Left(A),
        Right(B)
    }
    
    impl<A> Either<A, A> {
        pub fn unwrap (self) -> A {
            match self {
                Self::Left(a) => a,
                Self::Right(b) => b
            }
        }
    } 

    error as follows:

    warning: this could be a `const fn`
      --> src\either.rs:16:5
       |
    16 | /     pub fn unwrap (self) -> A {
    17 | |         match self {
    18 | |             Self::Left(a) => a,
    19 | |             Self::Right(b) => b
    20 | |         }
    21 | |     }
       | |_____^
    

    Error line is incorrect due to removed code - not clippy's fault.

  3. mahlquistj commented on Jul 4, 2023

    @mahlquistj

    I can also pitch in with my experience.

    I have a struct with a generic:

    pub struct Response<V> {
        ok: bool,
        value: Option<V>,
    }

    Which implements the following function:

    fn value(self) -> Option<V> {
        self.value
    }

    Clippy suggests making the function a const fn but when i do so, the compiler tells me the following:

    error[E0493]: destructor of `core::response::Response<V>` cannot be evaluated at compile-time
      --> src/core/response.rs:82:20
       |
    82 |     const fn value(self) -> Option<V> {
       |                    ^^^^ the destructor for this type cannot be evaluated in constant functions
    83 |         self.value
    84 |     }
       |     - value is dropped here
    

    Note: The struct has other fields and more implementations, but the above is the "minimal" example of the issue. If more is needed, i will happily provide it.

  4. Centri3 commented on Jul 4, 2023

    @Centri3
    Member
  5. johnperry-math commented on Jan 16, 2024

    @johnperry-math

    I believe this was already fixed in #10891.

    https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=7c430738d1e182a7bbb03c1ba398d1da

    When using Rust 1.75, I still see this clippy warning on a straightforward builder pattern and clippy::nursery.

  6. ada4a commented on Aug 8, 2025

    @ada4a
    Contributor

    @johnperry-math could you please provide a reproducer?

  7. johnperry-math commented on Aug 10, 2025

    @johnperry-math

    @johnperry-math could you please provide a reproducer?

    Not after 18 months.

  8. ada4a commented on Aug 10, 2025

    @ada4a
    Contributor

    Fair enough. Would you be okay with me closing this issue then? You can always open a new one if you do end up remembering the reproducer

  9. ada4a commented on Aug 22, 2025

    @ada4a
    Contributor

    I'll take that as a yes..

    @rustbot label S-fixed

  10. added
    S-fixedStatus: Issues that got fixed, waiting to be closed as completed
    on Aug 22, 2025
  11. johnperry-math commented on Aug 22, 2025

    @johnperry-math

    Oh, my apologies; I thought I'd replied.

  12. CommanderStorm commented on Sep 13, 2026

    @CommanderStorm
    Contributor

    I think the original issue is resolved, other issue needs an repro, which likely is better as an new issue

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

    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 groupS-fixedStatus: Issues that got fixed, waiting to be closed as completed

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions