Skip to content

Commit 15164cc

Browse files
committed
Issue the correct deref count for the implicit deref that occurs
as part of an autoslice operation (#6272). Fixes #6272.
1 parent ca95e7f commit 15164cc

File tree

6 files changed

+67
-19
lines changed

6 files changed

+67
-19
lines changed

src/librustc/middle/borrowck/gather_loans/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,7 @@ pub impl GatherLoanCtxt {
260260
r)
261261
}
262262
ty::AutoBorrowVec(r, m) | ty::AutoBorrowVecRef(r, m) => {
263-
let cmt_index = mcx.cat_index(expr, cmt);
263+
let cmt_index = mcx.cat_index(expr, cmt, autoderefs+1);
264264
self.guarantee_valid(expr.id,
265265
expr.span,
266266
cmt_index,
@@ -574,7 +574,7 @@ pub impl GatherLoanCtxt {
574574
let (slice_mutbl, slice_r) =
575575
self.vec_slice_info(slice_pat, slice_ty);
576576
let mcx = self.bccx.mc_ctxt();
577-
let cmt_index = mcx.cat_index(slice_pat, cmt);
577+
let cmt_index = mcx.cat_index(slice_pat, cmt, 0);
578578
self.guarantee_valid(pat.id, pat.span,
579579
cmt_index, slice_mutbl, slice_r);
580580
}

src/librustc/middle/borrowck/mod.rs

+10
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,16 @@ pub type LoanMap = @mut HashMap<ast::node_id, @Loan>;
184184
//
185185
// Note that there is no entry with derefs:3---the type of that expression
186186
// is T, which is not a box.
187+
//
188+
// Note that implicit dereferences also occur with indexing of `@[]`,
189+
// `@str`, etc. The same rules apply. So, for example, given a
190+
// variable `x` of type `@[@[...]]`, if I have an instance of the
191+
// expression `x[0]` which is then auto-slice'd, there would be two
192+
// potential entries in the root map, both with the id of the `x[0]`
193+
// expression. The entry with `derefs==0` refers to the deref of `x`
194+
// used as part of evaluating `x[0]`. The entry with `derefs==1`
195+
// refers to the deref of the `x[0]` that occurs as part of the
196+
// auto-slice.
187197
#[deriving(Eq, IterBytes)]
188198
pub struct root_map_key {
189199
id: ast::node_id,

src/librustc/middle/mem_categorization.rs

+36-5
Original file line numberDiff line numberDiff line change
@@ -405,7 +405,7 @@ pub impl mem_categorization_ctxt {
405405
}
406406

407407
let base_cmt = self.cat_expr(base);
408-
self.cat_index(expr, base_cmt)
408+
self.cat_index(expr, base_cmt, 0)
409409
}
410410

411411
ast::expr_path(_) => {
@@ -670,7 +670,39 @@ pub impl mem_categorization_ctxt {
670670

671671
fn cat_index<N:ast_node>(&self,
672672
elt: N,
673-
base_cmt: cmt) -> cmt {
673+
base_cmt: cmt,
674+
derefs: uint) -> cmt {
675+
//! Creates a cmt for an indexing operation (`[]`); this
676+
//! indexing operation may occurs as part of an
677+
//! AutoBorrowVec, which when converting a `~[]` to an `&[]`
678+
//! effectively takes the address of the 0th element.
679+
//!
680+
//! One subtle aspect of indexing that may not be
681+
//! immediately obvious: for anything other than a fixed-length
682+
//! vector, an operation like `x[y]` actually consists of two
683+
//! disjoint (from the point of view of borrowck) operations.
684+
//! The first is a deref of `x` to create a pointer `p` that points
685+
//! at the first element in the array. The second operation is
686+
//! an index which adds `y*sizeof(T)` to `p` to obtain the
687+
//! pointer to `x[y]`. `cat_index` will produce a resulting
688+
//! cmt containing both this deref and the indexing,
689+
//! presuming that `base_cmt` is not of fixed-length type.
690+
//!
691+
//! In the event that a deref is needed, the "deref count"
692+
//! is taken from the parameter `derefs`. See the comment
693+
//! on the def'n of `root_map_key` in borrowck/mod.rs
694+
//! for more details about deref counts; the summary is
695+
//! that `derefs` should be 0 for an explicit indexing
696+
//! operation and N+1 for an indexing that is part of
697+
//! an auto-adjustment, where N is the number of autoderefs
698+
//! in that adjustment.
699+
//!
700+
//! # Parameters
701+
//! - `elt`: the AST node being indexed
702+
//! - `base_cmt`: the cmt of `elt`
703+
//! - `derefs`: the deref number to be used for
704+
//! the implicit index deref, if any (see above)
705+
674706
let mt = match ty::index(base_cmt.ty) {
675707
Some(mt) => mt,
676708
None => {
@@ -698,7 +730,7 @@ pub impl mem_categorization_ctxt {
698730
let deref_cmt = @cmt_ {
699731
id:elt.id(),
700732
span:elt.span(),
701-
cat:cat_deref(base_cmt, 0u, ptr),
733+
cat:cat_deref(base_cmt, derefs, ptr),
702734
mutbl:m,
703735
ty:mt.ty
704736
};
@@ -878,8 +910,8 @@ pub impl mem_categorization_ctxt {
878910
}
879911

880912
ast::pat_vec(ref before, slice, ref after) => {
913+
let elt_cmt = self.cat_index(pat, cmt, 0);
881914
for before.each |&before_pat| {
882-
let elt_cmt = self.cat_index(pat, cmt);
883915
self.cat_pattern(elt_cmt, before_pat, op);
884916
}
885917
for slice.each |&slice_pat| {
@@ -888,7 +920,6 @@ pub impl mem_categorization_ctxt {
888920
self.cat_pattern(slice_cmt, slice_pat, op);
889921
}
890922
for after.each |&after_pat| {
891-
let elt_cmt = self.cat_index(pat, cmt);
892923
self.cat_pattern(elt_cmt, after_pat, op);
893924
}
894925
}

src/librustc/middle/trans/_match.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -885,7 +885,8 @@ pub fn extract_vec_elems(bcx: block,
885885
-> ExtractedBlock {
886886
let _icx = bcx.insn_ctxt("match::extract_vec_elems");
887887
let vec_datum = match_datum(bcx, val, pat_id);
888-
let (bcx, base, len) = vec_datum.get_vec_base_and_len(bcx, pat_span, pat_id);
888+
let (bcx, base, len) = vec_datum.get_vec_base_and_len(bcx, pat_span,
889+
pat_id, 0);
889890
let vt = tvec::vec_types(bcx, node_id_type(bcx, pat_id));
890891
891892
let mut elems = do vec::from_fn(elem_count) |i| {

src/librustc/middle/trans/datum.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -735,13 +735,14 @@ pub impl Datum {
735735
fn get_vec_base_and_len(&self,
736736
mut bcx: block,
737737
span: span,
738-
expr_id: ast::node_id)
738+
expr_id: ast::node_id,
739+
derefs: uint)
739740
-> (block, ValueRef, ValueRef) {
740741
//! Converts a vector into the slice pair. Performs rooting
741742
//! and write guards checks.
742743
743744
// only imp't for @[] and @str, but harmless
744-
bcx = write_guard::root_and_write_guard(self, bcx, span, expr_id, 0);
745+
bcx = write_guard::root_and_write_guard(self, bcx, span, expr_id, derefs);
745746
let (base, len) = self.get_vec_base_and_len_no_root(bcx);
746747
(bcx, base, len)
747748
}

src/librustc/middle/trans/expr.rs

+14-9
Original file line numberDiff line numberDiff line change
@@ -144,10 +144,9 @@ use middle::trans::tvec;
144144
use middle::trans::type_of;
145145
use middle::ty::struct_fields;
146146
use middle::ty::{AutoDerefRef, AutoAddEnv};
147-
use middle::ty::{AutoPtr, AutoBorrowVec, AutoBorrowVecRef, AutoBorrowFn};
148-
use middle::ty;
149147
use middle::ty::{AutoPtr, AutoBorrowVec, AutoBorrowVecRef, AutoBorrowFn,
150148
AutoDerefRef, AutoAddEnv, AutoUnsafe};
149+
use middle::ty;
151150
use util::common::indenter;
152151
use util::ppaux::Repr;
153152

@@ -215,10 +214,12 @@ pub fn trans_to_datum(bcx: block, expr: @ast::expr) -> DatumBlock {
215214
unpack_datum!(bcx, auto_ref(bcx, datum))
216215
}
217216
Some(AutoBorrowVec(*)) => {
218-
unpack_datum!(bcx, auto_slice(bcx, expr, datum))
217+
unpack_datum!(bcx, auto_slice(bcx, adj.autoderefs,
218+
expr, datum))
219219
}
220220
Some(AutoBorrowVecRef(*)) => {
221-
unpack_datum!(bcx, auto_slice_and_ref(bcx, expr, datum))
221+
unpack_datum!(bcx, auto_slice_and_ref(bcx, adj.autoderefs,
222+
expr, datum))
222223
}
223224
Some(AutoBorrowFn(*)) => {
224225
let adjusted_ty = ty::adjust_ty(bcx.tcx(), expr.span,
@@ -246,7 +247,10 @@ pub fn trans_to_datum(bcx: block, expr: @ast::expr) -> DatumBlock {
246247
mode: datum.mode, source: datum.source}}
247248
}
248249

249-
fn auto_slice(bcx: block, expr: @ast::expr, datum: Datum) -> DatumBlock {
250+
fn auto_slice(bcx: block,
251+
autoderefs: uint,
252+
expr: @ast::expr,
253+
datum: Datum) -> DatumBlock {
250254
// This is not the most efficient thing possible; since slices
251255
// are two words it'd be better if this were compiled in
252256
// 'dest' mode, but I can't find a nice way to structure the
@@ -256,9 +260,8 @@ pub fn trans_to_datum(bcx: block, expr: @ast::expr) -> DatumBlock {
256260
let tcx = bcx.tcx();
257261
let unit_ty = ty::sequence_element_type(tcx, datum.ty);
258262

259-
// FIXME(#6272) need to distinguish "auto-slice" from explicit index?
260263
let (bcx, base, len) =
261-
datum.get_vec_base_and_len(bcx, expr.span, expr.id);
264+
datum.get_vec_base_and_len(bcx, expr.span, expr.id, autoderefs+1);
262265

263266
// this type may have a different region/mutability than the
264267
// real one, but it will have the same runtime representation
@@ -292,9 +295,10 @@ pub fn trans_to_datum(bcx: block, expr: @ast::expr) -> DatumBlock {
292295
}
293296

294297
fn auto_slice_and_ref(bcx: block,
298+
autoderefs: uint,
295299
expr: @ast::expr,
296300
datum: Datum) -> DatumBlock {
297-
let DatumBlock { bcx, datum } = auto_slice(bcx, expr, datum);
301+
let DatumBlock { bcx, datum } = auto_slice(bcx, autoderefs, expr, datum);
298302
auto_ref(bcx, datum)
299303
}
300304
}
@@ -913,7 +917,8 @@ fn trans_lvalue_unadjusted(bcx: block, expr: @ast::expr) -> DatumBlock {
913917
base::maybe_name_value(bcx.ccx(), scaled_ix, ~"scaled_ix");
914918

915919
let mut (bcx, base, len) =
916-
base_datum.get_vec_base_and_len(bcx, index_expr.span, index_expr.id);
920+
base_datum.get_vec_base_and_len(bcx, index_expr.span,
921+
index_expr.id, 0);
917922

918923
if ty::type_is_str(base_ty) {
919924
// acccount for null terminator in the case of string

0 commit comments

Comments
 (0)