Skip to content

Commit c1f7f31

Browse files
committed
---
yaml --- r: 13159 b: refs/heads/master c: c2ce274 h: refs/heads/master i: 13157: 61c7919 13155: 2258c27 13151: 121a234 v: v3
1 parent 72e7f8c commit c1f7f31

File tree

7 files changed

+122
-59
lines changed

7 files changed

+122
-59
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
refs/heads/master: 0470abe1d290ef28fa72693b70f955328656e471
2+
refs/heads/master: c2ce2741a773b94d3a8f7293cb598322bc61f89d
33
refs/heads/snap-stage1: e33de59e47c5076a89eadeb38f4934f58a3618a6
44
refs/heads/snap-stage3: 4a81779abd786ff22d71434c6d9a5917ea4cdfff
55
refs/heads/try: 2898dcc5d97da9427ac367542382b6239d9c0bbf

trunk/src/rustc/middle/astencode.rs

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -562,6 +562,17 @@ impl of tr for method_origin {
562562
}
563563
}
564564

565+
// ______________________________________________________________________
566+
// Encoding and decoding of borrow
567+
568+
impl helper for ebml::ebml_deserializer {
569+
fn read_borrow(xcx: extended_decode_ctxt) -> ty::borrow {
570+
let borrow = ty::deserialize_borrow(self);
571+
{scope_id: xcx.tr_id(borrow.scope_id),
572+
mutbl: borrow.mutbl}
573+
}
574+
}
575+
565576
// ______________________________________________________________________
566577
// Encoding and decoding vtable_res
567578

@@ -866,10 +877,12 @@ fn encode_side_tables_for_id(ecx: @e::encode_ctxt,
866877
}
867878
}
868879

