Skip to content

Commit 6c35d51

Browse files
committed
auto merge of #15656 : nick29581/rust/index-bck, r=pnkfelix
Closes #15525 The important bit of this are the changes from line 445 in mem_categorization.rs. Most of the other changes are about adding an Implicit PointerKind, and this is only necessary for getting a decent error message :-s An alternative would have been to add an implciti/explicit flag to cat_deref, which could be mostly ignored and so would mean much fewer changes. However, the implicit state would only be valid if the PointerKind was BorrowedPtr, so it felt like it ought to be another kind of PointerKind. I still don't know which is the better design.
2 parents c523d86 + 2bc6547 commit 6c35d51

File tree

9 files changed

+96
-23
lines changed

9 files changed

+96
-23
lines changed

src/librustc/middle/borrowck/check_loans.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -734,7 +734,8 @@ impl<'a> CheckLoanCtxt<'a> {
734734
mc::cat_static_item |
735735
mc::cat_copied_upvar(..) |
736736
mc::cat_deref(_, _, mc::UnsafePtr(..)) |
737-
mc::cat_deref(_, _, mc::BorrowedPtr(..)) => {
737+
mc::cat_deref(_, _, mc::BorrowedPtr(..)) |
738+
mc::cat_deref(_, _, mc::Implicit(..)) => {
738739
assert_eq!(cmt.mutbl, mc::McDeclared);
739740
return;
740741
}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ fn check_and_get_illegal_move_origin(bccx: &BorrowckCtxt,
131131
cmt: &mc::cmt) -> Option<mc::cmt> {
132132
match cmt.cat {
133133
mc::cat_deref(_, _, mc::BorrowedPtr(..)) |
134+
mc::cat_deref(_, _, mc::Implicit(..)) |
134135
mc::cat_deref(_, _, mc::GcPtr) |
135136
mc::cat_deref(_, _, mc::UnsafePtr(..)) |
136137
mc::cat_upvar(..) | mc::cat_static_item |

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ impl<'a> GuaranteeLifetimeContext<'a> {
7272
mc::cat_arg(..) | // L-Local
7373
mc::cat_upvar(..) |
7474
mc::cat_deref(_, _, mc::BorrowedPtr(..)) | // L-Deref-Borrowed
75+
mc::cat_deref(_, _, mc::Implicit(..)) |
7576
mc::cat_deref(_, _, mc::UnsafePtr(..)) => {
7677
self.check_scope(self.scope(cmt))
7778
}
@@ -180,7 +181,8 @@ impl<'a> GuaranteeLifetimeContext<'a> {
180181
mc::cat_deref(_, _, mc::UnsafePtr(..)) => {
181182
ty::ReStatic
182183
}
183-
mc::cat_deref(_, _, mc::BorrowedPtr(_, r)) => {
184+
mc::cat_deref(_, _, mc::BorrowedPtr(_, r)) |
185+
mc::cat_deref(_, _, mc::Implicit(_, r)) => {
184186
r
185187
}
186188
mc::cat_downcast(ref cmt) |

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ fn group_errors_with_same_origin(errors: &Vec<MoveError>)
113113
fn report_cannot_move_out_of(bccx: &BorrowckCtxt, move_from: mc::cmt) {
114114
match move_from.cat {
115115
mc::cat_deref(_, _, mc::BorrowedPtr(..)) |
116+
mc::cat_deref(_, _, mc::Implicit(..)) |
116117
mc::cat_deref(_, _, mc::GcPtr) |
117118
mc::cat_deref(_, _, mc::UnsafePtr(..)) |
118119
mc::cat_upvar(..) | mc::cat_static_item |

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

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,9 @@ impl<'a> RestrictionsContext<'a> {
122122
}
123123

124124
mc::cat_deref(cmt_base, _, mc::BorrowedPtr(ty::ImmBorrow, lt)) |
125-
mc::cat_deref(cmt_base, _, mc::BorrowedPtr(ty::UniqueImmBorrow, lt)) => {
125+
mc::cat_deref(cmt_base, _, mc::BorrowedPtr(ty::UniqueImmBorrow, lt)) |
126+
mc::cat_deref(cmt_base, _, mc::Implicit(ty::ImmBorrow, lt)) |
127+
mc::cat_deref(cmt_base, _, mc::Implicit(ty::UniqueImmBorrow, lt)) => {
126128
// R-Deref-Imm-Borrowed
127129
if !self.bccx.is_subregion_of(self.loan_region, lt) {
128130
self.bccx.report(
@@ -137,7 +139,8 @@ impl<'a> RestrictionsContext<'a> {
137139
Safe
138140
}
139141

140-
mc::cat_deref(cmt_base, _, pk @ mc::BorrowedPtr(ty::MutBorrow, lt)) => {
142+
mc::cat_deref(cmt_base, _, pk @ mc::BorrowedPtr(ty::MutBorrow, lt)) |
143+
mc::cat_deref(cmt_base, _, pk @ mc::Implicit(ty::MutBorrow, lt)) => {
141144
// R-Deref-Mut-Borrowed
142145
if !self.bccx.is_subregion_of(self.loan_region, lt) {
143146
self.bccx.report(

src/librustc/middle/mem_categorization.rs

Lines changed: 51 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,8 @@ pub enum PointerKind {
106106
OwnedPtr,
107107
GcPtr,
108108
BorrowedPtr(ty::BorrowKind, ty::Region),
109-
UnsafePtr(ast::Mutability),
109+
Implicit(ty::BorrowKind, ty::Region), // Implicit deref of a borrowed ptr.
110+
UnsafePtr(ast::Mutability)
110111
}
111112

112113
// We use the term "interior" to mean "something reachable from the
@@ -293,7 +294,7 @@ impl MutabilityCategory {
293294
OwnedPtr => {
294295
base_mutbl.inherit()
295296
}
296-
BorrowedPtr(borrow_kind, _) => {
297+
BorrowedPtr(borrow_kind, _) | Implicit(borrow_kind, _) => {
297298
MutabilityCategory::from_borrow_kind(borrow_kind)
298299
}
299300
GcPtr => {
@@ -422,7 +423,7 @@ impl<'t,TYPER:Typer> MemCategorizationContext<'t,TYPER> {
422423
-> McResult<cmt> {
423424
let mut cmt = if_ok!(self.cat_expr_unadjusted(expr));
424425
for deref in range(1u, autoderefs + 1) {
425-
cmt = self.cat_deref(expr, cmt, deref);
426+
cmt = self.cat_deref(expr, cmt, deref, false);
426427
}
427428
return Ok(cmt);
428429
}
@@ -434,7 +435,7 @@ impl<'t,TYPER:Typer> MemCategorizationContext<'t,TYPER> {
434435
match expr.node {
435436
ast::ExprUnary(ast::UnDeref, ref e_base) => {
436437
let base_cmt = if_ok!(self.cat_expr(&**e_base));
437-
Ok(self.cat_deref(expr, base_cmt, 0))
438+
Ok(self.cat_deref(expr, base_cmt, 0, false))
438439
}
439440

440441
ast::ExprField(ref base, f_name, _) => {
@@ -443,8 +444,22 @@ impl<'t,TYPER:Typer> MemCategorizationContext<'t,TYPER> {
443444
}
444445

445446
ast::ExprIndex(ref base, _) => {
446-
let base_cmt = if_ok!(self.cat_expr(&**base));
447-
Ok(self.cat_index(expr, base_cmt, 0))
447+
let method_call = typeck::MethodCall::expr(expr.id());
448+
match self.typer.node_method_ty(method_call) {
449+
Some(method_ty) => {
450+
// If this is an index implemented by a method call, then it will
451+
// include an implicit deref of the result.
452+
let ret_ty = ty::ty_fn_ret(method_ty);
453+
Ok(self.cat_deref(expr,
454+
self.cat_rvalue_node(expr.id(),
455+
expr.span(),
456+
ret_ty), 1, true))
457+
}
458+
None => {
459+
let base_cmt = if_ok!(self.cat_expr(&**base));
460+
Ok(self.cat_index(expr, base_cmt, 0))
461+
}
462+
}
448463
}
449464

450465
ast::ExprPath(_) => {
@@ -687,13 +702,14 @@ impl<'t,TYPER:Typer> MemCategorizationContext<'t,TYPER> {
687702
}
688703

689704
pub fn cat_deref_obj<N:ast_node>(&self, node: &N, base_cmt: cmt) -> cmt {
690-
self.cat_deref_common(node, base_cmt, 0, ty::mk_nil())
705+
self.cat_deref_common(node, base_cmt, 0, ty::mk_nil(), false)
691706
}
692707

693708
fn cat_deref<N:ast_node>(&self,
694709
node: &N,
695710
base_cmt: cmt,
696-
deref_cnt: uint)
711+
deref_cnt: uint,
712+
implicit: bool)
697713
-> cmt {
698714
let adjustment = match self.typer.adjustments().borrow().find(&node.id()) {
699715
Some(&ty::AutoObject(..)) => typeck::AutoObject,
@@ -717,7 +733,7 @@ impl<'t,TYPER:Typer> MemCategorizationContext<'t,TYPER> {
717733
None => base_cmt
718734
};
719735
match ty::deref(base_cmt.ty, true) {
720-
Some(mt) => self.cat_deref_common(node, base_cmt, deref_cnt, mt.ty),
736+
Some(mt) => self.cat_deref_common(node, base_cmt, deref_cnt, mt.ty, implicit),
721737
None => {
722738
self.tcx().sess.span_bug(
723739
node.span(),
@@ -731,10 +747,20 @@ impl<'t,TYPER:Typer> MemCategorizationContext<'t,TYPER> {
731747
node: &N,
732748
base_cmt: cmt,
733749
deref_cnt: uint,
734-
deref_ty: ty::t)
750+
deref_ty: ty::t,
751+
implicit: bool)
735752
-> cmt {
736753
let (m, cat) = match deref_kind(self.tcx(), base_cmt.ty) {
737754
deref_ptr(ptr) => {
755+
let ptr = if implicit {
756+
match ptr {
757+
BorrowedPtr(bk, r) => Implicit(bk, r),
758+
_ => self.tcx().sess.span_bug(node.span(),
759+
"Implicit deref of non-borrowed pointer")
760+
}
761+
} else {
762+
ptr
763+
};
738764
// for unique ptrs, we inherit mutability from the
739765
// owning reference.
740766
(MutabilityCategory::from_pointer_kind(base_cmt.mutbl, ptr),
@@ -1073,7 +1099,7 @@ impl<'t,TYPER:Typer> MemCategorizationContext<'t,TYPER> {
10731099

10741100
ast::PatBox(ref subpat) | ast::PatRegion(ref subpat) => {
10751101
// @p1, ~p1
1076-
let subcmt = self.cat_deref(pat, cmt, 0);
1102+
let subcmt = self.cat_deref(pat, cmt, 0, false);
10771103
if_ok!(self.cat_pattern(subcmt, &**subpat, op));
10781104
}
10791105

@@ -1129,6 +1155,9 @@ impl<'t,TYPER:Typer> MemCategorizationContext<'t,TYPER> {
11291155
}
11301156
_ => {
11311157
match pk {
1158+
Implicit(..) => {
1159+
"dereference (dereference is implicit, due to indexing)".to_string()
1160+
}
11321161
OwnedPtr | GcPtr => format!("dereference of `{}`", ptr_sigil(pk)),
11331162
_ => format!("dereference of `{}`-pointer", ptr_sigil(pk))
11341163
}
@@ -1188,6 +1217,7 @@ impl cmt_ {
11881217
cat_deref(_, _, UnsafePtr(..)) |
11891218
cat_deref(_, _, GcPtr(..)) |
11901219
cat_deref(_, _, BorrowedPtr(..)) |
1220+
cat_deref(_, _, Implicit(..)) |
11911221
cat_upvar(..) => {
11921222
Rc::new((*self).clone())
11931223
}
@@ -1212,7 +1242,9 @@ impl cmt_ {
12121242

12131243
match self.cat {
12141244
cat_deref(ref b, _, BorrowedPtr(ty::MutBorrow, _)) |
1245+
cat_deref(ref b, _, Implicit(ty::MutBorrow, _)) |
12151246
cat_deref(ref b, _, BorrowedPtr(ty::UniqueImmBorrow, _)) |
1247+
cat_deref(ref b, _, Implicit(ty::UniqueImmBorrow, _)) |
12161248
cat_downcast(ref b) |
12171249
cat_deref(ref b, _, OwnedPtr) |
12181250
cat_interior(ref b, _) |
@@ -1252,7 +1284,8 @@ impl cmt_ {
12521284
Some(AliasableManaged)
12531285
}
12541286

1255-
cat_deref(_, _, BorrowedPtr(ty::ImmBorrow, _)) => {
1287+
cat_deref(_, _, BorrowedPtr(ty::ImmBorrow, _)) |
1288+
cat_deref(_, _, Implicit(ty::ImmBorrow, _)) => {
12561289
Some(AliasableBorrowed)
12571290
}
12581291
}
@@ -1300,9 +1333,12 @@ pub fn ptr_sigil(ptr: PointerKind) -> &'static str {
13001333
match ptr {
13011334
OwnedPtr => "Box",
13021335
GcPtr => "Gc",
1303-
BorrowedPtr(ty::ImmBorrow, _) => "&",
1304-
BorrowedPtr(ty::MutBorrow, _) => "&mut",
1305-
BorrowedPtr(ty::UniqueImmBorrow, _) => "&unique",
1336+
BorrowedPtr(ty::ImmBorrow, _) |
1337+
Implicit(ty::ImmBorrow, _) => "&",
1338+
BorrowedPtr(ty::MutBorrow, _) |
1339+
Implicit(ty::MutBorrow, _) => "&mut",
1340+
BorrowedPtr(ty::UniqueImmBorrow, _) |
1341+
Implicit(ty::UniqueImmBorrow, _) => "&unique",
13061342
UnsafePtr(_) => "*"
13071343
}
13081344
}

src/librustc/middle/typeck/check/regionck.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1219,7 +1219,8 @@ fn link_region(rcx: &Rcx,
12191219
kind.repr(rcx.tcx()),
12201220
cmt_borrowed.repr(rcx.tcx()));
12211221
match cmt_borrowed.cat.clone() {
1222-
mc::cat_deref(base, _, mc::BorrowedPtr(_, r_borrowed)) => {
1222+
mc::cat_deref(base, _, mc::BorrowedPtr(_, r_borrowed)) |
1223+
mc::cat_deref(base, _, mc::Implicit(_, r_borrowed)) => {
12231224
// References to an upvar `x` are translated to
12241225
// `*x`, since that is what happens in the
12251226
// underlying machine. We detect such references
@@ -1340,7 +1341,8 @@ fn adjust_upvar_borrow_kind_for_mut(rcx: &Rcx,
13401341
continue;
13411342
}
13421343

1343-
mc::cat_deref(base, _, mc::BorrowedPtr(..)) => {
1344+
mc::cat_deref(base, _, mc::BorrowedPtr(..)) |
1345+
mc::cat_deref(base, _, mc::Implicit(..)) => {
13441346
match base.cat {
13451347
mc::cat_upvar(ref upvar_id, _) => {
13461348
// if this is an implicit deref of an
@@ -1394,7 +1396,8 @@ fn adjust_upvar_borrow_kind_for_unique(rcx: &Rcx, cmt: mc::cmt) {
13941396
continue;
13951397
}
13961398

1397-
mc::cat_deref(base, _, mc::BorrowedPtr(..)) => {
1399+
mc::cat_deref(base, _, mc::BorrowedPtr(..)) |
1400+
mc::cat_deref(base, _, mc::Implicit(..)) => {
13981401
match base.cat {
13991402
mc::cat_upvar(ref upvar_id, _) => {
14001403
// if this is an implicit deref of an
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
struct MyVec<T> {
12+
data: Vec<T>,
13+
}
14+
15+
impl<T> Index<uint, T> for MyVec<T> {
16+
fn index<'a>(&'a self, &i: &uint) -> &'a T {
17+
self.data.get(i)
18+
}
19+
}
20+
21+
fn main() {
22+
let v = MyVec { data: vec!(box 1i, box 2, box 3) };
23+
let good = &v[0]; // Shouldn't fail here
24+
let bad = v[0];
25+
//~^ ERROR cannot move out of dereference (dereference is implicit, due to indexing)
26+
}

src/test/compile-fail/borrowck-overloaded-index.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ fn main() {
5858
x: 1,
5959
};
6060
s[2] = 20;
61-
//~^ ERROR cannot assign to immutable indexed content
61+
//~^ ERROR cannot assign to immutable dereference (dereference is implicit, due to indexing)
6262
}
6363

6464

0 commit comments

Comments
 (0)