Rollup merge of #48078 - alexcrichton:fix-required-const-and-proc-macro, r=eddyb
Disallow function pointers to #[rustc_args_required_const] This commit disallows acquiring a function pointer to functions tagged as `#[rustc_args_required_const]`. This is intended to be used as future-proofing for the stdsimd crate to avoid taking a function pointer to any intrinsic which has a hard requirement that one of the arguments is a constant value. Note that the first commit here isn't related specifically to this feature, but was necessary to get this working in stdsimd!
This commit is contained in:
commit
1e10ca0b03
|
@ -716,6 +716,10 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
|
|||
ReifyFnPointer => {
|
||||
match self.eval_operand(operand)?.ty.sty {
|
||||
ty::TyFnDef(def_id, substs) => {
|
||||
if self.tcx.has_attr(def_id, "rustc_args_required_const") {
|
||||
bug!("reifying a fn ptr that requires \
|
||||
const arguments");
|
||||
}
|
||||
let instance = self.resolve(def_id, substs)?;
|
||||
let fn_ptr = self.memory.create_fn_alloc(instance);
|
||||
let valty = ValTy {
|
||||
|
|
|
@ -714,6 +714,10 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
|
|||
mir::CastKind::ReifyFnPointer => {
|
||||
match operand.ty.sty {
|
||||
ty::TyFnDef(def_id, substs) => {
|
||||
if tcx.has_attr(def_id, "rustc_args_required_const") {
|
||||
bug!("reifying a fn ptr that requires \
|
||||
const arguments");
|
||||
}
|
||||
callee::resolve_and_get_fn(self.cx, def_id, substs)
|
||||
}
|
||||
_ => {
|
||||
|
|
|
@ -195,6 +195,10 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
|
|||
mir::CastKind::ReifyFnPointer => {
|
||||
match operand.layout.ty.sty {
|
||||
ty::TyFnDef(def_id, substs) => {
|
||||
if bx.cx.tcx.has_attr(def_id, "rustc_args_required_const") {
|
||||
bug!("reifying a fn ptr that requires \
|
||||
const arguments");
|
||||
}
|
||||
OperandValue::Immediate(
|
||||
callee::resolve_and_get_fn(bx.cx, def_id, substs))
|
||||
}
|
||||
|
|
|
@ -4897,6 +4897,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
self.check_rustc_args_require_const(def.def_id(), node_id, span);
|
||||
|
||||
debug!("instantiate_value_path: type of {:?} is {:?}",
|
||||
node_id,
|
||||
ty_substituted);
|
||||
|
@ -4904,6 +4906,36 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
ty_substituted
|
||||
}
|
||||
|
||||
fn check_rustc_args_require_const(&self,
|
||||
def_id: DefId,
|
||||
node_id: ast::NodeId,
|
||||
span: Span) {
|
||||
// We're only interested in functions tagged with
|
||||
// #[rustc_args_required_const], so ignore anything that's not.
|
||||
if !self.tcx.has_attr(def_id, "rustc_args_required_const") {
|
||||
return
|
||||
}
|
||||
|
||||
// If our calling expression is indeed the function itself, we're good!
|
||||
// If not, generate an error that this can only be called directly.
|
||||
match self.tcx.hir.get(self.tcx.hir.get_parent_node(node_id)) {
|
||||
Node::NodeExpr(expr) => {
|
||||
match expr.node {
|
||||
hir::ExprCall(ref callee, ..) => {
|
||||
if callee.id == node_id {
|
||||
return
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
self.tcx.sess.span_err(span, "this function can only be invoked \
|
||||
directly, not through a function pointer");
|
||||
}
|
||||
|
||||
/// Report errors if the provided parameters are too few or too many.
|
||||
fn check_path_parameter_count(&self,
|
||||
span: Span,
|
||||
|
|
|
@ -984,6 +984,11 @@ pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeG
|
|||
"wasm_import_memory attribute is currently unstable",
|
||||
cfg_fn!(wasm_import_memory))),
|
||||
|
||||
("rustc_args_required_const", Whitelisted, Gated(Stability::Unstable,
|
||||
"rustc_attrs",
|
||||
"never will be stable",
|
||||
cfg_fn!(rustc_attrs))),
|
||||
|
||||
// Crate level attributes
|
||||
("crate_name", CrateLevel, Ungated),
|
||||
("crate_type", CrateLevel, Ungated),
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(attr_literals, rustc_attrs, const_fn)]
|
||||
|
||||
#[rustc_args_required_const(0)]
|
||||
fn foo(_a: i32) {
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let a = foo; //~ ERROR: this function can only be invoked directly
|
||||
a(2);
|
||||
}
|
Loading…
Reference in New Issue