Issue the correct deref count for the implicit deref that occurs
as part of an autoslice operation (#6272). Fixes #6272.
This commit is contained in:
parent
ca95e7f94e
commit
15164cc6a6
@ -260,7 +260,7 @@ pub impl GatherLoanCtxt {
|
|||||||
r)
|
r)
|
||||||
}
|
}
|
||||||
ty::AutoBorrowVec(r, m) | ty::AutoBorrowVecRef(r, m) => {
|
ty::AutoBorrowVec(r, m) | ty::AutoBorrowVecRef(r, m) => {
|
||||||
let cmt_index = mcx.cat_index(expr, cmt);
|
let cmt_index = mcx.cat_index(expr, cmt, autoderefs+1);
|
||||||
self.guarantee_valid(expr.id,
|
self.guarantee_valid(expr.id,
|
||||||
expr.span,
|
expr.span,
|
||||||
cmt_index,
|
cmt_index,
|
||||||
@ -574,7 +574,7 @@ pub impl GatherLoanCtxt {
|
|||||||
let (slice_mutbl, slice_r) =
|
let (slice_mutbl, slice_r) =
|
||||||
self.vec_slice_info(slice_pat, slice_ty);
|
self.vec_slice_info(slice_pat, slice_ty);
|
||||||
let mcx = self.bccx.mc_ctxt();
|
let mcx = self.bccx.mc_ctxt();
|
||||||
let cmt_index = mcx.cat_index(slice_pat, cmt);
|
let cmt_index = mcx.cat_index(slice_pat, cmt, 0);
|
||||||
self.guarantee_valid(pat.id, pat.span,
|
self.guarantee_valid(pat.id, pat.span,
|
||||||
cmt_index, slice_mutbl, slice_r);
|
cmt_index, slice_mutbl, slice_r);
|
||||||
}
|
}
|
||||||
|
@ -184,6 +184,16 @@ pub type LoanMap = @mut HashMap<ast::node_id, @Loan>;
|
|||||||
//
|
//
|
||||||
// Note that there is no entry with derefs:3---the type of that expression
|
// Note that there is no entry with derefs:3---the type of that expression
|
||||||
// is T, which is not a box.
|
// is T, which is not a box.
|
||||||
|
//
|
||||||
|
// Note that implicit dereferences also occur with indexing of `@[]`,
|
||||||
|
// `@str`, etc. The same rules apply. So, for example, given a
|
||||||
|
// variable `x` of type `@[@[...]]`, if I have an instance of the
|
||||||
|
// expression `x[0]` which is then auto-slice'd, there would be two
|
||||||
|
// potential entries in the root map, both with the id of the `x[0]`
|
||||||
|
// expression. The entry with `derefs==0` refers to the deref of `x`
|
||||||
|
// used as part of evaluating `x[0]`. The entry with `derefs==1`
|
||||||
|
// refers to the deref of the `x[0]` that occurs as part of the
|
||||||
|
// auto-slice.
|
||||||
#[deriving(Eq, IterBytes)]
|
#[deriving(Eq, IterBytes)]
|
||||||
pub struct root_map_key {
|
pub struct root_map_key {
|
||||||
id: ast::node_id,
|
id: ast::node_id,
|
||||||
|
@ -405,7 +405,7 @@ pub impl mem_categorization_ctxt {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let base_cmt = self.cat_expr(base);
|
let base_cmt = self.cat_expr(base);
|
||||||
self.cat_index(expr, base_cmt)
|
self.cat_index(expr, base_cmt, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
ast::expr_path(_) => {
|
ast::expr_path(_) => {
|
||||||
@ -670,7 +670,39 @@ pub impl mem_categorization_ctxt {
|
|||||||
|
|
||||||
fn cat_index<N:ast_node>(&self,
|
fn cat_index<N:ast_node>(&self,
|
||||||
elt: N,
|
elt: N,
|
||||||
base_cmt: cmt) -> cmt {
|
base_cmt: cmt,
|
||||||
|
derefs: uint) -> cmt {
|
||||||
|
//! Creates a cmt for an indexing operation (`[]`); this
|
||||||
|
//! indexing operation may occurs as part of an
|
||||||
|
//! AutoBorrowVec, which when converting a `~[]` to an `&[]`
|
||||||
|
//! effectively takes the address of the 0th element.
|
||||||
|
//!
|
||||||
|
//! One subtle aspect of indexing that may not be
|
||||||
|
//! immediately obvious: for anything other than a fixed-length
|
||||||
|
//! vector, an operation like `x[y]` actually consists of two
|
||||||
|
//! disjoint (from the point of view of borrowck) operations.
|
||||||
|
//! The first is a deref of `x` to create a pointer `p` that points
|
||||||
|
//! at the first element in the array. The second operation is
|
||||||
|
//! an index which adds `y*sizeof(T)` to `p` to obtain the
|
||||||
|
//! pointer to `x[y]`. `cat_index` will produce a resulting
|
||||||
|
//! cmt containing both this deref and the indexing,
|
||||||
|
//! presuming that `base_cmt` is not of fixed-length type.
|
||||||
|
//!
|
||||||
|
//! In the event that a deref is needed, the "deref count"
|
||||||
|
//! is taken from the parameter `derefs`. See the comment
|
||||||
|
//! on the def'n of `root_map_key` in borrowck/mod.rs
|
||||||
|
//! for more details about deref counts; the summary is
|
||||||
|
//! that `derefs` should be 0 for an explicit indexing
|
||||||
|
//! operation and N+1 for an indexing that is part of
|
||||||
|
//! an auto-adjustment, where N is the number of autoderefs
|
||||||
|
//! in that adjustment.
|
||||||
|
//!
|
||||||
|
//! # Parameters
|
||||||
|
//! - `elt`: the AST node being indexed
|
||||||
|
//! - `base_cmt`: the cmt of `elt`
|
||||||
|
//! - `derefs`: the deref number to be used for
|
||||||
|
//! the implicit index deref, if any (see above)
|
||||||
|
|
||||||
let mt = match ty::index(base_cmt.ty) {
|
let mt = match ty::index(base_cmt.ty) {
|
||||||
Some(mt) => mt,
|
Some(mt) => mt,
|
||||||
None => {
|
None => {
|
||||||
@ -698,7 +730,7 @@ pub impl mem_categorization_ctxt {
|
|||||||
let deref_cmt = @cmt_ {
|
let deref_cmt = @cmt_ {
|
||||||
id:elt.id(),
|
id:elt.id(),
|
||||||
span:elt.span(),
|
span:elt.span(),
|
||||||
cat:cat_deref(base_cmt, 0u, ptr),
|
cat:cat_deref(base_cmt, derefs, ptr),
|
||||||
mutbl:m,
|
mutbl:m,
|
||||||
ty:mt.ty
|
ty:mt.ty
|
||||||
};
|
};
|
||||||
@ -878,8 +910,8 @@ pub impl mem_categorization_ctxt {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ast::pat_vec(ref before, slice, ref after) => {
|
ast::pat_vec(ref before, slice, ref after) => {
|
||||||
|
let elt_cmt = self.cat_index(pat, cmt, 0);
|
||||||
for before.each |&before_pat| {
|
for before.each |&before_pat| {
|
||||||
let elt_cmt = self.cat_index(pat, cmt);
|
|
||||||
self.cat_pattern(elt_cmt, before_pat, op);
|
self.cat_pattern(elt_cmt, before_pat, op);
|
||||||
}
|
}
|
||||||
for slice.each |&slice_pat| {
|
for slice.each |&slice_pat| {
|
||||||
@ -888,7 +920,6 @@ pub impl mem_categorization_ctxt {
|
|||||||
self.cat_pattern(slice_cmt, slice_pat, op);
|
self.cat_pattern(slice_cmt, slice_pat, op);
|
||||||
}
|
}
|
||||||
for after.each |&after_pat| {
|
for after.each |&after_pat| {
|
||||||
let elt_cmt = self.cat_index(pat, cmt);
|
|
||||||
self.cat_pattern(elt_cmt, after_pat, op);
|
self.cat_pattern(elt_cmt, after_pat, op);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -885,7 +885,8 @@ pub fn extract_vec_elems(bcx: block,
|
|||||||
-> ExtractedBlock {
|
-> ExtractedBlock {
|
||||||
let _icx = bcx.insn_ctxt("match::extract_vec_elems");
|
let _icx = bcx.insn_ctxt("match::extract_vec_elems");
|
||||||
let vec_datum = match_datum(bcx, val, pat_id);
|
let vec_datum = match_datum(bcx, val, pat_id);
|
||||||
let (bcx, base, len) = vec_datum.get_vec_base_and_len(bcx, pat_span, pat_id);
|
let (bcx, base, len) = vec_datum.get_vec_base_and_len(bcx, pat_span,
|
||||||
|
pat_id, 0);
|
||||||
let vt = tvec::vec_types(bcx, node_id_type(bcx, pat_id));
|
let vt = tvec::vec_types(bcx, node_id_type(bcx, pat_id));
|
||||||
|
|
||||||
let mut elems = do vec::from_fn(elem_count) |i| {
|
let mut elems = do vec::from_fn(elem_count) |i| {
|
||||||
|
@ -735,13 +735,14 @@ pub impl Datum {
|
|||||||
fn get_vec_base_and_len(&self,
|
fn get_vec_base_and_len(&self,
|
||||||
mut bcx: block,
|
mut bcx: block,
|
||||||
span: span,
|
span: span,
|
||||||
expr_id: ast::node_id)
|
expr_id: ast::node_id,
|
||||||
|
derefs: uint)
|
||||||
-> (block, ValueRef, ValueRef) {
|
-> (block, ValueRef, ValueRef) {
|
||||||
//! Converts a vector into the slice pair. Performs rooting
|
//! Converts a vector into the slice pair. Performs rooting
|
||||||
//! and write guards checks.
|
//! and write guards checks.
|
||||||
|
|
||||||
// only imp't for @[] and @str, but harmless
|
// only imp't for @[] and @str, but harmless
|
||||||
bcx = write_guard::root_and_write_guard(self, bcx, span, expr_id, 0);
|
bcx = write_guard::root_and_write_guard(self, bcx, span, expr_id, derefs);
|
||||||
let (base, len) = self.get_vec_base_and_len_no_root(bcx);
|
let (base, len) = self.get_vec_base_and_len_no_root(bcx);
|
||||||
(bcx, base, len)
|
(bcx, base, len)
|
||||||
}
|
}
|
||||||
|
@ -144,10 +144,9 @@ use middle::trans::tvec;
|
|||||||
use middle::trans::type_of;
|
use middle::trans::type_of;
|
||||||
use middle::ty::struct_fields;
|
use middle::ty::struct_fields;
|
||||||
use middle::ty::{AutoDerefRef, AutoAddEnv};
|
use middle::ty::{AutoDerefRef, AutoAddEnv};
|
||||||
use middle::ty::{AutoPtr, AutoBorrowVec, AutoBorrowVecRef, AutoBorrowFn};
|
|
||||||
use middle::ty;
|
|
||||||
use middle::ty::{AutoPtr, AutoBorrowVec, AutoBorrowVecRef, AutoBorrowFn,
|
use middle::ty::{AutoPtr, AutoBorrowVec, AutoBorrowVecRef, AutoBorrowFn,
|
||||||
AutoDerefRef, AutoAddEnv, AutoUnsafe};
|
AutoDerefRef, AutoAddEnv, AutoUnsafe};
|
||||||
|
use middle::ty;
|
||||||
use util::common::indenter;
|
use util::common::indenter;
|
||||||
use util::ppaux::Repr;
|
use util::ppaux::Repr;
|
||||||
|
|
||||||
@ -215,10 +214,12 @@ pub fn trans_to_datum(bcx: block, expr: @ast::expr) -> DatumBlock {
|
|||||||
unpack_datum!(bcx, auto_ref(bcx, datum))
|
unpack_datum!(bcx, auto_ref(bcx, datum))
|
||||||
}
|
}
|
||||||
Some(AutoBorrowVec(*)) => {
|
Some(AutoBorrowVec(*)) => {
|
||||||
unpack_datum!(bcx, auto_slice(bcx, expr, datum))
|
unpack_datum!(bcx, auto_slice(bcx, adj.autoderefs,
|
||||||
|
expr, datum))
|
||||||
}
|
}
|
||||||
Some(AutoBorrowVecRef(*)) => {
|
Some(AutoBorrowVecRef(*)) => {
|
||||||
unpack_datum!(bcx, auto_slice_and_ref(bcx, expr, datum))
|
unpack_datum!(bcx, auto_slice_and_ref(bcx, adj.autoderefs,
|
||||||
|
expr, datum))
|
||||||
}
|
}
|
||||||
Some(AutoBorrowFn(*)) => {
|
Some(AutoBorrowFn(*)) => {
|
||||||
let adjusted_ty = ty::adjust_ty(bcx.tcx(), expr.span,
|
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 {
|
|||||||
mode: datum.mode, source: datum.source}}
|
mode: datum.mode, source: datum.source}}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn auto_slice(bcx: block, expr: @ast::expr, datum: Datum) -> DatumBlock {
|
fn auto_slice(bcx: block,
|
||||||
|
autoderefs: uint,
|
||||||
|
expr: @ast::expr,
|
||||||
|
datum: Datum) -> DatumBlock {
|
||||||
// This is not the most efficient thing possible; since slices
|
// This is not the most efficient thing possible; since slices
|
||||||
// are two words it'd be better if this were compiled in
|
// are two words it'd be better if this were compiled in
|
||||||
// 'dest' mode, but I can't find a nice way to structure the
|
// '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 {
|
|||||||
let tcx = bcx.tcx();
|
let tcx = bcx.tcx();
|
||||||
let unit_ty = ty::sequence_element_type(tcx, datum.ty);
|
let unit_ty = ty::sequence_element_type(tcx, datum.ty);
|
||||||
|
|
||||||
// FIXME(#6272) need to distinguish "auto-slice" from explicit index?
|
|
||||||
let (bcx, base, len) =
|
let (bcx, base, len) =
|
||||||
datum.get_vec_base_and_len(bcx, expr.span, expr.id);
|
datum.get_vec_base_and_len(bcx, expr.span, expr.id, autoderefs+1);
|
||||||
|
|
||||||
// this type may have a different region/mutability than the
|
// this type may have a different region/mutability than the
|
||||||
// real one, but it will have the same runtime representation
|
// 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 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn auto_slice_and_ref(bcx: block,
|
fn auto_slice_and_ref(bcx: block,
|
||||||
|
autoderefs: uint,
|
||||||
expr: @ast::expr,
|
expr: @ast::expr,
|
||||||
datum: Datum) -> DatumBlock {
|
datum: Datum) -> DatumBlock {
|
||||||
let DatumBlock { bcx, datum } = auto_slice(bcx, expr, datum);
|
let DatumBlock { bcx, datum } = auto_slice(bcx, autoderefs, expr, datum);
|
||||||
auto_ref(bcx, datum)
|
auto_ref(bcx, datum)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -913,7 +917,8 @@ fn trans_lvalue_unadjusted(bcx: block, expr: @ast::expr) -> DatumBlock {
|
|||||||
base::maybe_name_value(bcx.ccx(), scaled_ix, ~"scaled_ix");
|
base::maybe_name_value(bcx.ccx(), scaled_ix, ~"scaled_ix");
|
||||||
|
|
||||||
let mut (bcx, base, len) =
|
let mut (bcx, base, len) =
|
||||||
base_datum.get_vec_base_and_len(bcx, index_expr.span, index_expr.id);
|
base_datum.get_vec_base_and_len(bcx, index_expr.span,
|
||||||
|
index_expr.id, 0);
|
||||||
|
|
||||||
if ty::type_is_str(base_ty) {
|
if ty::type_is_str(base_ty) {
|
||||||
// acccount for null terminator in the case of string
|
// acccount for null terminator in the case of string
|
||||||
|
Loading…
Reference in New Issue
Block a user