869-
option::iter(tcx.borrowings.find(id)) {|s|
880+
option::iter(tcx.borrowings.find(id)) {|borrow|
870881
ebml_w.tag(c::tag_table_borrowings) {||
871882
ebml_w.id(id);
872-
ebml_w.wr_tagged_i64(c::tag_table_val as uint, s as i64);
883+
ebml_w.tag(c::tag_table_val) {||
884+
ty::serialize_borrow(ebml_w, borrow)
885+
}
873886
}
874887
}
875888
}
@@ -979,8 +992,8 @@ fn decode_side_tables(xcx: extended_decode_ctxt,
979992
dcx.maps.vtable_map.insert(id,
980993
val_dsr.read_vtable_res(xcx));
981994
} else if tag == (c::tag_table_borrowings as uint) {
982-
let scope_id = ebml::doc_as_i64(val_doc) as int;
983-
dcx.tcx.borrowings.insert(id, scope_id);
995+
let borrow = val_dsr.read_borrow(xcx);
996+
dcx.tcx.borrowings.insert(id, borrow);
984997
} else {
985998
xcx.dcx.tcx.sess.bug(
986999
#fmt["unknown tag found in side tables: %x", tag]);

trunk/src/rustc/middle/borrowck.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -190,10 +190,10 @@ fn req_loans_in_expr(ex: @ast::expr,
190190
let tcx = bccx.tcx;
191191

192192
// If this expression is borrowed, have to ensure it remains valid:
193-
for tcx.borrowings.find(ex.id).each { |scope_id|
193+
for tcx.borrowings.find(ex.id).each { |borrow|
194194
let cmt = self.bccx.cat_borrow_of_expr(ex);
195-
let scope_r = ty::re_scope(scope_id);
196-
self.guarantee_valid(cmt, m_const, scope_r);
195+
let scope_r = ty::re_scope(borrow.scope_id);
196+
self.guarantee_valid(cmt, borrow.mutbl, scope_r);
197197
}
198198

199199
// Special checks for various kinds of expressions:

trunk/src/rustc/middle/ty.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ export mach_sty;
158158
export ty_sort_str;
159159
export normalize_ty;
160160
export to_str;
161+
export borrow, serialize_borrow, deserialize_borrow;
161162

162163
// Data types
163164

@@ -204,6 +205,12 @@ enum ast_ty_to_ty_cache_entry {
204205
atttce_resolved(t) /* resolved to a type, irrespective of region */
205206
}
206207

208+
#[auto_serialize]
209+
type borrow = {
210+
scope_id: ast::node_id,
211+
mutbl: ast::mutability
212+
};
213+
207214
type ctxt =
208215
@{diag: syntax::diagnostic::span_handler,
209216
interner: hashmap<intern_key, t_box>,
@@ -239,7 +246,7 @@ type ctxt =
239246
ty_param_bounds: hashmap<ast::node_id, param_bounds>,
240247
inferred_modes: hashmap<ast::node_id, ast::mode>,
241248
// maps the id of borrowed expr to scope of borrowed ptr
242-
borrowings: hashmap<ast::node_id, ast::node_id>,
249+
borrowings: hashmap<ast::node_id, borrow>,
243250
normalized_cache: hashmap<t, t>};
244251

245252
enum tbox_flag {

trunk/src/rustc/middle/typeck/infer.rs

Lines changed: 60 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,7 @@ import check::regionmanip::{replace_bound_regions_in_fn_ty};
157157
import driver::session::session;
158158
import util::common::{indent, indenter};
159159
import ast::{unsafe_fn, impure_fn, pure_fn, crust_fn};
160+
import ast::{m_const, m_imm, m_mutbl};
160161

161162
export infer_ctxt;
162163
export new_infer_ctxt;
@@ -961,24 +962,27 @@ impl methods for resolve_state {
961962
// we just fall back to requiring that a <: b.
962963
//
963964
// Assuming we have a bound from both sides, we will then examine
964-
// these bounds and see if they have the form (@MT_a, &rb.MT_b)
965-
// (resp. ~MT_a). If they do not, we fall back to subtyping.
965+
// these bounds and see if they have the form (@M_a T_a, &rb.M_b T_b)
966+
// (resp. ~M_a T_a, [M_a T_a], etc). If they do not, we fall back to
967+
// subtyping.
966968
//
967969
// If they *do*, then we know that the two types could never be
968-
// subtypes of one another. We will then construct a type @MT_b and
969-
// ensure that type a is a subtype of that. This allows for the
970+
// subtypes of one another. We will then construct a type @const T_b
971+
// and ensure that type a is a subtype of that. This allows for the
970972
// possibility of assigning from a type like (say) @[mut T1] to a type
971-
// &[const T2] where T1 <: T2. Basically we would require that @[mut
972-
// T1] <: @[const T2]. Next we require that the region for the
973-
// enclosing scope be a superregion of the region r. These two checks
974-
// together guarantee that the type A would be a subtype of the type B
975-
// if the @ were converted to a region r.
973+
// &[T2] where T1 <: T2. This might seem surprising, since the `@`
974+
// points at mutable memory but the `&` points at immutable memory.
975+
// This would in fact be unsound, except for the borrowck, which comes
976+
// later and guarantees that such mutability conversions are safe.
977+
// See borrowck for more details. Next we require that the region for
978+
// the enclosing scope be a superregion of the region r.
976979
//
977-
// You might wonder why we don't just make the type &e.MT_a where e is
978-
// the enclosing region and check that &e.MT_a <: B. The reason is
979-
// that the type @MT_a is (generally) just a *lower-bound*, so this
980-
// would be imposing @MT_a also as the upper-bound on type A. But
981-
// this upper-bound might be stricter than what is truly needed.
980+
// You might wonder why we don't make the type &e.const T_a where e is
981+
// the enclosing region and check that &e.const T_a <: B. The reason
982+
// is that the type of A is (generally) just a *lower-bound*, so this
983+
// would be imposing that lower-bound also as the upper-bound on type
984+
// A. But this upper-bound might be stricter than what is truly
985+
// needed.
982986

983987
impl assignment for infer_ctxt {
984988
fn assign_tys(anmnt: assignment, a: ty::t, b: ty::t) -> ures {
@@ -1051,35 +1055,39 @@ impl assignment for infer_ctxt {
10511055
(some(a_bnd), some(b_bnd)) {
10521056
alt (ty::get(a_bnd).struct, ty::get(b_bnd).struct) {
10531057
(ty::ty_box(mt_a), ty::ty_rptr(r_b, mt_b)) {
1054-
let nr_b = ty::mk_box(self.tcx, mt_b);
1055-
self.crosspollinate(anmnt, a, nr_b, r_b)
1058+
let nr_b = ty::mk_box(self.tcx, {ty: mt_b.ty,
1059+
mutbl: m_const});
1060+
self.crosspollinate(anmnt, a, nr_b, mt_b.mutbl, r_b)
10561061
}
10571062
(ty::ty_uniq(mt_a), ty::ty_rptr(r_b, mt_b)) {
1058-
let nr_b = ty::mk_uniq(self.tcx, mt_b);
1059-
self.crosspollinate(anmnt, a, nr_b, r_b)
1063+
let nr_b = ty::mk_uniq(self.tcx, {ty: mt_b.ty,
1064+
mutbl: m_const});
1065+
self.crosspollinate(anmnt, a, nr_b, mt_b.mutbl, r_b)
10601066
}
10611067
(ty::ty_estr(vs_a),
10621068
ty::ty_estr(ty::vstore_slice(r_b)))
10631069
if is_borrowable(vs_a) {
10641070
let nr_b = ty::mk_estr(self.tcx, vs_a);
1065-
self.crosspollinate(anmnt, a, nr_b, r_b)
1071+
self.crosspollinate(anmnt, a, nr_b, m_imm, r_b)
10661072
}
10671073
(ty::ty_str,
10681074
ty::ty_estr(ty::vstore_slice(r_b))) {
10691075
let nr_b = ty::mk_str(self.tcx);
1070-
self.crosspollinate(anmnt, a, nr_b, r_b)
1076+
self.crosspollinate(anmnt, a, nr_b, m_imm, r_b)
10711077
}
10721078

10731079
(ty::ty_evec(mt_a, vs_a),
10741080
ty::ty_evec(mt_b, ty::vstore_slice(r_b)))
10751081
if is_borrowable(vs_a) {
1076-
let nr_b = ty::mk_evec(self.tcx, mt_b, vs_a);
1077-
self.crosspollinate(anmnt, a, nr_b, r_b)
1082+
let nr_b = ty::mk_evec(self.tcx, {ty: mt_b.ty,
1083+
mutbl: m_const}, vs_a);
1084+
self.crosspollinate(anmnt, a, nr_b, mt_b.mutbl, r_b)
10781085
}
10791086
(ty::ty_vec(mt_a),
10801087
ty::ty_evec(mt_b, ty::vstore_slice(r_b))) {
1081-
let nr_b = ty::mk_vec(self.tcx, mt_b);
1082-
self.crosspollinate(anmnt, a, nr_b, r_b)
1088+
let nr_b = ty::mk_vec(self.tcx, {ty: mt_b.ty,
1089+
mutbl: m_const});
1090+
self.crosspollinate(anmnt, a, nr_b, mt_b.mutbl, r_b)
10831091
}
10841092
_ {
10851093
self.sub_tys(a, b)
@@ -1093,9 +1101,10 @@ impl assignment for infer_ctxt {
10931101
}
10941102

10951103
fn crosspollinate(anmnt: assignment,
1096-
a: ty::t,
1097-
nr_b: ty::t,
1098-
r_b: ty::region) -> ures {
1104+
a: ty::t,
1105+
nr_b: ty::t,
1106+
m: ast::mutability,
1107+
r_b: ty::region) -> ures {
10991108

11001109
#debug["crosspollinate(anmnt=%?, a=%s, nr_b=%s, r_b=%s)",
11011110
anmnt, a.to_str(self), nr_b.to_str(self),
@@ -1109,8 +1118,9 @@ impl assignment for infer_ctxt {
11091118
// if successful, add an entry indicating that
11101119
// borrowing occurred
11111120
#debug["borrowing expression #%?", anmnt];
1112-
self.tcx.borrowings.insert(anmnt.expr_id,
1113-
anmnt.borrow_scope);
1121+
let borrow = {scope_id: anmnt.borrow_scope,
1122+
mutbl: m};
1123+
self.tcx.borrowings.insert(anmnt.expr_id, borrow);
11141124
uok()
11151125
}
11161126
}
@@ -1561,17 +1571,17 @@ impl of combine for sub {
15611571
fn mts(a: ty::mt, b: ty::mt) -> cres<ty::mt> {
15621572
#debug("mts(%s <: %s)", a.to_str(*self), b.to_str(*self));
15631573

1564-
if a.mutbl != b.mutbl && b.mutbl != ast::m_const {
1574+
if a.mutbl != b.mutbl && b.mutbl != m_const {
15651575
ret err(ty::terr_mutability);
15661576
}
15671577

15681578
alt b.mutbl {
1569-
ast::m_mutbl {
1579+
m_mutbl {
15701580
// If supertype is mut, subtype must match exactly
15711581
// (i.e., invariant if mut):
15721582
self.infcx().eq_tys(a.ty, b.ty).then {|| ok(a) }
15731583
}
1574-
ast::m_imm | ast::m_const {
1584+
m_imm | m_const {
15751585
// Otherwise we can be covariant:
15761586
self.tys(a.ty, b.ty).chain {|_t| ok(a) }
15771587
}
@@ -1710,24 +1720,24 @@ impl of combine for lub {
17101720
let m = if a.mutbl == b.mutbl {
17111721
a.mutbl
17121722
} else {
1713-
ast::m_const
1723+
m_const
17141724
};
17151725

17161726
alt m {
1717-
ast::m_imm | ast::m_const {
1727+
m_imm | m_const {
17181728
self.tys(a.ty, b.ty).chain {|t|
17191729
ok({ty: t, mutbl: m})
17201730
}
17211731
}
17221732

1723-
ast::m_mutbl {
1733+
m_mutbl {
17241734
self.infcx().try {||
17251735
self.infcx().eq_tys(a.ty, b.ty).then {||
17261736
ok({ty: a.ty, mutbl: m})
17271737
}
17281738
}.chain_err {|_e|
17291739
self.tys(a.ty, b.ty).chain {|t|
1730-
ok({ty: t, mutbl: ast::m_const})
1740+
ok({ty: t, mutbl: m_const})
17311741
}
17321742
}
17331743
}
@@ -1893,43 +1903,43 @@ impl of combine for glb {
18931903
alt (a.mutbl, b.mutbl) {
18941904
// If one side or both is mut, then the GLB must use
18951905
// the precise type from the mut side.
1896-
(ast::m_mutbl, ast::m_const) {
1906+
(m_mutbl, m_const) {
18971907
sub(*self).tys(a.ty, b.ty).chain {|_t|
1898-
ok({ty: a.ty, mutbl: ast::m_mutbl})
1908+
ok({ty: a.ty, mutbl: m_mutbl})
18991909
}
19001910
}
1901-
(ast::m_const, ast::m_mutbl) {
1911+
(m_const, m_mutbl) {
19021912
sub(*self).tys(b.ty, a.ty).chain {|_t|
1903-
ok({ty: b.ty, mutbl: ast::m_mutbl})
1913+
ok({ty: b.ty, mutbl: m_mutbl})
19041914
}
19051915
}
1906-
(ast::m_mutbl, ast::m_mutbl) {
1916+
(m_mutbl, m_mutbl) {
19071917
self.infcx().eq_tys(a.ty, b.ty).then {||
1908-
ok({ty: a.ty, mutbl: ast::m_mutbl})
1918+
ok({ty: a.ty, mutbl: m_mutbl})
19091919
}
19101920
}
19111921

19121922
// If one side or both is immutable, we can use the GLB of
19131923
// both sides but mutbl must be `m_imm`.
1914-
(ast::m_imm, ast::m_const) |
1915-
(ast::m_const, ast::m_imm) |
1916-
(ast::m_imm, ast::m_imm) {
1924+
(m_imm, m_const) |
1925+
(m_const, m_imm) |
1926+
(m_imm, m_imm) {
19171927
self.tys(a.ty, b.ty).chain {|t|
1918-
ok({ty: t, mutbl: ast::m_imm})
1928+
ok({ty: t, mutbl: m_imm})
19191929
}
19201930
}
19211931

19221932
// If both sides are const, then we can use GLB of both
19231933
// sides and mutbl of only `m_const`.
1924-
(ast::m_const, ast::m_const) {
1934+
(m_const, m_const) {
19251935
self.tys(a.ty, b.ty).chain {|t|
1926-
ok({ty: t, mutbl: ast::m_const})
1936+
ok({ty: t, mutbl: m_const})
19271937
}
19281938
}
19291939

19301940
// There is no mutual subtype of these combinations.
1931-
(ast::m_mutbl, ast::m_imm) |
1932-
(ast::m_imm, ast::m_mutbl) {
1941+
(m_mutbl, m_imm) |
1942+
(m_imm, m_mutbl) {
19331943
err(ty::terr_mutability)
19341944
}
19351945
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// xfail-fast (compile-flags unsupported on windows)
2+
// compile-flags:--borrowck=err
3+
4+
fn want_slice(v: [int]/&) -> int {
5+
let mut sum = 0;
6+
for vec::each(v) { |i| sum += i; }
7+
ret sum;
8+
}
9+
10+
fn has_mut_vec(+v: @[mut int]) -> int {
11+
want_slice(*v) //! ERROR illegal borrow unless pure: creating immutable alias to aliasable, mutable memory
12+
//!^ NOTE impure due to access to impure function
13+
}
14+
15+
fn main() {
16+
assert has_mut_vec(@[mut 1, 2, 3]) == 6;
17+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// xfail-fast (compile-flags unsupported on windows)
2+
// compile-flags:--borrowck=err
3+
4+
fn want_slice(v: [int]/&) -> int {
5+
let mut sum = 0;
6+
for vec::each(v) { |i| sum += i; }
7+
ret sum;
8+
}
9+
10+
fn has_mut_vec(+v: [mut int]) -> int {
11+
want_slice(v)
12+
}
13+
14+
fn main() {
15+
assert has_mut_vec([mut 1, 2, 3]) == 6;
16+
}

0 commit comments

Comments
 (0)