Skip to content

Commit f69325a

Browse files
committed
---
yaml --- r: 151864 b: refs/heads/try2 c: e546452 h: refs/heads/master v: v3
1 parent 32156ae commit f69325a

File tree

7 files changed

+246
-21
lines changed

7 files changed

+246
-21
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ refs/heads/snap-stage3: 78a7676898d9f80ab540c6df5d4c9ce35bb50463
55
refs/heads/try: 519addf6277dbafccbb4159db4b710c37eaa2ec5
66
refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105
77
refs/heads/ndm: f3868061cd7988080c30d6d5bf352a5a5fe2460b
8-
refs/heads/try2: 84f43c6acd58c6c64fb1d0fde09f55e496d67332
8+
refs/heads/try2: e546452727379f701f2104eb826141a29d4b39fd
99
refs/heads/dist-snap: ba4081a5a8573875fed17545846f6f6902c8ba8d
1010
refs/tags/release-0.2: c870d2dffb391e14efb05aa27898f1f6333a9596
1111
refs/tags/release-0.3: b5f0d0f648d9a6153664837026ba1be43d3e2503

branches/try2/src/libcore/cell.rs

Lines changed: 151 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,157 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
//! Types that provide interior mutability.
11+
//! Sharable mutable containers.
12+
//!
13+
//! Values of the `Cell` and `RefCell` types may be mutated through
14+
//! shared references (i.e. the common `&T` type), whereas most Rust
15+
//! types can only be mutated through unique (`&mut T`) references. We
16+
//! say that `Cell` and `RefCell` provide *interior mutability*, in
17+
//! contrast with typical Rust types that exhibit *inherited
18+
//! mutability*.
19+
//!
20+
//! Cell types come in two flavors: `Cell` and `RefCell`. `Cell`
21+
//! provides `get` and `set` methods that change the
22+
//! interior value with a single method call. `Cell` though is only
23+
//! compatible with types that implement `Copy`. For other types,
24+
//! one must use the `RefCell` type, acquiring a write lock before
25+
//! mutating.
26+
//!
27+
//! `RefCell` uses Rust's lifetimes to implement *dynamic borrowing*,
28+
//! a process whereby one can claim temporary, exclusive, mutable
29+
//! access to the inner value. Borrows for `RefCell`s are tracked *at
30+
//! runtime*, unlike Rust's native reference types which are entirely
31+
//! tracked statically, at compile time. Because `RefCell` borrows are
32+
//! dynamic it is possible to attempt to borrow a value that is
33+
//! already mutably borrowed; when this happens it results in task
34+
//! failure.
35+
//!
36+
//! # When to choose interior mutability
37+
//!
38+
//! The more common inherited mutability, where one must have unique
39+
//! access to mutate a value, is one of the key language elements that
40+
//! enables Rust to reason strongly about pointer aliasing, statically
41+
//! preventing crash bugs. Because of that, inherited mutability is
42+
//! preferred, and interior mutability is something of a last
43+
//! resort. Since cell types enable mutation where it would otherwise
44+
//! be disallowed though, there are occassions when interior
45+
//! mutability might be appropriate, or even *must* be used, e.g.
46+
//!
47+
//! * Introducing inherited mutability roots to shared types.
48+
//! * Implementation details of logically-immutable methods.
49+
//! * Mutating implementations of `clone`.
50+
//!
51+
//! ## Introducing inherited mutability roots to shared types
52+
//!
53+
//! Shared smart pointer types, including `Rc` and `Arc`, provide
54+
//! containers that can be cloned and shared between multiple parties.
55+
//! Because the contained values may be multiply-aliased, they can
56+
//! only be borrowed as shared references, not mutable references.
57+
//! Without cells it would be impossible to mutate data inside of
58+
//! shared boxes at all!
59+
//!
60+
//! It's very common then to put a `RefCell` inside shared pointer
61+
//! types to reintroduce mutability:
62+
//!
63+
//! ```
64+
//! extern crate collections;
65+
//!
66+
//! use collections::HashMap;
67+
//! use std::cell::RefCell;
68+
//! use std::rc::Rc;
69+
//!
70+
//! fn main() {
71+
//! let shared_map: Rc<RefCell<_>> = Rc::new(RefCell::new(HashMap::new()));
72+
//! shared_map.borrow_mut().insert("africa", 92388);
73+
//! shared_map.borrow_mut().insert("kyoto", 11837);
74+
//! shared_map.borrow_mut().insert("piccadilly", 11826);
75+
//! shared_map.borrow_mut().insert("marbles", 38);
76+
//! }
77+
//! ```
78+
//!
79+
//! ## Implementation details of logically-immutable methods
80+
//!
81+
//! Occasionally it may be desirable not to expose in an API that
82+
//! there is mutation happening "under the hood". This may be because
83+
//! logically the operation is immutable, but e.g. caching forces the
84+
//! implementation to perform mutation; or because you must employ
85+
//! mutation to implement a trait method that was originally defined
86+
//! to take `&self`.
87+
//!
88+
//! ```
89+
//! extern crate collections;
90+
//!
91+
//! use collections::HashMap;
92+
//! use std::cell::RefCell;
93+
//!
94+
//! struct Graph {
95+
//! edges: HashMap<uint, uint>,
96+
//! span_tree_cache: RefCell<Option<Vec<(uint, uint)>>>
97+
//! }
98+
//!
99+
//! impl Graph {
100+
//! fn minimum_spanning_tree(&self) -> Vec<(uint, uint)> {
101+
//! // Create a new scope to contain the lifetime of the
102+
//! // dynamic borrow
103+
//! {
104+
//! // Take a reference to the inside of cache cell
105+
//! let mut cache = self.span_tree_cache.borrow_mut();
106+
//! if cache.is_some() {
107+
//! return cache.get_ref().clone();
108+
//! }
109+
//!
110+
//! let span_tree = self.calc_span_tree();
111+
//! *cache = Some(span_tree);
112+
//! }
113+
//!
114+
//! // Recursive call to return the just-cached value.
115+
//! // Note that if we had not let the previous borrow
116+
//! // of the cache fall out of scope then the subsequent
117+
//! // recursive borrow would cause a dynamic task failure.
118+
//! // This is the major hazard of using `RefCell`.
119+
//! self.minimum_spanning_tree()
120+
//! }
121+
//! # fn calc_span_tree(&self) -> Vec<(uint, uint)> { vec![] }
122+
//! }
123+
//! # fn main() { }
124+
//! ```
125+
//!
126+
//! ## Mutating implementations of `clone`
127+
//!
128+
//! This is simply a special - but common - case of the previous:
129+
//! hiding mutability for operations that appear to be immutable.
130+
//! The `clone` method is expected to not change the source value, and
131+
//! is declared to take `&self`, not `&mut self`. Therefore any
132+
//! mutation that happens in the `clone` method must use cell
133+
//! types. For example, `Rc` maintains its reference counts within a
134+
//! `Cell`.
135+
//!
136+
//! ```
137+
//! use std::cell::Cell;
138+
//!
139+
//! struct Rc<T> {
140+
//! ptr: *mut RcBox<T>
141+
//! }
142+
//!
143+
//! struct RcBox<T> {
144+
//! value: T,
145+
//! refcount: Cell<uint>
146+
//! }
147+
//!
148+
//! impl<T> Clone for Rc<T> {
149+
//! fn clone(&self) -> Rc<T> {
150+
//! unsafe {
151+
//! (*self.ptr).refcount.set((*self.ptr).refcount.get() + 1);
152+
//! Rc { ptr: self.ptr }
153+
//! }
154+
//! }
155+
//! }
156+
//! ```
157+
//!
158+
// FIXME: Explain difference between Cell and RefCell
159+
// FIXME: Downsides to interior mutability
160+
// FIXME: Can't be shared between threads. Dynamic borrows
161+
// FIXME: Relationship to Atomic types and RWLock
12162

