Skip to content

Commit fd1ccbc

Browse files
committed
fix(const_eval): correctly check const type for function pointers
- uses TypeReader for resolving local/return ty to support case where function pointer is before another type in a compound type
1 parent e4133ba commit fd1ccbc

File tree

1 file changed

+23
-15
lines changed
  • compiler/rustc_const_eval/src/transform/check_consts

1 file changed

+23
-15
lines changed

compiler/rustc_const_eval/src/transform/check_consts/check.rs

+23-15
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,17 @@ use rustc_infer::traits::{ImplSource, Obligation, ObligationCause};
99
use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor};
1010
use rustc_middle::mir::*;
1111
use rustc_middle::traits::BuiltinImplSource;
12+
use rustc_middle::ty::GenericArgs;
1213
use rustc_middle::ty::{self, adjustment::PointerCoercion, Instance, InstanceDef, Ty, TyCtxt};
13-
use rustc_middle::ty::{GenericArgKind, GenericArgs};
1414
use rustc_middle::ty::{TraitRef, TypeVisitableExt};
1515
use rustc_mir_dataflow::{self, Analysis};
1616
use rustc_span::{sym, Span, Symbol};
1717
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
1818
use rustc_trait_selection::traits::{self, ObligationCauseCode, ObligationCtxt, SelectionContext};
19+
use rustc_type_ir::visit::{TypeSuperVisitable, TypeVisitor};
1920

2021
use std::mem;
21-
use std::ops::Deref;
22+
use std::ops::{ControlFlow, Deref};
2223

2324
use super::ops::{self, NonConstOp, Status};
2425
use super::qualifs::{self, CustomEq, HasMutInterior, NeedsDrop};
@@ -188,6 +189,24 @@ impl<'mir, 'tcx> Qualifs<'mir, 'tcx> {
188189
}
189190
}
190191

192+
struct LocalReturnTyVisitor<'ck, 'mir, 'tcx> {
193+
kind: LocalKind,
194+
checker: &'ck mut Checker<'mir, 'tcx>,
195+
}
196+
197+
impl<'ck, 'mir, 'tcx> TypeVisitor<TyCtxt<'tcx>> for LocalReturnTyVisitor<'ck, 'mir, 'tcx> {
198+
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
199+
match t.kind() {
200+
ty::FnPtr(_) => ControlFlow::Continue(()),
201+
ty::Ref(_, _, hir::Mutability::Mut) => {
202+
self.checker.check_op(ops::ty::MutRef(self.kind));
203+
t.super_visit_with(self)
204+
}
205+
_ => t.super_visit_with(self),
206+
}
207+
}
208+
}
209+
191210
pub struct Checker<'mir, 'tcx> {
192211
ccx: &'mir ConstCx<'mir, 'tcx>,
193212
qualifs: Qualifs<'mir, 'tcx>,
@@ -346,20 +365,9 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> {
346365
fn check_local_or_return_ty(&mut self, ty: Ty<'tcx>, local: Local) {
347366
let kind = self.body.local_kind(local);
348367

349-
for ty in ty.walk() {
350-
let ty = match ty.unpack() {
351-
GenericArgKind::Type(ty) => ty,
352-
353-
// No constraints on lifetimes or constants, except potentially
354-
// constants' types, but `walk` will get to them as well.
355-
GenericArgKind::Lifetime(_) | GenericArgKind::Const(_) => continue,
356-
};
368+
let mut visitor = LocalReturnTyVisitor { kind, checker: self };
357369

358-
match *ty.kind() {
359-
ty::Ref(_, _, hir::Mutability::Mut) => self.check_op(ops::ty::MutRef(kind)),
360-
_ => {}
361-
}
362-
}
370+
visitor.visit_ty(ty);
363371
}
364372

365373
fn check_mut_borrow(&mut self, local: Local, kind: hir::BorrowKind) {

0 commit comments

Comments
 (0)