Skip to content

Commit 1e10ca0

Browse files
authored
Rollup merge of rust-lang#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!
2 parents d6394e5 + 7a20fc1 commit 1e10ca0

File tree

6 files changed

+69
-0
lines changed

6 files changed

+69
-0
lines changed

src/librustc_mir/interpret/eval_context.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -716,6 +716,10 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
716716
ReifyFnPointer => {
717717
match self.eval_operand(operand)?.ty.sty {
718718
ty::TyFnDef(def_id, substs) => {
719+
if self.tcx.has_attr(def_id, "rustc_args_required_const") {
720+
bug!("reifying a fn ptr that requires \
721+
const arguments");
722+
}
719723
let instance = self.resolve(def_id, substs)?;
720724
let fn_ptr = self.memory.create_fn_alloc(instance);
721725
let valty = ValTy {

src/librustc_trans/mir/constant.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -714,6 +714,10 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
714714
mir::CastKind::ReifyFnPointer => {
715715
match operand.ty.sty {
716716
ty::TyFnDef(def_id, substs) => {
717+
if tcx.has_attr(def_id, "rustc_args_required_const") {
718+
bug!("reifying a fn ptr that requires \
719+
const arguments");
720+
}
717721
callee::resolve_and_get_fn(self.cx, def_id, substs)
718722
}
719723
_ => {

src/librustc_trans/mir/rvalue.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,10 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
195195
mir::CastKind::ReifyFnPointer => {
196196
match operand.layout.ty.sty {
197197
ty::TyFnDef(def_id, substs) => {
198+
if bx.cx.tcx.has_attr(def_id, "rustc_args_required_const") {
199+
bug!("reifying a fn ptr that requires \
200+
const arguments");
201+
}
198202
OperandValue::Immediate(
199203
callee::resolve_and_get_fn(bx.cx, def_id, substs))
200204
}

src/librustc_typeck/check/mod.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4897,13 +4897,45 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
48974897
}
48984898
}
48994899

4900+
self.check_rustc_args_require_const(def.def_id(), node_id, span);
4901+
49004902
debug!("instantiate_value_path: type of {:?} is {:?}",
49014903
node_id,
49024904
ty_substituted);
49034905
self.write_substs(self.tcx.hir.node_to_hir_id(node_id), substs);
49044906
ty_substituted
49054907
}
49064908

4909+
fn check_rustc_args_require_const(&self,
4910+
def_id: DefId,
4911+
node_id: ast::NodeId,
4912+
span: Span) {
4913+
// We're only interested in functions tagged with
4914+
// #[rustc_args_required_const], so ignore anything that's not.
4915+
if !self.tcx.has_attr(def_id, "rustc_args_required_const") {
4916+
return
4917+
}
4918+
4919+
// If our calling expression is indeed the function itself, we're good!
4920+
// If not, generate an error that this can only be called directly.
4921+
match self.tcx.hir.get(self.tcx.hir.get_parent_node(node_id)) {
4922+
Node::NodeExpr(expr) => {
4923+
match expr.node {
4924+
hir::ExprCall(ref callee, ..) => {
4925+
if callee.id == node_id {
4926+
return
4927+
}
4928+
}
4929+
_ => {}
4930+
}
4931+
}
4932+
_ => {}
4933+
}
4934+
4935+
self.tcx.sess.span_err(span, "this function can only be invoked \
4936+
directly, not through a function pointer");
4937+
}
4938+
49074939
/// Report errors if the provided parameters are too few or too many.
49084940
fn check_path_parameter_count(&self,
49094941
span: Span,

src/libsyntax/feature_gate.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -984,6 +984,11 @@ pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeG
984984
"wasm_import_memory attribute is currently unstable",
985985
cfg_fn!(wasm_import_memory))),
986986

987+
("rustc_args_required_const", Whitelisted, Gated(Stability::Unstable,
988+
"rustc_attrs",
989+
"never will be stable",
990+
cfg_fn!(rustc_attrs))),
991+
987992
// Crate level attributes
988993
("crate_name", CrateLevel, Ungated),
989994
("crate_type", CrateLevel, Ungated),
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![feature(attr_literals, rustc_attrs, const_fn)]
12+
13+
#[rustc_args_required_const(0)]
14+
fn foo(_a: i32) {
15+
}
16+
17+
fn main() {
18+
let a = foo; //~ ERROR: this function can only be invoked directly
19+
a(2);
20+
}

0 commit comments

Comments
 (0)