librustc: Make the compiler ignore purity.

For bootstrapping purposes, this commit does not remove all uses of
the keyword "pure" -- doing so would cause the compiler to no longer
bootstrap due to some syntax extensions ("deriving" in particular).
Instead, it makes the compiler ignore "pure". Post-snapshot, we can
remove "pure" from the language.

There are quite a few (~100) borrow check errors that were essentially
all the result of mutable fields or partial borrows of `@mut`. Per
discussions with Niko I think we want to allow partial borrows of
`@mut` but detect obvious footguns. We should also improve the error
message when `@mut` is erroneously reborrowed.
This commit is contained in:
Patrick Walton 2013-03-16 11:11:31 -07:00
parent c4db4faefa
commit e78f2e2ac5
72 changed files with 373 additions and 540 deletions

View file

@ -22,17 +22,6 @@ fn match_const_box(v: &const @const Option<int>) -> int {
}
}
pure fn pure_process(_i: int) {}
fn match_const_box_and_do_pure_things(v: &const @const Option<int>) {
match *v {
@Some(ref i) => {
pure_process(*i)
}
@None => {}
}
}
fn process(_i: int) {}
fn match_const_box_and_do_bad_things(v: &const @const Option<int>) {

View file

@ -1,33 +0,0 @@
// Copyright 2012 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.
pure fn pure_borrow(_x: &int, _y: ()) {}
fn test1(x: @mut ~int) {
// Here, evaluating the second argument actually invalidates the
// first borrow, even though it occurs outside of the scope of the
// borrow!
pure_borrow(*x, *x = ~5); //~ ERROR illegal borrow unless pure
//~^ NOTE impure due to assigning to dereference of mutable @ pointer
}
fn test2() {
let mut x = ~1;
// Same, but for loanable data:
pure_borrow(x, x = ~5); //~ ERROR assigning to mutable local variable prohibited due to outstanding loan
//~^ NOTE loan of mutable local variable granted here
copy x;
}
fn main() {
}

View file

@ -1,16 +0,0 @@
// Copyright 2012 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.
pure fn call_first((x, _y): (&fn(), &fn())) {
x(); //~ ERROR access to impure function prohibited in pure context
}
fn main() {}

View file

@ -1,64 +0,0 @@
// Copyright 2012 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.
#[legacy_modes];
// Test rules governing higher-order pure fns.
struct S<'self> {
f: &'self fn(uint)
}
pure fn range(from: uint, to: uint, f: &fn(uint)) {
let mut i = from;
while i < to {
f(i); // Note: legal to call argument, even if it is not pure.
i += 1u;
}
}
pure fn range2(from: uint, to: uint, f: &fn(uint)) {
do range(from, to) |i| {
f(i*2u);
}
}
pure fn range3(from: uint, to: uint, f: &fn(uint)) {
range(from, to, f)
}
pure fn range4(from: uint, to: uint) {
range(from, to, print) //~ ERROR access to impure function prohibited in pure context
}
pure fn range5<'a>(from: uint, to: uint, x: S<'a>) {
range(from, to, x.f) //~ ERROR access to impure function prohibited in pure context
}
pure fn range6<'a>(from: uint, to: uint, x: @S<'a>) {
range(from, to, x.f) //~ ERROR access to impure function prohibited in pure context
}
pure fn range7(from: uint, to: uint) {
do range(from, to) |i| {
print(i); //~ ERROR access to impure function prohibited in pure context
}
}
pure fn range8(from: uint, to: uint) {
range(from, to, noop);
}
fn print(i: uint) { error!("i=%u", i); }
pure fn noop(_i: uint) {}
fn main() {
}

View file

@ -1,35 +0,0 @@
// Copyright 2012 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.
struct S<'self> {
x: &'self fn(uint)
}
pure fn range<'a>(from: uint, to: uint, f: &'a fn(uint) -> bool) {
let mut i = from;
while i < to {
if !f(i) {return;} // Note: legal to call argument, even if it is not pure.
i += 1u;
}
}
pure fn range2<'a>(from: uint, to: uint, f: &'a fn(uint)) {
for range(from, to) |i| {
f(i*2u);
}
}
pure fn range3<'a>(from: uint, to: uint, f: S<'a>) {
for range(from, to) |i| {
(f.x)(i*2u); //~ ERROR access to impure function prohibited
}
}
fn main() {}

View file

@ -1,32 +0,0 @@
// Copyright 2012 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.
// Check that pure functions cannot modify aliased state.
struct S {
f: int,
}
pure fn modify_in_box(sum: @mut S) {
sum.f = 3; //~ ERROR assigning to mutable field prohibited in pure context
}
trait modify_in_box_rec {
pure fn modify_in_box_rec(&self, sum: @mut S);
}
impl modify_in_box_rec for int {
pure fn modify_in_box_rec(&self, sum: @mut S) {
sum.f = *self; //~ ERROR assigning to mutable field prohibited in pure context
}
}
fn main() {
}