13163
use clone::Clone;
14164
use cmp::Eq;

branches/try2/src/libcore/lib.rs

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,28 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
//! The Rust core library
11+
//! The Rust Core Library
1212
//!
13-
//! This library is meant to represent the core functionality of rust that is
14-
//! maximally portable to other platforms. To that extent, this library has no
15-
//! knowledge of things like allocation, threads, I/O, etc. This library is
16-
//! built on the assumption of a few existing symbols:
13+
//! The Rust Core Library is the dependency-free foundation of [The
14+
//! Rust Standard Library](../std/index.html). It is the portable glue
15+
//! between the language and its libraries, defining the intrinsic and
16+
//! primitive building blocks of all Rust code. It links to no
17+
//! upstream libraries, no system libraries, and no libc.
18+
//!
19+
//! The core library is *minimal*: it isn't even aware of heap allocation,
20+
//! nor does it provide concurrency or I/O. These things require
21+
//! platform integration, and this library is platform-agnostic.
22+
//!
23+
//! *It is not recommended to use the core library*. The stable
24+
//! functionality of libcore is reexported from the
25+
//! [standard library](../std/index.html). The composition of this library is
26+
//! subject to change over time; only the interface exposed through libstd is
27+
//! intended to be stable.
28+
//!
29+
//! # How to use the core library
30+
//!
31+
// FIXME: Fill me in with more detail when the interface settles
32+
//! This library is built on the assumption of a few existing symbols:
1733
//!
1834
//! * `memcpy`, `memcmp`, `memset` - These are core memory routines which are
1935
//! often generated by LLVM. Additionally, this library can make explicit
@@ -23,16 +39,11 @@
2339
//! distribution.
2440
//!
2541
//! * `rust_begin_unwind` - This function takes three arguments, a
26-
//! `&fmt::Arguments`, a `&str`, and a `uint. These three arguments dictate
42+
//! `&fmt::Arguments`, a `&str`, and a `uint`. These three arguments dictate
2743
//! the failure message, the file at which failure was invoked, and the line.
2844
//! It is up to consumers of this core library to define this failure
2945
//! function; it is only required to never return.
3046
//!
31-
//! Currently, it is *not* recommended to use the core library. The stable
32-
//! functionality of libcore is exported directly into the
33-
//! [standard library](../std/index.html). The composition of this library is
34-
//! subject to change over time, only the interface exposed through libstd is
35-
//! intended to be stable.
3647
3748
#![crate_id = "core#0.11.0-pre"]
3849
#![license = "MIT/ASL2"]

