Skip to content

Commit 2e62745

Browse files
committed
---
yaml --- r: 10413 b: refs/heads/snap-stage3 c: d14d415 h: refs/heads/master i: 10411: 19fdf15 v: v3
1 parent b401c78 commit 2e62745

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+1181
-130
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
refs/heads/master: 2898dcc5d97da9427ac367542382b6239d9c0bbf
33
refs/heads/snap-stage1: e33de59e47c5076a89eadeb38f4934f58a3618a6
4-
refs/heads/snap-stage3: 7ec171f6ae795050e571dad2c5122ded584e2505
4+
refs/heads/snap-stage3: d14d4155dead7a18b2d5b8dcac1dd7311a26900a
55
refs/heads/try: 2898dcc5d97da9427ac367542382b6239d9c0bbf
66
refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105

branches/snap-stage3/doc/tutorial.md

Lines changed: 77 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1382,7 +1382,83 @@ gets access to them.
13821382

13831383
## Safe references
13841384

1385-
*This system has recently changed. An explanantion is forthcoming.*
1385+
There is one catch with this approach: sometimes the compiler can
1386+
*not* statically guarantee that the argument value at the caller side
1387+
will survive to the end of the call. Another argument might indirectly
1388+
refer to it and be used to overwrite it, or a closure might assign a
1389+
new value to it.
1390+
1391+
Fortunately, Rust tasks are single-threaded worlds, which share no
1392+
data with other tasks, and most data is immutable. This allows most
1393+
argument-passing situations to be proved safe without further
1394+
difficulty.
1395+
1396+
Take the following program:
1397+
1398+
~~~~
1399+
# fn get_really_big_record() -> int { 1 }
1400+
# fn myfunc(a: int) {}
1401+
fn main() {
1402+
let x = get_really_big_record();
1403+
myfunc(x);
1404+
}
1405+
~~~~
1406+
1407+
Here we know for sure that no one else has access to the `x` variable
1408+
in `main`, so we're good. But the call could also look like this:
1409+
1410+
~~~~
1411+
# fn myfunc(a: int, b: fn()) {}
1412+
# fn get_another_record() -> int { 1 }
1413+
# let mut x = 1;
1414+
myfunc(x, {|| x = get_another_record(); });
1415+
~~~~
1416+
1417+
Now, if `myfunc` first calls its second argument and then accesses its
1418+
first argument, it will see a different value from the one that was
1419+
passed to it.
1420+
1421+
In such a case, the compiler will insert an implicit copy of `x`,
1422+
*except* if `x` contains something mutable, in which case a copy would
1423+
result in code that behaves differently. If copying `x` might be
1424+
expensive (for example, if it holds a vector), the compiler will emit
1425+
a warning.
1426+
1427+
There are even more tricky cases, in which the Rust compiler is forced
1428+
to pessimistically assume a value will get mutated, even though it is
1429+
not sure.
1430+
1431+
~~~~
1432+
fn for_each(v: [mut @int], iter: fn(@int)) {
1433+
for v.each {|elt| iter(elt); }
1434+
}
1435+
~~~~
1436+
1437+
For all this function knows, calling `iter` (which is a closure that
1438+
might have access to the vector that's passed as `v`) could cause the
1439+
elements in the vector to be mutated, with the effect that it can not
1440+
guarantee that the boxes will live for the duration of the call. So it
1441+
has to copy them. In this case, this will happen implicitly (bumping a
1442+
reference count is considered cheap enough to not warn about it).
1443+
1444+
## The copy operator
1445+
1446+
If the `for_each` function given above were to take a vector of
1447+
`{mut a: int}` instead of `@int`, it would not be able to
1448+
implicitly copy, since if the `iter` function changes a copy of a
1449+
mutable record, the changes won't be visible in the record itself. If
1450+
we *do* want to allow copies there, we have to explicitly allow it
1451+
with the `copy` operator:
1452+
1453+
~~~~
1454+
type mutrec = {mut x: int};
1455+
fn for_each(v: [mut mutrec], iter: fn(mutrec)) {
1456+
for v.each {|elt| iter(copy elt); }
1457+
}
1458+
~~~~
1459+
1460+
Adding a `copy` operator is also the way to muffle warnings about
1461+
implicit copies.
13861462

13871463
## Other uses of safe references
13881464

branches/snap-stage3/src/libcore/int-template.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import T = inst::T;
22
import cmp::{eq, ord};
3-
import num::num;
43

54
export min_value, max_value;
65
export min, max;
@@ -124,7 +123,7 @@ impl eq of eq for T {
124123
}
125124
}
126125

