Skip to content

Commit 7ef825b

Browse files
committed
Revert "remove alias analysis and replace with borrowck"
18s perf regression compiling rustc with opts This reverts commit 7f6ee0c.
1 parent c058f1d commit 7ef825b

Some content is hidden

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

51 files changed

+1134
-31
lines changed

doc/tutorial.md

+77-1
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

src/rustc/driver/driver.rs

+16-3
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};

src/rustc/driver/session.rs

+5-1
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

src/rustc/metadata/common.rs

+1
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)