Skip to content

Commit db20601

Browse files
nikomatsakisJames Miller
authored and
James Miller
committed
Issue the correct deref count for the implicit deref that occurs
as part of an autoslice operation (rust-lang#6272). Fixes rust-lang#6272.
1 parent 94b60bc commit db20601

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)