Skip to content

Commit 0ba59f7

Browse files
committed
---
yaml --- r: 120502 b: refs/heads/dist-snap c: 8f2a2e2 h: refs/heads/master v: v3
1 parent f77265a commit 0ba59f7

File tree

7 files changed

+220
-42
lines changed

7 files changed

+220
-42
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ refs/heads/try: 1813e5aa1a03b0596b8de7abd1af31edf5d6098f
66
refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105
77
refs/heads/ndm: f3868061cd7988080c30d6d5bf352a5a5fe2460b
88
refs/heads/try2: 147ecfdd8221e4a4d4e090486829a06da1e0ca3c
9-
refs/heads/dist-snap: f9bd6b4e3900da77f06ebad04ae6bada1e26e042
9+
refs/heads/dist-snap: 8f2a2e2dd8320215f834376c9a8a237e285df64e
1010
refs/tags/release-0.2: c870d2dffb391e14efb05aa27898f1f6333a9596
1111
refs/tags/release-0.3: b5f0d0f648d9a6153664837026ba1be43d3e2503
1212
refs/heads/try3: 9387340aab40a73e8424c48fd42f0c521a4875c0

branches/dist-snap/src/compiletest/common.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
1+
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
22
// file at the top-level directory of this distribution and at
33
// http://rust-lang.org/COPYRIGHT.
44
//
@@ -91,9 +91,6 @@ pub struct Config {
9191
// Only run tests that match this filter
9292
pub filter: Option<Regex>,
9393

94-
// Precompiled regex for finding expected errors in cfail
95-
pub cfail_regex: Regex,
96-
9794
// Write out a parseable log of tests that were run
9895
pub logfile: Option<Path>,
9996

@@ -147,4 +144,5 @@ pub struct Config {
147144

148145
// Explain what's going on
149146
pub verbose: bool
147+
150148
}

branches/dist-snap/src/compiletest/compiletest.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
1+
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
22
// file at the top-level directory of this distribution and at
33
// http://rust-lang.org/COPYRIGHT.
44
//
@@ -33,7 +33,6 @@ use getopts::{optopt, optflag, reqopt};
3333
use common::Config;
3434
use common::{Pretty, DebugInfoGdb, Codegen};
3535
use util::logv;
36-
use regex::Regex;
3736

3837
pub mod procsrv;
3938
pub mod util;
@@ -148,7 +147,6 @@ pub fn parse_config(args: Vec<StrBuf> ) -> Config {
148147
.as_slice()).expect("invalid mode"),
149148
run_ignored: matches.opt_present("ignored"),
150149
filter: filter,
151-
cfail_regex: Regex::new(errors::EXPECTED_PATTERN).unwrap(),
152150
logfile: matches.opt_str("logfile").map(|s| Path::new(s)),
153151
save_metrics: matches.opt_str("save-metrics").map(|s| Path::new(s)),
154152
ratchet_metrics:
Lines changed: 54 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
1+
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
22
// file at the top-level directory of this distribution and at
33
// http://rust-lang.org/COPYRIGHT.
44
//
@@ -9,36 +9,68 @@
99
// except according to those terms.
1010

1111
use std::io::{BufferedReader, File};
12-
use regex::Regex;
1312

1413
pub struct ExpectedError {
1514
pub line: uint,
1615
pub kind: StrBuf,
1716
pub msg: StrBuf,
1817
}
1918

20-
pub static EXPECTED_PATTERN : &'static str = r"//~(?P<adjusts>\^*)\s*(?P<kind>\S*)\s*(?P<msg>.*)";
21-
2219
// Load any test directives embedded in the file
23-
pub fn load_errors(re: &Regex, testfile: &Path) -> Vec<ExpectedError> {
24-
let mut rdr = BufferedReader::new(File::open(testfile).unwrap());
20+
pub fn load_errors(testfile: &Path) -> Vec<ExpectedError> {
2521

26-
rdr.lines().enumerate().filter_map(|(line_no, ln)| {
27-
parse_expected(line_no + 1, ln.unwrap(), re)
28-
}).collect()
22+
let mut error_patterns = Vec::new();
23+
let mut rdr = BufferedReader::new(File::open(testfile).unwrap());
24+
let mut line_num = 1u;
25+
for ln in rdr.lines() {
26+
error_patterns.push_all_move(parse_expected(line_num,
27+
ln.unwrap().to_strbuf()));
28+
line_num += 1u;
29+
}
30+
return error_patterns;
2931
}
3032

31-
fn parse_expected(line_num: uint, line: &str, re: &Regex) -> Option<ExpectedError> {
32-
re.captures(line).and_then(|caps| {
33-
let adjusts = caps.name("adjusts").len();
34-
let kind = caps.name("kind").to_ascii().to_lower().into_str().to_strbuf();
35-
let msg = caps.name("msg").trim().to_strbuf();
36-
37-
debug!("line={} kind={} msg={}", line_num, kind, msg);
38-
Some(ExpectedError {
39-
line: line_num - adjusts,
40-
kind: kind,
41-
msg: msg,
42-
})
43-
})
33+
fn parse_expected(line_num: uint, line: StrBuf) -> Vec<ExpectedError> {
34+
let line = line.as_slice().trim().to_strbuf();
35+
let error_tag = "//~".to_strbuf();
36+
let mut idx;
37+
match line.as_slice().find_str(error_tag.as_slice()) {
38+
None => return Vec::new(),
39+
Some(nn) => { idx = (nn as uint) + error_tag.len(); }
40+
}
41+
42+
// "//~^^^ kind msg" denotes a message expected
43+
// three lines above current line:
44+
let mut adjust_line = 0u;
45+
let len = line.len();
46+
while idx < len && line.as_slice()[idx] == ('^' as u8) {
47+
adjust_line += 1u;
48+
idx += 1u;
49+
}
50+
51+
// Extract kind:
52+
while idx < len && line.as_slice()[idx] == (' ' as u8) {
53+
idx += 1u;
54+
}
55+
let start_kind = idx;
56+
while idx < len && line.as_slice()[idx] != (' ' as u8) {
57+
idx += 1u;
58+
}
59+
60+
let kind = line.as_slice().slice(start_kind, idx);
61+
let kind = kind.to_ascii().to_lower().into_str().to_strbuf();
62+
63+
// Extract msg:
64+
while idx < len && line.as_slice()[idx] == (' ' as u8) {
65+
idx += 1u;
66+
}
67+
let msg = line.as_slice().slice(idx, len).to_strbuf();
68+
69+
debug!("line={} kind={} msg={}", line_num - adjust_line, kind, msg);
70+
71+
return vec!(ExpectedError{
72+
line: line_num - adjust_line,
73+
kind: kind,
74+
msg: msg,
75+
});
4476
}

branches/dist-snap/src/compiletest/runtest.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
1+
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
22
// file at the top-level directory of this distribution and at
33
// http://rust-lang.org/COPYRIGHT.
44
//
@@ -79,7 +79,7 @@ fn run_cfail_test(config: &Config, props: &TestProps, testfile: &Path) {
7979

8080
check_correct_failure_status(&proc_res);
8181

82-
let expected_errors = errors::load_errors(&config.cfail_regex, testfile);
82+
let expected_errors = errors::load_errors(testfile);
8383
if !expected_errors.is_empty() {
8484
if !props.error_patterns.is_empty() {
8585
fatal("both error pattern and expected errors \

branches/dist-snap/src/doc/rust.md

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -848,11 +848,11 @@ extern crate foo = "some/where/rust-foo#foo:1.0"; // a full crate ID for externa
848848
##### Use declarations
849849

850850
~~~~ {.notrust .ebnf .gram}
851-
use_decl : "pub" ? "use" [ ident '=' path
852-
| path_glob ] ;
851+
use_decl : "pub" ? "use" ident [ '=' path
852+
| "::" path_glob ] ;
853853
854-
path_glob : ident [ "::" [ path_glob
855-
| '*' ] ] ?
854+
path_glob : ident [ "::" path_glob ] ?
855+
| '*'
856856
| '{' ident [ ',' ident ] * '}' ;
857857
~~~~
858858

@@ -1743,7 +1743,7 @@ import public items from their destination, not private items.
17431743
attribute : '#' '!' ? '[' meta_item ']' ;
17441744
meta_item : ident [ '=' literal
17451745
| '(' meta_seq ')' ] ? ;
1746-
meta_seq : meta_item [ ',' meta_seq ] ? ;
1746+
meta_seq : meta_item [ ',' meta_seq ]* ;
17471747
~~~~
17481748

17491749
Static entities in Rust &mdash; crates, modules and items &mdash; may have _attributes_
@@ -3027,11 +3027,11 @@ then any `else` block is executed.
30273027
### Match expressions
30283028

30293029
~~~~ {.notrust .ebnf .gram}
3030-
match_expr : "match" expr '{' match_arm * '}' ;
3030+
match_expr : "match" expr '{' match_arm [ '|' match_arm ] * '}' ;
30313031
3032-
match_arm : attribute * match_pat "=>" [ expr "," | '{' block '}' ] ;
3032+
match_arm : match_pat "=>" [ expr "," | '{' block '}' ] ;
30333033
3034-
match_pat : pat [ '|' pat ] * [ "if" expr ] ? ;
3034+
match_pat : pat [ ".." pat ] ? [ "if" expr ] ;
30353035
~~~~
30363036

30373037
A `match` expression branches on a *pattern*. The exact form of matching that
@@ -3137,7 +3137,7 @@ using the `ref` keyword,
31373137
or to a mutable reference using `ref mut`.
31383138

31393139
Subpatterns can also be bound to variables by the use of the syntax
3140-
`variable @ subpattern`.
3140+
`variable @ pattern`.
31413141
For example:
31423142

31433143
~~~~

branches/dist-snap/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 then 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.take_unwrap().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 - bot 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+
// TODO: Explain difference between Cell and RefCell
159+
// TODO: Downsides to interior mutability
160+
// TODO: Can't be shared between threads. Dynamic borrows
161+
// TODO: Relationship to Atomic types and RWLock
12162

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

0 commit comments

Comments
 (0)