Skip to content

Commit 8ed88c1

Browse files
committed
rollup merge of rust-lang#20751: nikomatsakis/issue-20232
Issue rust-lang#20232. Fun. r? @eddyb you prob know this system best
2 parents 6a09aa2 + ba87b54 commit 8ed88c1

28 files changed

+263
-111
lines changed

src/librustc/middle/mem_categorization.rs

Lines changed: 97 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ use middle::def;
7575
use middle::region;
7676
use middle::ty::{self, Ty};
7777
use util::nodemap::{NodeMap};
78-
use util::ppaux::{Repr};
78+
use util::ppaux::{Repr, UserString};
7979

8080
use syntax::ast::{MutImmutable, MutMutable};
8181
use syntax::ast;
@@ -113,10 +113,17 @@ pub struct Upvar {
113113
// different kinds of pointers:
114114
#[derive(Clone, Copy, PartialEq, Eq, Hash, Show)]
115115
pub enum PointerKind {
116+
/// `Box<T>`
116117
Unique,
118+
119+
/// `&T`
117120
BorrowedPtr(ty::BorrowKind, ty::Region),
118-
Implicit(ty::BorrowKind, ty::Region), // Implicit deref of a borrowed ptr.
119-
UnsafePtr(ast::Mutability)
121+
122+
/// `*T`
123+
UnsafePtr(ast::Mutability),
124+
125+
/// Implicit deref of the `&T` that results from an overloaded index `[]`.
126+
Implicit(ty::BorrowKind, ty::Region),
120127
}
121128

122129
// We use the term "interior" to mean "something reachable from the
@@ -453,7 +460,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
453460
autoderefs,
454461
cmt.repr(self.tcx()));
455462
for deref in range(1u, autoderefs + 1) {
456-
cmt = try!(self.cat_deref(expr, cmt, deref, false));
463+
cmt = try!(self.cat_deref(expr, cmt, deref));
457464
}
458465
return Ok(cmt);
459466
}
@@ -465,7 +472,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
465472
match expr.node {
466473
ast::ExprUnary(ast::UnDeref, ref e_base) => {
467474
let base_cmt = try!(self.cat_expr(&**e_base));
468-
self.cat_deref(expr, base_cmt, 0, false)
475+
self.cat_deref(expr, base_cmt, 0)
469476
}
470477

471478
ast::ExprField(ref base, f_name) => {
@@ -489,10 +496,23 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
489496
// If this is an index implemented by a method call, then it
490497
// will include an implicit deref of the result.
491498
let ret_ty = self.overloaded_method_return_ty(method_ty);
492-
self.cat_deref(expr,
493-
self.cat_rvalue_node(expr.id(),
494-
expr.span(),
495-
ret_ty), 1, true)
499+
500+
// The index method always returns an `&T`, so
501+
// dereference it to find the result type.
502+
let elem_ty = match ret_ty.sty {
503+
ty::ty_rptr(_, mt) => mt.ty,
504+
_ => {
505+
debug!("cat_expr_unadjusted: return type of overloaded index is {}?",
506+
ret_ty.repr(self.tcx()));
507+
return Err(());
508+
}
509+
};
510+
511+
// The call to index() returns a `&T` value, which
512+
// is an rvalue. That is what we will be
513+
// dereferencing.
514+
let base_cmt = self.cat_rvalue_node(expr.id(), expr.span(), ret_ty);
515+
self.cat_deref_common(expr, base_cmt, 1, elem_ty, true)
496516
}
497517
None => {
498518
self.cat_index(expr, try!(self.cat_expr(&**base)))
@@ -837,8 +857,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
837857
fn cat_deref<N:ast_node>(&self,
838858
node: &N,
839859
base_cmt: cmt<'tcx>,
840-
deref_cnt: uint,
841-
implicit: bool)
860+
deref_cnt: uint)
842861
-> McResult<cmt<'tcx>> {
843862
let adjustment = match self.typer.adjustments().borrow().get(&node.id()) {
844863
Some(adj) if ty::adjust_is_object(adj) => ty::AutoObject,
@@ -866,7 +885,8 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
866885
};
867886
let base_cmt_ty = base_cmt.ty;
868887
match ty::deref(base_cmt_ty, true) {
869-
Some(mt) => self.cat_deref_common(node, base_cmt, deref_cnt, mt.ty, implicit),
888+
Some(mt) => self.cat_deref_common(node, base_cmt, deref_cnt, mt.ty,
889+
/* implicit: */ false),
870890
None => {
871891
debug!("Explicit deref of non-derefable type: {}",
872892
base_cmt_ty.repr(self.tcx()));
@@ -1236,7 +1256,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
12361256
// box p1, &p1, &mut p1. we can ignore the mutability of
12371257
// PatRegion since that information is already contained
12381258
// in the type.
1239-
let subcmt = try!(self.cat_deref(pat, cmt, 0, false));
1259+
let subcmt = try!(self.cat_deref(pat, cmt, 0));
12401260
try!(self.cat_pattern_(subcmt, &**subpat, op));
12411261
}
12421262

@@ -1392,22 +1412,6 @@ impl<'tcx> cmt_<'tcx> {
13921412

13931413

13941414
pub fn descriptive_string(&self, tcx: &ty::ctxt) -> String {
1395-
fn upvar_to_string(upvar: &Upvar, is_copy: bool) -> String {
1396-
if upvar.is_unboxed {
1397-
let kind = match upvar.kind {
1398-
ty::FnUnboxedClosureKind => "Fn",
1399-
ty::FnMutUnboxedClosureKind => "FnMut",
1400-
ty::FnOnceUnboxedClosureKind => "FnOnce"
1401-
};
1402-
format!("captured outer variable in an `{}` closure", kind)
1403-
} else {
1404-
(match (upvar.kind, is_copy) {
1405-
(ty::FnOnceUnboxedClosureKind, true) => "captured outer variable in a proc",
1406-
_ => "captured outer variable"
1407-
}).to_string()
1408-
}
1409-
}
1410-
14111415
match self.cat {
14121416
cat_static_item => {
14131417
"static item".to_string()
@@ -1427,16 +1431,23 @@ impl<'tcx> cmt_<'tcx> {
14271431
let upvar = self.upvar();
14281432
match upvar.as_ref().map(|i| &i.cat) {
14291433
Some(&cat_upvar(ref var)) => {
1430-
upvar_to_string(var, false)
1434+
var.user_string(tcx)
14311435
}
14321436
Some(_) => unreachable!(),
14331437
None => {
14341438
match pk {
14351439
Implicit(..) => {
1436-
"dereference (dereference is implicit, due to indexing)".to_string()
1440+
format!("indexed content")
1441+
}
1442+
Unique => {
1443+
format!("`Box` content")
1444+
}
1445+
UnsafePtr(..) => {
1446+
format!("dereference of unsafe pointer")
1447+
}
1448+
BorrowedPtr(..) => {
1449+
format!("borrowed content")
14371450
}
1438-
Unique => format!("dereference of `{}`", ptr_sigil(pk)),
1439-
_ => format!("dereference of `{}`-pointer", ptr_sigil(pk))
14401451
}
14411452
}
14421453
}
@@ -1447,14 +1458,12 @@ impl<'tcx> cmt_<'tcx> {
14471458
cat_interior(_, InteriorField(PositionalField(_))) => {
14481459
"anonymous field".to_string()
14491460
}
1450-
cat_interior(_, InteriorElement(VecElement)) => {
1451-
"vec content".to_string()
1452-
}
1461+
cat_interior(_, InteriorElement(VecElement)) |
14531462
cat_interior(_, InteriorElement(OtherElement)) => {
14541463
"indexed content".to_string()
14551464
}
14561465
cat_upvar(ref var) => {
1457-
upvar_to_string(var, true)
1466+
var.user_string(tcx)
14581467
}
14591468
cat_downcast(ref cmt, _) => {
14601469
cmt.descriptive_string(tcx)
@@ -1483,7 +1492,7 @@ impl<'tcx> Repr<'tcx> for categorization<'tcx> {
14831492
format!("{:?}", *self)
14841493
}
14851494
cat_deref(ref cmt, derefs, ptr) => {
1486-
format!("{}-{}{}->", cmt.cat.repr(tcx), ptr_sigil(ptr), derefs)
1495+
format!("{}-{}{}->", cmt.cat.repr(tcx), ptr.repr(tcx), derefs)
14871496
}
14881497
cat_interior(ref cmt, interior) => {
14891498
format!("{}.{}", cmt.cat.repr(tcx), interior.repr(tcx))
@@ -1504,7 +1513,32 @@ pub fn ptr_sigil(ptr: PointerKind) -> &'static str {
15041513
Implicit(ty::MutBorrow, _) => "&mut",
15051514
BorrowedPtr(ty::UniqueImmBorrow, _) |
15061515
Implicit(ty::UniqueImmBorrow, _) => "&unique",
1507-
UnsafePtr(_) => "*"
1516+
UnsafePtr(_) => "*",
1517+
}
1518+
}
1519+
1520+
impl<'tcx> Repr<'tcx> for PointerKind {
1521+
fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
1522+
match *self {
1523+
Unique => {
1524+
format!("Box")
1525+
}
1526+
BorrowedPtr(ty::ImmBorrow, ref r) |
1527+
Implicit(ty::ImmBorrow, ref r) => {
1528+
format!("&{}", r.repr(tcx))
1529+
}
1530+
BorrowedPtr(ty::MutBorrow, ref r) |
1531+
Implicit(ty::MutBorrow, ref r) => {
1532+
format!("&{} mut", r.repr(tcx))
1533+
}
1534+
BorrowedPtr(ty::UniqueImmBorrow, ref r) |
1535+
Implicit(ty::UniqueImmBorrow, ref r) => {
1536+
format!("&{} uniq", r.repr(tcx))
1537+
}
1538+
UnsafePtr(_) => {
1539+
format!("*")
1540+
}
1541+
}
15081542
}
15091543
}
15101544

@@ -1531,3 +1565,27 @@ fn element_kind(t: Ty) -> ElementKind {
15311565
_ => OtherElement
15321566
}
15331567
}
1568+
1569+
impl<'tcx> Repr<'tcx> for ty::UnboxedClosureKind {
1570+
fn repr(&self, _: &ty::ctxt) -> String {
1571+
format!("Upvar({:?})", self)
1572+
}
1573+
}
1574+
1575+
impl<'tcx> Repr<'tcx> for Upvar {
1576+
fn repr(&self, tcx: &ty::ctxt) -> String {
1577+
format!("Upvar({})", self.kind.repr(tcx))
1578+
}
1579+
}
1580+
1581+
impl<'tcx> UserString<'tcx> for Upvar {
1582+
fn user_string(&self, _: &ty::ctxt) -> String {
1583+
let kind = match self.kind {
1584+
ty::FnUnboxedClosureKind => "Fn",
1585+
ty::FnMutUnboxedClosureKind => "FnMut",
1586+
ty::FnOnceUnboxedClosureKind => "FnOnce",
1587+
};
1588+
format!("captured outer variable in an `{}` closure", kind)
1589+
}
1590+
}
1591+

src/librustc_borrowck/borrowck/gather_loans/move_error.rs

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -115,29 +115,31 @@ fn report_cannot_move_out_of<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
115115
match move_from.cat {
116116
mc::cat_deref(_, _, mc::BorrowedPtr(..)) |
117117
mc::cat_deref(_, _, mc::Implicit(..)) |
118-
mc::cat_deref(_, _, mc::UnsafePtr(..)) |
119118
mc::cat_static_item => {
120-
bccx.span_err(
121-
move_from.span,
122-
&format!("cannot move out of {}",
123-
bccx.cmt_to_string(&*move_from))[]);
119+
bccx.span_err(move_from.span,
120+
&format!("cannot move out of {}",
121+
move_from.descriptive_string(bccx.tcx))[]);
124122
}
125123

126124
mc::cat_downcast(ref b, _) |
127125
mc::cat_interior(ref b, _) => {
128126
match b.ty.sty {
129-
ty::ty_struct(did, _)
130-
| ty::ty_enum(did, _) if ty::has_dtor(bccx.tcx, did) => {
127+
ty::ty_struct(did, _) |
128+
ty::ty_enum(did, _) if ty::has_dtor(bccx.tcx, did) => {
131129
bccx.span_err(
132130
move_from.span,
133131
&format!("cannot move out of type `{}`, \
134132
which defines the `Drop` trait",
135133
b.ty.user_string(bccx.tcx))[]);
136134
},
137-
_ => panic!("this path should not cause illegal move")
135+
_ => {
136+
bccx.span_bug(move_from.span, "this path should not cause illegal move")
137+
}
138138
}
139139
}
140-
_ => panic!("this path should not cause illegal move")
140+
_ => {
141+
bccx.span_bug(move_from.span, "this path should not cause illegal move")
142+
}
141143
}
142144
}
143145

src/librustc_borrowck/borrowck/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -681,6 +681,10 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
681681
self.tcx.sess.span_err(s, m);
682682
}
683683

684+
pub fn span_bug(&self, s: Span, m: &str) {
685+
self.tcx.sess.span_bug(s, m);
686+
}
687+
684688
pub fn span_note(&self, s: Span, m: &str) {
685689
self.tcx.sess.span_note(s, m);
686690
}

src/librustc_typeck/check/callee.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ pub fn check_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
7373
autoderef(fcx,
7474
callee_expr.span,
7575
original_callee_ty,
76-
Some(callee_expr.id),
76+
Some(callee_expr),
7777
LvaluePreference::NoPreference,
7878
|adj_ty, idx| {
7979
let autoderefref = ty::AutoDerefRef { autoderefs: idx, autoref: None };

src/librustc_typeck/check/method/confirm.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
143143
// time writing the results into the various tables.
144144
let (autoderefd_ty, n, result) =
145145
check::autoderef(
146-
self.fcx, self.span, unadjusted_self_ty, Some(self.self_expr.id), NoPreference,
146+
self.fcx, self.span, unadjusted_self_ty, Some(self.self_expr), NoPreference,
147147
|_, n| if n == auto_deref_ref.autoderefs { Some(()) } else { None });
148148
assert_eq!(n, auto_deref_ref.autoderefs);
149149
assert_eq!(result, Some(()));
@@ -492,7 +492,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
492492
exprs.repr(self.tcx()));
493493

494494
// Fix up autoderefs and derefs.
495-
for (i, expr) in exprs.iter().rev().enumerate() {
495+
for (i, &expr) in exprs.iter().rev().enumerate() {
496496
// Count autoderefs.
497497
let autoderef_count = match self.fcx
498498
.inh
@@ -512,8 +512,8 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
512512
if autoderef_count > 0 {
513513
check::autoderef(self.fcx,
514514
expr.span,
515-
self.fcx.expr_ty(*expr),
516-
Some(expr.id),
515+
self.fcx.expr_ty(expr),
516+
Some(expr),
517517
PreferMutLvalue,
518518
|_, autoderefs| {
519519
if autoderefs == autoderef_count + 1 {
@@ -567,7 +567,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
567567
let result = check::try_index_step(
568568
self.fcx,
569569
MethodCall::expr(expr.id),
570-
*expr,
570+
expr,
571571
&**base_expr,
572572
adjusted_base_ty,
573573
base_adjustment,
@@ -577,7 +577,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
577577
if let Some((input_ty, return_ty)) = result {
578578
demand::suptype(self.fcx, index_expr.span, input_ty, index_expr_ty);
579579

580-
let expr_ty = self.fcx.expr_ty(&**expr);
580+
let expr_ty = self.fcx.expr_ty(&*expr);
581581
demand::suptype(self.fcx, expr.span, expr_ty, return_ty);
582582
}
583583
}

src/librustc_typeck/check/method/mod.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -102,9 +102,9 @@ pub fn lookup<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
102102
Ok(confirm::confirm(fcx, span, self_expr, call_expr, self_ty, pick, supplied_method_types))
103103
}
104104

105-
pub fn lookup_in_trait<'a, 'tcx>(fcx: &'a FnCtxt<'a, 'tcx>,
105+
pub fn lookup_in_trait<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
106106
span: Span,
107-
self_expr: Option<&'a ast::Expr>,
107+
self_expr: Option<&ast::Expr>,
108108
m_name: ast::Name,
109109
trait_def_id: DefId,
110110
self_ty: Ty<'tcx>,
@@ -125,9 +125,9 @@ pub fn lookup_in_trait<'a, 'tcx>(fcx: &'a FnCtxt<'a, 'tcx>,
125125
/// method-lookup code. In particular, autoderef on index is basically identical to autoderef with
126126
/// normal probes, except that the test also looks for built-in indexing. Also, the second half of
127127
/// this method is basically the same as confirmation.
128-
pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &'a FnCtxt<'a, 'tcx>,
128+
pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
129129
span: Span,
130-
self_expr: Option<&'a ast::Expr>,
130+
self_expr: Option<&ast::Expr>,
131131
m_name: ast::Name,
132132
trait_def_id: DefId,
133133
autoderefref: ty::AutoDerefRef<'tcx>,

0 commit comments

Comments
 (0)