From f2c0ecded5f831eb03c187a2b13f04e959f5e3a3 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Thu, 14 Jan 2016 15:03:48 +0100 Subject: [PATCH] enable cross crate and unsafe const fn --- src/librustc/middle/const_eval.rs | 69 +++---------------- src/test/compile-fail/const-call.rs | 5 -- .../const-fn-stability-calls-2.rs | 22 ------ src/test/run-pass/const-fn-cross-crate.rs | 1 + src/test/run-pass/const-fn.rs | 6 ++ 5 files changed, 18 insertions(+), 85 deletions(-) delete mode 100644 src/test/compile-fail/const-fn-stability-calls-2.rs diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs index eae2aa9cb7e73..5a07124792d9c 100644 --- a/src/librustc/middle/const_eval.rs +++ b/src/librustc/middle/const_eval.rs @@ -27,7 +27,7 @@ use util::num::ToPrimitive; use util::nodemap::NodeMap; use graphviz::IntoCow; -use syntax::{ast, abi}; +use syntax::ast; use rustc_front::hir::Expr; use rustc_front::hir; use rustc_front::intravisit::FnKind; @@ -1089,19 +1089,16 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>, hir::ExprCall(ref callee, ref args) => { let sub_ty_hint = ty_hint.erase_hint(); let callee_val = try!(eval_const_expr_partial(tcx, callee, sub_ty_hint, fn_args)); - let (decl, block, constness) = try!(get_fn_def(tcx, e, callee_val)); - match (ty_hint, constness) { - (ExprTypeChecked, _) => { - // no need to check for constness... either check_const - // already forbids this or we const eval over whatever - // we want - }, - (_, hir::Constness::Const) => { - // we don't know much about the function, so we force it to be a const fn - // so compilation will fail later in case the const fn's body is not const - }, - _ => signal!(e, NonConstPath), - } + let did = match callee_val { + Function(did) => did, + callee => signal!(e, CallOn(callee)), + }; + let (decl, result) = if let Some(fn_like) = lookup_const_fn_by_id(tcx, did) { + (fn_like.decl(), &fn_like.body().expr) + } else { + signal!(e, NonConstPath) + }; + let result = result.as_ref().expect("const fn has no result expression"); assert_eq!(decl.inputs.len(), args.len()); let mut call_args = NodeMap(); @@ -1116,7 +1113,6 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>, let old = call_args.insert(arg.pat.id, arg_val); assert!(old.is_none()); } - let result = block.expr.as_ref().unwrap(); debug!("const call({:?})", call_args); try!(eval_const_expr_partial(tcx, &**result, ty_hint, Some(&call_args))) }, @@ -1397,46 +1393,3 @@ pub fn compare_lit_exprs<'tcx>(tcx: &ty::ctxt<'tcx>, }; compare_const_vals(&a, &b) } - - -// returns Err if callee is not `Function` -// `e` is only used for error reporting/spans -fn get_fn_def<'a>(tcx: &'a ty::ctxt, - e: &hir::Expr, - callee: ConstVal) - -> Result<(&'a hir::FnDecl, &'a hir::Block, hir::Constness), ConstEvalErr> { - let did = match callee { - Function(did) => did, - callee => signal!(e, CallOn(callee)), - }; - debug!("fn call: {:?}", tcx.map.get_if_local(did)); - match tcx.map.get_if_local(did) { - None => signal!(e, UnimplementedConstVal("calling non-local const fn")), // non-local - Some(ast_map::NodeItem(it)) => match it.node { - hir::ItemFn( - ref decl, - hir::Unsafety::Normal, - constness, - abi::Abi::Rust, - _, // ducktype generics? types are funky in const_eval - ref block, - ) => Ok((&**decl, &**block, constness)), - _ => signal!(e, NonConstPath), - }, - Some(ast_map::NodeImplItem(it)) => match it.node { - hir::ImplItemKind::Method( - hir::MethodSig { - ref decl, - unsafety: hir::Unsafety::Normal, - constness, - abi: abi::Abi::Rust, - .. // ducktype generics? types are funky in const_eval - }, - ref block, - ) => Ok((decl, block, constness)), - _ => signal!(e, NonConstPath), - }, - Some(ast_map::NodeTraitItem(..)) => signal!(e, NonConstPath), - Some(_) => signal!(e, UnimplementedConstVal("calling struct, tuple or variant")), - } -} diff --git a/src/test/compile-fail/const-call.rs b/src/test/compile-fail/const-call.rs index d49da47a87c83..1143d3bd5cd96 100644 --- a/src/test/compile-fail/const-call.rs +++ b/src/test/compile-fail/const-call.rs @@ -10,15 +10,10 @@ #![feature(const_fn)] -const unsafe fn g(x: usize) -> usize { - x -} - fn f(x: usize) -> usize { x } fn main() { let _ = [0; f(2)]; //~ ERROR: non-constant path in constant expression [E0307] - let _ = [0; g(2)]; //~ ERROR: non-constant path in constant expression [E0307] } diff --git a/src/test/compile-fail/const-fn-stability-calls-2.rs b/src/test/compile-fail/const-fn-stability-calls-2.rs deleted file mode 100644 index 592a312d80048..0000000000000 --- a/src/test/compile-fail/const-fn-stability-calls-2.rs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2015 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Test use of const fn from another crate without a feature gate. - -// aux-build:const_fn_lib.rs - -extern crate const_fn_lib; - -use const_fn_lib::foo; - -fn main() { - let x: [usize; foo()] = []; - //~^ ERROR unimplemented constant expression: calling non-local const fn [E0250] -} diff --git a/src/test/run-pass/const-fn-cross-crate.rs b/src/test/run-pass/const-fn-cross-crate.rs index 5d0c17af71719..7b4b751fd7f25 100644 --- a/src/test/run-pass/const-fn-cross-crate.rs +++ b/src/test/run-pass/const-fn-cross-crate.rs @@ -22,4 +22,5 @@ const FOO: usize = foo(); fn main() { assert_eq!(FOO, 22); + let _: [i32; foo()] = [42; 22]; } diff --git a/src/test/run-pass/const-fn.rs b/src/test/run-pass/const-fn.rs index 38c73febc3108..5961ed8d3390d 100644 --- a/src/test/run-pass/const-fn.rs +++ b/src/test/run-pass/const-fn.rs @@ -20,14 +20,20 @@ const fn sub(x: u32, y: u32) -> u32 { x - y } +const unsafe fn div(x: u32, y: u32) -> u32 { + x / y +} + const SUM: u32 = add(44, 22); const DIFF: u32 = sub(44, 22); +const DIV: u32 = unsafe{div(44, 22)}; fn main() { assert_eq!(SUM, 66); assert!(SUM != 88); assert_eq!(DIFF, 22); + assert_eq!(DIV, 2); let _: [&'static str; sub(100, 99) as usize] = ["hi"]; }