diff options
| author | bors <bors@rust-lang.org> | 2023-10-14 09:18:28 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2023-10-14 09:18:28 +0000 |
| commit | 139f63a6eba2b7a10462e1c9f0ef396b01e524f5 (patch) | |
| tree | edbe781b55693b6b999d9685b8a5d57ab63c32c7 /compiler/rustc_const_eval/src | |
| parent | 481d45abeced571b533016a994cba7337102a4a4 (diff) | |
| parent | d975ae502749fa41d460588be39314f19b77db5d (diff) | |
| download | rust-139f63a6eba2b7a10462e1c9f0ef396b01e524f5.tar.gz rust-139f63a6eba2b7a10462e1c9f0ef396b01e524f5.zip | |
Auto merge of #116015 - EvanMerlock:master, r=oli-obk
const_eval: allow function pointer signatures containing &mut T in const contexts potentially fixes #114994 We utilize a `TypeVisitor` here in order to more easily handle control flow. - In the event the typekind the Visitor sees is a function pointer, we skip over it - However, otherwise we do one of two things: - If we find a mutable reference, check it, then continue visiting types - If we find any other type, continue visiting types This means we will check if the function pointer _itself_ is mutable, but not if any of the types _within_ are.
Diffstat (limited to 'compiler/rustc_const_eval/src')
| -rw-r--r-- | compiler/rustc_const_eval/src/transform/check_consts/check.rs | 38 |
1 files changed, 23 insertions, 15 deletions
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs index f8f9bfb0470..90819d492f4 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -9,16 +9,17 @@ use rustc_infer::traits::{ImplSource, Obligation, ObligationCause}; use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::*; use rustc_middle::traits::BuiltinImplSource; +use rustc_middle::ty::GenericArgs; use rustc_middle::ty::{self, adjustment::PointerCoercion, Instance, InstanceDef, Ty, TyCtxt}; -use rustc_middle::ty::{GenericArgKind, GenericArgs}; 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}; +use rustc_type_ir::visit::{TypeSuperVisitable, TypeVisitor}; use std::mem; -use std::ops::Deref; +use std::ops::{ControlFlow, Deref}; use super::ops::{self, NonConstOp, Status}; use super::qualifs::{self, CustomEq, HasMutInterior, NeedsDrop}; @@ -188,6 +189,24 @@ impl<'mir, 'tcx> Qualifs<'mir, 'tcx> { } } +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), + } + } +} + pub struct Checker<'mir, 'tcx> { ccx: &'mir ConstCx<'mir, 'tcx>, qualifs: Qualifs<'mir, 'tcx>, @@ -346,20 +365,9 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> { fn check_local_or_return_ty(&mut self, ty: Ty<'tcx>, local: Local) { let kind = self.body.local_kind(local); - 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, - }; + let mut visitor = LocalReturnTyVisitor { kind, checker: self }; - match *ty.kind() { - ty::Ref(_, _, hir::Mutability::Mut) => self.check_op(ops::ty::MutRef(kind)), - _ => {} - } - } + visitor.visit_ty(ty); } fn check_mut_borrow(&mut self, local: Local, kind: hir::BorrowKind) { |