127-
impl num of num for T {
126+
impl num of num::num for T {
128127
fn add(&&other: T) -> T { ret self + other; }
129128
fn sub(&&other: T) -> T { ret self - other; }
130129
fn mul(&&other: T) -> T { ret self * other; }
@@ -196,7 +195,7 @@ fn test_to_str() {
196195

197196
#[test]
198197
fn test_ifaces() {
199-
fn test<U:num>(ten: U) {
198+
fn test<U:num::num>(ten: U) {
200199
assert (ten.to_int() == 10);
201200

202201
let two = ten.from_int(2);

branches/snap-stage3/src/libcore/str.rs

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -592,22 +592,7 @@ Section: Comparing strings
592592
*/
593593

594594
#[doc = "Bytewise string equality"]
595-
pure fn eq(&&a: str, &&b: str) -> bool {
596-
// FIXME: This should just be "a == b" but that calls into the shape code
597-
// :(
598-
let a_len = a.len();
599-
let b_len = b.len();
600-
if a_len != b_len { ret false; }
601-
let mut end = uint::min(a_len, b_len);
602-
603-
let mut i = 0u;
604-
while i < end {
605-
if a[i] != b[i] { ret false; }
606-
i += 1u;
607-
}
608-
609-
ret true;
610-
}
595+
pure fn eq(&&a: str, &&b: str) -> bool { a == b }
611596

612597
#[doc = "Bytewise less than or equal"]
613598
pure fn le(&&a: str, &&b: str) -> bool { a <= b }
@@ -1876,11 +1861,11 @@ impl extensions for str {
18761861
18771862
Alphanumeric characters are determined by `char::is_alphanumeric`
18781863
"]
1879-
#[inline]
1864+
#[inlune]
18801865
fn is_alphanumeric() -> bool { is_alphanumeric(self) }
18811866
#[inline]
18821867
#[doc ="Returns the size in bytes not counting the null terminator"]
1883-
pure fn len() -> uint { len(self) }
1868+
fn len() -> uint { len(self) }
18841869
#[doc = "
18851870
Returns a slice of the given string from the byte range [`begin`..`end`)
18861871

branches/snap-stage3/src/libcore/uint-template.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import T = inst::T;
22
import cmp::{eq, ord};
3-
import num::num;
43

54
export min_value, max_value;
65
export min, max;
@@ -65,7 +64,7 @@ impl eq of eq for T {
6564
}
6665
}
6766

68-
impl num of num for T {
67+
impl num of num::num for T {
6968
fn add(&&other: T) -> T { ret self + other; }
7069
fn sub(&&other: T) -> T { ret self - other; }
7170
fn mul(&&other: T) -> T { ret self * other; }

branches/snap-stage3/src/libsyntax/parse/parser.rs

Lines changed: 7 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,7 @@ class parser {
7070
let mut token: token::token;
7171
let mut span: span;
7272
let mut last_span: span;
73-
let mut buffer: [mut {tok: token::token, span: span}]/4;
74-
let mut buffer_start: int;
75-
let mut buffer_end: int;
73+
let buffer: dvec<{tok: token::token, span: span}>;
7674
let mut restriction: restriction;
7775
let reader: reader;
7876
let keywords: hashmap<str, ()>;
@@ -88,14 +86,7 @@ class parser {
8886
self.token = tok0.tok;
8987
self.span = span0;
9088
self.last_span = span0;
91-
self.buffer = [mut
92-
{tok: tok0.tok, span: span0},
93-
{tok: tok0.tok, span: span0},
94-
{tok: tok0.tok, span: span0},
95-
{tok: tok0.tok, span: span0}
96-
]/4;
97-
self.buffer_start = 0;
98-
self.buffer_end = 0;
89+
self.buffer = dvec::dvec();
9990
self.restriction = UNRESTRICTED;
10091
self.reader = rdr;
10192
self.keywords = token::keyword_table();
@@ -107,13 +98,12 @@ class parser {
10798

10899
fn bump() {
109100
self.last_span = self.span;
110-
if self.buffer_start == self.buffer_end {
101+
if self.buffer.len() == 0u {
111102
let next = lexer::next_token(self.reader);
112103
self.token = next.tok;
113104
self.span = mk_sp(next.chpos, self.reader.chpos);
114105
} else {
115-
let next = self.buffer[self.buffer_start];
116-
self.buffer_start = (self.buffer_start + 1) & 3;
106+
let next = self.buffer.shift();
117107
self.token = next.tok;
118108
self.span = next.span;
119109
}
@@ -122,21 +112,13 @@ class parser {
122112
self.token = next;
123113
self.span = mk_sp(lo, hi);
124114
}
125-
fn buffer_length() -> int {
126-
if self.buffer_start <= self.buffer_end {
127-
ret self.buffer_end - self.buffer_start;
128-
}
129-
ret (4 - self.buffer_start) + self.buffer_end;
130-
}
131115
fn look_ahead(distance: uint) -> token::token {
132-
let dist = distance as int;
133-
while self.buffer_length() < dist {
116+
while self.buffer.len() < distance {
134117
let next = lexer::next_token(self.reader);
135118
let sp = mk_sp(next.chpos, self.reader.chpos);
136-
self.buffer[self.buffer_end] = {tok: next.tok, span: sp};
137-
self.buffer_end = (self.buffer_end + 1) & 3;
119+
self.buffer.push({tok: next.tok, span: sp});
138120
}
139-
ret copy self.buffer[(self.buffer_start + dist - 1) & 3].tok;
121+
ret self.buffer[distance - 1u].tok;
140122
}
141123
fn fatal(m: str) -> ! {
142124
self.sess.span_diagnostic.span_fatal(copy self.span, m)

branches/snap-stage3/src/rustc/driver/driver.rs

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,9 @@ fn compile_upto(sess: session, cfg: ast::crate_cfg,
204204
let (root_map, mutbl_map) = time(
205205
time_passes, "borrow checking",
206206
bind middle::borrowck::check_crate(ty_cx, method_map, crate));
207+
let (copy_map, _ref_map) =
208+
time(time_passes, "alias checking",
209+
bind middle::alias::check_crate(ty_cx, crate));
207210
time(time_passes, "kind checking",
208211
bind kind::check_crate(ty_cx, method_map, last_use_map, crate));
209212
time(time_passes, "lint checking",
@@ -213,7 +216,7 @@ fn compile_upto(sess: session, cfg: ast::crate_cfg,
213216
let outputs = option::get(outputs);
214217

215218
let maps = {mutbl_map: mutbl_map, root_map: root_map,
216-
last_use_map: last_use_map,
219+
copy_map: copy_map, last_use_map: last_use_map,
217220
impl_map: impl_map, method_map: method_map,
218221
vtable_map: vtable_map};
219222

@@ -445,6 +448,14 @@ fn build_session_options(match: getopts::match,
445448
let sysroot_opt = getopts::opt_maybe_str(match, "sysroot");
446449
let target_opt = getopts::opt_maybe_str(match, "target");
447450
let save_temps = getopts::opt_present(match, "save-temps");
451+
let borrowck = alt getopts::opt_maybe_str(match, "borrowck") {
452+
none { 0u }
453+
some("warn") { 1u }
454+
some("err") { 2u }
455+
some(_) {
456+
early_error(demitter, "borrowck may be warn or err")
457+
}
458+
};
448459
alt output_type {
449460
// unless we're emitting huamn-readable assembly, omit comments.
450461
link::output_type_llvm_assembly | link::output_type_assembly {}
@@ -493,7 +504,8 @@ fn build_session_options(match: getopts::match,
493504
test: test,
494505
parse_only: parse_only,
495506
no_trans: no_trans,
496-
debugging_opts: debugging_opts};
507+
debugging_opts: debugging_opts,
508+
borrowck: borrowck};
497509
ret sopts;
498510
}
499511

@@ -570,7 +582,8 @@ fn opts() -> [getopts::opt] {
570582
optmulti("Z"),
571583

572584
optmulti("cfg"), optflag("test"),
573-
optflag("lib"), optflag("bin"), optflag("static"), optflag("gc")];
585+
optflag("lib"), optflag("bin"), optflag("static"), optflag("gc"),
586+
optopt("borrowck")];
574587
}
575588

576589
type output_filenames = @{out_filename: str, obj_filename:str};

branches/snap-stage3/src/rustc/driver/session.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,9 @@ type options =
6666
no_trans: bool,
6767

6868
debugging_opts: uint,
69+
70+
// temporary hack: 0=off,1=warn,2=err --> if 2, alias is disabled
71+
borrowck: uint,
6972
};
7073

7174
type crate_metadata = {name: str, data: [u8]};
@@ -178,7 +181,8 @@ fn basic_options() -> @options {
178181
test: false,
179182
parse_only: false,
180183
no_trans: false,
181-
debugging_opts: 0u
184+
debugging_opts: 0u,
185+
borrowck: 0u,
182186
}
183187
}
184188

branches/snap-stage3/src/rustc/metadata/common.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ enum astencode_tag { // Reserves 0x50 -- 0x6f
116116
tag_table_param_bounds,
117117
tag_table_inferred_modes,
118118
tag_table_mutbl,
119+
tag_table_copy,
119120
tag_table_last_use,
120121
tag_table_spill,
121122
tag_table_method_map,

0 commit comments

Comments
 (0)