Auto merge of #25609 - nikomatsakis:const-fn, r=pnkfelix

This is a port of @eddyb's `const-fn` branch. I rebased it, tweaked a few things, and added tests as well as a feature gate. The set of tests is still pretty rudimentary, I'd appreciate suggestions on new tests to write. Also, a double-check that the feature-gate covers all necessary cases.

One question: currently, the feature-gate allows the *use* of const functions from stable code, just not the definition. This seems to fit our usual strategy, and implies that we might (perhaps) allow some constant functions in libstd someday, even before stabilizing const-fn, if we were willing to commit to the existence of const fns but found some details of their impl unsatisfactory.

r? @pnkfelix
This commit is contained in:
bors 2015-05-24 11:12:34 +00:00
commit ba0e1cd814
55 changed files with 848 additions and 212 deletions

View file

@ -117,7 +117,7 @@ static mut STATIC14: SafeStruct = SafeStruct {
//~^ ERROR mutable statics are not allowed to have destructors
field1: SafeEnum::Variant1,
field2: SafeEnum::Variant4("str".to_string())
//~^ ERROR static contains unimplemented expression type
//~^ ERROR method calls in statics are limited to constant inherent methods
};
static STATIC15: &'static [Box<MyOwned>] = &[

View file

@ -0,0 +1,26 @@
// 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 <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.
// Test that we can't declare a const fn in an impl -- right now it's
// just not allowed at all, though eventually it'd make sense to allow
// it if the trait fn is const (but right now no trait fns can be
// const).
#![feature(const_fn)]
trait Foo {
fn f() -> u32;
}
impl Foo for u32 {
const fn f() -> u32 { 22 } //~ ERROR E0379
}
fn main() { }

View file

@ -0,0 +1,21 @@
// 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 <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.
// Test that const fn is illegal in a trait declaration, whether or
// not a default is provided.
#![feature(const_fn)]
trait Foo {
const fn f() -> u32; //~ ERROR trait fns cannot be declared const
const fn g() -> u32 { 0 } //~ ERROR trait fns cannot be declared const
}
fn main() { }

View file

@ -0,0 +1,47 @@
// 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 <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.
// Test that we can't call random fns in a const fn or do other bad things.
#![feature(const_fn)]
use std::mem::transmute;
fn random() -> u32 { 0 }
const fn sub(x: &u32) -> usize {
unsafe { transmute(x) } //~ ERROR E0015
}
const fn sub1() -> u32 {
random() //~ ERROR E0015
}
static Y: u32 = 0;
const fn get_Y() -> u32 {
Y
//~^ ERROR E0013
//~| ERROR cannot refer to other statics by value
}
const fn get_Y_addr() -> &'static u32 {
&Y
//~^ ERROR E0013
}
const fn get() -> u32 {
let x = 22; //~ ERROR E0016
let y = 44; //~ ERROR E0016
x + y
}
fn main() {
}

View file

@ -0,0 +1,28 @@
// 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 <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.
// Test use of const fn without feature gate.
const fn foo() -> usize { 0 } //~ ERROR const fn is unstable
trait Foo {
const fn foo() -> u32; //~ ERROR const fn is unstable
const fn bar() -> u32 { 0 } //~ ERROR const fn is unstable
}
impl Foo {
const fn baz() -> u32 { 0 } //~ ERROR const fn is unstable
}
impl Foo for u32 {
const fn foo() -> u32 { 0 } //~ ERROR const fn is unstable
}
fn main() { }

View file

@ -20,6 +20,6 @@ mod Y {
static foo: *const Y::X = Y::foo(Y::x as *const Y::X);
//~^ ERROR the trait `core::marker::Sync` is not implemented for the type
//~| ERROR function calls in statics are limited to struct and enum constructors
//~| ERROR E0015
fn main() {}

View file

@ -17,6 +17,6 @@ static boxed: Box<RefCell<isize>> = box RefCell::new(0);
//~^ ERROR allocations are not allowed in statics
//~| ERROR the trait `core::marker::Sync` is not implemented for the type
//~| ERROR the trait `core::marker::Sync` is not implemented for the type
//~| ERROR function calls in statics are limited to struct and enum constructors
//~| ERROR E0015
fn main() { }

View file

@ -11,6 +11,6 @@
fn foo() -> isize { 23 }
static a: [isize; 2] = [foo(); 2];
//~^ ERROR: function calls in statics are limited to struct and enum constructors
//~^ ERROR: E0015
fn main() {}

View file

@ -0,0 +1,23 @@
// 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 <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.
// Test a call whose argument is the result of another call.
#![feature(const_fn)]
const fn sub(x: u32, y: u32) -> u32 {
x - y
}
const X: u32 = sub(sub(88, 44), 22);
fn main() {
assert_eq!(X, 22);
}

View file

@ -0,0 +1,32 @@
// 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 <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.
// A very basic test of const fn functionality.
#![feature(const_fn)]
const fn add(x: u32, y: u32) -> u32 {
x + y
}
const fn sub(x: u32, y: u32) -> u32 {
x - y
}
const SUM: u32 = add(44, 22);
const DIFF: u32 = sub(44, 22);
fn main() {
assert_eq!(SUM, 66);
assert!(SUM != 88);
assert_eq!(DIFF, 22);
}