Change:
Proposing to extract this from . The following examples shouldn't error: While this has been considered part of for a while, it's also been acknowledged as a bug and suggested by to address separately ahead of stabilizing . Indeed it's surprising for users that this would count as handling a mutable reference in const contexts. See: <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
Cc Fixing this requires changing to skip traversing things inside function pointers. I'm not sure what the best way to achieve that is.
claim
Is there any reason returning a function trait object (e.g. , , etc.) does not work? It works with the feature, but IMO it should have been pulled out like the function pointers. For example this does not compile:
We didn't exhaustively look through all cases that we can exempt here. Anyway, is on the , so this question will be moot soon. :)

Discussion:
use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::*; use rustc_middle::traits::BuiltinImplSource; <ins> use rustc_middle::ty::GenericArgs; </ins> use rustc_middle::ty::{self, adjustment::PointerCoercion, Instance, InstanceDef, Ty, TyCtxt}; <del> use rustc_middle::ty::{GenericArgKind, GenericArgs}; </del> use rustc_middle::ty::{TraitRef, TypeVisitableExt}; use rustc_mir_dataflow::{self, Analysis}; use rustc_span::{sym, Span, Symbol}; use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _; use rustc_trait_selection::traits::{self, ObligationCauseCode, ObligationCtxt, SelectionContext}; <ins> use rustc_type_ir::visit::{TypeSuperVisitable, TypeVisitor}; </ins> use std::mem; <del> use std::ops::Deref; </del> <ins> use std::ops::{ControlFlow, Deref}; </ins> use super::ops::{self, NonConstOp, Status}; use super::qualifs::{self, CustomEq, HasMutInterior, NeedsDrop};

} } <ins> struct LocalReturnTyVisitor<'ck, 'mir, 'tcx> { kind: LocalKind, checker: &'ck mut Checker<'mir, 'tcx>, } impl<'ck, 'mir, 'tcx> TypeVisitor<TyCtxt<'tcx>> for LocalReturnTyVisitor<'ck, 'mir, 'tcx> { fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { match t.kind() { ty::FnPtr(_) => ControlFlow::Continue(()), ty::Ref(_, _, hir::Mutability::Mut) => { self.checker.check_op(ops::ty::MutRef(self.kind)); t.super_visit_with(self) } _ => t.super_visit_with(self), } } } </ins> pub struct Checker<'mir, 'tcx> { ccx: &'mir ConstCx<'mir, 'tcx>, qualifs: Qualifs<'mir, 'tcx>,

fn check_local_or_return_ty(&mut self, ty: Ty<'tcx>, local: Local) { let kind = self.body.local_kind(local); <del> for ty in ty.walk() { let ty = match ty.unpack() { GenericArgKind::Type(ty) => ty, // No constraints on lifetimes or constants, except potentially // constants' types, but `walk` will get to them as well. GenericArgKind::Lifetime(_) | GenericArgKind::Const(_) => continue, }; </del> <ins> let mut visitor = LocalReturnTyVisitor { kind, checker: self }; </ins> <del> match *ty.kind() { ty::Ref(_, _, hir::Mutability::Mut) => self.check_op(ops::ty::MutRef(kind)), _ => {} } } </del> <ins> visitor.visit_ty(ty); </ins> } fn check_mut_borrow(&mut self, local: Local, kind: hir::BorrowKind) {

<ins> // This checks that function pointer signatures that are referenced mutably // but contain a &mut T parameter still fail in a constant context: see issue #114994. // // check-fail const fn use_mut_const_fn(_f: &mut fn(&mut String)) { //~ ERROR mutable references are not allowed in constant functions () } const fn use_mut_const_tuple_fn(_f: (fn(), &mut u32)) { //~ ERROR mutable references are not allowed in constant functions } fn main() {} </ins>

<ins> error[E0658]: mutable references are not allowed in constant functions --> $DIR/issue-114994-fail.rs:6:27 | LL | const fn use_mut_const_fn(_f: &mut fn(&mut String)) { |                           ^^ | = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable error[E0658]: mutable references are not allowed in constant functions --> $DIR/issue-114994-fail.rs:10:33 | LL | const fn use_mut_const_tuple_fn(_f: (fn(), &mut u32)) { |                                 ^^ | = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0658`. </ins>

<ins> // This checks that function pointer signatures containing &mut T types // work in a constant context: see issue #114994. // // check-pass const fn use_const_fn(_f: fn(&mut String)) { () } const fn get_some_fn() -> fn(&mut String) { String::clear } const fn some_const_fn() { let _f: fn(&mut String) = String::clear; } fn main() {} </ins>