Auto merge of #27215 - pnkfelix:fsk-placer-take-5-just-in, r=nikomatsakis

Macro desugaring of `in PLACE { BLOCK }` into "simpler" expressions following the in-development "Placer" protocol.

Includes Placer API that one can override to integrate support for `in` into one's own type.  (See [RFC 809].)

[RFC 809]: https://github.com/rust-lang/rfcs/blob/master/text/0809-box-and-in-for-stdlib.md

Part of #22181

Replaced PR #26180.

Turns on the `in PLACE { BLOCK }` syntax, while leaving in support for the old `box (PLACE) EXPR` syntax (since we need to support that at least until we have a snapshot with support for `in PLACE { BLOCK }`.

(Note that we are not 100% committed to the `in PLACE { BLOCK }` syntax.  In particular I still want to play around with some other alternatives.  Still, I want to get the fundamental framework for the protocol landed so we can play with implementing it for non `Box` types.)

----

Also, this PR leaves out support for desugaring-based `box EXPR`.  We will hopefully land that in the future, but for the short term there are type-inference issues injected by that change that we want to resolve separately.
This commit is contained in:
bors 2015-07-24 10:12:20 +00:00
commit 9413a926fc
28 changed files with 899 additions and 47 deletions

View file

@ -8,15 +8,18 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
fn main() {
use std::boxed::HEAP;
// Check that `box EXPR` is feature-gated.
//
// See also feature-gate-placement-expr.rs
//
// (Note that the two tests are separated since the checks appear to
// be performed at distinct phases, with an abort_if_errors call
// separating them.)
fn main() {
let x = box 'c'; //~ ERROR box expression syntax is experimental
println!("x: {}", x);
let x = box () 'c'; //~ ERROR box expression syntax is experimental
println!("x: {}", x);
let x = box (HEAP) 'c'; //~ ERROR box expression syntax is experimental
println!("x: {}", x);
}

View file

@ -0,0 +1,27 @@
// 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.
// Check that `in PLACE { EXPR }` is feature-gated.
//
// See also feature-gate-box-expr.rs
//
// (Note that the two tests are separated since the checks appear to
// be performed at distinct phases, with an abort_if_errors call
// separating them.)
fn main() {
use std::boxed::HEAP;
let x = box (HEAP) 'c'; //~ ERROR placement-in expression syntax is experimental
println!("x: {}", x);
let x = in HEAP { 'c' }; //~ ERROR placement-in expression syntax is experimental
println!("x: {}", x);
}

View file

@ -0,0 +1,14 @@
// 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.
fn main() {
let c = push_unsafe!('c'); //~ ERROR push/pop_unsafe macros are experimental
let c = pop_unsafe!('c'); //~ ERROR push/pop_unsafe macros are experimental
}

View file

@ -9,8 +9,10 @@
// except according to those terms.
#![feature(box_syntax)]
#![feature(placement_in_syntax)]
fn main() {
box ( () ) 0;
//~^ ERROR: only the exchange heap is currently supported
//~^ ERROR: the trait `core::ops::Placer<_>` is not implemented
//~| ERROR: the trait `core::ops::Placer<_>` is not implemented
}

View file

@ -0,0 +1,74 @@
// 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.
// Basic sanity check for `push_unsafe!(EXPR)` and
// `pop_unsafe!(EXPR)`: we can call unsafe code when there are a
// positive number of pushes in the stack, or if we are within a
// normal `unsafe` block, but otherwise cannot.
#![feature(pushpop_unsafe)]
static mut X: i32 = 0;
unsafe fn f() { X += 1; return; }
fn g() { unsafe { X += 1_000; } return; }
fn main() {
push_unsafe!( {
f(); pop_unsafe!({
f() //~ ERROR: call to unsafe function
})
} );
push_unsafe!({
f();
pop_unsafe!({
g();
f(); //~ ERROR: call to unsafe function
})
} );
push_unsafe!({
g(); pop_unsafe!({
unsafe {
f();
}
f(); //~ ERROR: call to unsafe function
})
});
// Note: For implementation simplicity the compiler just
// ICE's if you underflow the push_unsafe stack.
//
// Thus all of the following cases cause an ICE.
//
// (The "ERROR" notes are from an earlier version
// that used saturated arithmetic rather than checked
// arithmetic.)
// pop_unsafe!{ g() };
//
// push_unsafe!({
// pop_unsafe!(pop_unsafe!{ g() })
// });
//
// push_unsafe!({
// g();
// pop_unsafe!(pop_unsafe!({
// f() // ERROR: call to unsafe function
// }))
// });
//
// pop_unsafe!({
// f(); // ERROR: call to unsafe function
// })
}

View file

@ -12,7 +12,7 @@
fn main() {
box (1 + 1)
//~^ HELP try using `box()` instead:
//~| SUGGESTION box() (1 + 1)
//~^ HELP try using `box ()` instead:
//~| SUGGESTION box () (1 + 1)
; //~ ERROR expected expression, found `;`
}

View file

@ -20,7 +20,7 @@ use std::mem::{self, transmute};
mod rusti {
extern "rust-intrinsic" {
pub fn init<T>() -> T;
pub fn move_val_init<T>(dst: &mut T, src: T);
pub fn move_val_init<T>(dst: *mut T, src: T);
}
}

View file

@ -13,8 +13,13 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
#![allow(warnings)]
#![allow(dead_code, unused_variables)]
#![feature(box_syntax, box_heap)]
#![feature(placement_in_syntax)]
// during check-pretty, the expanded code needs to opt into these
// features
#![feature(placement_new_protocol, core_intrinsics)]
// Tests that the new `box` syntax works with unique pointers.
@ -30,4 +35,9 @@ pub fn main() {
let y: Box<isize> = box 2;
let b: Box<isize> = box()(1 + 2);
let c = box()(3 + 4);
let s: Box<Structure> = box Structure {
x: 3,
y: 4,
};
}

View file

@ -0,0 +1,37 @@
// 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.
#![allow(dead_code, unused_variables)]
#![feature(box_heap)]
#![feature(placement_in_syntax)]
// Tests that the new `in` syntax works with unique pointers.
//
// Compare with new-box-syntax.rs
use std::boxed::{Box, HEAP};
struct Structure {
x: isize,
y: isize,
}
pub fn main() {
let x: Box<isize> = in HEAP { 2 };
let b: Box<isize> = in HEAP { 1 + 2 };
let c = in HEAP { 3 + 4 };
let s: Box<Structure> = in HEAP {
Structure {
x: 3,
y: 4,
}
};
}

View file

@ -0,0 +1,56 @@
// 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.
// Basic sanity check for `push_unsafe!(EXPR)` and
// `pop_unsafe!(EXPR)`: we can call unsafe code when there are a
// positive number of pushes in the stack, or if we are within a
// normal `unsafe` block, but otherwise cannot.
// ignore-pretty because the `push_unsafe!` and `pop_unsafe!` macros
// are not integrated with the pretty-printer.
#![feature(pushpop_unsafe)]
static mut X: i32 = 0;
unsafe fn f() { X += 1; return; }
fn g() { unsafe { X += 1_000; } return; }
fn check_reset_x(x: i32) -> bool {
#![allow(unused_parens)] // dont you judge my style choices!
unsafe {
let ret = (x == X);
X = 0;
ret
}
}
fn main() {
// double-check test infrastructure
assert!(check_reset_x(0));
unsafe { f(); }
assert!(check_reset_x(1));
assert!(check_reset_x(0));
{ g(); }
assert!(check_reset_x(1000));
assert!(check_reset_x(0));
unsafe { f(); g(); g(); }
assert!(check_reset_x(2001));
push_unsafe!( { f(); pop_unsafe!( g() ) } );
assert!(check_reset_x(1_001));
push_unsafe!( { g(); pop_unsafe!( unsafe { f(); f(); } ) } );
assert!(check_reset_x(1_002));
unsafe { push_unsafe!( { f(); pop_unsafe!( { f(); f(); } ) } ); }
assert!(check_reset_x(3));
push_unsafe!( { f(); push_unsafe!( { pop_unsafe!( { f(); f(); f(); } ) } ); } );
assert!(check_reset_x(4));
}