From 46c00a21e1e89ebbf7757dcbee35f89332575134 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Tue, 26 Nov 2019 12:55:11 +0100 Subject: [PATCH] Move all intrinsic whitelists into the constness check file --- src/librustc/ty/constness.rs | 35 ++++++++++++ .../transform/qualify_min_const_fn.rs | 55 +------------------ .../const-extern-fn-call-extern-fn.rs | 4 +- .../const-extern-fn-call-extern-fn.stderr | 4 +- 4 files changed, 42 insertions(+), 56 deletions(-) diff --git a/src/librustc/ty/constness.rs b/src/librustc/ty/constness.rs index 0fb3f575b5255..8ec5120d6b37d 100644 --- a/src/librustc/ty/constness.rs +++ b/src/librustc/ty/constness.rs @@ -36,12 +36,47 @@ impl<'tcx> TyCtxt<'tcx> { } } + /// Returns `true` if the `def_id` refers to an intrisic which we've whitelisted + /// for being called from stable `const fn`s (`min_const_fn`). + /// + /// Adding more intrinsics requires sign-off from @rust-lang/lang. + fn is_intrinsic_min_const_fn(self, def_id: DefId) -> bool { + match self.item_name(def_id) { + | sym::size_of + | sym::min_align_of + | sym::needs_drop + // Arithmetic: + | sym::add_with_overflow // ~> .overflowing_add + | sym::sub_with_overflow // ~> .overflowing_sub + | sym::mul_with_overflow // ~> .overflowing_mul + | sym::wrapping_add // ~> .wrapping_add + | sym::wrapping_sub // ~> .wrapping_sub + | sym::wrapping_mul // ~> .wrapping_mul + | sym::saturating_add // ~> .saturating_add + | sym::saturating_sub // ~> .saturating_sub + | sym::unchecked_shl // ~> .wrapping_shl + | sym::unchecked_shr // ~> .wrapping_shr + | sym::rotate_left // ~> .rotate_left + | sym::rotate_right // ~> .rotate_right + | sym::ctpop // ~> .count_ones + | sym::ctlz // ~> .leading_zeros + | sym::cttz // ~> .trailing_zeros + | sym::bswap // ~> .swap_bytes + | sym::bitreverse // ~> .reverse_bits + => true, + _ => false, + } + } + /// Returns `true` if this function must conform to `min_const_fn` pub fn is_min_const_fn(self, def_id: DefId) -> bool { // Bail out if the signature doesn't contain `const` if !self.is_const_fn_raw(def_id) { return false; } + if let Abi::RustIntrinsic = self.fn_sig(def_id).abi() { + return self.is_intrinsic_min_const_fn(def_id); + } if self.features().staged_api { // in order for a libstd function to be considered min_const_fn diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs index b7e1b83ee05b8..cf04d3e975b6f 100644 --- a/src/librustc_mir/transform/qualify_min_const_fn.rs +++ b/src/librustc_mir/transform/qualify_min_const_fn.rs @@ -2,7 +2,6 @@ use rustc::hir::def_id::DefId; use rustc::hir; use rustc::mir::*; use rustc::ty::{self, Predicate, Ty, TyCtxt, adjustment::{PointerCast}}; -use rustc_target::spec::abi; use std::borrow::Cow; use syntax_pos::Span; use syntax::symbol::{sym, Symbol}; @@ -356,18 +355,8 @@ fn check_terminator( } => { let fn_ty = func.ty(body, tcx); if let ty::FnDef(def_id, _) = fn_ty.kind { - - // some intrinsics are waved through if called inside the - // standard library. Users never need to call them directly - match tcx.fn_sig(def_id).abi() { - abi::Abi::RustIntrinsic => if !is_intrinsic_whitelisted(tcx, def_id) { - return Err(( - span, - "can only call a curated list of intrinsics in `min_const_fn`".into(), - )) - }, - abi::Abi::Rust if tcx.is_min_const_fn(def_id) => {}, - abi::Abi::Rust => return Err(( + if !tcx.is_min_const_fn(def_id) { + return Err(( span, format!( "can only call other `const fn` within a `const fn`, \ @@ -375,14 +364,7 @@ fn check_terminator( func, ) .into(), - )), - abi => return Err(( - span, - format!( - "cannot call functions with `{}` abi in `min_const_fn`", - abi, - ).into(), - )), + )); } check_operand(tcx, func, span, def_id, body)?; @@ -410,34 +392,3 @@ fn check_terminator( } } -/// Returns `true` if the `def_id` refers to an intrisic which we've whitelisted -/// for being called from stable `const fn`s (`min_const_fn`). -/// -/// Adding more intrinsics requires sign-off from @rust-lang/lang. -fn is_intrinsic_whitelisted(tcx: TyCtxt<'tcx>, def_id: DefId) -> bool { - match tcx.item_name(def_id) { - | sym::size_of - | sym::min_align_of - | sym::needs_drop - // Arithmetic: - | sym::add_with_overflow // ~> .overflowing_add - | sym::sub_with_overflow // ~> .overflowing_sub - | sym::mul_with_overflow // ~> .overflowing_mul - | sym::wrapping_add // ~> .wrapping_add - | sym::wrapping_sub // ~> .wrapping_sub - | sym::wrapping_mul // ~> .wrapping_mul - | sym::saturating_add // ~> .saturating_add - | sym::saturating_sub // ~> .saturating_sub - | sym::unchecked_shl // ~> .wrapping_shl - | sym::unchecked_shr // ~> .wrapping_shr - | sym::rotate_left // ~> .rotate_left - | sym::rotate_right // ~> .rotate_right - | sym::ctpop // ~> .count_ones - | sym::ctlz // ~> .leading_zeros - | sym::cttz // ~> .trailing_zeros - | sym::bswap // ~> .swap_bytes - | sym::bitreverse // ~> .reverse_bits - => true, - _ => false, - } -} diff --git a/src/test/ui/consts/const-extern-fn/const-extern-fn-call-extern-fn.rs b/src/test/ui/consts/const-extern-fn/const-extern-fn-call-extern-fn.rs index 7c6a574a2110f..6469a65700dad 100644 --- a/src/test/ui/consts/const-extern-fn/const-extern-fn-call-extern-fn.rs +++ b/src/test/ui/consts/const-extern-fn/const-extern-fn-call-extern-fn.rs @@ -7,7 +7,7 @@ extern "C" { const extern fn bar() { unsafe { regular_in_block(); - //~^ ERROR: cannot call functions with `"C"` abi in `min_const_fn` + //~^ ERROR: can only call other `const fn` within a `const fn` } } @@ -16,7 +16,7 @@ extern fn regular() {} const extern fn foo() { unsafe { regular(); - //~^ ERROR: cannot call functions with `"C"` abi in `min_const_fn` + //~^ ERROR: can only call other `const fn` within a `const fn` } } diff --git a/src/test/ui/consts/const-extern-fn/const-extern-fn-call-extern-fn.stderr b/src/test/ui/consts/const-extern-fn/const-extern-fn-call-extern-fn.stderr index d8bdf0a57cf66..eed279ecf7503 100644 --- a/src/test/ui/consts/const-extern-fn/const-extern-fn-call-extern-fn.stderr +++ b/src/test/ui/consts/const-extern-fn/const-extern-fn-call-extern-fn.stderr @@ -1,4 +1,4 @@ -error[E0723]: cannot call functions with `"C"` abi in `min_const_fn` +error[E0723]: can only call other `const fn` within a `const fn`, but `const regular_in_block` is not stable as `const fn` --> $DIR/const-extern-fn-call-extern-fn.rs:9:9 | LL | regular_in_block(); @@ -7,7 +7,7 @@ LL | regular_in_block(); = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563 = help: add `#![feature(const_fn)]` to the crate attributes to enable -error[E0723]: cannot call functions with `"C"` abi in `min_const_fn` +error[E0723]: can only call other `const fn` within a `const fn`, but `const regular` is not stable as `const fn` --> $DIR/const-extern-fn-call-extern-fn.rs:18:9 | LL | regular();