Skip to content

Commit

Permalink
Rollup merge of rust-lang#48078 - alexcrichton:fix-required-const-and…
Browse files Browse the repository at this point in the history
…-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!
  • Loading branch information
kennytm authored Feb 9, 2018
2 parents ec01b28 + 7a20fc1 commit 6747b17
Show file tree
Hide file tree
Showing 6 changed files with 69 additions and 0 deletions.
4 changes: 4 additions & 0 deletions src/librustc_mir/interpret/eval_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
4 changes: 4 additions & 0 deletions src/librustc_trans/mir/constant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
_ => {
Expand Down
4 changes: 4 additions & 0 deletions src/librustc_trans/mir/rvalue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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))
}
Expand Down
32 changes: 32 additions & 0 deletions src/librustc_typeck/check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4897,13 +4897,45 @@ 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);
self.write_substs(self.tcx.hir.node_to_hir_id(node_id), substs);
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,
Expand Down
5 changes: 5 additions & 0 deletions src/libsyntax/feature_gate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down
20 changes: 20 additions & 0 deletions src/test/compile-fail/rustc-args-required-const2.rs
Original file line number Diff line number Diff line change
@@ -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);
}

0 comments on commit 6747b17

Please sign in to comment.