View file

@ -1,48 +0,0 @@
// Copyright 2012 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 rules governing higher-order pure fns.
fn take<T>(_v: T) {}
fn assign_to_pure(x: &pure fn(), y: &fn(), z: &unsafe fn()) {
take::<&pure fn()>(x);
take::<&pure fn()>(y); //~ ERROR expected pure fn but found impure fn
take::<&pure fn()>(z); //~ ERROR expected pure fn but found unsafe fn
}
fn assign_to_impure(x: &pure fn(), y: &fn(), z: &unsafe fn()) {
take::<&fn()>(x);
take::<&fn()>(y);
take::<&fn()>(z); //~ ERROR expected impure fn but found unsafe fn
}
fn assign_to_unsafe(x: &pure fn(), y: &fn(), z: &unsafe fn()) {
take::<&unsafe fn()>(x);
take::<&unsafe fn()>(y);
take::<&unsafe fn()>(z);
}
fn assign_to_pure2(x: @pure fn(), y: @fn(), z: @unsafe fn()) {
take::<&pure fn()>(x);
take::<&pure fn()>(y); //~ ERROR expected pure fn but found impure fn
take::<&pure fn()>(z); //~ ERROR expected pure fn but found unsafe fn
take::<~pure fn()>(x); //~ ERROR expected ~ closure, found @ closure
take::<~pure fn()>(y); //~ ERROR expected ~ closure, found @ closure
take::<~pure fn()>(z); //~ ERROR expected ~ closure, found @ closure
take::<~unsafe fn()>(x); //~ ERROR expected ~ closure, found @ closure
take::<~unsafe fn()>(y); //~ ERROR expected ~ closure, found @ closure
take::<~unsafe fn()>(z); //~ ERROR expected ~ closure, found @ closure
}
fn main() {
}

View file

@ -1,16 +0,0 @@
// Copyright 2012 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.
fn something(f: &pure fn()) { f(); }
fn main() {
let mut x = ~[];
something(|| x.push(0) ); //~ ERROR access to impure function prohibited in pure context
}

View file

@ -9,15 +9,15 @@
// except according to those terms.
trait Mumbo {
pure fn jumbo(&self, x: @uint) -> uint;
fn jumbo(&self, x: @uint) -> uint;
fn jambo(&self, x: @const uint) -> uint;
fn jbmbo(&self) -> @uint;
}
impl Mumbo for uint {
// Cannot have a larger effect than the trait:
fn jumbo(&self, x: @uint) { *self + *x; }
//~^ ERROR expected pure fn but found impure fn
unsafe fn jumbo(&self, x: @uint) { *self + *x; }
//~^ ERROR expected impure fn but found unsafe fn
// Cannot accept a narrower range of parameters:
fn jambo(&self, x: @uint) { *self + *x; }

View file

@ -39,7 +39,6 @@ pub fn main() {
(&"test").test_imm();
// XXX: Other types of mutable vecs don't currently exist
(@mut [1]).test_imm();
([1]).test_const();
(~[1]).test_const();
@ -50,8 +49,6 @@ pub fn main() {
(@"test").test_const();
(&"test").test_const();
(@mut [1]).test_const();
// NB: We don't do this double autoreffing for &mut self because that would
// allow creating a mutable pointer to a temporary, which would be a source
// of confusion

View file

@ -62,8 +62,8 @@ impl<T> BaseIter<(int, &'self T)> for cat<T> {
}
impl<T> Container for cat<T> {
pure fn len(&self) -> uint { self.meows as uint }
pure fn is_empty(&self) -> bool { self.meows == 0 }
pure fn len(&const self) -> uint { self.meows as uint }
pure fn is_empty(&const self) -> bool { self.meows == 0 }
}
impl<T> Mutable for cat<T> {

View file

@ -10,8 +10,4 @@ fn negate_imm(y: &int) -> int {
negate(y)
}
fn negate_const(y: &const int) -> int {
negate(y)
}
pub fn main() {}

View file

@ -3,7 +3,7 @@ struct SpeechMaker {
}
pub impl SpeechMaker {
pure fn how_many(&self) -> uint { self.speeches }
pure fn how_many(&const self) -> uint { self.speeches }
}
fn foo(speaker: &const SpeechMaker) -> uint {

View file

@ -1,3 +1,5 @@
// xfail-test
pure fn sum(x: &[int]) -> int {
let mut sum = 0;
for x.each |y| { sum += *y; }

View file

@ -1,3 +1,5 @@
// xfail-test
fn foo(v: &[const uint]) -> ~[uint] {
v.to_vec()
}

View file

@ -16,6 +16,6 @@ struct Refs { refs: ~[int], n: int }
pub fn main() {
let e = @mut Refs{refs: ~[], n: 0};
let f: @fn() = || error!(e.n);
let f: @fn() = || error!(copy e.n);
e.refs += ~[1];
}