1
Fork 0

Clean up special function const checks

Mark them as const and `#[rustc_do_not_const_check]` instead of hard-coding
them in const-eval checks.
This commit is contained in:
Gary Guo 2021-10-25 17:07:16 +01:00
parent 235d9853d8
commit cc4345a1c5
8 changed files with 53 additions and 87 deletions

View file

@ -24,7 +24,7 @@ use std::ops::Deref;
use super::ops::{self, NonConstOp, Status};
use super::qualifs::{self, CustomEq, HasMutInterior, NeedsDrop, NeedsNonConstDrop};
use super::resolver::FlowSensitiveAnalysis;
use super::{is_lang_panic_fn, is_lang_special_const_fn, ConstCx, Qualif};
use super::{ConstCx, Qualif};
use crate::const_eval::is_unstable_const_fn;
// We are using `MaybeMutBorrowedLocals` as a proxy for whether an item may have been mutated
@ -918,31 +918,27 @@ impl Visitor<'tcx> for Checker<'mir, 'tcx> {
}
// At this point, we are calling a function, `callee`, whose `DefId` is known...
if is_lang_special_const_fn(tcx, callee) {
// `begin_panic` and `panic_display` are generic functions that accept
// types other than str. Check to enforce that only str can be used in
// const-eval.
// const-eval of the `begin_panic` fn assumes the argument is `&str`
if Some(callee) == tcx.lang_items().begin_panic_fn() {
match args[0].ty(&self.ccx.body.local_decls, tcx).kind() {
ty::Ref(_, ty, _) if ty.is_str() => (),
_ => self.check_op(ops::PanicNonStr),
}
// `begin_panic` and `panic_display` are generic functions that accept
// types other than str. Check to enforce that only str can be used in
// const-eval.
// const-eval of the `begin_panic` fn assumes the argument is `&str`
if Some(callee) == tcx.lang_items().begin_panic_fn() {
match args[0].ty(&self.ccx.body.local_decls, tcx).kind() {
ty::Ref(_, ty, _) if ty.is_str() => return,
_ => self.check_op(ops::PanicNonStr),
}
}
// const-eval of the `panic_display` fn assumes the argument is `&&str`
if Some(callee) == tcx.lang_items().panic_display() {
match args[0].ty(&self.ccx.body.local_decls, tcx).kind() {
ty::Ref(_, ty, _) if matches!(ty.kind(), ty::Ref(_, ty, _) if ty.is_str()) =>
{}
_ => self.check_op(ops::PanicNonStr),
// const-eval of the `panic_display` fn assumes the argument is `&&str`
if Some(callee) == tcx.lang_items().panic_display() {
match args[0].ty(&self.ccx.body.local_decls, tcx).kind() {
ty::Ref(_, ty, _) if matches!(ty.kind(), ty::Ref(_, ty, _) if ty.is_str()) =>
{
return;
}
}
if is_lang_panic_fn(tcx, callee) {
// run stability check on non-panic special const fns.
return;
_ => self.check_op(ops::PanicNonStr),
}
}

View file

@ -72,24 +72,6 @@ impl ConstCx<'mir, 'tcx> {
}
}
/// Returns `true` if this `DefId` points to one of the official `panic` lang items.
pub fn is_lang_panic_fn(tcx: TyCtxt<'tcx>, def_id: DefId) -> bool {
Some(def_id) == tcx.lang_items().panic_fn()
|| Some(def_id) == tcx.lang_items().panic_str()
|| Some(def_id) == tcx.lang_items().panic_display()
|| Some(def_id) == tcx.lang_items().begin_panic_fn()
|| Some(def_id) == tcx.lang_items().panic_fmt()
}
/// Returns `true` if this `DefId` points to one of the lang items that will be handled differently
/// in const_eval.
pub fn is_lang_special_const_fn(tcx: TyCtxt<'tcx>, def_id: DefId) -> bool {
// We can allow calls to these functions because `hook_special_const_fn` in
// `const_eval/machine.rs` ensures the calls are handled specially.
// Keep in sync with what that function handles!
is_lang_panic_fn(tcx, def_id) || Some(def_id) == tcx.lang_items().const_eval_select()
}
pub fn rustc_allow_const_fn_unstable(
tcx: TyCtxt<'tcx>,
def_id: DefId,