auto merge of #17725 : alexcrichton/rust/rollup, r=alexcrichton

This commit is contained in:
bors 2014-10-03 05:02:37 +00:00
commit aa034cd3ba
320 changed files with 1055 additions and 5371 deletions

View File

@ -1,60 +1,26 @@
# Use something that's not 'ruby' so we don't set up things like
# RVM/bundler/ruby and whatnot. Right now 'rust' isn't a language on travis and
# it treats unknown languages as ruby-like I believe.
# RVM/bundler/ruby and whatnot. Right now 'rust' as a language actually
# downloads a rust/cargo snapshot, which we don't really want for building rust.
language: c
# Before we start doing anything, install a stock LLVM
# Make sure we've got an up-to-date g++ compiler to get past the LLVM configure
# script.
install:
- sudo sh -c "echo 'deb http://llvm.org/apt/precise/ llvm-toolchain-precise-3.4 main' >> /etc/apt/sources.list"
- sudo sh -c "echo 'deb http://llvm.org/apt/precise/ llvm-toolchain-precise main' >> /etc/apt/sources.list"
- sudo sh -c "echo 'deb http://ppa.launchpad.net/ubuntu-toolchain-r/test/ubuntu precise main' >> /etc/apt/sources.list"
- wget -O - http://llvm.org/apt/llvm-snapshot.gpg.key | sudo apt-key add -
- sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
- sudo apt-get update -qq
- sudo apt-get install -qq --force-yes -y llvm-$LLVM_VERSION
llvm-${LLVM_VERSION}-dev clang-$LLVM_VERSION lldb-$LLVM_VERSION
- sudo apt-get install g++-4.7
# All of the llvm tools are suffixed with "-$VERS" which we don't want, so
# symlink them all into a local directory and just use that
# The test suite is in general way too stressful for travis, especially in
# terms of time limit and reliability. In the past we've tried to scale things
# back to only build the stage1 compiler and run a subset of tests, but this
# didn't end up panning out very well.
#
# FIXME: this shouldn't update the src/llvm sub-repo, that takes about a minute
# it's gotta download so much stuff.
# As a result, we're just using travis to run `make tidy` now. It'll help
# everyone find out about their trailing spaces early on!
before_script:
- mkdir -p local-llvm/bin
- ln -nsf /usr/bin/llvm-config-$LLVM_VERSION local-llvm/bin/llvm-config
- ln -nsf /usr/bin/llvm-mc-$LLVM_VERSION local-llvm/bin/llvm-mc
- ln -nsf /usr/bin/llvm-as-$LLVM_VERSION local-llvm/bin/llvm-as
- ln -nsf /usr/bin/llvm-dis-$LLVM_VERSION local-llvm/bin/llvm-dis
- ln -nsf /usr/bin/llc-$LLVM_VERSION local-llvm/bin/llc
- ln -nsf /usr/include/llvm-$LLVM_VERSION local-llvm/include
- ./configure --disable-optimize-tests --llvm-root=`pwd`/local-llvm
--enable-fast-make --enable-clang
# Tidy everything up first, then build a few things, and then run a few tests.
# Note that this is meant to run in a "fairly small" amount of time, so this
# isn't exhaustive at all.
#
# As a result of https://github.com/travis-ci/travis-ci/issues/1066, we run
# everything in one large command instead of multiple commands.
script: |
if [[ $TRAVIS_PULL_REQUEST != 'false' ]]; then
if [[ $LLVM_VERSION != '3.4' ]]; then exit 0; fi
fi &&
make tidy &&
make -j4 rustc-stage1 RUSTFLAGS='-Z time-passes' &&
make check-stage1-std check-stage1-rpass check-stage1-cfail check-stage1-rfail check-stage1-doc
env:
global:
- NO_BENCH=1
matrix:
- LLVM_VERSION=3.3
- LLVM_VERSION=3.4
# We track this ourselves, and in theory we don't have to update the LLVM repo
# (but sadly we do right now anyway).
git:
submodules: false
- ./configure
script:
- make tidy
notifications:
email: false

View File