branches/try2/src/libcore/ops.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
/*!
1212
*
13-
* Traits representing built-in operators, useful for overloading
13+
* Overloadable operators
1414
*
1515
* Implementing these traits allows you to get an effect similar to
1616
* overloading operators.

branches/try2/src/librustc/middle/typeck/infer/region_inference/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,9 @@ impl<'a> RegionVarBindings<'a> {
299299
sub.repr(self.tcx),
300300
sup.repr(self.tcx)));
301301
}
302+
(_, ReStatic) => {
303+
// all regions are subregions of static, so we can ignore this
304+
}
302305
(ReInfer(ReVar(sub_id)), ReInfer(ReVar(sup_id))) => {
303306
self.add_constraint(ConstrainVarSubVar(sub_id, sup_id), origin);
304307
}

branches/try2/src/libstd/lib.rs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,8 @@
1616
//!
1717
//! ## Intrinsic types and operations
1818
//!
19-
//! The [`ptr`](../core/ptr/index.html), [`mem`](../core/mem/index.html),
20-
//! and [`cast`](../core/cast/index.html) modules deal with unsafe pointers,
21-
//! memory manipulation, and coercion.
19+
//! The [`ptr`](../core/ptr/index.html) and [`mem`](../core/mem/index.html)
20+
//! modules deal with unsafe pointers and memory manipulation.
2221
//! [`kinds`](../core/kinds/index.html) defines the special built-in traits,
2322
//! and [`raw`](../core/raw/index.html) the runtime representation of Rust types.
2423
//! These are some of the lowest-level building blocks of Rust
@@ -135,24 +134,26 @@ extern crate libc;
135134
#[cfg(test)] pub use realstd::cmp;
136135
#[cfg(test)] pub use realstd::ty;
137136

138-
#[cfg(not(test))] pub use core::cmp;
139-
#[cfg(not(test))] pub use core::kinds;
140-
#[cfg(not(test))] pub use core::ops;
141-
#[cfg(not(test))] pub use core::ty;
137+
138+
// NB: These reexports are in the order they should be listed in rustdoc
142139

143140
pub use core::any;
144141
pub use core::bool;
145142
pub use core::cell;
146143
pub use core::char;
147144
pub use core::clone;
145+
#[cfg(not(test))] pub use core::cmp;
148146
pub use core::container;
149147
pub use core::default;
150148
pub use core::intrinsics;
151149
pub use core::iter;
150+
#[cfg(not(test))] pub use core::kinds;
152151
pub use core::mem;
152+
#[cfg(not(test))] pub use core::ops;
153153
pub use core::ptr;
154154
pub use core::raw;
155155
pub use core::tuple;
156+
#[cfg(not(test))] pub use core::ty;
156157
pub use core::result;
157158

158159
pub use alloc::owned;
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// In this fn, the type `F` is a function that takes a reference to a
12+
// struct and returns another reference with the same lifetime.
13+
//
14+
// Meanwhile, the bare fn `foo` takes a reference to a struct with
15+
// *ANY* lifetime and returns a reference with the 'static lifetime.
16+
// This can safely be considered to be an instance of `F` because all
17+
// lifetimes are sublifetimes of 'static.
18+
19+
#![allow(dead_code)]
20+
#![allow(unused_variable)]
21+
22+
struct S;
23+
24+
// Given 'cx, return 'cx
25+
type F = fn<'cx>(&'cx S) -> &'cx S;
26+
fn want_F(f: F) { }
27+
28+
// Given anything, return 'static
29+
type G = fn<'cx>(&'cx S) -> &'static S;
30+
fn want_G(f: G) { }
31+
32+
// Should meet both.
33+
fn foo(x: &S) -> &'static S {
34+
fail!()
35+
}
36+
37+
// Should meet both.
38+
fn bar<'a,'b>(x: &'a S) -> &'b S {
39+
fail!()
40+
}
41+
42+
// Meets F, but not G.
43+
fn baz<'a>(x: &'a S) -> &'a S {
44+
fail!()
45+
}
46+
47+
fn supply_F() {
48+
want_F(foo);
49+
want_F(bar);
50+
want_F(baz);
51+
}
52+
53+
fn supply_G() {
54+
want_G(foo);
55+
want_G(bar);
56+
want_G(baz); //~ ERROR expected concrete lifetime
57+
}
58+
59+
pub fn main() {
60+
}

0 commit comments

Comments
 (0)