@ -28,7 +28,7 @@ CTAGS_LOCATIONS=$(patsubst ${CFG_SRC_DIR}src/llvm,, \
$(patsubst ${CFG_SRC_DIR}src/rt/sundown,, \
$(patsubst ${CFG_SRC_DIR}src/rt/vg,, \
$(wildcard ${CFG_SRC_DIR}src/*) $(wildcard ${CFG_SRC_DIR}src/rt/*) \
)))))))))))
)))))))))
CTAGS_OPTS=--options="${CFG_SRC_DIR}src/etc/ctags.rust" --languages=-javascript --recurse ${CTAGS_LOCATIONS}
# We could use `--languages=Rust`, but there is value in producing tags for the
# C++ parts of the code base too (at the time of writing, those are .h and .cpp

View File

@ -35,7 +35,7 @@
# that's per-target so you're allowed to conditionally add files based on the
# target.
################################################################################
NATIVE_LIBS := rust_builtin hoedown uv_support morestack miniz context_switch \
NATIVE_LIBS := rust_builtin hoedown morestack miniz context_switch \
rustrt_native rust_test_helpers
# $(1) is the target triple
@ -50,7 +50,6 @@ NATIVE_DEPS_hoedown_$(1) := hoedown/src/autolink.c \
hoedown/src/html_smartypants.c \
hoedown/src/stack.c \
hoedown/src/version.c
NATIVE_DEPS_uv_support_$(1) := rust_uv.c
NATIVE_DEPS_miniz_$(1) = miniz.c
NATIVE_DEPS_rust_builtin_$(1) := rust_builtin.c \
rust_android_dummy.c

View File

@ -305,10 +305,9 @@ copying.
# Circle(Point, f64), // origin, radius
# Rectangle(Point, Size) // upper-left, dimensions
# }
# static tau: f64 = 6.28;
fn compute_area(shape: &Shape) -> f64 {
match *shape {
Circle(_, radius) => 0.5 * tau * radius * radius,
Circle(_, radius) => std::f64::consts::PI * radius * radius,
Rectangle(_, ref size) => size.w * size.h
}
}
@ -316,10 +315,7 @@ fn compute_area(shape: &Shape) -> f64 {
The first case matches against circles. Here, the pattern extracts the
radius from the shape variant and the action uses it to compute the
area of the circle. (Like any up-to-date engineer, we use the [tau
circle constant][tau] and not that dreadfully outdated notion of pi).
[tau]: http://www.math.utah.edu/~palais/pi.html
area of the circle.
The second match is more interesting. Here we match against a
rectangle and extract its size: but rather than copy the `size`

View File

@ -632,19 +632,6 @@ This part is coming soon.
This part is coming soon.
# Gc
The `Gc<T>` type exists for historical reasons, and is [still used
internally](https://github.com/rust-lang/rust/issues/7929) by the compiler.
It is not even a 'real' garbage collected type at the moment.
In the future, Rust may have a real garbage collected type, and so it
has not yet been removed for that reason.
## Best practices
There is currently no legitimate use case for the `Gc<T>` type.
# Raw Pointers
This part is coming soon.

View File

@ -31,7 +31,6 @@ list):
* Task synchronization
* Task-local storage
* Logging
* Local heaps (GC heaps)
* Task unwinding
## What is the runtime accomplishing?

View File

@ -208,9 +208,7 @@ pub struct Unique<T> {
// Implement methods for creating and using the values in the box.
// NB: For simplicity and correctness, we require that T has kind Send
// (owned boxes relax this restriction, and can contain managed (GC) boxes).
// This is because, as implemented, the garbage collector would not know
// about any shared boxes stored in the malloc'd region of memory.
// (owned boxes relax this restriction).
impl<T: Send> Unique<T> {
pub fn new(value: T) -> Unique<T> {
unsafe {

View File

@ -195,9 +195,11 @@ The second point is the `println!()` part. This is calling a Rust **macro**,
which is how metaprogramming is done in Rust. If it were a function instead, it
would look like this: `println()`. For our purposes, we don't need to worry
about this difference. Just know that sometimes, you'll see a `!`, and that
means that you're calling a macro instead of a normal function. One last thing
to mention: Rust's macros are significantly different than C macros, if you've
used those. Don't be scared of using macros. We'll get to the details
means that you're calling a macro instead of a normal function. Rust implements
`println!` as a macro rather than a function for good reasons, but that's a
very advanced topic. You'll learn more when we talk about macros later. One
last thing to mention: Rust's macros are significantly different than C macros,
if you've used those. Don't be scared of using macros. We'll get to the details
eventually, you'll just have to trust us for now.
Next, `"Hello, world!"` is a **string**. Strings are a surprisingly complicated
@ -659,14 +661,12 @@ error: mismatched types: expected `int` but found `()` (expected int but found (
```
We expected an integer, but we got `()`. `()` is pronounced 'unit', and is a
special type in Rust's type system. `()` is different than `null` in other
languages, because `()` is distinct from other types. For example, in C, `null`
is a valid value for a variable of type `int`. In Rust, `()` is _not_ a valid
value for a variable of type `int`. It's only a valid value for variables of
the type `()`, which aren't very useful. Remember how we said statements don't
return a value? Well, that's the purpose of unit in this case. The semicolon
turns any expression into a statement by throwing away its value and returning
unit instead.
special type in Rust's type system. In Rust, `()` is _not_ a valid value for a
variable of type `int`. It's only a valid value for variables of the type `()`,
which aren't very useful. Remember how we said statements don't return a value?
Well, that's the purpose of unit in this case. The semicolon turns any
expression into a statement by throwing away its value and returning unit
instead.
There's one more time in which you won't see a semicolon at the end of a line
of Rust code. For that, we'll need our next concept: functions.
@ -1680,11 +1680,11 @@ just `int`s.
Rust provides a method on these `IoResult<T>`s called `ok()`, which does the
same thing as our `match` statement, but assuming that we have a valid value.
If we don't, it will terminate our program. In this case, if we can't get
input, our program doesn't work, so we're okay with that. In most cases, we
would want to handle the error case explicitly. The result of `ok()` has a
method, `expect()`, which allows us to give an error message if this crash
happens.
We then call `expect()` on the result, which will terminate our program if we
don't have a valid value. In this case, if we can't get input, our program
doesn't work, so we're okay with that. In most cases, we would want to handle
the error case explicitly. `expect()` allows us to give an error message if
this crash happens.
We will cover the exact details of how all of this works later in the Guide.
For now, this gives you enough of a basic understanding to work with.
@ -2030,7 +2030,7 @@ fn main() {
match cmp(input, secret_number) {
Less => println!("Too small!"),
Greater => println!("Too big!"),
Equal => { println!("You win!"); },
Equal => println!("You win!"),
}
}
@ -2727,7 +2727,8 @@ mod hello {
}
```
This will work:
Usage of the `pub` keyword is sometimes called 'exporting', because
we're making the function available for other modules. This will work:
```{notrust,ignore}
$ cargo run
@ -3291,8 +3292,7 @@ use super::times_four;
Because we've made a nested module, we can import functions from the parent
module by using `super`. Sub-modules are allowed to 'see' private functions in
the parent. We sometimes call this usage of `use` a 're-export,' because we're
exporting the name again, somewhere else.
the parent.
We've now covered the basics of testing. Rust's tools are primitive, but they
work well in the simple cases. There are some Rustaceans working on building

View File

@ -3381,7 +3381,7 @@ fn main() {
```
Patterns can also dereference pointers by using the `&`, `box` or `@` symbols,
Patterns can also dereference pointers by using the `&`, `box` symbols,
as appropriate. For example, these two matches on `x: &int` are equivalent:
```

View File

@ -373,14 +373,6 @@
fun:_ZN4llvm4UsernwEjj
}
{
libuv-0-byte-realloc
Memcheck:Leak
fun:malloc
...
fun:*uv_loop_delete*
}
{
race-or-something-ask-pcwalton-0
Memcheck:Value4
@ -502,15 +494,3 @@
fun:*
...
}
{
libuv-mac-no-thread-join
Memcheck:Leak
fun:malloc_zone_malloc
fun:_CFRuntimeCreateInstance
fun:CFRunLoopSourceCreate
fun:uv__platform_loop_init
fun:uv__loop_init
fun:uv_loop_new
...
}

View File

@ -182,9 +182,15 @@ mod imp {
#[inline]
pub unsafe fn reallocate_inplace(ptr: *mut u8, size: uint, align: uint,
_old_size: uint) -> bool {
old_size: uint) -> bool {
let flags = align_to_flags(align);
je_xallocx(ptr as *mut c_void, size as size_t, 0, flags) == size as size_t
let new_size = je_xallocx(ptr as *mut c_void, size as size_t, 0, flags) as uint;
// checking for failure to shrink is tricky
if size < old_size {
usable_size(size, align) == new_size as uint
} else {
new_size >= size
}
}
#[inline]
@ -250,9 +256,9 @@ mod imp {
}
#[inline]
pub unsafe fn reallocate_inplace(_ptr: *mut u8, _size: uint, _align: uint,
_old_size: uint) -> bool {
false
pub unsafe fn reallocate_inplace(_ptr: *mut u8, size: uint, _align: uint,
old_size: uint) -> bool {
size == old_size
}
#[inline]
@ -312,9 +318,9 @@ mod imp {
}
#[inline]
pub unsafe fn reallocate_inplace(_ptr: *mut u8, _size: uint, _align: uint,
_old_size: uint) -> bool {
false
pub unsafe fn reallocate_inplace(_ptr: *mut u8, size: uint, _align: uint,
old_size: uint) -> bool {
size == old_size
}
#[inline]
@ -335,9 +341,21 @@ mod imp {
}
#[cfg(test)]
mod bench {
mod test {
extern crate test;
use self::test::Bencher;
use heap;
#[test]
fn basic_reallocate_inplace_noop() {
unsafe {
let size = 4000;
let ptr = heap::allocate(size, 8);
let ret = heap::reallocate_inplace(ptr, size, 8, size);
heap::deallocate(ptr, size, 8);
assert!(ret);
}
}
#[bench]
fn alloc_owned_small(b: &mut Bencher) {

View File

@ -92,7 +92,6 @@ pub use boxed as owned;
pub mod heap;
pub mod libc_heap;
pub mod util;
// Primitive types using the heaps above

View File

@ -541,14 +541,6 @@ mod tests {
assert!(y.upgrade().is_none());
}
#[test]
fn gc_inside() {
// see issue #11532
use std::gc::GC;
let a = Rc::new(RefCell::new(box(GC) 1i));
assert!(a.try_borrow_mut().is_some());
}
#[test]
fn weak_self_cyclic() {
struct Cycle {

View File

@ -1,30 +0,0 @@
// Copyright 2013 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.
#![doc(hidden)]
use core::mem;
use core::raw;
#[inline]
#[deprecated]
pub fn get_box_size(body_size: uint, body_align: uint) -> uint {
let header_size = mem::size_of::<raw::GcBox<()>>();
let total_size = align_to(header_size, body_align) + body_size;
total_size
}
// Rounds size to the next alignment. Alignment is required to be a power of
// two.
#[inline]
fn align_to(size: uint, align: uint) -> uint {
assert!(align != 0);
(size + align - 1) & !(align - 1)
}

View File

@ -46,12 +46,12 @@ struct AbsEntries<T> {
}
/// An iterator over a BTreeMap's entries.
pub struct Entries<'a, K, V> {
pub struct Entries<'a, K: 'a, V: 'a> {
inner: AbsEntries<Traversal<'a, K, V>>
}
/// A mutable iterator over a BTreeMap's entries.
pub struct MutEntries<'a, K, V> {
pub struct MutEntries<'a, K: 'a, V: 'a> {
inner: AbsEntries<MutTraversal<'a, K, V>>
}

View File

@ -19,7 +19,7 @@
html_root_url = "http://doc.rust-lang.org/master/",
html_playground_url = "http://play.rust-lang.org/")]
#![feature(macro_rules, managed_boxes, default_type_params, phase, globs)]
#![feature(macro_rules, default_type_params, phase, globs)]
#![feature(unsafe_destructor, import_shadowing)]
#![no_std]

View File

@ -532,7 +532,6 @@ impl<T: fmt::Show> fmt::Show for RingBuf<T> {
mod tests {
use std::fmt::Show;
use std::prelude::*;
use std::gc::{GC, Gc};
use std::hash;
use test::Bencher;
use test;
@ -587,43 +586,6 @@ mod tests {
assert_eq!(*d.get(3), 4);
}
#[test]
#[allow(deprecated)]
fn test_boxes() {
let a: Gc<int> = box(GC) 5;
let b: Gc<int> = box(GC) 72;
let c: Gc<int> = box(GC) 64;
let d: Gc<int> = box(GC) 175;
let mut deq = RingBuf::new();
assert_eq!(deq.len(), 0);
deq.push_front(a);
deq.push_front(b);
deq.push(c);
assert_eq!(deq.len(), 3);
deq.push(d);
assert_eq!(deq.len(), 4);
assert_eq!(deq.front(), Some(&b));
assert_eq!(deq.back(), Some(&d));
assert_eq!(deq.pop_front(), Some(b));
assert_eq!(deq.pop(), Some(d));
assert_eq!(deq.pop(), Some(c));
assert_eq!(deq.pop(), Some(a));
assert_eq!(deq.len(), 0);
deq.push(c);
assert_eq!(deq.len(), 1);
deq.push_front(b);
assert_eq!(deq.len(), 2);
deq.push(d);
assert_eq!(deq.len(), 3);
deq.push_front(a);
assert_eq!(deq.len(), 4);
assert_eq!(*deq.get(0), a);
assert_eq!(*deq.get(1), b);
assert_eq!(*deq.get(2), c);
assert_eq!(*deq.get(3), d);
}
#[cfg(test)]
fn test_parameterized<T:Clone + PartialEq + Show>(a: T, b: T, c: T, d: T) {
let mut deq = RingBuf::new();
@ -755,12 +717,6 @@ mod tests {
test_parameterized::<int>(5, 72, 64, 175);
}
#[test]
fn test_param_at_int() {
test_parameterized::<Gc<int>>(box(GC) 5, box(GC) 72,
box(GC) 64, box(GC) 175);
}
#[test]
fn test_param_taggy() {
test_parameterized::<Taggy>(One(1), Two(1, 2), Three(1, 2, 3), Two(17, 42));

View File

@ -791,11 +791,16 @@ impl<T> Vec<T> {
#[inline]
pub fn into_iter(self) -> MoveItems<T> {
unsafe {
let iter = mem::transmute(self.as_slice().iter());
let ptr = self.ptr;
let cap = self.cap;
let begin = self.ptr as *const T;
let end = if mem::size_of::<T>() == 0 {
(ptr as uint + self.len()) as *const T
} else {
ptr.offset(self.len() as int) as *const T
};
mem::forget(self);
MoveItems { allocation: ptr, cap: cap, iter: iter }
MoveItems { allocation: ptr, cap: cap, ptr: begin, end: end }
}
}
@ -1719,7 +1724,8 @@ impl<T> MutableSeq<T> for Vec<T> {
pub struct MoveItems<T> {
allocation: *mut T, // the block of memory allocated for the vector
cap: uint, // the capacity of the vector
iter: Items<'static, T>
ptr: *const T,
end: *const T
}
impl<T> MoveItems<T> {
@ -1728,7 +1734,7 @@ impl<T> MoveItems<T> {
pub fn unwrap(mut self) -> Vec<T> {
unsafe {
for _x in self { }
let MoveItems { allocation, cap, iter: _iter } = self;
let MoveItems { allocation, cap, ptr: _ptr, end: _end } = self;
mem::forget(self);
Vec { ptr: allocation, cap: cap, len: 0 }
}
@ -1739,17 +1745,33 @@ impl<T> Iterator<T> for MoveItems<T> {
#[inline]
fn next<'a>(&'a mut self) -> Option<T> {
unsafe {
// Unsafely transmute from Items<'static, T> to Items<'a,
// T> because otherwise the type checker requires that T
// be bounded by 'static.
let iter: &mut Items<'a, T> = mem::transmute(&mut self.iter);
iter.next().map(|x| ptr::read(x))
if self.ptr == self.end {
None
} else {
if mem::size_of::<T>() == 0 {
// purposefully don't use 'ptr.offset' because for
// vectors with 0-size elements this would return the
// same pointer.
self.ptr = mem::transmute(self.ptr as uint + 1);
// Use a non-null pointer value
Some(ptr::read(mem::transmute(1u)))
} else {
let old = self.ptr;
self.ptr = self.ptr.offset(1);
Some(ptr::read(old))
}
}
}
}
#[inline]
fn size_hint(&self) -> (uint, Option<uint>) {
self.iter.size_hint()
let diff = (self.end as uint) - (self.ptr as uint);
let size = mem::size_of::<T>();
let exact = diff / (if size == 0 {1} else {size});
(exact, Some(exact))
}
}
@ -1757,11 +1779,21 @@ impl<T> DoubleEndedIterator<T> for MoveItems<T> {
#[inline]
fn next_back<'a>(&'a mut self) -> Option<T> {
unsafe {
// Unsafely transmute from Items<'static, T> to Items<'a,
// T> because otherwise the type checker requires that T
// be bounded by 'static.
let iter: &mut Items<'a, T> = mem::transmute(&mut self.iter);
iter.next_back().map(|x| ptr::read(x))
if self.end == self.ptr {
None
} else {
if mem::size_of::<T>() == 0 {
// See above for why 'ptr.offset' isn't used
self.end = mem::transmute(self.end as uint - 1);
// Use a non-null pointer value
Some(ptr::read(mem::transmute(1u)))
} else {
self.end = self.end.offset(-1);
Some(ptr::read(mem::transmute(self.end)))
}
}
}
}
}
@ -2473,6 +2505,36 @@ mod tests {
assert_eq!(v.map_in_place(|_| ZeroSized).as_slice(), [ZeroSized, ZeroSized].as_slice());
}
#[test]
fn test_move_items() {
let mut vec = vec!(1i, 2, 3);
let mut vec2 : Vec<int> = vec!();
for i in vec.into_iter() {
vec2.push(i);
}
assert!(vec2 == vec!(1i, 2, 3));
}
#[test]
fn test_move_items_reverse() {
let mut vec = vec!(1i, 2, 3);
let mut vec2 : Vec<int> = vec!();
for i in vec.into_iter().rev() {
vec2.push(i);
}
assert!(vec2 == vec!(3i, 2, 1));
}
#[test]
fn test_move_items_zero_sized() {
let mut vec = vec!((), (), ());
let mut vec2 : Vec<()> = vec!();
for i in vec.into_iter() {
vec2.push(i);
}
assert!(vec2 == vec!((), (), ()));
}
#[bench]
fn bench_new(b: &mut Bencher) {
b.iter(|| {

View File

@ -57,7 +57,7 @@
html_playground_url = "http://play.rust-lang.org/")]
#![no_std]
#![feature(globs, intrinsics, lang_items, macro_rules, managed_boxes, phase)]
#![feature(globs, intrinsics, lang_items, macro_rules, phase)]
#![feature(simd, unsafe_destructor)]
#![deny(missing_doc)]

View File

@ -20,15 +20,6 @@
use mem;
/// The representation of `std::gc::Gc`.
pub struct GcBox<T> {
pub ref_count: uint,
pub drop_glue: fn(ptr: *mut u8),
pub prev: *mut GcBox<T>,
pub next: *mut GcBox<T>,
pub data: T,
}
/// The representation of a Rust slice
pub struct Slice<T> {
pub data: *const T,

View File

@ -1218,7 +1218,7 @@ macro_rules! iterator {
/// Immutable slice iterator
#[experimental = "needs review"]
pub struct Items<'a, T> {
pub struct Items<'a, T: 'a> {
ptr: *const T,
end: *const T,
marker: marker::ContravariantLifetime<'a>
@ -1261,7 +1261,7 @@ impl<'a, T> RandomAccessIterator<&'a T> for Items<'a, T> {
/// Mutable slice iterator.
#[experimental = "needs review"]
pub struct MutItems<'a, T> {
pub struct MutItems<'a, T: 'a> {
ptr: *mut T,
end: *mut T,
marker: marker::ContravariantLifetime<'a>,

View File

@ -528,9 +528,8 @@ fn test_rposition() {
#[test]
#[should_fail]
fn test_rposition_fail() {
use std::gc::GC;
let v = [(box 0i, box(GC) 0i), (box 0i, box(GC) 0i),
(box 0i, box(GC) 0i), (box 0i, box(GC) 0i)];
let v = [(box 0i, box 0i), (box 0i, box 0i),
(box 0i, box 0i), (box 0i, box 0i)];
let mut i = 0i;
v.iter().rposition(|_elt| {
if i == 2 {

View File

@ -25,7 +25,7 @@
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
html_root_url = "http://doc.rust-lang.org/master/")]
#![experimental]
#![feature(managed_boxes, macro_rules)]
#![feature(macro_rules)]
#![allow(experimental)]
pub mod fmt;

View File

@ -18,7 +18,6 @@ Runtime type reflection
use std::intrinsics::{Disr, Opaque, TyDesc, TyVisitor};
use std::mem;
use std::gc::Gc;
/**
* Trait for visitor that wishes to reflect on data.
@ -194,9 +193,9 @@ impl<V:TyVisitor + MovePtr> TyVisitor for MovePtrAdaptor<V> {
}
fn visit_box(&mut self, mtbl: uint, inner: *const TyDesc) -> bool {
self.align_to::<Gc<u8>>();
self.align_to::<Box<u8>>();
if ! self.inner.visit_box(mtbl, inner) { return false; }
self.bump_past::<Gc<u8>>();
self.bump_past::<Box<u8>>();
true
}

View File

@ -274,13 +274,9 @@ impl<'a> TyVisitor for ReprVisitor<'a> {
self.get::<&str>(|this, s| this.write_escaped_slice(*s))
}
fn visit_box(&mut self, mtbl: uint, inner: *const TyDesc) -> bool {
try!(self, self.writer.write("box(GC) ".as_bytes()));
self.write_mut_qualifier(mtbl);
self.get::<&raw::GcBox<()>>(|this, b| {
let p = &b.data as *const () as *const u8;
this.visit_ptr_inner(p, inner)
})
fn visit_box(&mut self, _mtbl: uint, _inner: *const TyDesc) -> bool {
try!(self, self.writer.write("box(GC) ???".as_bytes()));
true
}
fn visit_uniq(&mut self, _mtbl: uint, inner: *const TyDesc) -> bool {
@ -576,7 +572,6 @@ fn test_repr() {
use std::io::stdio::println;
use std::char::is_alphabetic;
use std::mem::swap;
use std::gc::GC;
fn exact_test<T>(t: &T, e:&str) {
let mut m = io::MemWriter::new();
@ -591,7 +586,6 @@ fn test_repr() {
exact_test(&1.234f64, "1.234f64");
exact_test(&("hello"), "\"hello\"");
exact_test(&(box(GC) 10i), "box(GC) 10");
exact_test(&(box 10i), "box 10");
exact_test(&(&10i), "&10");
let mut x = 10i;
@ -605,8 +599,6 @@ fn test_repr() {
"&[\"hi\", \"there\"]");
exact_test(&(P{a:10, b:1.234}),
"repr::P{a: 10, b: 1.234f64}");
exact_test(&(box(GC) P{a:10, b:1.234}),
"box(GC) repr::P{a: 10, b: 1.234f64}");
exact_test(&(box P{a:10, b:1.234}),
"box repr::P{a: 10, b: 1.234f64}");

View File

@ -50,7 +50,7 @@ fn main() {
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
html_root_url = "http://doc.rust-lang.org/master/")]
#![feature(plugin_registrar, managed_boxes)]
#![feature(plugin_registrar)]
extern crate syntax;
extern crate rustc;

View File

@ -73,13 +73,13 @@ impl BasicLoop {
RunRemote(i) => {
match self.remotes.iter_mut().find(|& &(id, _)| id == i) {
Some(&(_, ref mut f)) => f.call(),
None => unreachable!()
None => fail!("bad remote: {}", i),
}
}
RemoveRemote(i) => {
match self.remotes.iter().position(|&(id, _)| id == i) {
Some(i) => { self.remotes.remove(i).unwrap(); }
None => unreachable!()
None => fail!("bad remote: {}", i),
}
}
}

View File

@ -46,7 +46,7 @@ fn main() {
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
html_root_url = "http://doc.rust-lang.org/master/")]
#![feature(plugin_registrar, managed_boxes)]
#![feature(plugin_registrar)]
extern crate syntax;
extern crate rustc;

View File

@ -583,10 +583,11 @@ fn spawn_process_os(cfg: ProcessConfig,
let mut bytes = [0, ..4];
return match input.inner_read(bytes) {
Ok(4) => {
let errno = (bytes[0] << 24) as i32 |
(bytes[1] << 16) as i32 |
(bytes[2] << 8) as i32 |
(bytes[3] << 0) as i32;
let errno = (bytes[0] as i32 << 24) |
(bytes[1] as i32 << 16) |
(bytes[2] as i32 << 8) |
(bytes[3] as i32 << 0);
Err(IoError {
code: errno as uint,
detail: None,
@ -637,10 +638,10 @@ fn spawn_process_os(cfg: ProcessConfig,
fn fail(output: &mut file::FileDesc) -> ! {
let errno = os::errno();
let bytes = [
(errno << 24) as u8,
(errno << 16) as u8,
(errno << 8) as u8,
(errno << 0) as u8,
(errno >> 24) as u8,
(errno >> 16) as u8,
(errno >> 8) as u8,
(errno >> 0) as u8,
];
assert!(output.inner_write(bytes).is_ok());
unsafe { libc::_exit(1) }

View File

@ -19,7 +19,7 @@
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
html_root_url = "http://doc.rust-lang.org/master/")]
#![feature(plugin_registrar, managed_boxes, quote)]
#![feature(plugin_registrar, quote)]
extern crate regex;
extern crate syntax;

View File

@ -125,6 +125,21 @@ fn run_compiler(args: &[String]) {
driver::compile_input(sess, cfg, &input, &odir, &ofile, None);
}
/// Returns a version string such as "0.12.0-dev".
pub fn release_str() -> Option<&'static str> {
option_env!("CFG_RELEASE")
}
/// Returns the full SHA1 hash of HEAD of the Git repo from which rustc was built.
pub fn commit_hash_str() -> Option<&'static str> {
option_env!("CFG_VER_HASH")
}
/// Returns the "commit date" of HEAD of the Git repo from which rustc was built as a static string.
pub fn commit_date_str() -> Option<&'static str> {
option_env!("CFG_VER_DATE")
}
/// Prints version information and returns None on success or an error
/// message on failure.
pub fn version(binary: &str, matches: &getopts::Matches) -> Option<String> {
@ -134,13 +149,14 @@ pub fn version(binary: &str, matches: &getopts::Matches) -> Option<String> {
Some(s) => return Some(format!("Unrecognized argument: {}", s))
};
println!("{} {}", binary, env!("CFG_VERSION"));
println!("{} {}", binary, option_env!("CFG_VERSION").unwrap_or("unknown version"));
if verbose {
fn unw(x: Option<&str>) -> &str { x.unwrap_or("unknown") }
println!("binary: {}", binary);
println!("commit-hash: {}", option_env!("CFG_VER_HASH").unwrap_or("unknown"));
println!("commit-date: {}", option_env!("CFG_VER_DATE").unwrap_or("unknown"));
println!("commit-hash: {}", unw(commit_hash_str()));
println!("commit-date: {}", unw(commit_date_str()));
println!("host: {}", driver::host_triple());
println!("release: {}", env!("CFG_RELEASE"));
println!("release: {}", unw(release_str()));
}
None
}

View File

@ -412,26 +412,16 @@ impl LintPass for CTypes {
}
}
declare_lint!(MANAGED_HEAP_MEMORY, Allow,
"use of managed (@ type) heap memory")
declare_lint!(OWNED_HEAP_MEMORY, Allow,
"use of owned (Box type) heap memory")
declare_lint!(HEAP_MEMORY, Allow,
"use of any (Box type or @ type) heap memory")
pub struct HeapMemory;
impl HeapMemory {
fn check_heap_type(&self, cx: &Context, span: Span, ty: ty::t) {
let mut n_box = 0i;
let mut n_uniq = 0i;
ty::fold_ty(cx.tcx, ty, |t| {
match ty::get(t).sty {
ty::ty_box(_) => {
n_box += 1;
}
ty::ty_uniq(_) |
ty::ty_closure(box ty::ClosureTy {
store: ty::UniqTraitStore,
@ -449,21 +439,13 @@ impl HeapMemory {
let s = ty_to_string(cx.tcx, ty);
let m = format!("type uses owned (Box type) pointers: {}", s);
cx.span_lint(OWNED_HEAP_MEMORY, span, m.as_slice());
cx.span_lint(HEAP_MEMORY, span, m.as_slice());
}
if n_box > 0 {
let s = ty_to_string(cx.tcx, ty);
let m = format!("type uses managed (@ type) pointers: {}", s);
cx.span_lint(MANAGED_HEAP_MEMORY, span, m.as_slice());
cx.span_lint(HEAP_MEMORY, span, m.as_slice());
}
}
}
impl LintPass for HeapMemory {
fn get_lints(&self) -> LintArray {
lint_array!(MANAGED_HEAP_MEMORY, OWNED_HEAP_MEMORY, HEAP_MEMORY)
lint_array!(OWNED_HEAP_MEMORY)
}
fn check_item(&mut self, cx: &Context, it: &ast::Item) {
@ -1289,7 +1271,7 @@ impl LintPass for UnnecessaryAllocation {
fn check_expr(&mut self, cx: &Context, e: &ast::Expr) {
match e.node {
ast::ExprUnary(ast::UnUniq, _) | ast::ExprUnary(ast::UnBox, _) => (),
ast::ExprUnary(ast::UnUniq, _) => (),
_ => return
}

View File

@ -397,7 +397,6 @@ fn parse_ty(st: &mut PState, conv: conv_did) -> ty::t {
assert_eq!(next(st), '|');
return ty::mk_param(st.tcx, space, index, did);
}
'@' => return ty::mk_box(st.tcx, parse_ty(st, |x,y| conv(x,y))),
'~' => return ty::mk_uniq(st.tcx, parse_ty(st, |x,y| conv(x,y))),
'*' => return ty::mk_ptr(st.tcx, parse_mt(st, |x,y| conv(x,y))),
'&' => {

View File

@ -244,7 +244,6 @@ fn enc_sty(w: &mut SeekableMemWriter, cx: &ctxt, st: &ty::sty) {
for t in ts.iter() { enc_ty(w, cx, *t); }
mywrite!(w, "]");
}
ty::ty_box(typ) => { mywrite!(w, "@"); enc_ty(w, cx, typ); }
ty::ty_uniq(typ) => { mywrite!(w, "~"); enc_ty(w, cx, typ); }
ty::ty_ptr(mt) => { mywrite!(w, "*"); enc_mt(w, cx, mt); }
ty::ty_rptr(r, mt) => {

View File

@ -815,11 +815,6 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
return;
}
mc::cat_deref(_, _, mc::GcPtr) => {
assert_eq!(cmt.mutbl, mc::McImmutable);
return;
}
mc::cat_rvalue(..) |
mc::cat_static_item |
mc::cat_deref(_, _, mc::UnsafePtr(..)) |

View File

@ -74,7 +74,7 @@ to an `LV` of `(*a).f`.
Here is the formal grammar for the types we'll consider:
```text
TY = () | S<'LT...> | Box<TY> | & 'LT MQ TY | @ MQ TY
TY = () | S<'LT...> | Box<TY> | & 'LT MQ TY
MQ = mut | imm | const
```
@ -263,9 +263,7 @@ compatible with the aliasability of `LV`. The goal is to prevent
`&mut` borrows of aliasability data.
3. `LIFETIME(LV, LT, MQ)`: The lifetime of the borrow does not exceed
the lifetime of the value being borrowed. This pass is also
responsible for inserting root annotations to keep managed values
alive.
the lifetime of the value being borrowed.
4. `RESTRICTIONS(LV, LT, ACTIONS) = RS`: This pass checks and computes the
restrictions to maintain memory safety. These are the restrictions
@ -316,17 +314,13 @@ MUTABILITY(*LV, MQ) // M-Deref-Unique
### Checking mutability of immutable pointer types
Immutable pointer types like `&T` and `@T` can only
Immutable pointer types like `&T` can only
be borrowed if MQ is immutable or const:
```text
MUTABILITY(*LV, MQ) // M-Deref-Borrowed-Imm
TYPE(LV) = &Ty
MQ == imm | const
MUTABILITY(*LV, MQ) // M-Deref-Managed-Imm
TYPE(LV) = @Ty
MQ == imm | const
```
### Checking mutability of mutable pointer types
@ -390,11 +384,10 @@ ALIASABLE(*LV, MQ) // M-Deref-Borrowed-Mut
## Checking lifetime
These rules aim to ensure that no data is borrowed for a scope that exceeds
its lifetime. In addition, these rules manage the rooting of `@` values.
These two computations wind up being intimately related. Formally, we define
a predicate `LIFETIME(LV, LT, MQ)`, which states that "the lvalue `LV` can be
safely borrowed for the lifetime `LT` with mutability `MQ`". The Rust
code corresponding to this predicate is the module
its lifetime. These two computations wind up being intimately related.
Formally, we define a predicate `LIFETIME(LV, LT, MQ)`, which states that
"the lvalue `LV` can be safely borrowed for the lifetime `LT` with mutability
`MQ`". The Rust code corresponding to this predicate is the module
`middle::borrowck::gather_loans::lifetime`.
### The Scope function
@ -423,14 +416,6 @@ the pointer itself `LV` goes out of scope:
SCOPE(*LV) = SCOPE(LV) if LV has type Box<T>
```
The scope of a managed referent is also the scope of the pointer. This
is a conservative approximation, since there may be other aliases for
that same managed box that would cause it to live longer:
```text
SCOPE(*LV) = SCOPE(LV) if LV has type @T
```
The scope of a borrowed referent is the scope associated with the
pointer. This is a conservative approximation, since the data that
the pointer points at may actually live longer:
@ -477,59 +462,6 @@ LIFETIME(*LV, LT, MQ) // L-Deref-Borrowed
LT <= LT'
```
### Checking lifetime for derefs of managed, immutable pointers
Managed pointers are valid so long as the data within them is
*rooted*. There are two ways that this can be achieved. The first is
when the user guarantees such a root will exist. For this to be true,
three conditions must be met:
```text
LIFETIME(*LV, LT, MQ) // L-Deref-Managed-Imm-User-Root
TYPE(LV) = @Ty
LT <= SCOPE(LV) // (1)
LV is immutable // (2)
LV is not moved or not movable // (3)
```
Condition (1) guarantees that the managed box will be rooted for at
least the lifetime `LT` of the borrow, presuming that no mutation or
moves occur. Conditions (2) and (3) then serve to guarantee that the
value is not mutated or moved. Note that lvalues are either
(ultimately) owned by a local variable, in which case we can check
whether that local variable is ever moved in its scope, or they are
owned by the referent of an (immutable, due to condition 2) managed or
references, in which case moves are not permitted because the
location is aliasable.
If the conditions of `L-Deref-Managed-Imm-User-Root` are not met, then
there is a second alternative. The compiler can attempt to root the
managed pointer itself. This permits great flexibility, because the
location `LV` where the managed pointer is found does not matter, but
there are some limitations. The lifetime of the borrow can only extend
to the innermost enclosing loop or function body. This guarantees that
the compiler never requires an unbounded amount of stack space to
perform the rooting; if this condition were violated, the compiler
might have to accumulate a list of rooted objects, for example if the
borrow occurred inside the body of a loop but the scope of the borrow
extended outside the loop. More formally, the requirement is that
there is no path starting from the borrow that leads back to the
borrow without crossing the exit from the scope `LT`.
The rule for compiler rooting is as follows:
```text
LIFETIME(*LV, LT, MQ) // L-Deref-Managed-Imm-Compiler-Root
TYPE(LV) = @Ty
LT <= innermost enclosing loop/func
ROOT LV at *LV for LT
```
Here I have written `ROOT LV at *LV FOR LT` to indicate that the code
makes a note in a side-table that the box `LV` must be rooted into the
stack when `*LV` is evaluated, and that this root can be released when
the scope `LT` exits.
## Computing the restrictions
The final rules govern the computation of *restrictions*, meaning that
@ -599,22 +531,18 @@ RESTRICTIONS(*LV, LT, ACTIONS) = RS, (*LV, ACTIONS) // R-Deref-Send-Pointer
RESTRICTIONS(LV, LT, ACTIONS|MUTATE|CLAIM) = RS
```
### Restrictions for loans of immutable managed/borrowed referents
### Restrictions for loans of immutable borrowed referents
Immutable managed/borrowed referents are freely aliasable, meaning that
Immutable borrowed referents are freely aliasable, meaning that
the compiler does not prevent you from copying the pointer. This
implies that issuing restrictions is useless. We might prevent the
user from acting on `*LV` itself, but there could be another path
`*LV1` that refers to the exact same memory, and we would not be
restricting that path. Therefore, the rule for `&Ty` and `@Ty`
pointers always returns an empty set of restrictions, and it only
permits restricting `MUTATE` and `CLAIM` actions:
restricting that path. Therefore, the rule for `&Ty` pointers
always returns an empty set of restrictions, and it only permits
restricting `MUTATE` and `CLAIM` actions:
```text
RESTRICTIONS(*LV, LT, ACTIONS) = [] // R-Deref-Imm-Managed
TYPE(LV) = @Ty
ACTIONS subset of [MUTATE, CLAIM]
RESTRICTIONS(*LV, LT, ACTIONS) = [] // R-Deref-Imm-Borrowed
TYPE(LV) = &LT' Ty
LT <= LT' // (1)
@ -623,8 +551,8 @@ RESTRICTIONS(*LV, LT, ACTIONS) = [] // R-Deref-Imm-Borrowed
The reason that we can restrict `MUTATE` and `CLAIM` actions even
without a restrictions list is that it is never legal to mutate nor to
borrow mutably the contents of a `&Ty` or `@Ty` pointer. In other
words, those restrictions are already inherent in the type.
borrow mutably the contents of a `&Ty` pointer. In other words,
those restrictions are already inherent in the type.
Clause (1) in the rule for `&Ty` deserves mention. Here I
specify that the lifetime of the loan must be less than the lifetime
@ -729,13 +657,12 @@ are affine.)
Freeze pointers are read-only. There may be `&mut` or `&` aliases, and
we can not prevent *anything* but moves in that case. So the
`RESTRICTIONS` function is only defined if `ACTIONS` is the empty set.
Because moves from a `&const` or `@const` lvalue are never legal, it
is not necessary to add any restrictions at all to the final
result.
Because moves from a `&const` lvalue are never legal, it is not
necessary to add any restrictions at all to the final result.
```text
RESTRICTIONS(*LV, LT, []) = [] // R-Deref-Freeze-Borrowed
TYPE(LV) = &const Ty or @const Ty
TYPE(LV) = &const Ty
```
### Restrictions for loans of mutable borrowed referents
@ -957,8 +884,7 @@ moves and the declaration of uninitialized variables. For each of
these points, we create a bit in the dataflow set. Assignments to a
variable `x` or path `a.b.c` kill the move/uninitialization bits for
those paths and any subpaths (e.g., `x`, `x.y`, `a.b.c`, `*a.b.c`).
The bits are also killed when the root variables (`x`, `a`) go out of
scope. Bits are unioned when two control-flow paths join. Thus, the
Bits are unioned when two control-flow paths join. Thus, the
presence of a bit indicates that the move may have occurred without an
intervening assignment to the same memory. At each use of a variable,
we examine the bits in scope, and check that none of them are

View File

@ -132,7 +132,6 @@ fn check_and_get_illegal_move_origin(bccx: &BorrowckCtxt,
match cmt.cat {
mc::cat_deref(_, _, mc::BorrowedPtr(..)) |
mc::cat_deref(_, _, mc::Implicit(..)) |
mc::cat_deref(_, _, mc::GcPtr) |
mc::cat_deref(_, _, mc::UnsafePtr(..)) |
mc::cat_upvar(..) | mc::cat_static_item |
mc::cat_copied_upvar(mc::CopiedUpvar { onceness: ast::Many, .. }) => {

View File

@ -82,8 +82,7 @@ impl<'a, 'tcx> GuaranteeLifetimeContext<'a, 'tcx> {
mc::cat_downcast(ref base) |
mc::cat_deref(ref base, _, mc::OwnedPtr) | // L-Deref-Send
mc::cat_interior(ref base, _) | // L-Field
mc::cat_deref(ref base, _, mc::GcPtr) => {
mc::cat_interior(ref base, _) => { // L-Field
self.check(base, discr_scope)
}
@ -185,7 +184,6 @@ impl<'a, 'tcx> GuaranteeLifetimeContext<'a, 'tcx> {
}
mc::cat_downcast(ref cmt) |
mc::cat_deref(ref cmt, _, mc::OwnedPtr) |
mc::cat_deref(ref cmt, _, mc::GcPtr) |
mc::cat_interior(ref cmt, _) |
mc::cat_discr(ref cmt, _) => {
self.scope(cmt)

View File

@ -114,7 +114,6 @@ fn report_cannot_move_out_of(bccx: &BorrowckCtxt, move_from: mc::cmt) {
match move_from.cat {
mc::cat_deref(_, _, mc::BorrowedPtr(..)) |
mc::cat_deref(_, _, mc::Implicit(..)) |
mc::cat_deref(_, _, mc::GcPtr) |
mc::cat_deref(_, _, mc::UnsafePtr(..)) |
mc::cat_upvar(..) | mc::cat_static_item |
mc::cat_copied_upvar(mc::CopiedUpvar { onceness: ast::Many, .. }) => {

View File

@ -101,16 +101,13 @@ impl<'a, 'tcx> RestrictionsContext<'a, 'tcx> {
self.extend(result, cmt.mutbl, LpInterior(i))
}
mc::cat_deref(cmt_base, _, pk @ mc::OwnedPtr) |
mc::cat_deref(cmt_base, _, pk @ mc::GcPtr) => {
mc::cat_deref(cmt_base, _, pk @ mc::OwnedPtr) => {
// R-Deref-Send-Pointer
//
// When we borrow the interior of an owned pointer, we
// cannot permit the base to be mutated, because that
// would cause the unique pointer to be freed.
//
// For a managed pointer, the rules are basically the
// same, because this could be the last ref.
// Eventually we should make these non-special and
// just rely on Deref<T> implementation.
let result = self.restrict(cmt_base);

View File

@ -730,11 +730,6 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
span,
format!("{} in a static location", prefix).as_slice());
}
mc::AliasableManaged => {
self.tcx.sess.span_err(
span,
format!("{} in a `Gc` pointer", prefix).as_slice());
}
mc::AliasableBorrowed => {
self.tcx.sess.span_err(
span,

View File

@ -100,7 +100,7 @@ fn check_expr(v: &mut CheckCrateVisitor, e: &Expr) {
if v.in_const {
match e.node {
ExprUnary(UnDeref, _) => { }
ExprUnary(UnBox, _) | ExprUnary(UnUniq, _) => {
ExprUnary(UnUniq, _) => {
span_err!(v.tcx.sess, e.span, E0010, "cannot do allocations in constant expressions");
return;
}
@ -149,7 +149,7 @@ fn check_expr(v: &mut CheckCrateVisitor, e: &Expr) {
}
ExprCall(ref callee, _) => {
match v.tcx.def_map.borrow().find(&callee.id) {
Some(&DefStruct(..)) => {} // OK.
Some(&DefStruct(..)) |
Some(&DefVariant(..)) => {} // OK.
_ => {
span_err!(v.tcx.sess, e.span, E0015,

View File

@ -440,11 +440,6 @@ fn construct_witness(cx: &MatchCheckCtxt, ctor: &Constructor,
}
}
ty::ty_box(_) => {
assert_eq!(pats_len, 1);
PatBox(pats.nth(0).unwrap())
}
ty::ty_vec(_, Some(len)) => {
assert_eq!(pats_len, len);
PatVec(pats.collect(), None, vec![])
@ -681,7 +676,7 @@ fn pat_constructors(cx: &MatchCheckCtxt, p: &Pat,
pub fn constructor_arity(cx: &MatchCheckCtxt, ctor: &Constructor, ty: ty::t) -> uint {
match ty::get(ty).sty {
ty::ty_tup(ref fs) => fs.len(),
ty::ty_box(_) | ty::ty_uniq(_) => 1u,
ty::ty_uniq(_) => 1u,
ty::ty_rptr(_, ty::mt { ty: ty, .. }) => match ty::get(ty).sty {
ty::ty_vec(_, None) => match *ctor {
Slice(length) => length,
@ -757,7 +752,7 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat],
DefStatic(..) =>
cx.tcx.sess.span_bug(pat_span, "static pattern should've been rewritten"),
DefVariant(_, id, _) if *constructor != Variant(id) => None,
DefVariant(..) | DefFn(..) | DefStruct(..) => {
DefVariant(..) | DefStruct(..) => {
Some(match args {
&Some(ref args) => args.iter().map(|p| &**p).collect(),
&None => Vec::from_elem(arity, &DUMMY_WILD_PAT)

View File

@ -115,10 +115,6 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckStaticVisitor<'a, 'tcx> {
span_err!(self.tcx.sess, e.span, E0020,
"static items are not allowed to have mutable slices");
},
ast::ExprUnary(ast::UnBox, _) => {
span_err!(self.tcx.sess, e.span, E0021,
"static items are not allowed to have managed pointers");
}
ast::ExprBox(..) |
ast::ExprUnary(ast::UnUniq, _) => {
span_err!(self.tcx.sess, e.span, E0022,

View File

@ -28,8 +28,8 @@ fn type_size_is_affected_by_type_parameters(tcx: &ty::ctxt, typ: ty::t)
let mut result = false;
ty::maybe_walk_ty(typ, |typ| {
match ty::get(typ).sty {
ty::ty_box(_) | ty::ty_uniq(_) | ty::ty_ptr(_) |
ty::ty_rptr(..) | ty::ty_bare_fn(..) | ty::ty_closure(..) => {
ty::ty_uniq(_) | ty::ty_ptr(_) | ty::ty_rptr(..) |
ty::ty_bare_fn(..) | ty::ty_closure(..) => {
false
}
ty::ty_param(_) => {

View File

@ -279,8 +279,6 @@ lets_do_this! {
ExchangeMallocFnLangItem, "exchange_malloc", exchange_malloc_fn;
ExchangeFreeFnLangItem, "exchange_free", exchange_free_fn;
MallocFnLangItem, "malloc", malloc_fn;
FreeFnLangItem, "free", free_fn;
StrDupUniqFnLangItem, "strdup_uniq", strdup_uniq_fn;
StartFnLangItem, "start", start_fn;
@ -293,9 +291,7 @@ lets_do_this! {
EhPersonalityLangItem, "eh_personality", eh_personality;
ManagedHeapLangItem, "managed_heap", managed_heap;
ExchangeHeapLangItem, "exchange_heap", exchange_heap;
GcLangItem, "gc", gc;
OwnedBoxLangItem, "owned_box", owned_box;
CovariantTypeItem, "covariant_type", covariant_type;

View File

@ -104,7 +104,6 @@ pub struct CopiedUpvar {
#[deriving(Clone, PartialEq, Eq, Hash)]
pub enum PointerKind {
OwnedPtr,
GcPtr,
BorrowedPtr(ty::BorrowKind, ty::Region),
Implicit(ty::BorrowKind, ty::Region), // Implicit deref of a borrowed ptr.
UnsafePtr(ast::Mutability)
@ -191,10 +190,6 @@ pub fn opt_deref_kind(t: ty::t) -> Option<deref_kind> {
Some(deref_ptr(BorrowedPtr(ty::ImmBorrow, r)))
}
ty::ty_box(..) => {
Some(deref_ptr(GcPtr))
}
ty::ty_ptr(ref mt) => {
Some(deref_ptr(UnsafePtr(mt.mutbl)))
}
@ -302,9 +297,6 @@ impl MutabilityCategory {
BorrowedPtr(borrow_kind, _) | Implicit(borrow_kind, _) => {
MutabilityCategory::from_borrow_kind(borrow_kind)
}
GcPtr => {
McImmutable
}
UnsafePtr(m) => {
MutabilityCategory::from_mutbl(m)
}
@ -1083,7 +1075,6 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
if_ok!(self.cat_pattern(subcmt, &**subpat, |x,y,z| op(x,y,z)));
}
}
Some(&def::DefFn(..)) |
Some(&def::DefStruct(..)) => {
for (i, subpat) in subpats.iter().enumerate() {
let subpat_ty = if_ok!(self.pat_ty(&**subpat)); // see (*2)
@ -1200,7 +1191,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
Implicit(..) => {
"dereference (dereference is implicit, due to indexing)".to_string()
}
OwnedPtr | GcPtr => format!("dereference of `{}`", ptr_sigil(pk)),
OwnedPtr => format!("dereference of `{}`", ptr_sigil(pk)),
_ => format!("dereference of `{}`-pointer", ptr_sigil(pk))
}
}
@ -1237,7 +1228,6 @@ pub enum InteriorSafety {
}
pub enum AliasableReason {
AliasableManaged,
AliasableBorrowed,
AliasableOther,
AliasableStatic(InteriorSafety),
@ -1256,7 +1246,6 @@ impl cmt_ {
cat_copied_upvar(..) |
cat_local(..) |
cat_deref(_, _, UnsafePtr(..)) |
cat_deref(_, _, GcPtr(..)) |
cat_deref(_, _, BorrowedPtr(..)) |
cat_deref(_, _, Implicit(..)) |
cat_upvar(..) => {
@ -1320,10 +1309,6 @@ impl cmt_ {
}
}
cat_deref(_, _, GcPtr) => {
Some(AliasableManaged)
}
cat_deref(_, _, BorrowedPtr(ty::ImmBorrow, _)) |
cat_deref(_, _, Implicit(ty::ImmBorrow, _)) => {
Some(AliasableBorrowed)
@ -1371,7 +1356,6 @@ impl Repr for categorization {
pub fn ptr_sigil(ptr: PointerKind) -> &'static str {
match ptr {
OwnedPtr => "Box",
GcPtr => "Gc",
BorrowedPtr(ty::ImmBorrow, _) |
Implicit(ty::ImmBorrow, _) => "&",
BorrowedPtr(ty::MutBorrow, _) |

View File

@ -931,15 +931,6 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
maybe_did.unwrap_or(did)
})
}
// Tuple struct constructors across crates are identified as
// DefFn types, so we explicitly handle that case here.
Some(&def::DefFn(did, _, _)) if !is_local(did) => {
match csearch::get_tuple_struct_definition_if_ctor(
&self.tcx.sess.cstore, did) {
Some(did) => guard(did),
None => {}
}
}
_ => {}
}
}

View File

@ -1824,6 +1824,11 @@ impl<'a> Resolver<'a> {
child_name_bindings.define_value(def, DUMMY_SP, is_exported);
}
}
DefFn(ctor_id, _, true) => {
child_name_bindings.define_value(
csearch::get_tuple_struct_definition_if_ctor(&self.session.cstore, ctor_id)
.map_or(def, |_| DefStruct(ctor_id)), DUMMY_SP, is_public);
}
DefFn(..) | DefStaticMethod(..) | DefStatic(..) => {
debug!("(building reduced graph for external \
crate) building value (fn/static) {}", final_ident);

View File

@ -104,11 +104,6 @@ pub fn ty_is_local(tcx: &ty::ctxt,
krate == Some(ast::LOCAL_CRATE) || ty_is_local(tcx, t)
}
ty::ty_box(t) => {
let krate = tcx.lang_items.gc().map(|d| d.krate);
krate == Some(ast::LOCAL_CRATE) || ty_is_local(tcx, t)
}
ty::ty_vec(t, _) |
ty::ty_ptr(ty::mt { ty: t, .. }) |
ty::ty_rptr(_, ty::mt { ty: t, .. }) => {

View File

@ -713,23 +713,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
ok(self, Always)
}
ty::ty_box(_) => {
match bound {
ty::BoundSync |
ty::BoundSend |
ty::BoundCopy => {
// Managed data is not copyable, sendable, nor
// synchronized, regardless of referent.
ok(self, Never)
}
ty::BoundSized => {
// But it is sized, regardless of referent.
ok(self, Always)
}
}
}
ty::ty_uniq(referent_ty) => { // Box<T>
match bound {
ty::BoundCopy => {

View File

@ -698,7 +698,6 @@ fn any_irrefutable_adt_pat(tcx: &ty::ctxt, m: &[Match], col: uint) -> bool {
}
ast::PatEnum(..) | ast::PatIdent(_, _, None) => {
match tcx.def_map.borrow().find(&pat.id) {
Some(&def::DefFn(..)) |
Some(&def::DefStruct(..)) => true,
_ => false
}
@ -1646,7 +1645,6 @@ fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
}
}
}
Some(def::DefFn(..)) |
Some(def::DefStruct(..)) => {
match *sub_pats {
None => {

View File

@ -321,9 +321,6 @@ impl Case {
_ => return Some(ThinPointer(i))
},
// Gc<T> is just a pointer
ty::ty_box(..) => return Some(ThinPointer(i)),
// Functions are just pointers
ty::ty_bare_fn(..) => return Some(ThinPointer(i)),

View File

@ -397,36 +397,6 @@ pub fn malloc_raw_dyn_proc<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, t: ty::t) -> Resu
Result::new(bcx, llbox)
}
pub fn malloc_raw_dyn_managed<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
t: ty::t,
alloc_fn: LangItem,
size: ValueRef)
-> Result<'blk, 'tcx> {
let _icx = push_ctxt("malloc_raw_dyn_managed");
let ccx = bcx.ccx();
let langcall = require_alloc_fn(bcx, t, alloc_fn);
// Grab the TypeRef type of box_ptr_ty.
let box_ptr_ty = ty::mk_box(bcx.tcx(), t);
let llty = type_of(ccx, box_ptr_ty);
let llalign = C_uint(ccx, type_of::align_of(ccx, box_ptr_ty) as uint);
// Allocate space:
let drop_glue = glue::get_drop_glue(ccx, t);
let r = callee::trans_lang_call(
bcx,
langcall,
[
PointerCast(bcx, drop_glue, Type::glue_fn(ccx, Type::i8p(ccx)).ptr_to()),
size,
llalign
],
None);
Result::new(r.bcx, PointerCast(r.bcx, r.val, llty))
}
// Type descriptor and type glue stuff
pub fn get_tydesc(ccx: &CrateContext, t: ty::t) -> Rc<tydesc_info> {

View File

@ -960,7 +960,6 @@ impl Cleanup for DropValue {
}
pub enum Heap {
HeapManaged,
HeapExchange
}
@ -986,9 +985,6 @@ impl Cleanup for FreeValue {
apply_debug_loc(bcx.fcx, debug_loc);
match self.heap {
HeapManaged => {
glue::trans_free(bcx, self.ptr)
}
HeapExchange => {
glue::trans_exchange_free_ty(bcx, self.ptr, self.content_ty)
}
@ -1019,9 +1015,6 @@ impl Cleanup for FreeSlice {
apply_debug_loc(bcx.fcx, debug_loc);
match self.heap {
HeapManaged => {
glue::trans_free(bcx, self.ptr)
}
HeapExchange => {
glue::trans_exchange_free_dyn(bcx, self.ptr, self.size, self.align)
}

View File

@ -71,7 +71,7 @@ pub fn type_is_immediate(ccx: &CrateContext, ty: ty::t) -> bool {
use middle::trans::type_of::sizing_type_of;
let tcx = ccx.tcx();
let simple = ty::type_is_scalar(ty) || ty::type_is_boxed(ty) ||
let simple = ty::type_is_scalar(ty) ||
ty::type_is_unique(ty) || ty::type_is_region_ptr(ty) ||
type_is_newtype_immediate(ccx, ty) || ty::type_is_bot(ty) ||
ty::type_is_simd(tcx, ty);

View File

@ -421,7 +421,7 @@ fn const_expr_unadjusted(cx: &CrateContext, e: &ast::Expr,
let ty = ty::expr_ty(cx.tcx(), &**e);
let is_float = ty::type_is_fp(ty);
return (match u {
ast::UnBox | ast::UnUniq | ast::UnDeref => {
ast::UnUniq | ast::UnDeref => {
let (dv, _dt) = const_deref(cx, te, ty, true);
dv
}
@ -547,6 +547,9 @@ fn const_expr_unadjusted(cx: &CrateContext, e: &ast::Expr,
(expr::cast_integral, expr::cast_pointer) => {
llvm::LLVMConstIntToPtr(v, llty.to_ref())
}
(expr::cast_pointer, expr::cast_integral) => {
llvm::LLVMConstPtrToInt(v, llty.to_ref())
}
_ => {
cx.sess().impossible_case(e.span,
"bad combination of types for cast")

View File

@ -20,7 +20,6 @@ use middle::trans::common::*;
use middle::trans::cleanup;
use middle::trans::cleanup::CleanupMethods;
use middle::trans::expr;
use middle::trans::glue;
use middle::trans::tvec;
use middle::trans::type_of;
use middle::ty;
@ -240,14 +239,9 @@ impl KindOps for Lvalue {
*/
if ty::type_needs_drop(bcx.tcx(), ty) {
if ty::type_moves_by_default(bcx.tcx(), ty) {
// cancel cleanup of affine values by zeroing out
let () = zero_mem(bcx, val, ty);
bcx
} else {
// incr. refcount for @T or newtype'd @T
glue::take_ty(bcx, val, ty)
}
// cancel cleanup of affine values by zeroing out
let () = zero_mem(bcx, val, ty);
bcx
} else {
bcx
}
@ -567,15 +561,15 @@ impl<K:KindOps> Datum<K> {
* is moved).
*/
self.shallow_copy(bcx, dst);
self.shallow_copy_raw(bcx, dst);
self.kind.post_store(bcx, self.val, self.ty)
}
fn shallow_copy<'blk, 'tcx>(&self,
bcx: Block<'blk, 'tcx>,
dst: ValueRef)
-> Block<'blk, 'tcx> {
fn shallow_copy_raw<'blk, 'tcx>(&self,
bcx: Block<'blk, 'tcx>,
dst: ValueRef)
-> Block<'blk, 'tcx> {
/*!
* Helper function that performs a shallow copy of this value
* into `dst`, which should be a pointer to a memory location
@ -584,10 +578,9 @@ impl<K:KindOps> Datum<K> {
*
* This function is private to datums because it leaves memory
* in an unstable state, where the source value has been
* copied but not zeroed. Public methods are `store_to` (if
* you no longer need the source value) or
* `shallow_copy_and_take` (if you wish the source value to
* remain valid).
* copied but not zeroed. Public methods are `store_to`
* (if you no longer need the source value) or `shallow_copy`
* (if you wish the source value to remain valid).
*/
let _icx = push_ctxt("copy_to_no_check");
@ -605,22 +598,19 @@ impl<K:KindOps> Datum<K> {
return bcx;
}
pub fn shallow_copy_and_take<'blk, 'tcx>(&self,
bcx: Block<'blk, 'tcx>,
dst: ValueRef)
-> Block<'blk, 'tcx> {
pub fn shallow_copy<'blk, 'tcx>(&self,
bcx: Block<'blk, 'tcx>,
dst: ValueRef)
-> Block<'blk, 'tcx> {
/*!
* Copies the value into a new location and runs any necessary
* take glue on the new location. This function always
* Copies the value into a new location. This function always
* preserves the existing datum as a valid value. Therefore,
* it does not consume `self` and, also, cannot be applied to
* affine values (since they must never be duplicated).
*/
assert!(!ty::type_moves_by_default(bcx.tcx(), self.ty));
let mut bcx = bcx;
bcx = self.shallow_copy(bcx, dst);
glue::take_ty(bcx, dst, self.ty)
self.shallow_copy_raw(bcx, dst)
}
#[allow(dead_code)] // useful for debugging

View File

@ -373,12 +373,6 @@ impl TypeMap {
unique_type_id.push_str(component_type_id.as_slice());
}
},
ty::ty_box(inner_type) => {
unique_type_id.push_char('@');
let inner_type_id = self.get_unique_type_id_of_type(cx, inner_type);
let inner_type_id = self.get_unique_type_id_as_string(inner_type_id);
unique_type_id.push_str(inner_type_id.as_slice());
},
ty::ty_uniq(inner_type) => {
unique_type_id.push_char('~');
let inner_type_id = self.get_unique_type_id_of_type(cx, inner_type);
@ -596,18 +590,6 @@ impl TypeMap {
let interner_key = self.unique_id_interner.intern(Rc::new(enum_variant_type_id));
UniqueTypeId(interner_key)
}
fn get_unique_type_id_of_gc_box(&mut self,
cx: &CrateContext,
element_type: ty::t)
-> UniqueTypeId {
let element_type_id = self.get_unique_type_id_of_type(cx, element_type);
let gc_box_type_id = format!("{{GC_BOX<{}>}}",
self.get_unique_type_id_as_string(element_type_id)
.as_slice());
let interner_key = self.unique_id_interner.intern(Rc::new(gc_box_type_id));
UniqueTypeId(interner_key)
}
}
// Returns from the enclosing function if the type metadata with the given
@ -2646,105 +2628,6 @@ fn create_struct_stub(cx: &CrateContext,
return metadata_stub;
}
fn at_box_metadata(cx: &CrateContext,
at_pointer_type: ty::t,
content_type: ty::t,
unique_type_id: UniqueTypeId)
-> MetadataCreationResult {
let content_type_metadata = type_metadata(cx, content_type, codemap::DUMMY_SP);
return_if_metadata_created_in_meantime!(cx, unique_type_id);
let content_type_name = compute_debuginfo_type_name(cx, content_type, true);
let content_type_name = content_type_name.as_slice();
let content_llvm_type = type_of::type_of(cx, content_type);
let box_type_name = format!("GcBox<{}>", content_type_name);
let box_llvm_type = Type::at_box(cx, content_llvm_type);
let member_llvm_types = box_llvm_type.field_types();
assert!(box_layout_is_correct(cx,
member_llvm_types.as_slice(),
content_llvm_type));
let int_type = ty::mk_int();
let nil_pointer_type = ty::mk_nil_ptr(cx.tcx());
let nil_pointer_type_metadata = type_metadata(cx,
nil_pointer_type,
codemap::DUMMY_SP);
let member_descriptions = [
MemberDescription {
name: "refcnt".to_string(),
llvm_type: *member_llvm_types.get(0),
type_metadata: type_metadata(cx, int_type, codemap::DUMMY_SP),
offset: ComputedMemberOffset,
flags: FLAGS_ARTIFICAL,
},
MemberDescription {
name: "drop_glue".to_string(),
llvm_type: *member_llvm_types.get(1),
type_metadata: nil_pointer_type_metadata,
offset: ComputedMemberOffset,
flags: FLAGS_ARTIFICAL,
},
MemberDescription {
name: "prev".to_string(),
llvm_type: *member_llvm_types.get(2),
type_metadata: nil_pointer_type_metadata,
offset: ComputedMemberOffset,
flags: FLAGS_ARTIFICAL,
},
MemberDescription {
name: "next".to_string(),
llvm_type: *member_llvm_types.get(3),
type_metadata: nil_pointer_type_metadata,
offset: ComputedMemberOffset,
flags: FLAGS_ARTIFICAL,
},
MemberDescription {
name: "val".to_string(),
llvm_type: *member_llvm_types.get(4),
type_metadata: content_type_metadata,
offset: ComputedMemberOffset,
flags: FLAGS_ARTIFICAL,
}
];
let gc_box_unique_id = debug_context(cx).type_map
.borrow_mut()
.get_unique_type_id_of_gc_box(cx, content_type);
let gc_box_metadata = composite_type_metadata(
cx,
box_llvm_type,
box_type_name.as_slice(),
gc_box_unique_id,
member_descriptions,
UNKNOWN_SCOPE_METADATA,
UNKNOWN_FILE_METADATA,
codemap::DUMMY_SP);
let gc_pointer_metadata = pointer_type_metadata(cx,
at_pointer_type,
gc_box_metadata);
return MetadataCreationResult::new(gc_pointer_metadata, false);
// Unfortunately, we cannot assert anything but the correct types here---and
// not whether the 'next' and 'prev' pointers are in the correct order.
fn box_layout_is_correct(cx: &CrateContext,
member_llvm_types: &[Type],
content_llvm_type: Type)
-> bool {
member_llvm_types.len() == 5 &&
member_llvm_types[0] == cx.int_type() &&
member_llvm_types[1] == Type::generic_glue_fn(cx).ptr_to() &&
member_llvm_types[2] == Type::i8(cx).ptr_to() &&
member_llvm_types[3] == Type::i8(cx).ptr_to() &&
member_llvm_types[4] == content_llvm_type
}
}
fn fixed_vec_metadata(cx: &CrateContext,
unique_type_id: UniqueTypeId,
element_type: ty::t,
@ -2968,9 +2851,6 @@ fn type_metadata(cx: &CrateContext,
ty::ty_enum(def_id, _) => {
prepare_enum_metadata(cx, t, def_id, unique_type_id, usage_site_span).finalize(cx)
}
ty::ty_box(pointee_type) => {
at_box_metadata(cx, t, pointee_type, unique_type_id)
}
ty::ty_vec(typ, Some(len)) => {
fixed_vec_metadata(cx, unique_type_id, typ, len, usage_site_span)
}
@ -3702,7 +3582,7 @@ fn populate_scope_map(cx: &CrateContext,
ast::ExprInlineAsm(ast::InlineAsm { inputs: ref inputs,
outputs: ref outputs,
.. }) => {
// inputs, outputs: ~[(String, Gc<expr>)]
// inputs, outputs: Vec<(String, P<Expr>)>
for &(_, ref exp) in inputs.iter() {
walk_expr(cx, &**exp, scope_stack, scope_map);
}
@ -3777,10 +3657,6 @@ fn push_debuginfo_type_name(cx: &CrateContext,
push_debuginfo_type_name(cx, inner_type, true, output);
output.push_char('>');
},
ty::ty_box(inner_type) => {
output.push_char('@');
push_debuginfo_type_name(cx, inner_type, true, output);
},
ty::ty_ptr(ty::mt { ty: inner_type, mutbl } ) => {
output.push_char('*');
match mutbl {

View File

@ -65,7 +65,7 @@ Some of the datum methods, however, are designed to work only on
copyable values such as ints or pointers. Those methods may borrow the
datum (`&self`) rather than consume it, but they always include
assertions on the type of the value represented to check that this
makes sense. An example is `shallow_copy_and_take()`, which duplicates
makes sense. An example is `shallow_copy()`, which duplicates
a datum value.
Translating an expression always yields a `Datum<Expr>` result, but

View File

@ -38,7 +38,6 @@ use llvm;
use llvm::{ValueRef};
use metadata::csearch;
use middle::def;
use middle::lang_items::MallocFnLangItem;
use middle::mem_categorization::Typer;
use middle::subst;
use middle::subst::Subst;
@ -624,18 +623,15 @@ fn trans_datum_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
DatumBlock::new(bcx, scratch.to_expr_datum())
}
ast::ExprBox(_, ref contents) => {
// Special case for `Box<T>` and `Gc<T>`
// Special case for `Box<T>`
let box_ty = expr_ty(bcx, expr);
let contents_ty = expr_ty(bcx, &**contents);
match ty::get(box_ty).sty {
ty::ty_uniq(..) => {
trans_uniq_expr(bcx, box_ty, &**contents, contents_ty)
}
ty::ty_box(..) => {
trans_managed_expr(bcx, box_ty, &**contents, contents_ty)
}
_ => bcx.sess().span_bug(expr.span,
"expected unique or managed box")
"expected unique box")
}
}
@ -1533,9 +1529,6 @@ fn trans_unary<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
};
immediate_rvalue_bcx(bcx, llneg, un_ty).to_expr_datumblock()
}
ast::UnBox => {
trans_managed_expr(bcx, un_ty, sub_expr, expr_ty(bcx, sub_expr))
}
ast::UnUniq => {
trans_uniq_expr(bcx, un_ty, sub_expr, expr_ty(bcx, sub_expr))
}
@ -1575,26 +1568,6 @@ fn trans_uniq_expr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
immediate_rvalue_bcx(bcx, val, box_ty).to_expr_datumblock()
}
fn trans_managed_expr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
box_ty: ty::t,
contents: &ast::Expr,
contents_ty: ty::t)
-> DatumBlock<'blk, 'tcx, Expr> {
let _icx = push_ctxt("trans_managed_expr");
let fcx = bcx.fcx;
let ty = type_of::type_of(bcx.ccx(), contents_ty);
let Result {bcx, val: bx} = malloc_raw_dyn_managed(bcx, contents_ty, MallocFnLangItem,
llsize_of(bcx.ccx(), ty));
let body = GEPi(bcx, bx, [0u, abi::box_field_body]);
let custom_cleanup_scope = fcx.push_custom_cleanup_scope();
fcx.schedule_free_value(cleanup::CustomScope(custom_cleanup_scope),
bx, cleanup::HeapManaged, contents_ty);
let bcx = trans_into(bcx, contents, SaveIn(body));
fcx.pop_custom_cleanup_scope(custom_cleanup_scope);
immediate_rvalue_bcx(bcx, bx, box_ty).to_expr_datumblock()
}
fn trans_addr_of<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
expr: &ast::Expr,
subexpr: &ast::Expr)
@ -1927,10 +1900,6 @@ pub fn cast_type_kind(tcx: &ty::ctxt, t: ty::t) -> cast_kind {
}
fn cast_is_noop(t_in: ty::t, t_out: ty::t) -> bool {
if ty::type_is_boxed(t_in) || ty::type_is_boxed(t_out) {
return false;
}
match (ty::deref(t_in, true), ty::deref(t_out, true)) {
(Some(ty::mt{ ty: t_in, .. }), Some(ty::mt{ ty: t_out, .. })) => {
t_in == t_out
@ -2163,15 +2132,6 @@ fn deref_once<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
}
}
ty::ty_box(content_ty) => {
let datum = unpack_datum!(
bcx, datum.to_lvalue_datum(bcx, "deref", expr.id));
let llptrref = datum.to_llref();
let llptr = Load(bcx, llptrref);
let llbody = GEPi(bcx, llptr, [0u, abi::box_field_body]);
DatumBlock::new(bcx, Datum::new(llbody, content_ty, LvalueExpr))
}
ty::ty_ptr(ty::mt { ty: content_ty, .. }) |
ty::ty_rptr(_, ty::mt { ty: content_ty, .. }) => {
if ty::type_is_sized(bcx.tcx(), content_ty) {

View File

@ -17,7 +17,7 @@ use back::abi;
use back::link::*;
use llvm::{ValueRef, True, get_param};
use llvm;
use middle::lang_items::{FreeFnLangItem, ExchangeFreeFnLangItem};
use middle::lang_items::ExchangeFreeFnLangItem;
use middle::subst;
use middle::subst::Subst;
use middle::trans::adt;
@ -46,15 +46,6 @@ use libc::c_uint;
use syntax::ast;
use syntax::parse::token;
pub fn trans_free<'blk, 'tcx>(cx: Block<'blk, 'tcx>, v: ValueRef)
-> Block<'blk, 'tcx> {
let _icx = push_ctxt("trans_free");
callee::trans_lang_call(cx,
langcall(cx, None, "", FreeFnLangItem),
[PointerCast(cx, v, Type::i8p(cx.ccx()))],
Some(expr::Ignore)).bcx
}
pub fn trans_exchange_free_dyn<'blk, 'tcx>(cx: Block<'blk, 'tcx>, v: ValueRef,
size: ValueRef, align: ValueRef)
-> Block<'blk, 'tcx> {
@ -87,20 +78,6 @@ pub fn trans_exchange_free_ty<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ptr: ValueRef,
}
}
pub fn take_ty<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, v: ValueRef, t: ty::t)
-> Block<'blk, 'tcx> {
// NB: v is an *alias* of type t here, not a direct value.
let _icx = push_ctxt("take_ty");
match ty::get(t).sty {
ty::ty_box(_) => incr_refcnt_of_boxed(bcx, v),
_ if ty::type_is_structural(t)
&& ty::type_needs_drop(bcx.tcx(), t) => {
iter_structural_ty(bcx, v, t, take_ty)
}
_ => bcx
}
}
pub fn get_drop_glue_type(ccx: &CrateContext, t: ty::t) -> ty::t {
let tcx = ccx.tcx();
// Even if there is no dtor for t, there might be one deeper down and we
@ -446,9 +423,6 @@ fn make_drop_glue<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, v0: ValueRef, t: ty::t)
// NB: v0 is an *alias* of type t here, not a direct value.
let _icx = push_ctxt("make_drop_glue");
match ty::get(t).sty {
ty::ty_box(body_ty) => {
decr_refcnt_maybe_free(bcx, v0, body_ty)
}
ty::ty_uniq(content_ty) => {
match ty::get(content_ty).sty {
ty::ty_vec(ty, None) => {
@ -568,48 +542,6 @@ fn make_drop_glue<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, v0: ValueRef, t: ty::t)
}
}
fn decr_refcnt_maybe_free<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
box_ptr_ptr: ValueRef,
t: ty::t) -> Block<'blk, 'tcx> {
let _icx = push_ctxt("decr_refcnt_maybe_free");
let fcx = bcx.fcx;
let ccx = bcx.ccx();
let decr_bcx = fcx.new_temp_block("decr");
let free_bcx = fcx.new_temp_block("free");
let next_bcx = fcx.new_temp_block("next");
let box_ptr = Load(bcx, box_ptr_ptr);
let llnotnull = IsNotNull(bcx, box_ptr);
CondBr(bcx, llnotnull, decr_bcx.llbb, next_bcx.llbb);
let rc_ptr = GEPi(decr_bcx, box_ptr, [0u, abi::box_field_refcnt]);
let rc = Sub(decr_bcx, Load(decr_bcx, rc_ptr), C_int(ccx, 1));
Store(decr_bcx, rc, rc_ptr);
CondBr(decr_bcx, IsNull(decr_bcx, rc), free_bcx.llbb, next_bcx.llbb);
let v = Load(free_bcx, box_ptr_ptr);
let body = GEPi(free_bcx, v, [0u, abi::box_field_body]);
let free_bcx = drop_ty(free_bcx, body, t, None);
let free_bcx = trans_free(free_bcx, v);
Br(free_bcx, next_bcx.llbb);
next_bcx
}
fn incr_refcnt_of_boxed<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
box_ptr_ptr: ValueRef) -> Block<'blk, 'tcx> {
let _icx = push_ctxt("incr_refcnt_of_boxed");
let ccx = bcx.ccx();
let box_ptr = Load(bcx, box_ptr_ptr);
let rc_ptr = GEPi(bcx, box_ptr, [0u, abi::box_field_refcnt]);
let rc = Load(bcx, rc_ptr);
let rc = Add(bcx, rc, C_int(ccx, 1));
Store(bcx, rc, rc_ptr);
bcx
}
// Generates the declaration for (but doesn't emit) a type descriptor.
pub fn declare_tydesc(ccx: &CrateContext, t: ty::t) -> tydesc_info {
// If emit_tydescs already ran, then we shouldn't be creating any new

View File

@ -169,14 +169,6 @@ impl<'a, 'blk, 'tcx> Reflector<'a, 'blk, 'tcx> {
extra.push(self.c_tydesc(ty));
self.visit("evec_fixed", extra.as_slice())
}
// Should remove mt from box and uniq.
ty::ty_box(typ) => {
let extra = self.c_mt(&ty::mt {
ty: typ,
mutbl: ast::MutImmutable,
});
self.visit("box", extra.as_slice())
}
ty::ty_ptr(ref mt) => {
match ty::get(mt.ty).sty {
ty::ty_vec(ty, None) => {

View File

@ -325,7 +325,7 @@ pub fn write_content<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
let bcx = iter_vec_loop(bcx, lldest, vt,
C_uint(bcx.ccx(), count), |set_bcx, lleltptr, _| {
elem.shallow_copy_and_take(set_bcx, lleltptr)
elem.shallow_copy(set_bcx, lleltptr)
});
elem.add_clean_if_rvalue(bcx, element.id);

View File

@ -174,7 +174,6 @@ pub fn sizing_type_of(cx: &CrateContext, t: ty::t) -> Type {
ty::ty_uint(t) => Type::uint_from_ty(cx, t),
ty::ty_float(t) => Type::float_from_ty(cx, t),
ty::ty_box(..) => Type::i8p(cx),
ty::ty_uniq(ty) | ty::ty_rptr(_, ty::mt{ty, ..}) | ty::ty_ptr(ty::mt{ty, ..}) => {
if ty::type_is_sized(cx.tcx(), ty) {
Type::i8p(cx)
@ -299,9 +298,6 @@ pub fn type_of(cx: &CrateContext, t: ty::t) -> Type {
let name = llvm_type_name(cx, an_unboxed_closure, did, []);
adt::incomplete_type_of(cx, &*repr, name.as_slice())
}
ty::ty_box(typ) => {
Type::at_box(cx, type_of(cx, typ)).ptr_to()
}
ty::ty_uniq(ty) | ty::ty_rptr(_, ty::mt{ty, ..}) | ty::ty_ptr(ty::mt{ty, ..}) => {
match ty::get(ty).sty {

View File

@ -940,7 +940,6 @@ pub enum sty {
/// the `ast_ty_to_ty_cache`. This is probably true for `ty_struct` as
/// well.`
ty_enum(DefId, Substs),
ty_box(t),
ty_uniq(t),
ty_str,
ty_vec(t, Option<uint>), // Second field is length.
@ -1621,7 +1620,7 @@ pub fn mk_t(cx: &ctxt, st: sty) -> t {
flags |= sflags(substs);
flags |= flags_for_bounds(bounds);
}
&ty_box(tt) | &ty_uniq(tt) | &ty_vec(tt, _) | &ty_open(tt) => {
&ty_uniq(tt) | &ty_vec(tt, _) | &ty_open(tt) => {
flags |= get(tt).flags
}
&ty_ptr(ref m) => {
@ -1776,8 +1775,6 @@ pub fn mk_enum(cx: &ctxt, did: ast::DefId, substs: Substs) -> t {
mk_t(cx, ty_enum(did, substs))
}
pub fn mk_box(cx: &ctxt, ty: t) -> t { mk_t(cx, ty_box(ty)) }
pub fn mk_uniq(cx: &ctxt, ty: t) -> t { mk_t(cx, ty_uniq(ty)) }
pub fn mk_ptr(cx: &ctxt, tm: mt) -> t { mk_t(cx, ty_ptr(tm)) }
@ -1901,7 +1898,7 @@ pub fn maybe_walk_ty(ty: t, f: |t| -> bool) {
match get(ty).sty {
ty_nil | ty_bot | ty_bool | ty_char | ty_int(_) | ty_uint(_) | ty_float(_) |
ty_str | ty_infer(_) | ty_param(_) | ty_unboxed_closure(_, _) | ty_err => {}
ty_box(ty) | ty_uniq(ty) | ty_vec(ty, _) | ty_open(ty) => maybe_walk_ty(ty, f),
ty_uniq(ty) | ty_vec(ty, _) | ty_open(ty) => maybe_walk_ty(ty, f),
ty_ptr(ref tm) | ty_rptr(_, ref tm) => {
maybe_walk_ty(tm.ty, f);
}
@ -2014,7 +2011,7 @@ pub fn type_is_vec(ty: t) -> bool {
match get(ty).sty {
ty_vec(..) => true,
ty_ptr(mt{ty: t, ..}) | ty_rptr(_, mt{ty: t, ..}) |
ty_box(t) | ty_uniq(t) => match get(t).sty {
ty_uniq(t) => match get(t).sty {
ty_vec(_, None) => true,
_ => false
},
@ -2067,13 +2064,6 @@ pub fn simd_size(cx: &ctxt, ty: t) -> uint {
}
}
pub fn type_is_boxed(ty: t) -> bool {
match get(ty).sty {
ty_box(_) => true,
_ => false
}
}
pub fn type_is_region_ptr(ty: t) -> bool {
match get(ty).sty {
ty_rptr(..) => true,
@ -2144,29 +2134,22 @@ pub fn type_needs_unwind_cleanup(cx: &ctxt, ty: t) -> bool {
let mut tycache = HashSet::new();
let needs_unwind_cleanup =
type_needs_unwind_cleanup_(cx, ty, &mut tycache, false);
type_needs_unwind_cleanup_(cx, ty, &mut tycache);
cx.needs_unwind_cleanup_cache.borrow_mut().insert(ty, needs_unwind_cleanup);
return needs_unwind_cleanup;
needs_unwind_cleanup
}
fn type_needs_unwind_cleanup_(cx: &ctxt, ty: t,
tycache: &mut HashSet<t>,
encountered_box: bool) -> bool {
tycache: &mut HashSet<t>) -> bool {
// Prevent infinite recursion
if !tycache.insert(ty) {
return false;
}
let mut encountered_box = encountered_box;
let mut needs_unwind_cleanup = false;
maybe_walk_ty(ty, |ty| {
let old_encountered_box = encountered_box;
let result = match get(ty).sty {
ty_box(_) => {
encountered_box = true;
true
}
ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
ty_tup(_) | ty_ptr(_) => {
true
@ -2176,33 +2159,21 @@ fn type_needs_unwind_cleanup_(cx: &ctxt, ty: t,
for aty in v.args.iter() {
let t = aty.subst(cx, substs);
needs_unwind_cleanup |=
type_needs_unwind_cleanup_(cx, t, tycache,
encountered_box);
type_needs_unwind_cleanup_(cx, t, tycache);
}
}
!needs_unwind_cleanup
}
ty_uniq(_) => {
// Once we're inside a box, the annihilator will find
// it and destroy it.
if !encountered_box {
needs_unwind_cleanup = true;
false
} else {
true
}
}
_ => {
needs_unwind_cleanup = true;
false
}
};
encountered_box = old_encountered_box;
result
});
return needs_unwind_cleanup;
needs_unwind_cleanup
}
/**
@ -2460,10 +2431,6 @@ pub fn type_contents(cx: &ctxt, ty: t) -> TypeContents {
closure_contents(cx, &**c) | TC::ReachesFfiUnsafe
}
ty_box(typ) => {
tc_ty(cx, typ, cache).managed_pointer() | TC::ReachesFfiUnsafe
}
ty_uniq(typ) => {
TC::ReachesFfiUnsafe | match get(typ).sty {
ty_str => TC::OwnsOwned,
@ -2782,7 +2749,7 @@ pub fn is_instantiable(cx: &ctxt, r_ty: t) -> bool {
ty_vec(_, None) => {
false
}
ty_box(typ) | ty_uniq(typ) | ty_open(typ) => {
ty_uniq(typ) | ty_open(typ) => {
type_requires(cx, seen, r_ty, typ)
}
ty_rptr(_, ref mt) => {
@ -3092,7 +3059,7 @@ pub fn type_is_c_like_enum(cx: &ctxt, ty: t) -> bool {
// Some types---notably unsafe ptrs---can only be dereferenced explicitly.
pub fn deref(t: t, explicit: bool) -> Option<mt> {
match get(t).sty {
ty_box(ty) | ty_uniq(ty) => {
ty_uniq(ty) => {
Some(mt {
ty: ty,
mutbl: ast::MutImmutable,
@ -3106,9 +3073,7 @@ pub fn deref(t: t, explicit: bool) -> Option<mt> {
pub fn deref_or_dont(t: t) -> t {
match get(t).sty {
ty_box(ty) | ty_uniq(ty) => {
ty
},
ty_uniq(ty) => ty,
ty_rptr(_, mt) | ty_ptr(mt) => mt.ty,
_ => t
}
@ -3124,7 +3089,7 @@ pub fn close_type(cx: &ctxt, t: t) -> t {
pub fn type_content(t: t) -> t {
match get(t).sty {
ty_box(ty) | ty_uniq(ty) => ty,
ty_uniq(ty) => ty,
ty_rptr(_, mt) |ty_ptr(mt) => mt.ty,
_ => t
}
@ -3695,14 +3660,13 @@ pub fn expr_kind(tcx: &ctxt, expr: &ast::Expr) -> ExprKind {
}
ast::ExprBox(ref place, _) => {
// Special case `Box<T>`/`Gc<T>` for now:
// Special case `Box<T>` for now:
let definition = match tcx.def_map.borrow().find(&place.id) {
Some(&def) => def,
None => fail!("no def for place"),
};
let def_id = definition.def_id();
if tcx.lang_items.exchange_heap() == Some(def_id) ||
tcx.lang_items.managed_heap() == Some(def_id) {
if tcx.lang_items.exchange_heap() == Some(def_id) {
RvalueDatumExpr
} else {
RvalueDpsExpr
@ -3753,7 +3717,6 @@ pub fn ty_sort_string(cx: &ctxt, t: t) -> String {
}
ty_enum(id, _) => format!("enum {}", item_path_str(cx, id)),
ty_box(_) => "Gc-ptr".to_string(),
ty_uniq(_) => "box".to_string(),
ty_vec(_, Some(_)) => "array".to_string(),
ty_vec(_, None) => "unsized array".to_string(),
@ -5223,19 +5186,15 @@ pub fn hash_crate_independent(tcx: &ctxt, t: t, svh: &Svh) -> u64 {
byte!(8);
did(&mut state, d);
}
ty_box(_) => {
ty_uniq(_) => {
byte!(9);
}
ty_uniq(_) => {
byte!(10);
}
ty_vec(_, Some(n)) => {
byte!(11);
byte!(10);
n.hash(&mut state);
}
ty_vec(_, None) => {
byte!(11);
0u8.hash(&mut state);
}
ty_ptr(m) => {
byte!(12);
@ -5586,7 +5545,6 @@ pub fn accumulate_lifetimes_in_type(accumulator: &mut Vec<ty::Region>,
ty_int(_) |
ty_uint(_) |
ty_float(_) |
ty_box(_) |
ty_uniq(_) |
ty_str |
ty_vec(_, _) |

View File

@ -485,9 +485,6 @@ pub fn super_fold_mt<'tcx, T: TypeFolder<'tcx>>(this: &mut T,
pub fn super_fold_sty<'tcx, T: TypeFolder<'tcx>>(this: &mut T,
sty: &ty::sty) -> ty::sty {
match *sty {
ty::ty_box(typ) => {
ty::ty_box(typ.fold_with(this))
}
ty::ty_uniq(typ) => {
ty::ty_uniq(typ.fold_with(this))
}

View File

@ -559,44 +559,6 @@ pub fn ast_ty_to_builtin_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
"not enough type parameters supplied to `Box<T>`");
Some(ty::mk_err())
}
def::DefTy(did, _) | def::DefStruct(did)
if Some(did) == this.tcx().lang_items.gc() => {
if path.segments
.iter()
.flat_map(|s| s.types.iter())
.count() > 1 {
span_err!(this.tcx().sess, path.span, E0048,
"`Gc` has only one type parameter");
}
for inner_ast_type in path.segments
.iter()
.flat_map(|s| s.types.iter()) {
return Some(mk_pointer(this,
rscope,
ast::MutImmutable,
&**inner_ast_type,
Box,
|typ| {
match ty::get(typ).sty {
ty::ty_str => {
span_err!(this.tcx().sess, path.span, E0114,
"`Gc<str>` is not a type");
ty::mk_err()
}
ty::ty_vec(_, None) => {
span_err!(this.tcx().sess, path.span, E0115,
"`Gc<[T]>` is not a type");
ty::mk_err()
}
_ => ty::mk_box(this.tcx(), typ),
}
}))
}
this.tcx().sess.span_bug(path.span,
"not enough type parameters \
supplied to `Gc<T>`")
}
_ => None
}
}
@ -606,7 +568,6 @@ pub fn ast_ty_to_builtin_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
#[deriving(Show)]
enum PointerTy {
Box,
RPtr(ty::Region),
Uniq
}
@ -614,7 +575,6 @@ enum PointerTy {
impl PointerTy {
fn default_region(&self) -> ty::Region {
match *self {
Box => ty::ReStatic,
Uniq => ty::ReStatic,
RPtr(r) => r,
}
@ -702,14 +662,6 @@ fn mk_pointer<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
r,
ty::mt {mutbl: a_seq_mutbl, ty: tr});
}
_ => {
tcx.sess.span_err(
a_seq_ty.span,
"~trait or &trait are the only supported \
forms of casting-to-trait");
return ty::mk_err();
}
}
}
ast::TyPath(ref path, ref opt_bounds, id) => {
@ -726,11 +678,6 @@ fn mk_pointer<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
RPtr(r) => {
return ty::mk_str_slice(tcx, r, ast::MutImmutable);
}
_ => {
tcx.sess
.span_err(path.span,
"managed strings are not supported")
}
}
}
Some(&def::DefTrait(trait_def_id)) => {
@ -767,13 +714,6 @@ fn mk_pointer<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
RPtr(r) => {
return ty::mk_rptr(tcx, r, ty::mt{mutbl: a_seq_mutbl, ty: tr});
}
_ => {
tcx.sess.span_err(
path.span,
"~trait or &trait are the only supported \
forms of casting-to-trait");
return ty::mk_err();
}
};
}
_ => {}
@ -856,10 +796,6 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
match ast_ty.node {
ast::TyNil => ty::mk_nil(),
ast::TyBot => ty::mk_bot(),
ast::TyBox(ref ty) => {
mk_pointer(this, rscope, ast::MutImmutable, &**ty, Box,
|ty| ty::mk_box(tcx, ty))
}
ast::TyUniq(ref ty) => {
mk_pointer(this, rscope, ast::MutImmutable, &**ty, Uniq,
|ty| ty::mk_uniq(tcx, ty))

View File

@ -1094,7 +1094,7 @@ impl<'a, 'tcx> LookupContext<'a, 'tcx> {
let tcx = self.tcx();
match ty::get(self_ty).sty {
ty_bare_fn(..) | ty_box(..) | ty_uniq(..) | ty_rptr(..) |
ty_bare_fn(..) | ty_uniq(..) | ty_rptr(..) |
ty_infer(IntVar(_)) |
ty_infer(FloatVar(_)) |
ty_param(..) | ty_nil | ty_bot | ty_bool |

View File

@ -1468,7 +1468,7 @@ fn check_cast(fcx: &FnCtxt,
// casts to scalars other than `char` and `bare fn` are trivial
let t_1_is_trivial = t_1_is_scalar && !t_1_is_char && !t_1_is_bare_fn;
if ty::type_is_c_like_enum(fcx.tcx(), t_e) && t_1_is_trivial {
if t_1_is_float {
if t_1_is_float || ty::type_is_unsafe_ptr(t_1) {
fcx.type_error_message(span, |actual| {
format!("illegal cast; cast through an \
integer first: `{}` as `{}`",
@ -3820,12 +3820,6 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
if tcx.lang_items.exchange_heap() == Some(def_id) {
fcx.write_ty(id, ty::mk_uniq(tcx, referent_ty));
checked = true
} else if tcx.lang_items.managed_heap() == Some(def_id) {
fcx.register_region_obligation(infer::Managed(expr.span),
referent_ty,
ty::ReStatic);
fcx.write_ty(id, ty::mk_box(tcx, referent_ty));
checked = true
}
}
_ => {}
@ -3881,8 +3875,8 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
ast::ExprUnary(unop, ref oprnd) => {
let expected_inner = expected.map(fcx, |sty| {
match unop {
ast::UnBox | ast::UnUniq => match *sty {
ty::ty_box(ty) | ty::ty_uniq(ty) => {
ast::UnUniq => match *sty {
ty::ty_uniq(ty) => {
ExpectHasType(ty)
}
_ => {
@ -3907,11 +3901,6 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
if !ty::type_is_error(oprnd_t) {
match unop {
ast::UnBox => {
if !ty::type_is_bot(oprnd_t) {
oprnd_t = ty::mk_box(tcx, oprnd_t)
}
}
ast::UnUniq => {
if !ty::type_is_bot(oprnd_t) {
oprnd_t = ty::mk_uniq(tcx, oprnd_t);

View File

@ -663,14 +663,6 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) {
visit::walk_expr(rcx, expr);
}
ast::ExprUnary(ast::UnBox, ref base) => {
// Managed data must not have borrowed pointers within it:
let base_ty = rcx.resolve_node_type(base.id);
type_must_outlive(rcx, infer::Managed(expr.span),
base_ty, ty::ReStatic);
visit::walk_expr(rcx, expr);
}
ast::ExprUnary(ast::UnDeref, ref base) => {
// For *a, the lifetime of a must enclose the deref
let method_call = MethodCall::expr(expr.id);
@ -1474,7 +1466,6 @@ fn link_region(rcx: &Rcx,
mc::cat_discr(cmt_base, _) |
mc::cat_downcast(cmt_base) |
mc::cat_deref(cmt_base, _, mc::GcPtr(..)) |
mc::cat_deref(cmt_base, _, mc::OwnedPtr) |
mc::cat_interior(cmt_base, _) => {
// Borrowing interior or owned data requires the base
@ -1707,7 +1698,6 @@ fn adjust_upvar_borrow_kind_for_mut(rcx: &Rcx,
}
mc::cat_deref(_, _, mc::UnsafePtr(..)) |
mc::cat_deref(_, _, mc::GcPtr) |
mc::cat_static_item |
mc::cat_rvalue(_) |
mc::cat_copied_upvar(_) |
@ -1758,7 +1748,6 @@ fn adjust_upvar_borrow_kind_for_unique(rcx: &Rcx, cmt: mc::cmt) {
}
mc::cat_deref(_, _, mc::UnsafePtr(..)) |
mc::cat_deref(_, _, mc::GcPtr) |
mc::cat_static_item |
mc::cat_rvalue(_) |
mc::cat_copied_upvar(_) |

View File

@ -129,7 +129,6 @@ impl<'a, 'tcx> Wf<'a, 'tcx> {
ty::ty_vec(t, _) |
ty::ty_ptr(ty::mt { ty: t, .. }) |
ty::ty_box(t) |
ty::ty_uniq(t) => {
self.accumulate_from_ty(t)
}

View File

@ -95,7 +95,7 @@ pub fn check_object_cast(fcx: &FnCtxt,
}
}
// Because we currently give unsound lifetimes to the "ty_box", I
// Because we currently give unsound lifetimes to the "t_box", I
// could have written &'static ty::TyTrait here, but it seems
// gratuitously unsafe.
fn object_trait<'a>(t: &'a ty::t) -> &'a ty::TyTrait {

View File

@ -23,7 +23,7 @@ use middle::subst::{Substs};
use middle::ty::get;
use middle::ty::{ImplContainer, ImplOrTraitItemId, MethodTraitItemId};
use middle::ty::{TypeTraitItemId, lookup_item_type};
use middle::ty::{t, ty_bool, ty_char, ty_bot, ty_box, ty_enum, ty_err};
use middle::ty::{t, ty_bool, ty_char, ty_bot, ty_enum, ty_err};
use middle::ty::{ty_str, ty_vec, ty_float, ty_infer, ty_int, ty_nil, ty_open};
use middle::ty::{ty_param, Polytype, ty_ptr};
use middle::ty::{ty_rptr, ty_struct, ty_trait, ty_tup};
@ -84,8 +84,8 @@ fn get_base_type(inference_context: &InferCtxt,
ty_nil | ty_bot | ty_bool | ty_char | ty_int(..) | ty_uint(..) | ty_float(..) |
ty_str(..) | ty_vec(..) | ty_bare_fn(..) | ty_closure(..) | ty_tup(..) |
ty_infer(..) | ty_param(..) | ty_err | ty_open(..) |
ty_box(_) | ty_uniq(_) | ty_ptr(_) | ty_rptr(_, _) => {
ty_infer(..) | ty_param(..) | ty_err | ty_open(..) | ty_uniq(_) |
ty_ptr(_) | ty_rptr(_, _) => {
debug!("(getting base type) no base type; found {:?}",
get(original_type).sty);
None

View File

@ -258,7 +258,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
let r_borrow = self.get_ref().infcx.next_region_var(coercion);
let inner_ty = match *sty_a {
ty::ty_box(_) | ty::ty_uniq(_) => return Err(ty::terr_mismatch),
ty::ty_uniq(_) => return Err(ty::terr_mismatch),
ty::ty_rptr(_, mt_a) => mt_a.ty,
_ => {
return self.subtype(a, b);

View File

@ -495,10 +495,6 @@ pub fn super_tys<'tcx, C: Combine<'tcx>>(this: &C, a: ty::t, b: ty::t) -> cres<t
Ok(ty::mk_unboxed_closure(tcx, a_id, region))
}
(&ty::ty_box(a_inner), &ty::ty_box(b_inner)) => {
this.tys(a_inner, b_inner).and_then(|typ| Ok(ty::mk_box(tcx, typ)))
}
(&ty::ty_uniq(a_inner), &ty::ty_uniq(b_inner)) => {
let typ = try!(this.tys(a_inner, b_inner));
check_ptr_to_unsized(this, a, b, a_inner, b_inner, ty::mk_uniq(tcx, typ))

View File

@ -776,11 +776,6 @@ impl<'a, 'tcx> ErrorReporting for InferCtxt<'a, 'tcx> {
sup,
"");
}
infer::Managed(span) => {
self.tcx.sess.span_err(
span,
format!("cannot put borrowed references into managed memory").as_slice());
}
}
}
@ -1285,7 +1280,6 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> {
ast::TyPtr(ref mut_ty) => {
ty_queue.push(&*mut_ty.ty);
}
ast::TyBox(ref ty) |
ast::TyVec(ref ty) |
ast::TyUniq(ref ty) |
ast::TyFixedLengthVec(ref ty, _) => {
@ -1323,7 +1317,6 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> {
ty: build_to(mut_ty.ty, to),
})
}
ast::TyBox(ty) => ast::TyBox(build_to(ty, to)),
ast::TyVec(ty) => ast::TyVec(build_to(ty, to)),
ast::TyUniq(ty) => ast::TyUniq(build_to(ty, to)),
ast::TyFixedLengthVec(ty, e) => {
@ -1614,11 +1607,6 @@ impl<'a, 'tcx> ErrorReportingHelpers for InferCtxt<'a, 'tcx> {
does not outlive the data it points at",
self.ty_to_string(ty)).as_slice());
}
infer::Managed(span) => {
self.tcx.sess.span_note(
span,
"...so that the value can be stored in managed memory.");
}
infer::RelateParamBound(span, param_ty, t) => {
self.tcx.sess.span_note(
span,

View File

@ -216,9 +216,6 @@ pub enum SubregionOrigin {
// An auto-borrow that does not enclose the expr where it occurs
AutoBorrow(Span),
// Managed data cannot contain borrowed pointers.
Managed(Span),
}
/// Reasons to create a region inference variable
@ -1029,7 +1026,6 @@ impl SubregionOrigin {
CallReturn(a) => a,
AddrOf(a) => a,
AutoBorrow(a) => a,
Managed(a) => a,
}
}
}
@ -1102,7 +1098,6 @@ impl Repr for SubregionOrigin {
CallReturn(a) => format!("CallReturn({})", a.repr(tcx)),
AddrOf(a) => format!("AddrOf({})", a.repr(tcx)),
AutoBorrow(a) => format!("AutoBorrow({})", a.repr(tcx)),
Managed(a) => format!("Managed({})", a.repr(tcx)),
}
}
}

View File

@ -143,7 +143,6 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TypeSkolemizer<'a, 'tcx> {
ty::ty_uint(..) |
ty::ty_float(..) |
ty::ty_enum(..) |
ty::ty_box(..) |
ty::ty_uniq(..) |
ty::ty_str |
ty::ty_err |

View File

@ -742,7 +742,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
self.add_constraints_from_mt(mt, variance);
}
ty::ty_uniq(typ) | ty::ty_box(typ) | ty::ty_vec(typ, _) | ty::ty_open(typ) => {
ty::ty_uniq(typ) | ty::ty_vec(typ, _) | ty::ty_open(typ) => {
self.add_constraints_from_ty(typ, variance);
}

View File

@ -17,7 +17,7 @@ use middle::ty::{ReEarlyBound, BrFresh, ctxt};
use middle::ty::{ReFree, ReScope, ReInfer, ReStatic, Region, ReEmpty};
use middle::ty::{ReSkolemized, ReVar};
use middle::ty::{mt, t, ParamTy};
use middle::ty::{ty_bool, ty_char, ty_bot, ty_box, ty_struct, ty_enum};
use middle::ty::{ty_bool, ty_char, ty_bot, ty_struct, ty_enum};
use middle::ty::{ty_err, ty_str, ty_vec, ty_float, ty_bare_fn, ty_closure};
use middle::ty::{ty_nil, ty_param, ty_ptr, ty_rptr, ty_tup, ty_open};
use middle::ty::{ty_unboxed_closure};
@ -375,7 +375,6 @@ pub fn ty_to_string(cx: &ctxt, typ: t) -> String {
ty_int(t) => ast_util::int_ty_to_string(t, None).to_string(),
ty_uint(t) => ast_util::uint_ty_to_string(t, None).to_string(),
ty_float(t) => ast_util::float_ty_to_string(t).to_string(),
ty_box(typ) => format!("Gc<{}>", ty_to_string(cx, typ)),
ty_uniq(typ) => format!("Box<{}>", ty_to_string(cx, typ)),
ty_ptr(ref tm) => {
format!("*{} {}", match tm.mutbl {

View File

@ -1087,7 +1087,6 @@ pub enum Type {
/// aka TyBot
Bottom,
Unique(Box<Type>),
Managed(Box<Type>),
RawPointer(Mutability, Box<Type>),
BorrowedRef {
pub lifetime: Option<Lifetime>,
@ -1215,7 +1214,6 @@ impl Clean<Type> for ast::Ty {
TyRptr(ref l, ref m) =>
BorrowedRef {lifetime: l.clean(cx), mutability: m.mutbl.clean(cx),
type_: box m.ty.clean(cx)},
TyBox(ref ty) => Managed(box ty.clean(cx)),
TyUniq(ref ty) => Unique(box ty.clean(cx)),
TyVec(ref ty) => Vector(box ty.clean(cx)),
TyFixedLengthVec(ref ty, ref e) => FixedVector(box ty.clean(cx),
@ -1254,12 +1252,6 @@ impl Clean<Type> for ty::t {
ty::ty_float(ast::TyF32) => Primitive(F32),
ty::ty_float(ast::TyF64) => Primitive(F64),
ty::ty_str => Primitive(Str),
ty::ty_box(t) => {
let gc_did = cx.tcx_opt().and_then(|tcx| {
tcx.lang_items.gc()
});
lang_struct(cx, gc_did, t, "Gc", Managed)
}
ty::ty_uniq(t) => {
let box_did = cx.tcx_opt().and_then(|tcx| {
tcx.lang_items.owned_box()

View File

@ -476,7 +476,7 @@ impl fmt::Show for clean::Type {
};
write!(f, "&amp;{}{}{}", lt, MutableSpace(mutability), **ty)
}
clean::Unique(..) | clean::Managed(..) => {
clean::Unique(..) => {
fail!("should have been cleaned")
}
}

View File

@ -15,7 +15,7 @@
#![crate_type = "dylib"]
#![crate_type = "rlib"]
#![feature(globs, struct_variant, managed_boxes, macro_rules, phase)]
#![feature(globs, struct_variant, macro_rules, phase)]
extern crate arena;
extern crate debug;

View File

@ -16,7 +16,7 @@
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
html_root_url = "http://doc.rust-lang.org/master/")]
#![feature(macro_rules, phase, globs, thread_local, managed_boxes, asm)]
#![feature(macro_rules, phase, globs, thread_local, asm)]
#![feature(linkage, lang_items, unsafe_destructor, default_type_params)]
#![feature(import_shadowing)]
#![no_std]
@ -57,7 +57,6 @@ pub mod c_str;
pub mod exclusive;
pub mod local;
pub mod local_data;
pub mod local_heap;
pub mod mutex;
pub mod rtio;
pub mod stack;
@ -104,9 +103,8 @@ pub static DEFAULT_ERROR_CODE: int = 101;
/// One-time runtime initialization.
///
/// Initializes global state, including frobbing
/// the crate's logging flags, registering GC
/// metadata, and storing the process arguments.
/// Initializes global state, including frobbing the crate's logging flags,
/// and storing the process arguments.
pub fn init(argc: int, argv: *const *const u8) {
// FIXME: Derefing these pointers is not safe.
// Need to propagate the unsafety to `start`.

View File

@ -411,7 +411,6 @@ mod tests {
extern crate test;
use std::prelude::*;
use std::gc::{Gc, GC};
use super::*;
use std::task;
@ -467,11 +466,11 @@ mod tests {
#[test]
fn test_tls_multiple_types() {
static str_key: Key<String> = &KeyValueKey;
static box_key: Key<Gc<()>> = &KeyValueKey;
static box_key: Key<Box<int>> = &KeyValueKey;
static int_key: Key<int> = &KeyValueKey;
task::spawn(proc() {
str_key.replace(Some("string data".to_string()));
box_key.replace(Some(box(GC) ()));
box_key.replace(Some(box 0));
int_key.replace(Some(42));
});
}
@ -479,13 +478,13 @@ mod tests {
#[test]
fn test_tls_overwrite_multiple_types() {
static str_key: Key<String> = &KeyValueKey;
static box_key: Key<Gc<()>> = &KeyValueKey;
static box_key: Key<Box<int>> = &KeyValueKey;
static int_key: Key<int> = &KeyValueKey;
task::spawn(proc() {
str_key.replace(Some("string data".to_string()));
str_key.replace(Some("string data 2".to_string()));
box_key.replace(Some(box(GC) ()));
box_key.replace(Some(box(GC) ()));
box_key.replace(Some(box 0));
box_key.replace(Some(box 1));
int_key.replace(Some(42));
// This could cause a segfault if overwriting-destruction is done
// with the crazy polymorphic transmute rather than the provided
@ -498,13 +497,13 @@ mod tests {
#[should_fail]
fn test_tls_cleanup_on_failure() {
static str_key: Key<String> = &KeyValueKey;
static box_key: Key<Gc<()>> = &KeyValueKey;
static box_key: Key<Box<int>> = &KeyValueKey;
static int_key: Key<int> = &KeyValueKey;
str_key.replace(Some("parent data".to_string()));
box_key.replace(Some(box(GC) ()));
box_key.replace(Some(box 0));
task::spawn(proc() {
str_key.replace(Some("string data".to_string()));
box_key.replace(Some(box(GC) ()));
box_key.replace(Some(box 2));
int_key.replace(Some(42));
fail!();
});

View File

@ -1,345 +0,0 @@
// Copyright 2013 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.
//! The local, garbage collected heap
use core::prelude::*;
use alloc::libc_heap;
use alloc::util;
use libc::{c_void, free};
use core::mem;
use core::ptr;
use core::raw;
use local::Local;
use task::Task;
static RC_IMMORTAL : uint = 0x77777777;
pub type Box = raw::GcBox<()>;
pub struct MemoryRegion {
live_allocations: uint,
}
pub struct LocalHeap {
memory_region: MemoryRegion,
live_allocs: *mut raw::GcBox<()>,
}
impl LocalHeap {
pub fn new() -> LocalHeap {
LocalHeap {
memory_region: MemoryRegion { live_allocations: 0 },
live_allocs: ptr::null_mut(),
}
}
#[inline]
#[allow(deprecated)]
pub fn alloc(&mut self,
drop_glue: fn(*mut u8),
size: uint,
align: uint) -> *mut Box {
let total_size = util::get_box_size(size, align);
let alloc = self.memory_region.malloc(total_size);
{
// Make sure that we can't use `mybox` outside of this scope
let mybox: &mut Box = unsafe { mem::transmute(alloc) };
// Clear out this box, and move it to the front of the live
// allocations list
mybox.drop_glue = drop_glue;
mybox.ref_count = 1;
mybox.prev = ptr::null_mut();
mybox.next = self.live_allocs;
if !self.live_allocs.is_null() {
unsafe { (*self.live_allocs).prev = alloc; }
}
self.live_allocs = alloc;
}
return alloc;
}
#[inline]
pub fn realloc(&mut self, ptr: *mut Box, size: uint) -> *mut Box {
// Make sure that we can't use `mybox` outside of this scope
let total_size = size + mem::size_of::<Box>();
let new_box = self.memory_region.realloc(ptr, total_size);
{
// Fix links because we could have moved around
let mybox: &mut Box = unsafe { mem::transmute(new_box) };
if !mybox.prev.is_null() {
unsafe { (*mybox.prev).next = new_box; }
}
if !mybox.next.is_null() {
unsafe { (*mybox.next).prev = new_box; }
}
}
if self.live_allocs == ptr {
self.live_allocs = new_box;
}
return new_box;
}
#[inline]
pub fn free(&mut self, alloc: *mut Box) {
{
// Make sure that we can't use `mybox` outside of this scope
let mybox: &mut Box = unsafe { mem::transmute(alloc) };
// Unlink it from the linked list
if !mybox.prev.is_null() {
unsafe { (*mybox.prev).next = mybox.next; }
}
if !mybox.next.is_null() {
unsafe { (*mybox.next).prev = mybox.prev; }
}
if self.live_allocs == alloc {
self.live_allocs = mybox.next;
}
}
self.memory_region.free(alloc);
}
/// Immortalize all pending allocations, forcing them to live forever.
///
/// This function will freeze all allocations to prevent all pending
/// allocations from being deallocated. This is used in preparation for when
/// a task is about to destroy TLD.
pub unsafe fn immortalize(&mut self) {
let mut n_total_boxes = 0u;
// Pass 1: Make all boxes immortal.
//
// In this pass, nothing gets freed, so it does not matter whether
// we read the next field before or after the callback.
self.each_live_alloc(true, |_, alloc| {
n_total_boxes += 1;
(*alloc).ref_count = RC_IMMORTAL;
});
if debug_mem() {
// We do logging here w/o allocation.
rterrln!("total boxes annihilated: {}", n_total_boxes);
}
}
/// Continues deallocation of the all pending allocations in this arena.
///
/// This is invoked from the destructor, and requires that `immortalize` has
/// been called previously.
unsafe fn annihilate(&mut self) {
// Pass 2: Drop all boxes.
//
// In this pass, unique-managed boxes may get freed, but not
// managed boxes, so we must read the `next` field *after* the
// callback, as the original value may have been freed.
self.each_live_alloc(false, |_, alloc| {
let drop_glue = (*alloc).drop_glue;
let data = &mut (*alloc).data as *mut ();
drop_glue(data as *mut u8);
});
// Pass 3: Free all boxes.
//
// In this pass, managed boxes may get freed (but not
// unique-managed boxes, though I think that none of those are
// left), so we must read the `next` field before, since it will
// not be valid after.
self.each_live_alloc(true, |me, alloc| {
me.free(alloc);
});
}
unsafe fn each_live_alloc(&mut self, read_next_before: bool,
f: |&mut LocalHeap, alloc: *mut raw::GcBox<()>|) {
//! Walks the internal list of allocations
let mut alloc = self.live_allocs;
while alloc != ptr::null_mut() {
let next_before = (*alloc).next;
f(self, alloc);
if read_next_before {
alloc = next_before;
} else {
alloc = (*alloc).next;
}
}
}
}
impl Drop for LocalHeap {
fn drop(&mut self) {
unsafe { self.annihilate() }
assert!(self.live_allocs.is_null());
}
}
struct AllocHeader;
impl AllocHeader {
fn init(&mut self, _size: u32) {}
fn assert_sane(&self) {}
fn update_size(&mut self, _size: u32) {}
fn as_box(&mut self) -> *mut Box {
let myaddr: uint = unsafe { mem::transmute(self) };
(myaddr + AllocHeader::size()) as *mut Box
}
fn size() -> uint {
// For some platforms, 16 byte alignment is required.
let ptr_size = 16;
let header_size = mem::size_of::<AllocHeader>();
return (header_size + ptr_size - 1) / ptr_size * ptr_size;
}
fn from(a_box: *mut Box) -> *mut AllocHeader {
(a_box as uint - AllocHeader::size()) as *mut AllocHeader
}
}
#[cfg(unix)]
fn debug_mem() -> bool {
// FIXME: Need to port the environment struct to newsched
false
}
#[cfg(windows)]
fn debug_mem() -> bool {
false
}
impl MemoryRegion {
#[inline]
fn malloc(&mut self, size: uint) -> *mut Box {
let total_size = size + AllocHeader::size();
let alloc: *mut AllocHeader = unsafe {
libc_heap::malloc_raw(total_size) as *mut AllocHeader
};
let alloc: &mut AllocHeader = unsafe { mem::transmute(alloc) };
alloc.init(size as u32);
self.claim(alloc);
self.live_allocations += 1;
return alloc.as_box();
}
#[inline]
fn realloc(&mut self, alloc: *mut Box, size: uint) -> *mut Box {
rtassert!(!alloc.is_null());
let orig_alloc = AllocHeader::from(alloc);
unsafe { (*orig_alloc).assert_sane(); }
let total_size = size + AllocHeader::size();
let alloc: *mut AllocHeader = unsafe {
libc_heap::realloc_raw(orig_alloc as *mut u8, total_size) as *mut AllocHeader
};
let alloc: &mut AllocHeader = unsafe { mem::transmute(alloc) };
alloc.assert_sane();
alloc.update_size(size as u32);
self.update(alloc, orig_alloc as *mut AllocHeader);
return alloc.as_box();
}
#[inline]
fn free(&mut self, alloc: *mut Box) {
rtassert!(!alloc.is_null());
let alloc = AllocHeader::from(alloc);
unsafe {
(*alloc).assert_sane();
self.release(mem::transmute(alloc));
rtassert!(self.live_allocations > 0);
self.live_allocations -= 1;
free(alloc as *mut c_void)
}
}
#[inline]
fn claim(&mut self, _alloc: &mut AllocHeader) {}
#[inline]
fn release(&mut self, _alloc: &AllocHeader) {}
#[inline]
fn update(&mut self, _alloc: &mut AllocHeader, _orig: *mut AllocHeader) {}
}
impl Drop for MemoryRegion {
fn drop(&mut self) {
if self.live_allocations != 0 {
rtabort!("leaked managed memory ({} objects)", self.live_allocations);
}
}
}
#[cfg(not(test))]
#[lang="malloc"]
#[inline]
pub unsafe fn local_malloc_(drop_glue: fn(*mut u8), size: uint,
align: uint) -> *mut u8 {
local_malloc(drop_glue, size, align)
}
#[inline]
pub unsafe fn local_malloc(drop_glue: fn(*mut u8), size: uint,
align: uint) -> *mut u8 {
// FIXME: Unsafe borrow for speed. Lame.
let task: Option<*mut Task> = Local::try_unsafe_borrow();
match task {
Some(task) => {
(*task).heap.alloc(drop_glue, size, align) as *mut u8
}
None => rtabort!("local malloc outside of task")
}
}
#[cfg(not(test))]
#[lang="free"]
#[inline]
pub unsafe fn local_free_(ptr: *mut u8) {
local_free(ptr)
}
// NB: Calls to free CANNOT be allowed to fail, as throwing an exception from
// inside a landing pad may corrupt the state of the exception handler. If a
// problem occurs, call exit instead.
#[inline]
pub unsafe fn local_free(ptr: *mut u8) {
// FIXME: Unsafe borrow for speed. Lame.
let task_ptr: Option<*mut Task> = Local::try_unsafe_borrow();
match task_ptr {
Some(task) => {
(*task).heap.free(ptr as *mut Box)
}
None => rtabort!("local free outside of task")
}
}
#[cfg(test)]
mod bench {
extern crate test;
use self::test::Bencher;
use std::gc::GC;
#[bench]
fn alloc_managed_small(b: &mut Bencher) {
b.iter(|| { box(GC) 10i });
}
#[bench]
fn alloc_managed_big(b: &mut Bencher) {
b.iter(|| { box(GC) ([10i, ..1000]) });
}
}

View File

@ -9,9 +9,8 @@
// except according to those terms.
//! Language-level runtime services that should reasonably expected
//! to be available 'everywhere'. Local heaps, GC, unwinding,
//! local storage, and logging. Even a 'freestanding' Rust would likely want
//! to implement this.
//! to be available 'everywhere'. Unwinding, local storage, and logging.
//! Even a 'freestanding' Rust would likely want to implement this.
use alloc::arc::Arc;
use alloc::boxed::{BoxAny, Box};
@ -27,7 +26,6 @@ use core::raw;
use local_data;
use Runtime;
use local::Local;
use local_heap::LocalHeap;
use rtio::LocalIo;
use unwind;
use unwind::Unwinder;
@ -95,8 +93,6 @@ use collections::str::SendStr;
/// # }
/// ```
pub struct Task {
pub heap: LocalHeap,
pub gc: GarbageCollector,
pub storage: LocalStorage,
pub unwinder: Unwinder,
pub death: Death,
@ -132,7 +128,6 @@ pub struct TaskOpts {
/// children tasks complete, recommend using a result future.
pub type Result = ::core::result::Result<(), Box<Any + Send>>;
pub struct GarbageCollector;
pub struct LocalStorage(pub Option<local_data::Map>);
/// A handle to a blocked task. Usually this means having the Box<Task>
@ -163,8 +158,6 @@ impl Task {
/// task creation functions through libnative or libgreen.
pub fn new() -> Task {
Task {
heap: LocalHeap::new(),
gc: GarbageCollector,
storage: LocalStorage(None),
unwinder: Unwinder::new(),
death: Death::new(),
@ -264,32 +257,22 @@ impl Task {
/// already been destroyed and/or annihilated.
fn cleanup(self: Box<Task>, result: Result) -> Box<Task> {
// The first thing to do when cleaning up is to deallocate our local
// resources, such as TLD and GC data.
// resources, such as TLD.
//
// FIXME: there are a number of problems with this code
//
// 1. If any TLD object fails destruction, then all of TLD will leak.
// This appears to be a consequence of #14875.
//
// 2. Failing during GC annihilation aborts the runtime #14876.
// 2. Setting a TLD key while destroying TLD will abort the runtime #14807.
//
// 3. Setting a TLD key while destroying TLD or while destroying GC will
// abort the runtime #14807.
//
// 4. Invoking GC in GC destructors will abort the runtime #6996.
//
// 5. The order of destruction of TLD and GC matters, but either way is
// susceptible to leaks (see 3/4) #8302.
// 3. The order of destruction of TLD matters, but either way is
// susceptible to leaks (see 2) #8302.
//
// That being said, there are a few upshots to this code
//
// 1. If TLD destruction fails, heap destruction will be attempted.
// There is a test for this at fail-during-tld-destroy.rs. Sadly the
// other way can't be tested due to point 2 above. Note that we must
// immortalize the heap first because if any deallocations are
// attempted while TLD is being dropped it will attempt to free the
// allocation from the wrong heap (because the current one has been
// replaced).
// There is a test for this at fail-during-tld-destroy.rs.
//
// 2. One failure in destruction is tolerable, so long as the task
// didn't originally fail while it was running.
@ -301,15 +284,10 @@ impl Task {
let &LocalStorage(ref mut optmap) = &mut task.storage;
optmap.take()
};
let mut heap = mem::replace(&mut task.heap, LocalHeap::new());
unsafe { heap.immortalize() }
drop(task);
// First, destroy task-local storage. This may run user dtors.
drop(tld);
// Destroy remaining boxes. Also may run user dtors.
drop(heap);
});
// If the above `run` block failed, then it must be the case that the
@ -327,9 +305,8 @@ impl Task {
Local::put(task);
// FIXME: this is running in a seriously constrained context. If this
// allocates GC or allocates TLD then it will likely abort the
// runtime. Similarly, if this fails, this will also likely abort
// the runtime.
// allocates TLD then it will likely abort the runtime. Similarly,
// if this fails, this will also likely abort the runtime.
//
// This closure is currently limited to a channel send via the
// standard library's task interface, but this needs
@ -577,23 +554,14 @@ mod test {
use super::*;
use std::prelude::*;
use std::task;
use std::gc::{Gc, GC};
#[test]
fn local_heap() {
let a = box(GC) 5i;
let b = a;
assert!(*a == 5);
assert!(*b == 5);
}
#[test]
fn tls() {
local_data_key!(key: Gc<String>)
key.replace(Some(box(GC) "data".to_string()));
local_data_key!(key: String)
key.replace(Some("data".to_string()));
assert_eq!(key.get().unwrap().as_slice(), "data");
local_data_key!(key2: Gc<String>)
key2.replace(Some(box(GC) "data".to_string()));
local_data_key!(key2: String)
key2.replace(Some("data".to_string()));
assert_eq!(key2.get().unwrap().as_slice(), "data");
}
@ -628,23 +596,6 @@ mod test {
assert!(rx.recv() == 10);
}
#[test]
fn heap_cycles() {
use std::cell::RefCell;
struct List {
next: Option<Gc<RefCell<List>>>,
}
let a = box(GC) RefCell::new(List { next: None });
let b = box(GC) RefCell::new(List { next: Some(a) });
{
let mut a = a.borrow_mut();
a.next = Some(b);
}
}
#[test]
#[should_fail]
fn test_begin_unwind() {

View File

@ -23,7 +23,7 @@ Core encoding and decoding interfaces.
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
html_root_url = "http://doc.rust-lang.org/master/",
html_playground_url = "http://play.rust-lang.org/")]
#![feature(macro_rules, managed_boxes, default_type_params, phase)]
#![feature(macro_rules, default_type_params, phase)]
// test harness access
#[cfg(test)]

View File

@ -16,7 +16,6 @@ Core encoding and decoding interfaces.
use std::path;
use std::rc::Rc;
use std::gc::{Gc, GC};
use std::cell::{Cell, RefCell};
pub trait Encoder<E> {
@ -392,12 +391,6 @@ impl<E, D:Decoder<E>,T:Decodable<D, E>> Decodable<D, E> for Box<T> {
}
}
impl<E, S:Encoder<E>,T:'static + Encodable<S, E>> Encodable<S, E> for Gc<T> {
fn encode(&self, s: &mut S) -> Result<(), E> {
(**self).encode(s)
}
}
impl<E, S:Encoder<E>,T:Encodable<S, E>> Encodable<S, E> for Rc<T> {
#[inline]
fn encode(&self, s: &mut S) -> Result<(), E> {
@ -412,12 +405,6 @@ impl<E, D:Decoder<E>,T:Decodable<D, E>> Decodable<D, E> for Rc<T> {
}
}
impl<E, D:Decoder<E>,T:Decodable<D, E> + 'static> Decodable<D, E> for Gc<T> {
fn decode(d: &mut D) -> Result<Gc<T>, E> {
Ok(box(GC) try!(Decodable::decode(d)))
}
}
impl<'a, E, S:Encoder<E>,T:Encodable<S, E>> Encodable<S, E> for &'a [T] {
fn encode(&self, s: &mut S) -> Result<(), E> {
s.emit_seq(self.len(), |s| {

View File

@ -1,156 +0,0 @@
// Copyright 2013 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.
/*! Task-local garbage-collected boxes
The `Gc` type provides shared ownership of an immutable value. Destruction is not deterministic, and
will occur some time between every `Gc` handle being gone and the end of the task. The garbage
collector is task-local so `Gc<T>` is not sendable.
*/
#![experimental]
#![allow(experimental)]
use clone::Clone;
use cmp::{Ord, PartialOrd, Ordering, Eq, PartialEq};
use default::Default;
use fmt;
use hash;
use kinds::marker;
use option::Option;
use ops::Deref;
use raw;
/// Immutable garbage-collected pointer type
#[lang="gc"]
#[experimental = "Gc is currently based on reference-counting and will not collect cycles until \
task annihilation. For now, cycles need to be broken manually by using `Rc<T>` \
with a non-owning `Weak<T>` pointer. A tracing garbage collector is planned."]
pub struct Gc<T> {
_ptr: *mut T,
marker: marker::NoSend,
}
#[unstable]
impl<T> Clone for Gc<T> {
/// Clone the pointer only
#[inline]
fn clone(&self) -> Gc<T> { *self }
}
/// An value that represents the task-local managed heap.
///
/// Use this like `let foo = box(GC) Bar::new(...);`
#[lang="managed_heap"]
#[cfg(not(test))]
pub static GC: () = ();
impl<T: PartialEq + 'static> PartialEq for Gc<T> {
#[inline]
fn eq(&self, other: &Gc<T>) -> bool { *(*self) == *(*other) }
#[inline]
fn ne(&self, other: &Gc<T>) -> bool { *(*self) != *(*other) }
}
impl<T: PartialOrd + 'static> PartialOrd for Gc<T> {
#[inline]
fn partial_cmp(&self, other: &Gc<T>) -> Option<Ordering> {
(**self).partial_cmp(&**other)
}
#[inline]
fn lt(&self, other: &Gc<T>) -> bool { *(*self) < *(*other) }
#[inline]
fn le(&self, other: &Gc<T>) -> bool { *(*self) <= *(*other) }
#[inline]
fn ge(&self, other: &Gc<T>) -> bool { *(*self) >= *(*other) }
#[inline]
fn gt(&self, other: &Gc<T>) -> bool { *(*self) > *(*other) }
}
impl<T: Ord + 'static> Ord for Gc<T> {
#[inline]
fn cmp(&self, other: &Gc<T>) -> Ordering { (**self).cmp(&**other) }
}
impl<T: Eq + 'static> Eq for Gc<T> {}
impl<T: 'static> Deref<T> for Gc<T> {
fn deref<'a>(&'a self) -> &'a T { &**self }
}
impl<T: Default + 'static> Default for Gc<T> {
fn default() -> Gc<T> {
box(GC) Default::default()
}
}
impl<T: 'static> raw::Repr<*const raw::GcBox<T>> for Gc<T> {}
impl<S: hash::Writer, T: hash::Hash<S> + 'static> hash::Hash<S> for Gc<T> {
fn hash(&self, s: &mut S) {
(**self).hash(s)
}
}
impl<T: 'static + fmt::Show> fmt::Show for Gc<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
(**self).fmt(f)
}
}
#[cfg(test)]
mod tests {
use prelude::*;
use super::*;
use cell::RefCell;
#[test]
fn test_managed_clone() {
let a = box(GC) 5i;
let b: Gc<int> = a.clone();
assert!(a == b);
}
#[test]
fn test_clone() {
let x = Gc::new(RefCell::new(5));
let y = x.clone();
*x.borrow().borrow_mut() = 20;
assert_eq!(*y.borrow().borrow(), 20);
}
#[test]
fn test_simple() {
let x = Gc::new(5);
assert_eq!(*x.borrow(), 5);
}
#[test]
fn test_simple_clone() {
let x = Gc::new(5);
let y = x.clone();
assert_eq!(*x.borrow(), 5);
assert_eq!(*y.borrow(), 5);
}
#[test]
fn test_ptr_eq() {
let x = Gc::new(5);
let y = x.clone();
let z = Gc::new(7);
assert!(x.ptr_eq(&x));
assert!(x.ptr_eq(&y));
assert!(!x.ptr_eq(&z));
}
#[test]
fn test_destructor() {
let x = Gc::new(box 5);
assert_eq!(**x.borrow(), 5);
}
}

View File

@ -958,7 +958,9 @@ mod tests {
// don't check windows magical empty-named variables
assert!(k.is_empty() ||
output.as_slice()
.contains(format!("{}={}", *k, *v).as_slice()));
.contains(format!("{}={}", *k, *v).as_slice()),
"output doesn't contain `{}={}`\n{}",
k, v, output);
}
}
#[cfg(target_os="android")]

View File

@ -105,7 +105,7 @@
html_root_url = "http://doc.rust-lang.org/master/",
html_playground_url = "http://play.rust-lang.org/")]
#![feature(macro_rules, globs, managed_boxes, linkage)]
#![feature(macro_rules, globs, linkage)]
#![feature(default_type_params, phase, lang_items, unsafe_destructor)]
#![feature(import_shadowing)]
@ -136,7 +136,6 @@ extern crate rustrt;
#[cfg(test)] pub use realstd::cmp;
#[cfg(test)] pub use realstd::ty;
#[cfg(test)] pub use realstd::boxed;
#[cfg(test)] pub use realstd::gc;
// NB: These reexports are in the order they should be listed in rustdoc
@ -219,9 +218,6 @@ pub mod rand;
pub mod ascii;
#[cfg(not(test))]
pub mod gc;
pub mod time;
/* Common traits */

View File

@ -201,12 +201,13 @@ mod test {
#[test]
fn test_sendable_future() {
let expected = "schlorf";
let (tx, rx) = channel();
let f = Future::spawn(proc() { expected });
task::spawn(proc() {
let mut f = f;
let actual = f.get();
assert_eq!(actual, expected);
tx.send(f.get());
});
assert_eq!(rx.recv(), expected);
}
#[test]

View File

@ -416,7 +416,6 @@ pub enum BinOp {
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
pub enum UnOp {
UnBox,
UnUniq,
UnDeref,
UnNot,
@ -953,7 +952,6 @@ pub struct UnboxedFnTy {
pub enum Ty_ {
TyNil,
TyBot, /* bottom type */
TyBox(P<Ty>),
TyUniq(P<Ty>),
TyVec(P<Ty>),
TyFixedLengthVec(P<Ty>, P<Expr>),

View File

@ -90,7 +90,6 @@ pub fn is_shift_binop(b: BinOp) -> bool {
pub fn unop_to_string(op: UnOp) -> &'static str {
match op {
UnBox => "box(GC) ",
UnUniq => "box() ",
UnDeref => "*",
UnNot => "!",

View File

@ -112,7 +112,6 @@ pub trait AstBuilder {
fn expr_deref(&self, sp: Span, e: P<ast::Expr>) -> P<ast::Expr>;
fn expr_unary(&self, sp: Span, op: ast::UnOp, e: P<ast::Expr>) -> P<ast::Expr>;
fn expr_managed(&self, sp: Span, e: P<ast::Expr>) -> P<ast::Expr>;
fn expr_addr_of(&self, sp: Span, e: P<ast::Expr>) -> P<ast::Expr>;
fn expr_mut_addr_of(&self, sp: Span, e: P<ast::Expr>) -> P<ast::Expr>;
fn expr_field_access(&self, span: Span, expr: P<ast::Expr>, ident: ast::Ident) -> P<ast::Expr>;
@ -565,10 +564,6 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
self.expr(sp, ast::ExprUnary(op, e))
}
fn expr_managed(&self, sp: Span, e: P<ast::Expr>) -> P<ast::Expr> {
self.expr_unary(sp, ast::UnBox, e)
}
fn expr_field_access(&self, sp: Span, expr: P<ast::Expr>, ident: ast::Ident) -> P<ast::Expr> {
let field_name = token::get_ident(ident);
let field_span = Span {

View File

@ -40,7 +40,7 @@ static KNOWN_FEATURES: &'static [(&'static str, Status)] = &[
("struct_variant", Active),
("once_fns", Active),
("asm", Active),
("managed_boxes", Active),
("managed_boxes", Removed),
("non_ascii_idents", Active),
("thread_local", Active),
("link_args", Active),
@ -135,14 +135,6 @@ impl<'a> Context<'a> {
}
}
fn gate_box(&self, span: Span) {
self.gate_feature("managed_boxes", span,
"The managed box syntax is being replaced by the \
`std::gc::Gc` and `std::rc::Rc` types. Equivalent \
functionality to managed trait objects will be \
implemented but is currently missing.");
}
fn has_feature(&self, feature: &str) -> bool {
self.features.iter().any(|n| n.as_slice() == feature)
}
@ -330,7 +322,6 @@ impl<'a, 'v> Visitor<'v> for Context<'a> {
experimental and likely to be removed");
},
ast::TyBox(_) => { self.gate_box(t.span); }
ast::TyUnboxedFn(..) => {
self.gate_feature("unboxed_closure_sugar",
t.span,
@ -344,9 +335,6 @@ impl<'a, 'v> Visitor<'v> for Context<'a> {
fn visit_expr(&mut self, e: &ast::Expr) {
match e.node {
ast::ExprUnary(ast::UnBox, _) => {
self.gate_box(e.span);
}
ast::ExprUnboxedFn(..) => {
self.gate_feature("unboxed_closures",
e.span,

View File

@ -372,7 +372,6 @@ pub fn noop_fold_ty<T: Folder>(t: P<Ty>, fld: &mut T) -> P<Ty> {
id: fld.new_id(id),
node: match node {
TyNil | TyBot | TyInfer => node,
TyBox(ty) => TyBox(fld.fold_ty(ty)),
TyUniq(ty) => TyUniq(fld.fold_ty(ty)),
TyVec(ty) => TyVec(fld.fold_ty(ty)),
TyPtr(mt) => TyPtr(fld.fold_mt(mt)),

View File

@ -31,8 +31,6 @@ pub enum ObsoleteSyntax {
ObsoleteOwnedPattern,
ObsoleteOwnedVector,
ObsoleteOwnedSelf,
ObsoleteManagedType,
ObsoleteManagedExpr,
ObsoleteImportRenaming,
ObsoleteSubsliceMatch,
ObsoleteExternCrateRenaming,
@ -77,14 +75,6 @@ impl<'a> ParserObsoleteMethods for parser::Parser<'a> {
"`~self` is no longer supported",
"write `self: Box<Self>` instead"
),
ObsoleteManagedType => (
"`@` notation for managed pointers",
"use `Gc<T>` in `std::gc` instead"
),
ObsoleteManagedExpr => (
"`@` notation for a managed pointer allocation",
"use the `box(GC)` operator instead of `@`"
),
ObsoleteImportRenaming => (
"`use foo = bar` syntax",
"write `use bar as foo` instead"

Some files were not shown because too many files have changed in this diff Show More