Re-introduce McResult<>
as a way of aborting mem-categorization (and
expr-use-visitor) early. Turns out I was wrong to remove this; it causes a lot of pain trying to run EUV etc during typeck without ICEing on erroneous programs.
This commit is contained in:
parent
fc2ba13939
commit
f7abf47058
5 changed files with 175 additions and 130 deletions
|
@ -300,6 +300,20 @@ pub struct ExprUseVisitor<'d,'t,'tcx:'t,TYPER:'t> {
|
||||||
mc: mc::MemCategorizationContext<'t,TYPER>,
|
mc: mc::MemCategorizationContext<'t,TYPER>,
|
||||||
delegate: &'d mut (Delegate<'tcx>+'d),
|
delegate: &'d mut (Delegate<'tcx>+'d),
|
||||||
param_env: &'t ParameterEnvironment<'tcx>,
|
param_env: &'t ParameterEnvironment<'tcx>,
|
||||||
|
// If the TYPER results in an error, it's because the type check
|
||||||
|
// failed (or will fail, when the error is uncovered and reported
|
||||||
|
// during writeback). In this case, we just ignore this part of the
|
||||||
|
// code.
|
||||||
|
//
|
||||||
|
// Note that this macro appears similar to try!(), but, unlike try!(),
|
||||||
|
// it does not propagate the error.
|
||||||
|
macro_rules! return_if_err {
|
||||||
|
($inp: expr) => (
|
||||||
|
match $inp {
|
||||||
|
Ok(v) => v,
|
||||||
|
Err(()) => return
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Whether the elements of an overloaded operation are passed by value or by reference
|
/// Whether the elements of an overloaded operation are passed by value or by reference
|
||||||
|
@ -332,7 +346,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
|
||||||
decl: &ast::FnDecl,
|
decl: &ast::FnDecl,
|
||||||
body: &ast::Block) {
|
body: &ast::Block) {
|
||||||
for arg in decl.inputs.iter() {
|
for arg in decl.inputs.iter() {
|
||||||
let arg_ty = self.typer.node_ty(arg.pat.id);
|
let arg_ty = return_if_err!(self.typer.node_ty(arg.pat.id));
|
||||||
|
|
||||||
let fn_body_scope = region::CodeExtent::from_node_id(body.id);
|
let fn_body_scope = region::CodeExtent::from_node_id(body.id);
|
||||||
let arg_cmt = self.mc.cat_rvalue(
|
let arg_cmt = self.mc.cat_rvalue(
|
||||||
|
@ -369,7 +383,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
|
||||||
pub fn consume_expr(&mut self, expr: &ast::Expr) {
|
pub fn consume_expr(&mut self, expr: &ast::Expr) {
|
||||||
debug!("consume_expr(expr={})", expr.repr(self.tcx()));
|
debug!("consume_expr(expr={})", expr.repr(self.tcx()));
|
||||||
|
|
||||||
let cmt = self.mc.cat_expr(expr);
|
let cmt = return_if_err!(self.mc.cat_expr(expr));
|
||||||
self.delegate_consume(expr.id, expr.span, cmt);
|
self.delegate_consume(expr.id, expr.span, cmt);
|
||||||
self.walk_expr(expr);
|
self.walk_expr(expr);
|
||||||
}
|
}
|
||||||
|
@ -378,7 +392,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
|
||||||
assignment_expr: &ast::Expr,
|
assignment_expr: &ast::Expr,
|
||||||
expr: &ast::Expr,
|
expr: &ast::Expr,
|
||||||
mode: MutateMode) {
|
mode: MutateMode) {
|
||||||
let cmt = self.mc.cat_expr(expr);
|
let cmt = return_if_err!(self.mc.cat_expr(expr));
|
||||||
self.delegate.mutate(assignment_expr.id, assignment_expr.span, cmt, mode);
|
self.delegate.mutate(assignment_expr.id, assignment_expr.span, cmt, mode);
|
||||||
self.walk_expr(expr);
|
self.walk_expr(expr);
|
||||||
}
|
}
|
||||||
|
@ -391,7 +405,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
|
||||||
debug!("borrow_expr(expr={}, r={}, bk={})",
|
debug!("borrow_expr(expr={}, r={}, bk={})",
|
||||||
expr.repr(self.tcx()), r.repr(self.tcx()), bk.repr(self.tcx()));
|
expr.repr(self.tcx()), r.repr(self.tcx()), bk.repr(self.tcx()));
|
||||||
|
|
||||||
let cmt = self.mc.cat_expr(expr);
|
let cmt = return_if_err!(self.mc.cat_expr(expr));
|
||||||
self.delegate.borrow(expr.id, expr.span, cmt, r, bk, cause);
|
self.delegate.borrow(expr.id, expr.span, cmt, r, bk, cause);
|
||||||
|
|
||||||
// Note: Unlike consume, we can ignore ExprParen. cat_expr
|
// Note: Unlike consume, we can ignore ExprParen. cat_expr
|
||||||
|
@ -491,7 +505,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
|
||||||
}
|
}
|
||||||
|
|
||||||
ast::ExprMatch(ref discr, ref arms, _) => {
|
ast::ExprMatch(ref discr, ref arms, _) => {
|
||||||
let discr_cmt = self.mc.cat_expr(&**discr);
|
let discr_cmt = return_if_err!(self.mc.cat_expr(&**discr));
|
||||||
self.borrow_expr(&**discr, ty::ReEmpty, ty::ImmBorrow, MatchDiscriminant);
|
self.borrow_expr(&**discr, ty::ReEmpty, ty::ImmBorrow, MatchDiscriminant);
|
||||||
|
|
||||||
// treatment of the discriminant is handled while walking the arms.
|
// treatment of the discriminant is handled while walking the arms.
|
||||||
|
@ -509,7 +523,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
|
||||||
ast::ExprAddrOf(m, ref base) => { // &base
|
ast::ExprAddrOf(m, ref base) => { // &base
|
||||||
// make sure that the thing we are pointing out stays valid
|
// make sure that the thing we are pointing out stays valid
|
||||||
// for the lifetime `scope_r` of the resulting ptr:
|
// for the lifetime `scope_r` of the resulting ptr:
|
||||||
let expr_ty = ty::expr_ty(self.tcx(), expr);
|
let expr_ty = return_if_err!(self.typer.node_ty(expr.id));
|
||||||
let r = ty::ty_region(self.tcx(), expr.span, expr_ty);
|
let r = ty::ty_region(self.tcx(), expr.span, expr_ty);
|
||||||
let bk = ty::BorrowKind::from_mutbl(m);
|
let bk = ty::BorrowKind::from_mutbl(m);
|
||||||
self.borrow_expr(&**base, r, bk, AddrOf);
|
self.borrow_expr(&**base, r, bk, AddrOf);
|
||||||
|
@ -550,7 +564,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
|
||||||
|
|
||||||
// Fetch the type of the value that the iteration yields to
|
// Fetch the type of the value that the iteration yields to
|
||||||
// produce the pattern's categorized mutable type.
|
// produce the pattern's categorized mutable type.
|
||||||
let pattern_type = self.typer.node_ty(pat.id);
|
let pattern_type = return_if_err!(self.typer.node_ty(pat.id));
|
||||||
let blk_scope = region::CodeExtent::from_node_id(blk.id);
|
let blk_scope = region::CodeExtent::from_node_id(blk.id);
|
||||||
let pat_cmt = self.mc.cat_rvalue(pat.id,
|
let pat_cmt = self.mc.cat_rvalue(pat.id,
|
||||||
pat.span,
|
pat.span,
|
||||||
|
@ -638,7 +652,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn walk_callee(&mut self, call: &ast::Expr, callee: &ast::Expr) {
|
fn walk_callee(&mut self, call: &ast::Expr, callee: &ast::Expr) {
|
||||||
let callee_ty = self.typer.expr_ty_adjusted(callee);
|
let callee_ty = return_if_err!(self.typer.expr_ty_adjusted(callee));
|
||||||
debug!("walk_callee: callee={} callee_ty={}",
|
debug!("walk_callee: callee={} callee_ty={}",
|
||||||
callee.repr(self.tcx()), callee_ty.repr(self.tcx()));
|
callee.repr(self.tcx()), callee_ty.repr(self.tcx()));
|
||||||
let call_scope = region::CodeExtent::from_node_id(call.id);
|
let call_scope = region::CodeExtent::from_node_id(call.id);
|
||||||
|
@ -735,7 +749,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
|
||||||
// "assigns", which is handled by
|
// "assigns", which is handled by
|
||||||
// `walk_pat`:
|
// `walk_pat`:
|
||||||
self.walk_expr(&**expr);
|
self.walk_expr(&**expr);
|
||||||
let init_cmt = self.mc.cat_expr(&**expr);
|
let init_cmt = return_if_err!(self.mc.cat_expr(&**expr));
|
||||||
self.walk_irrefutable_pat(init_cmt, &*local.pat);
|
self.walk_irrefutable_pat(init_cmt, &*local.pat);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -769,7 +783,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
|
||||||
None => { return; }
|
None => { return; }
|
||||||
};
|
};
|
||||||
|
|
||||||
let with_cmt = self.mc.cat_expr(&*with_expr);
|
let with_cmt = return_if_err!(self.mc.cat_expr(&*with_expr));
|
||||||
|
|
||||||
// Select just those fields of the `with`
|
// Select just those fields of the `with`
|
||||||
// expression that will actually be used
|
// expression that will actually be used
|
||||||
|
@ -824,7 +838,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
|
||||||
// rvalue.
|
// rvalue.
|
||||||
debug!("walk_adjustment(AutoAddEnv|AdjustReifyFnPointer)");
|
debug!("walk_adjustment(AutoAddEnv|AdjustReifyFnPointer)");
|
||||||
let cmt_unadjusted =
|
let cmt_unadjusted =
|
||||||
self.mc.cat_expr_unadjusted(expr);
|
return_if_err!(self.mc.cat_expr_unadjusted(expr));
|
||||||
self.delegate_consume(expr.id, expr.span, cmt_unadjusted);
|
self.delegate_consume(expr.id, expr.span, cmt_unadjusted);
|
||||||
}
|
}
|
||||||
ty::AdjustDerefRef(ty::AutoDerefRef {
|
ty::AdjustDerefRef(ty::AutoDerefRef {
|
||||||
|
@ -858,7 +872,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
|
||||||
match self.typer.node_method_ty(deref_id) {
|
match self.typer.node_method_ty(deref_id) {
|
||||||
None => {}
|
None => {}
|
||||||
Some(method_ty) => {
|
Some(method_ty) => {
|
||||||
let cmt = self.mc.cat_expr_autoderefd(expr, i);
|
let cmt = return_if_err!(self.mc.cat_expr_autoderefd(expr, i));
|
||||||
let self_ty = ty::ty_fn_args(method_ty)[0];
|
let self_ty = ty::ty_fn_args(method_ty)[0];
|
||||||
let (m, r) = match self_ty.sty {
|
let (m, r) = match self_ty.sty {
|
||||||
ty::ty_rptr(r, ref m) => (m.mutbl, r),
|
ty::ty_rptr(r, ref m) => (m.mutbl, r),
|
||||||
|
@ -888,14 +902,15 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
|
||||||
assert!(n == 1, format!("Expected exactly 1 deref with Uniq \
|
assert!(n == 1, format!("Expected exactly 1 deref with Uniq \
|
||||||
AutoRefs, found: {}", n));
|
AutoRefs, found: {}", n));
|
||||||
let cmt_unadjusted =
|
let cmt_unadjusted =
|
||||||
self.mc.cat_expr_unadjusted(expr);
|
return_if_err!(self.mc.cat_expr_unadjusted(expr));
|
||||||
self.delegate_consume(expr.id, expr.span, cmt_unadjusted);
|
self.delegate_consume(expr.id, expr.span, cmt_unadjusted);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
let cmt_derefd = self.mc.cat_expr_autoderefd(expr, n);
|
let cmt_derefd = return_if_err!(
|
||||||
|
self.mc.cat_expr_autoderefd(expr, n));
|
||||||
debug!("walk_adjustment: cmt_derefd={}",
|
debug!("walk_adjustment: cmt_derefd={}",
|
||||||
cmt_derefd.repr(self.tcx()));
|
cmt_derefd.repr(self.tcx()));
|
||||||
|
|
||||||
|
@ -988,7 +1003,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
|
||||||
mode: &mut TrackMatchMode<Span>) {
|
mode: &mut TrackMatchMode<Span>) {
|
||||||
debug!("determine_pat_move_mode cmt_discr={} pat={}", cmt_discr.repr(self.tcx()),
|
debug!("determine_pat_move_mode cmt_discr={} pat={}", cmt_discr.repr(self.tcx()),
|
||||||
pat.repr(self.tcx()));
|
pat.repr(self.tcx()));
|
||||||
self.mc.cat_pattern(cmt_discr, pat, |_mc, cmt_pat, pat| {
|
return_if_err!(self.mc.cat_pattern(cmt_discr, pat, |_mc, cmt_pat, pat| {
|
||||||
let tcx = self.typer.tcx();
|
let tcx = self.typer.tcx();
|
||||||
let def_map = &self.typer.tcx().def_map;
|
let def_map = &self.typer.tcx().def_map;
|
||||||
if pat_util::pat_is_binding(def_map, pat) {
|
if pat_util::pat_is_binding(def_map, pat) {
|
||||||
|
@ -1011,7 +1026,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The core driver for walking a pattern; `match_mode` must be
|
/// The core driver for walking a pattern; `match_mode` must be
|
||||||
|
@ -1028,8 +1043,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
|
||||||
let typer = self.typer;
|
let typer = self.typer;
|
||||||
let def_map = &self.typer.tcx().def_map;
|
let def_map = &self.typer.tcx().def_map;
|
||||||
let delegate = &mut self.delegate;
|
let delegate = &mut self.delegate;
|
||||||
let param_env = self.param_env;
|
return_if_err!(mc.cat_pattern(cmt_discr.clone(), pat, |mc, cmt_pat, pat| {
|
||||||
mc.cat_pattern(cmt_discr.clone(), pat, |mc, cmt_pat, pat| {
|
|
||||||
if pat_util::pat_is_binding(def_map, pat) {
|
if pat_util::pat_is_binding(def_map, pat) {
|
||||||
let tcx = typer.tcx();
|
let tcx = typer.tcx();
|
||||||
|
|
||||||
|
@ -1039,7 +1053,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
|
||||||
match_mode);
|
match_mode);
|
||||||
|
|
||||||
// pat_ty: the type of the binding being produced.
|
// pat_ty: the type of the binding being produced.
|
||||||
let pat_ty = typer.node_ty(pat.id);
|
let pat_ty = return_if_err!(typer.node_ty(pat.id));
|
||||||
|
|
||||||
// Each match binding is effectively an assignment to the
|
// Each match binding is effectively an assignment to the
|
||||||
// binding being produced.
|
// binding being produced.
|
||||||
|
@ -1080,7 +1094,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
|
||||||
// matched.
|
// matched.
|
||||||
|
|
||||||
let (slice_cmt, slice_mutbl, slice_r) =
|
let (slice_cmt, slice_mutbl, slice_r) =
|
||||||
mc.cat_slice_pattern(cmt_pat, &**slice_pat);
|
return_if_err!(mc.cat_slice_pattern(cmt_pat, &**slice_pat));
|
||||||
|
|
||||||
// Note: We declare here that the borrow
|
// Note: We declare here that the borrow
|
||||||
// occurs upon entering the `[...]`
|
// occurs upon entering the `[...]`
|
||||||
|
@ -1110,13 +1124,13 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
|
||||||
_ => { }
|
_ => { }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
}));
|
||||||
|
|
||||||
// Do a second pass over the pattern, calling `matched_pat` on
|
// Do a second pass over the pattern, calling `matched_pat` on
|
||||||
// the interior nodes (enum variants and structs), as opposed
|
// the interior nodes (enum variants and structs), as opposed
|
||||||
// to the above loop's visit of than the bindings that form
|
// to the above loop's visit of than the bindings that form
|
||||||
// the leaves of the pattern tree structure.
|
// the leaves of the pattern tree structure.
|
||||||
mc.cat_pattern(cmt_discr, pat, |mc, cmt_pat, pat| {
|
return_if_err!(mc.cat_pattern(cmt_discr, pat, |mc, cmt_pat, pat| {
|
||||||
let def_map = def_map.borrow();
|
let def_map = def_map.borrow();
|
||||||
let tcx = typer.tcx();
|
let tcx = typer.tcx();
|
||||||
|
|
||||||
|
@ -1197,7 +1211,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
|
||||||
// cases either.
|
// cases either.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn walk_captures(&mut self, closure_expr: &ast::Expr) {
|
fn walk_captures(&mut self, closure_expr: &ast::Expr) {
|
||||||
|
@ -1221,9 +1235,9 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
|
||||||
freevars: &[ty::Freevar]) {
|
freevars: &[ty::Freevar]) {
|
||||||
for freevar in freevars.iter() {
|
for freevar in freevars.iter() {
|
||||||
let id_var = freevar.def.def_id().node;
|
let id_var = freevar.def.def_id().node;
|
||||||
let cmt_var = self.cat_captured_var(closure_expr.id,
|
let cmt_var = return_if_err!(self.cat_captured_var(closure_expr.id,
|
||||||
closure_expr.span,
|
closure_expr.span,
|
||||||
freevar.def);
|
freevar.def));
|
||||||
|
|
||||||
// Lookup the kind of borrow the callee requires, as
|
// Lookup the kind of borrow the callee requires, as
|
||||||
// inferred by regionbk
|
// inferred by regionbk
|
||||||
|
@ -1244,11 +1258,10 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
|
||||||
closure_expr: &ast::Expr,
|
closure_expr: &ast::Expr,
|
||||||
freevars: &[ty::Freevar]) {
|
freevars: &[ty::Freevar]) {
|
||||||
for freevar in freevars.iter() {
|
for freevar in freevars.iter() {
|
||||||
let cmt_var = self.cat_captured_var(closure_expr.id,
|
let cmt_var = return_if_err!(self.cat_captured_var(closure_expr.id,
|
||||||
closure_expr.span,
|
closure_expr.span,
|
||||||
freevar.def);
|
freevar.def));
|
||||||
let mode = copy_or_move(self.tcx(), cmt_var.ty,
|
let mode = copy_or_move(self.typer, &cmt_var, CaptureMove);
|
||||||
self.param_env, CaptureMove);
|
|
||||||
self.delegate.consume(closure_expr.id, freevar.span, cmt_var, mode);
|
self.delegate.consume(closure_expr.id, freevar.span, cmt_var, mode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1257,11 +1270,11 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
|
||||||
closure_id: ast::NodeId,
|
closure_id: ast::NodeId,
|
||||||
closure_span: Span,
|
closure_span: Span,
|
||||||
upvar_def: def::Def)
|
upvar_def: def::Def)
|
||||||
-> mc::cmt<'tcx> {
|
-> mc::McResult<mc::cmt<'tcx>> {
|
||||||
// Create the cmt for the variable being borrowed, from the
|
// Create the cmt for the variable being borrowed, from the
|
||||||
// caller's perspective
|
// caller's perspective
|
||||||
let var_id = upvar_def.def_id().node;
|
let var_id = upvar_def.def_id().node;
|
||||||
let var_ty = self.typer.node_ty(var_id);
|
let var_ty = try!(self.typer.node_ty(var_id));
|
||||||
self.mc.cat_def(closure_id, closure_span, var_ty, upvar_def)
|
self.mc.cat_def(closure_id, closure_span, var_ty, upvar_def)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,7 +75,7 @@ use middle::def;
|
||||||
use middle::region;
|
use middle::region;
|
||||||
use middle::ty::{mod, Ty};
|
use middle::ty::{mod, Ty};
|
||||||
use util::nodemap::{NodeMap};
|
use util::nodemap::{NodeMap};
|
||||||
use util::ppaux::{ty_to_string, Repr};
|
use util::ppaux::{Repr};
|
||||||
|
|
||||||
use syntax::ast::{MutImmutable, MutMutable};
|
use syntax::ast::{MutImmutable, MutMutable};
|
||||||
use syntax::ast;
|
use syntax::ast;
|
||||||
|
@ -264,6 +264,8 @@ pub struct MemCategorizationContext<'t,TYPER:'t> {
|
||||||
|
|
||||||
impl<'t,TYPER:'t> Copy for MemCategorizationContext<'t,TYPER> {}
|
impl<'t,TYPER:'t> Copy for MemCategorizationContext<'t,TYPER> {}
|
||||||
|
|
||||||
|
pub type McResult<T> = Result<T, ()>;
|
||||||
|
|
||||||
/// The `Typer` trait provides the interface for the mem-categorization
|
/// The `Typer` trait provides the interface for the mem-categorization
|
||||||
/// module to the results of the type check. It can be used to query
|
/// module to the results of the type check. It can be used to query
|
||||||
/// the type assigned to an expression node, to inquire after adjustments,
|
/// the type assigned to an expression node, to inquire after adjustments,
|
||||||
|
@ -282,8 +284,10 @@ impl<'t,TYPER:'t> Copy for MemCategorizationContext<'t,TYPER> {}
|
||||||
/// can be sure that only `Ok` results will occur.
|
/// can be sure that only `Ok` results will occur.
|
||||||
pub trait Typer<'tcx> : ty::UnboxedClosureTyper<'tcx> {
|
pub trait Typer<'tcx> : ty::UnboxedClosureTyper<'tcx> {
|
||||||
fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx>;
|
fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx>;
|
||||||
fn node_ty(&self, id: ast::NodeId) -> Ty<'tcx>;
|
fn param_env<'a>(&'a self) -> &'a ty::ParameterEnvironment<'a, 'tcx>;
|
||||||
fn expr_ty_adjusted(&self, expr: &ast::Expr) -> Ty<'tcx>;
|
fn node_ty(&self, id: ast::NodeId) -> McResult<Ty<'tcx>>;
|
||||||
|
fn expr_ty_adjusted(&self, expr: &ast::Expr) -> McResult<Ty<'tcx>>;
|
||||||
|
fn type_moves_by_default(&self, span: Span, ty: Ty<'tcx>) -> bool;
|
||||||
fn node_method_ty(&self, method_call: ty::MethodCall) -> Option<Ty<'tcx>>;
|
fn node_method_ty(&self, method_call: ty::MethodCall) -> Option<Ty<'tcx>>;
|
||||||
fn node_method_origin(&self, method_call: ty::MethodCall)
|
fn node_method_origin(&self, method_call: ty::MethodCall)
|
||||||
-> Option<ty::MethodOrigin<'tcx>>;
|
-> Option<ty::MethodOrigin<'tcx>>;
|
||||||
|
@ -382,22 +386,22 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
|
||||||
self.typer.tcx()
|
self.typer.tcx()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expr_ty(&self, expr: &ast::Expr) -> Ty<'tcx> {
|
fn expr_ty(&self, expr: &ast::Expr) -> McResult<Ty<'tcx>> {
|
||||||
self.typer.node_ty(expr.id)
|
self.typer.node_ty(expr.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expr_ty_adjusted(&self, expr: &ast::Expr) -> Ty<'tcx> {
|
fn expr_ty_adjusted(&self, expr: &ast::Expr) -> McResult<Ty<'tcx>> {
|
||||||
let unadjusted_ty = self.expr_ty(expr);
|
let unadjusted_ty = try!(self.expr_ty(expr));
|
||||||
ty::adjust_ty(self.tcx(), expr.span, expr.id, unadjusted_ty,
|
Ok(ty::adjust_ty(self.tcx(), expr.span, expr.id, unadjusted_ty,
|
||||||
self.typer.adjustments().borrow().get(&expr.id),
|
self.typer.adjustments().borrow().get(&expr.id),
|
||||||
|method_call| self.typer.node_method_ty(method_call))
|
|method_call| self.typer.node_method_ty(method_call)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn node_ty(&self, id: ast::NodeId) -> Ty<'tcx> {
|
fn node_ty(&self, id: ast::NodeId) -> McResult<Ty<'tcx>> {
|
||||||
self.typer.node_ty(id)
|
self.typer.node_ty(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pat_ty(&self, pat: &ast::Pat) -> Ty<'tcx> {
|
fn pat_ty(&self, pat: &ast::Pat) -> McResult<Ty<'tcx>> {
|
||||||
let tcx = self.typer.tcx();
|
let tcx = self.typer.tcx();
|
||||||
let base_ty = self.typer.node_ty(pat.id);
|
let base_ty = self.typer.node_ty(pat.id);
|
||||||
// FIXME (Issue #18207): This code detects whether we are
|
// FIXME (Issue #18207): This code detects whether we are
|
||||||
|
@ -420,7 +424,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
|
||||||
ret_ty
|
ret_ty
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cat_expr(&self, expr: &ast::Expr) -> cmt<'tcx> {
|
pub fn cat_expr(&self, expr: &ast::Expr) -> McResult<cmt<'tcx>> {
|
||||||
match self.typer.adjustments().borrow().get(&expr.id) {
|
match self.typer.adjustments().borrow().get(&expr.id) {
|
||||||
None => {
|
None => {
|
||||||
// No adjustments.
|
// No adjustments.
|
||||||
|
@ -434,8 +438,8 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
|
||||||
expr.repr(self.tcx()));
|
expr.repr(self.tcx()));
|
||||||
// Convert a bare fn to a closure by adding NULL env.
|
// Convert a bare fn to a closure by adding NULL env.
|
||||||
// Result is an rvalue.
|
// Result is an rvalue.
|
||||||
let expr_ty = self.expr_ty_adjusted(expr);
|
let expr_ty = try!(self.expr_ty_adjusted(expr));
|
||||||
self.cat_rvalue_node(expr.id(), expr.span(), expr_ty)
|
Ok(self.cat_rvalue_node(expr.id(), expr.span(), expr_ty))
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::AdjustDerefRef(
|
ty::AdjustDerefRef(
|
||||||
|
@ -445,8 +449,8 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
|
||||||
expr.repr(self.tcx()));
|
expr.repr(self.tcx()));
|
||||||
// Equivalent to &*expr or something similar.
|
// Equivalent to &*expr or something similar.
|
||||||
// Result is an rvalue.
|
// Result is an rvalue.
|
||||||
let expr_ty = self.expr_ty_adjusted(expr);
|
let expr_ty = try!(self.expr_ty_adjusted(expr));
|
||||||
self.cat_rvalue_node(expr.id(), expr.span(), expr_ty)
|
Ok(self.cat_rvalue_node(expr.id(), expr.span(), expr_ty))
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::AdjustDerefRef(
|
ty::AdjustDerefRef(
|
||||||
|
@ -463,46 +467,46 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
|
||||||
pub fn cat_expr_autoderefd(&self,
|
pub fn cat_expr_autoderefd(&self,
|
||||||
expr: &ast::Expr,
|
expr: &ast::Expr,
|
||||||
autoderefs: uint)
|
autoderefs: uint)
|
||||||
-> cmt<'tcx> {
|
-> McResult<cmt<'tcx>> {
|
||||||
let mut cmt = self.cat_expr_unadjusted(expr);
|
let mut cmt = try!(self.cat_expr_unadjusted(expr));
|
||||||
debug!("cat_expr_autoderefd: autoderefs={}, cmt={}",
|
debug!("cat_expr_autoderefd: autoderefs={}, cmt={}",
|
||||||
autoderefs,
|
autoderefs,
|
||||||
cmt.repr(self.tcx()));
|
cmt.repr(self.tcx()));
|
||||||
for deref in range(1u, autoderefs + 1) {
|
for deref in range(1u, autoderefs + 1) {
|
||||||
cmt = self.cat_deref(expr, cmt, deref, false);
|
cmt = try!(self.cat_deref(expr, cmt, deref, false));
|
||||||
}
|
}
|
||||||
return cmt;
|
return Ok(cmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cat_expr_unadjusted(&self, expr: &ast::Expr) -> cmt<'tcx> {
|
pub fn cat_expr_unadjusted(&self, expr: &ast::Expr) -> McResult<cmt<'tcx>> {
|
||||||
debug!("cat_expr: id={} expr={}", expr.id, expr.repr(self.tcx()));
|
debug!("cat_expr: id={} expr={}", expr.id, expr.repr(self.tcx()));
|
||||||
|
|
||||||
let expr_ty = self.expr_ty(expr);
|
let expr_ty = try!(self.expr_ty(expr));
|
||||||
match expr.node {
|
match expr.node {
|
||||||
ast::ExprUnary(ast::UnDeref, ref e_base) => {
|
ast::ExprUnary(ast::UnDeref, ref e_base) => {
|
||||||
let base_cmt = self.cat_expr(&**e_base);
|
let base_cmt = try!(self.cat_expr(&**e_base));
|
||||||
self.cat_deref(expr, base_cmt, 0, false)
|
self.cat_deref(expr, base_cmt, 0, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
ast::ExprField(ref base, f_name) => {
|
ast::ExprField(ref base, f_name) => {
|
||||||
let base_cmt = self.cat_expr(&**base);
|
let base_cmt = try!(self.cat_expr(&**base));
|
||||||
debug!("cat_expr(cat_field): id={} expr={} base={}",
|
debug!("cat_expr(cat_field): id={} expr={} base={}",
|
||||||
expr.id,
|
expr.id,
|
||||||
expr.repr(self.tcx()),
|
expr.repr(self.tcx()),
|
||||||
base_cmt.repr(self.tcx()));
|
base_cmt.repr(self.tcx()));
|
||||||
self.cat_field(expr, base_cmt, f_name.node.name, expr_ty)
|
Ok(self.cat_field(expr, base_cmt, f_name.node.name, expr_ty))
|
||||||
}
|
}
|
||||||
|
|
||||||
ast::ExprTupField(ref base, idx) => {
|
ast::ExprTupField(ref base, idx) => {
|
||||||
let base_cmt = self.cat_expr(&**base);
|
let base_cmt = try!(self.cat_expr(&**base));
|
||||||
self.cat_tup_field(expr, base_cmt, idx.node, expr_ty)
|
Ok(self.cat_tup_field(expr, base_cmt, idx.node, expr_ty))
|
||||||
}
|
}
|
||||||
|
|
||||||
ast::ExprIndex(ref base, ref idx) => {
|
ast::ExprIndex(ref base, ref idx) => {
|
||||||
match idx.node {
|
match idx.node {
|
||||||
ast::ExprRange(..) => {
|
ast::ExprRange(..) => {
|
||||||
// Slicing syntax special case (KILLME).
|
// Slicing syntax special case (KILLME).
|
||||||
self.cat_rvalue_node(expr.id(), expr.span(), expr_ty)
|
Ok(self.cat_rvalue_node(expr.id(), expr.span(), expr_ty))
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
let method_call = ty::MethodCall::expr(expr.id());
|
let method_call = ty::MethodCall::expr(expr.id());
|
||||||
|
@ -517,7 +521,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
|
||||||
ret_ty), 1, true)
|
ret_ty), 1, true)
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
self.cat_index(expr, self.cat_expr(&**base))
|
self.cat_index(expr, try!(self.cat_expr(&**base)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -545,7 +549,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
|
||||||
ast::ExprAgain(..) | ast::ExprStruct(..) | ast::ExprRepeat(..) |
|
ast::ExprAgain(..) | ast::ExprStruct(..) | ast::ExprRepeat(..) |
|
||||||
ast::ExprInlineAsm(..) | ast::ExprBox(..) |
|
ast::ExprInlineAsm(..) | ast::ExprBox(..) |
|
||||||
ast::ExprForLoop(..) => {
|
ast::ExprForLoop(..) => {
|
||||||
self.cat_rvalue_node(expr.id(), expr.span(), expr_ty)
|
Ok(self.cat_rvalue_node(expr.id(), expr.span(), expr_ty))
|
||||||
}
|
}
|
||||||
|
|
||||||
ast::ExprIfLet(..) => {
|
ast::ExprIfLet(..) => {
|
||||||
|
@ -562,43 +566,43 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
|
||||||
span: Span,
|
span: Span,
|
||||||
expr_ty: Ty<'tcx>,
|
expr_ty: Ty<'tcx>,
|
||||||
def: def::Def)
|
def: def::Def)
|
||||||
-> cmt<'tcx> {
|
-> McResult<cmt<'tcx>> {
|
||||||
debug!("cat_def: id={} expr={} def={}",
|
debug!("cat_def: id={} expr={} def={}",
|
||||||
id, expr_ty.repr(self.tcx()), def);
|
id, expr_ty.repr(self.tcx()), def);
|
||||||
|
|
||||||
match def {
|
match def {
|
||||||
def::DefStruct(..) | def::DefVariant(..) | def::DefFn(..) |
|
def::DefStruct(..) | def::DefVariant(..) | def::DefFn(..) |
|
||||||
def::DefStaticMethod(..) | def::DefConst(..) => {
|
def::DefStaticMethod(..) | def::DefConst(..) => {
|
||||||
self.cat_rvalue_node(id, span, expr_ty)
|
Ok(self.cat_rvalue_node(id, span, expr_ty))
|
||||||
}
|
}
|
||||||
def::DefMod(_) | def::DefForeignMod(_) | def::DefUse(_) |
|
def::DefMod(_) | def::DefForeignMod(_) | def::DefUse(_) |
|
||||||
def::DefTrait(_) | def::DefTy(..) | def::DefPrimTy(_) |
|
def::DefTrait(_) | def::DefTy(..) | def::DefPrimTy(_) |
|
||||||
def::DefTyParam(..) | def::DefTyParamBinder(..) | def::DefRegion(_) |
|
def::DefTyParam(..) | def::DefTyParamBinder(..) | def::DefRegion(_) |
|
||||||
def::DefLabel(_) | def::DefSelfTy(..) | def::DefMethod(..) |
|
def::DefLabel(_) | def::DefSelfTy(..) | def::DefMethod(..) |
|
||||||
def::DefAssociatedTy(..) | def::DefAssociatedPath(..)=> {
|
def::DefAssociatedTy(..) | def::DefAssociatedPath(..)=> {
|
||||||
Rc::new(cmt_ {
|
Ok(Rc::new(cmt_ {
|
||||||
id:id,
|
id:id,
|
||||||
span:span,
|
span:span,
|
||||||
cat:cat_static_item,
|
cat:cat_static_item,
|
||||||
mutbl: McImmutable,
|
mutbl: McImmutable,
|
||||||
ty:expr_ty,
|
ty:expr_ty,
|
||||||
note: NoteNone
|
note: NoteNone
|
||||||
})
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
def::DefStatic(_, mutbl) => {
|
def::DefStatic(_, mutbl) => {
|
||||||
Rc::new(cmt_ {
|
Ok(Rc::new(cmt_ {
|
||||||
id:id,
|
id:id,
|
||||||
span:span,
|
span:span,
|
||||||
cat:cat_static_item,
|
cat:cat_static_item,
|
||||||
mutbl: if mutbl { McDeclared } else { McImmutable},
|
mutbl: if mutbl { McDeclared } else { McImmutable},
|
||||||
ty:expr_ty,
|
ty:expr_ty,
|
||||||
note: NoteNone
|
note: NoteNone
|
||||||
})
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
def::DefUpvar(var_id, fn_node_id, _) => {
|
def::DefUpvar(var_id, fn_node_id, _) => {
|
||||||
let ty = self.node_ty(fn_node_id);
|
let ty = try!(self.node_ty(fn_node_id));
|
||||||
match ty.sty {
|
match ty.sty {
|
||||||
ty::ty_closure(ref closure_ty) => {
|
ty::ty_closure(ref closure_ty) => {
|
||||||
// Translate old closure type info into unboxed
|
// Translate old closure type info into unboxed
|
||||||
|
@ -635,14 +639,14 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
|
||||||
}
|
}
|
||||||
|
|
||||||
def::DefLocal(vid) => {
|
def::DefLocal(vid) => {
|
||||||
Rc::new(cmt_ {
|
Ok(Rc::new(cmt_ {
|
||||||
id: id,
|
id: id,
|
||||||
span: span,
|
span: span,
|
||||||
cat: cat_local(vid),
|
cat: cat_local(vid),
|
||||||
mutbl: MutabilityCategory::from_local(self.tcx(), vid),
|
mutbl: MutabilityCategory::from_local(self.tcx(), vid),
|
||||||
ty: expr_ty,
|
ty: expr_ty,
|
||||||
note: NoteNone
|
note: NoteNone
|
||||||
})
|
}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -657,7 +661,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
|
||||||
kind: ty::UnboxedClosureKind,
|
kind: ty::UnboxedClosureKind,
|
||||||
mode: ast::CaptureClause,
|
mode: ast::CaptureClause,
|
||||||
is_unboxed: bool)
|
is_unboxed: bool)
|
||||||
-> cmt<'tcx> {
|
-> McResult<cmt<'tcx>> {
|
||||||
// An upvar can have up to 3 components. The base is a
|
// An upvar can have up to 3 components. The base is a
|
||||||
// `cat_upvar`. Next, we add a deref through the implicit
|
// `cat_upvar`. Next, we add a deref through the implicit
|
||||||
// environment pointer with an anonymous free region 'env and
|
// environment pointer with an anonymous free region 'env and
|
||||||
|
@ -679,7 +683,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
|
||||||
// FnOnce | copied | upvar -> &'up bk
|
// FnOnce | copied | upvar -> &'up bk
|
||||||
// old stack | N/A | upvar -> &'env mut -> &'up bk
|
// old stack | N/A | upvar -> &'env mut -> &'up bk
|
||||||
// old proc/once | copied | N/A
|
// old proc/once | copied | N/A
|
||||||
let var_ty = self.node_ty(var_id);
|
let var_ty = try!(self.node_ty(var_id));
|
||||||
|
|
||||||
let upvar_id = ty::UpvarId { var_id: var_id,
|
let upvar_id = ty::UpvarId { var_id: var_id,
|
||||||
closure_expr_id: fn_node_id };
|
closure_expr_id: fn_node_id };
|
||||||
|
@ -727,7 +731,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
|
||||||
});
|
});
|
||||||
|
|
||||||
// First, switch by capture mode
|
// First, switch by capture mode
|
||||||
match mode {
|
Ok(match mode {
|
||||||
ast::CaptureByValue => {
|
ast::CaptureByValue => {
|
||||||
let mut base = cmt_ {
|
let mut base = cmt_ {
|
||||||
id: id,
|
id: id,
|
||||||
|
@ -809,7 +813,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
|
||||||
note: NoteUpvarRef(upvar_id)
|
note: NoteUpvarRef(upvar_id)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cat_rvalue_node(&self,
|
pub fn cat_rvalue_node(&self,
|
||||||
|
@ -882,7 +886,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
|
||||||
base_cmt: cmt<'tcx>,
|
base_cmt: cmt<'tcx>,
|
||||||
deref_cnt: uint,
|
deref_cnt: uint,
|
||||||
implicit: bool)
|
implicit: bool)
|
||||||
-> cmt<'tcx> {
|
-> McResult<cmt<'tcx>> {
|
||||||
let adjustment = match self.typer.adjustments().borrow().get(&node.id()) {
|
let adjustment = match self.typer.adjustments().borrow().get(&node.id()) {
|
||||||
Some(adj) if ty::adjust_is_object(adj) => ty::AutoObject,
|
Some(adj) if ty::adjust_is_object(adj) => ty::AutoObject,
|
||||||
_ if deref_cnt != 0 => ty::AutoDeref(deref_cnt),
|
_ if deref_cnt != 0 => ty::AutoDeref(deref_cnt),
|
||||||
|
@ -922,8 +926,9 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
|
||||||
deref_cnt: uint,
|
deref_cnt: uint,
|
||||||
deref_ty: Ty<'tcx>,
|
deref_ty: Ty<'tcx>,
|
||||||
implicit: bool)
|
implicit: bool)
|
||||||
-> cmt<'tcx> {
|
-> McResult<cmt<'tcx>>
|
||||||
let (m, cat) = match deref_kind(self.tcx(), base_cmt.ty) {
|
{
|
||||||
|
let (m, cat) = match try!(deref_kind(base_cmt.ty)) {
|
||||||
deref_ptr(ptr) => {
|
deref_ptr(ptr) => {
|
||||||
let ptr = if implicit {
|
let ptr = if implicit {
|
||||||
match ptr {
|
match ptr {
|
||||||
|
@ -943,20 +948,20 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
|
||||||
(base_cmt.mutbl.inherit(), cat_interior(base_cmt, interior))
|
(base_cmt.mutbl.inherit(), cat_interior(base_cmt, interior))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Rc::new(cmt_ {
|
Ok(Rc::new(cmt_ {
|
||||||
id: node.id(),
|
id: node.id(),
|
||||||
span: node.span(),
|
span: node.span(),
|
||||||
cat: cat,
|
cat: cat,
|
||||||
mutbl: m,
|
mutbl: m,
|
||||||
ty: deref_ty,
|
ty: deref_ty,
|
||||||
note: NoteNone
|
note: NoteNone
|
||||||
})
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cat_index<N:ast_node>(&self,
|
pub fn cat_index<N:ast_node>(&self,
|
||||||
elt: &N,
|
elt: &N,
|
||||||
mut base_cmt: cmt<'tcx>)
|
mut base_cmt: cmt<'tcx>)
|
||||||
-> cmt<'tcx> {
|
-> McResult<cmt<'tcx>> {
|
||||||
//! Creates a cmt for an indexing operation (`[]`).
|
//! Creates a cmt for an indexing operation (`[]`).
|
||||||
//!
|
//!
|
||||||
//! One subtle aspect of indexing that may not be
|
//! One subtle aspect of indexing that may not be
|
||||||
|
@ -1021,15 +1026,16 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
|
||||||
fn deref_vec<N:ast_node>(&self,
|
fn deref_vec<N:ast_node>(&self,
|
||||||
elt: &N,
|
elt: &N,
|
||||||
base_cmt: cmt<'tcx>)
|
base_cmt: cmt<'tcx>)
|
||||||
-> cmt<'tcx> {
|
-> McResult<cmt<'tcx>>
|
||||||
match deref_kind(self.tcx(), base_cmt.ty) {
|
{
|
||||||
|
match try!(deref_kind(base_cmt.ty)) {
|
||||||
deref_ptr(ptr) => {
|
deref_ptr(ptr) => {
|
||||||
// for unique ptrs, we inherit mutability from the
|
// for unique ptrs, we inherit mutability from the
|
||||||
// owning reference.
|
// owning reference.
|
||||||
let m = MutabilityCategory::from_pointer_kind(base_cmt.mutbl, ptr);
|
let m = MutabilityCategory::from_pointer_kind(base_cmt.mutbl, ptr);
|
||||||
|
|
||||||
// the deref is explicit in the resulting cmt
|
// the deref is explicit in the resulting cmt
|
||||||
Rc::new(cmt_ {
|
Ok(Rc::new(cmt_ {
|
||||||
id:elt.id(),
|
id:elt.id(),
|
||||||
span:elt.span(),
|
span:elt.span(),
|
||||||
cat:cat_deref(base_cmt.clone(), 0, ptr),
|
cat:cat_deref(base_cmt.clone(), 0, ptr),
|
||||||
|
@ -1039,11 +1045,11 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
|
||||||
None => self.tcx().sess.bug("Found non-derefable type")
|
None => self.tcx().sess.bug("Found non-derefable type")
|
||||||
},
|
},
|
||||||
note: NoteNone
|
note: NoteNone
|
||||||
})
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
deref_interior(_) => {
|
deref_interior(_) => {
|
||||||
base_cmt
|
Ok(base_cmt)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1058,13 +1064,13 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
|
||||||
pub fn cat_slice_pattern(&self,
|
pub fn cat_slice_pattern(&self,
|
||||||
vec_cmt: cmt<'tcx>,
|
vec_cmt: cmt<'tcx>,
|
||||||
slice_pat: &ast::Pat)
|
slice_pat: &ast::Pat)
|
||||||
-> (cmt<'tcx>, ast::Mutability, ty::Region) {
|
-> McResult<(cmt<'tcx>, ast::Mutability, ty::Region)> {
|
||||||
let slice_ty = self.node_ty(slice_pat.id);
|
let slice_ty = try!(self.node_ty(slice_pat.id));
|
||||||
let (slice_mutbl, slice_r) = vec_slice_info(self.tcx(),
|
let (slice_mutbl, slice_r) = vec_slice_info(self.tcx(),
|
||||||
slice_pat,
|
slice_pat,
|
||||||
slice_ty);
|
slice_ty);
|
||||||
let cmt_slice = self.cat_index(slice_pat, self.deref_vec(slice_pat, vec_cmt));
|
let cmt_slice = try!(self.cat_index(slice_pat, try!(self.deref_vec(slice_pat, vec_cmt))));
|
||||||
return (cmt_slice, slice_mutbl, slice_r);
|
return Ok((cmt_slice, slice_mutbl, slice_r));
|
||||||
|
|
||||||
/// In a pattern like [a, b, ..c], normally `c` has slice type, but if you have [a, b,
|
/// In a pattern like [a, b, ..c], normally `c` has slice type, but if you have [a, b,
|
||||||
/// ..ref c], then the type of `ref c` will be `&&[]`, so to extract the slice details we
|
/// ..ref c], then the type of `ref c` will be `&&[]`, so to extract the slice details we
|
||||||
|
@ -1119,15 +1125,16 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cat_pattern<F>(&self, cmt: cmt<'tcx>, pat: &ast::Pat, mut op: F) where
|
pub fn cat_pattern<F>(&self, cmt: cmt<'tcx>, pat: &ast::Pat, mut op: F) -> McResult<()>
|
||||||
F: FnMut(&MemCategorizationContext<'t, TYPER>, cmt<'tcx>, &ast::Pat),
|
where F: FnMut(&MemCategorizationContext<'t, TYPER>, cmt<'tcx>, &ast::Pat),
|
||||||
{
|
{
|
||||||
self.cat_pattern_(cmt, pat, &mut op)
|
self.cat_pattern_(cmt, pat, &mut op)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME(#19596) This is a workaround, but there should be a better way to do this
|
// FIXME(#19596) This is a workaround, but there should be a better way to do this
|
||||||
fn cat_pattern_<F>(&self, cmt: cmt<'tcx>, pat: &ast::Pat, op: &mut F) where
|
fn cat_pattern_<F>(&self, cmt: cmt<'tcx>, pat: &ast::Pat, op: &mut F)
|
||||||
F: FnMut(&MemCategorizationContext<'t, TYPER>, cmt<'tcx>, &ast::Pat),
|
-> McResult<()>
|
||||||
|
where F : FnMut(&MemCategorizationContext<'t, TYPER>, cmt<'tcx>, &ast::Pat),
|
||||||
{
|
{
|
||||||
// Here, `cmt` is the categorization for the value being
|
// Here, `cmt` is the categorization for the value being
|
||||||
// matched and pat is the pattern it is being matched against.
|
// matched and pat is the pattern it is being matched against.
|
||||||
|
@ -1208,29 +1215,29 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
|
||||||
Some(&def::DefVariant(..)) => {
|
Some(&def::DefVariant(..)) => {
|
||||||
// variant(x, y, z)
|
// variant(x, y, z)
|
||||||
for (i, subpat) in subpats.iter().enumerate() {
|
for (i, subpat) in subpats.iter().enumerate() {
|
||||||
let subpat_ty = self.pat_ty(&**subpat); // see (*2)
|
let subpat_ty = try!(self.pat_ty(&**subpat)); // see (*2)
|
||||||
|
|
||||||
let subcmt =
|
let subcmt =
|
||||||
self.cat_imm_interior(
|
self.cat_imm_interior(
|
||||||
pat, cmt.clone(), subpat_ty,
|
pat, cmt.clone(), subpat_ty,
|
||||||
InteriorField(PositionalField(i)));
|
InteriorField(PositionalField(i)));
|
||||||
|
|
||||||
self.cat_pattern_(subcmt, &**subpat, op);
|
try!(self.cat_pattern_(subcmt, &**subpat, op));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some(&def::DefStruct(..)) => {
|
Some(&def::DefStruct(..)) => {
|
||||||
for (i, subpat) in subpats.iter().enumerate() {
|
for (i, subpat) in subpats.iter().enumerate() {
|
||||||
let subpat_ty = self.pat_ty(&**subpat); // see (*2)
|
let subpat_ty = try!(self.pat_ty(&**subpat)); // see (*2)
|
||||||
let cmt_field =
|
let cmt_field =
|
||||||
self.cat_imm_interior(
|
self.cat_imm_interior(
|
||||||
pat, cmt.clone(), subpat_ty,
|
pat, cmt.clone(), subpat_ty,
|
||||||
InteriorField(PositionalField(i)));
|
InteriorField(PositionalField(i)));
|
||||||
self.cat_pattern_(cmt_field, &**subpat, op);
|
try!(self.cat_pattern_(cmt_field, &**subpat, op));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some(&def::DefConst(..)) => {
|
Some(&def::DefConst(..)) => {
|
||||||
for subpat in subpats.iter() {
|
for subpat in subpats.iter() {
|
||||||
self.cat_pattern_(cmt.clone(), &**subpat, op);
|
try!(self.cat_pattern_(cmt.clone(), &**subpat, op));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
|
@ -1242,7 +1249,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
|
||||||
}
|
}
|
||||||
|
|
||||||
ast::PatIdent(_, _, Some(ref subpat)) => {
|
ast::PatIdent(_, _, Some(ref subpat)) => {
|
||||||
self.cat_pattern_(cmt, &**subpat, op);
|
try!(self.cat_pattern_(cmt, &**subpat, op));
|
||||||
}
|
}
|
||||||
|
|
||||||
ast::PatIdent(_, _, None) => {
|
ast::PatIdent(_, _, None) => {
|
||||||
|
@ -1252,42 +1259,42 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
|
||||||
ast::PatStruct(_, ref field_pats, _) => {
|
ast::PatStruct(_, ref field_pats, _) => {
|
||||||
// {f1: p1, ..., fN: pN}
|
// {f1: p1, ..., fN: pN}
|
||||||
for fp in field_pats.iter() {
|
for fp in field_pats.iter() {
|
||||||
let field_ty = self.pat_ty(&*fp.node.pat); // see (*2)
|
let field_ty = try!(self.pat_ty(&*fp.node.pat)); // see (*2)
|
||||||
let cmt_field = self.cat_field(pat, cmt.clone(), fp.node.ident.name, field_ty);
|
let cmt_field = self.cat_field(pat, cmt.clone(), fp.node.ident.name, field_ty);
|
||||||
self.cat_pattern_(cmt_field, &*fp.node.pat, op);
|
try!(self.cat_pattern_(cmt_field, &*fp.node.pat, op));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ast::PatTup(ref subpats) => {
|
ast::PatTup(ref subpats) => {
|
||||||
// (p1, ..., pN)
|
// (p1, ..., pN)
|
||||||
for (i, subpat) in subpats.iter().enumerate() {
|
for (i, subpat) in subpats.iter().enumerate() {
|
||||||
let subpat_ty = self.pat_ty(&**subpat); // see (*2)
|
let subpat_ty = try!(self.pat_ty(&**subpat)); // see (*2)
|
||||||
let subcmt =
|
let subcmt =
|
||||||
self.cat_imm_interior(
|
self.cat_imm_interior(
|
||||||
pat, cmt.clone(), subpat_ty,
|
pat, cmt.clone(), subpat_ty,
|
||||||
InteriorField(PositionalField(i)));
|
InteriorField(PositionalField(i)));
|
||||||
self.cat_pattern_(subcmt, &**subpat, op);
|
try!(self.cat_pattern_(subcmt, &**subpat, op));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ast::PatBox(ref subpat) | ast::PatRegion(ref subpat) => {
|
ast::PatBox(ref subpat) | ast::PatRegion(ref subpat) => {
|
||||||
// @p1, ~p1, ref p1
|
// @p1, ~p1, ref p1
|
||||||
let subcmt = self.cat_deref(pat, cmt, 0, false);
|
let subcmt = try!(self.cat_deref(pat, cmt, 0, false));
|
||||||
self.cat_pattern_(subcmt, &**subpat, op);
|
try!(self.cat_pattern_(subcmt, &**subpat, op));
|
||||||
}
|
}
|
||||||
|
|
||||||
ast::PatVec(ref before, ref slice, ref after) => {
|
ast::PatVec(ref before, ref slice, ref after) => {
|
||||||
let elt_cmt = self.cat_index(pat, self.deref_vec(pat, cmt));
|
let elt_cmt = try!(self.cat_index(pat, try!(self.deref_vec(pat, cmt))));
|
||||||
for before_pat in before.iter() {
|
for before_pat in before.iter() {
|
||||||
self.cat_pattern_(elt_cmt.clone(), &**before_pat, op);
|
try!(self.cat_pattern_(elt_cmt.clone(), &**before_pat, op));
|
||||||
}
|
}
|
||||||
for slice_pat in slice.iter() {
|
for slice_pat in slice.iter() {
|
||||||
let slice_ty = self.pat_ty(&**slice_pat);
|
let slice_ty = try!(self.pat_ty(&**slice_pat));
|
||||||
let slice_cmt = self.cat_rvalue_node(pat.id(), pat.span(), slice_ty);
|
let slice_cmt = self.cat_rvalue_node(pat.id(), pat.span(), slice_ty);
|
||||||
self.cat_pattern_(slice_cmt, &**slice_pat, op);
|
try!(self.cat_pattern_(slice_cmt, &**slice_pat, op));
|
||||||
}
|
}
|
||||||
for after_pat in after.iter() {
|
for after_pat in after.iter() {
|
||||||
self.cat_pattern_(elt_cmt.clone(), &**after_pat, op);
|
try!(self.cat_pattern_(elt_cmt.clone(), &**after_pat, op));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5708,7 +5708,10 @@ pub fn unboxed_closure_upvars<'tcx>(typer: &mc::Typer<'tcx>,
|
||||||
freevars.iter()
|
freevars.iter()
|
||||||
.map(|freevar| {
|
.map(|freevar| {
|
||||||
let freevar_def_id = freevar.def.def_id();
|
let freevar_def_id = freevar.def.def_id();
|
||||||
let freevar_ty = typer.node_ty(freevar_def_id.node);
|
let freevar_ty = match typer.node_ty(freevar_def_id.node) {
|
||||||
|
Ok(t) => { t }
|
||||||
|
Err(()) => { return None; }
|
||||||
|
};
|
||||||
let freevar_ty = freevar_ty.subst(tcx, substs);
|
let freevar_ty = freevar_ty.subst(tcx, substs);
|
||||||
|
|
||||||
match capture_mode {
|
match capture_mode {
|
||||||
|
|
|
@ -289,12 +289,17 @@ impl<'a, 'tcx> mc::Typer<'tcx> for FnCtxt<'a, 'tcx> {
|
||||||
self.ccx.tcx
|
self.ccx.tcx
|
||||||
}
|
}
|
||||||
fn node_ty(&self, id: ast::NodeId) -> Ty<'tcx> {
|
fn node_ty(&self, id: ast::NodeId) -> Ty<'tcx> {
|
||||||
|
fn node_ty(&self, id: ast::NodeId) -> McResult<Ty<'tcx>> {
|
||||||
let ty = self.node_ty(id);
|
let ty = self.node_ty(id);
|
||||||
self.infcx().resolve_type_vars_if_possible(&ty)
|
self.resolve_type_vars_or_error(&ty)
|
||||||
}
|
}
|
||||||
fn expr_ty_adjusted(&self, expr: &ast::Expr) -> Ty<'tcx> {
|
fn expr_ty_adjusted(&self, expr: &ast::Expr) -> McResult<Ty<'tcx>> {
|
||||||
let ty = self.expr_ty_adjusted(expr);
|
let ty = self.adjust_expr_ty(expr, self.inh.adjustments.borrow().get(&expr.id));
|
||||||
self.infcx().resolve_type_vars_if_possible(&ty)
|
self.resolve_type_vars_or_error(&ty)
|
||||||
|
}
|
||||||
|
fn type_moves_by_default(&self, span: Span, ty: Ty<'tcx>) -> bool {
|
||||||
|
let ty = self.infcx().resolve_type_vars_if_possible(&ty);
|
||||||
|
traits::type_known_to_meet_builtin_bound(self.infcx(), self, ty, ty::BoundCopy, span)
|
||||||
}
|
}
|
||||||
fn node_method_ty(&self, method_call: ty::MethodCall)
|
fn node_method_ty(&self, method_call: ty::MethodCall)
|
||||||
-> Option<Ty<'tcx>> {
|
-> Option<Ty<'tcx>> {
|
||||||
|
@ -1671,6 +1676,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
self.ccx.tcx.sess.err_count() - self.err_count_on_creation
|
self.ccx.tcx.sess.err_count() - self.err_count_on_creation
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Resolves all type variables in `t` and then, if any were left
|
||||||
|
/// unresolved, substitutes an error type. This is used after the
|
||||||
|
/// main checking when doing a second pass before writeback. The
|
||||||
|
/// justification is that writeback will produce an error for
|
||||||
|
/// these unconstrained type variables.
|
||||||
|
fn resolve_type_vars_or_error(&self, t: &Ty<'tcx>) -> mc::McResult<Ty<'tcx>> {
|
||||||
|
let t = self.infcx().resolve_type_vars_if_possible(t);
|
||||||
|
if ty::type_has_ty_infer(t) || ty::type_is_error(t) { Err(()) } else { Ok(t) }
|
||||||
|
}
|
||||||
|
|
||||||
pub fn tag(&self) -> String {
|
pub fn tag(&self) -> String {
|
||||||
format!("{}", self as *const FnCtxt)
|
format!("{}", self as *const FnCtxt)
|
||||||
}
|
}
|
||||||
|
|
|
@ -140,6 +140,10 @@ use std::collections::hash_map::Entry::{Vacant, Occupied};
|
||||||
use self::RepeatingScope::Repeating;
|
use self::RepeatingScope::Repeating;
|
||||||
use self::SubjectNode::Subject;
|
use self::SubjectNode::Subject;
|
||||||
|
|
||||||
|
// a variation on try that just returns unit
|
||||||
|
macro_rules! ignore_err {
|
||||||
|
($e:expr) => (match $e { Ok(e) => e, Err(_) => return () })
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// PUBLIC ENTRY POINTS
|
// PUBLIC ENTRY POINTS
|
||||||
|
@ -1027,7 +1031,7 @@ fn constrain_callee(rcx: &mut Rcx,
|
||||||
// While we're here, link the closure's region with a unique
|
// While we're here, link the closure's region with a unique
|
||||||
// immutable borrow (gathered later in borrowck)
|
// immutable borrow (gathered later in borrowck)
|
||||||
let mc = mc::MemCategorizationContext::new(rcx.fcx);
|
let mc = mc::MemCategorizationContext::new(rcx.fcx);
|
||||||
let expr_cmt = mc.cat_expr(callee_expr);
|
let expr_cmt = ignore_err!(mc.cat_expr(callee_expr));
|
||||||
link_region(rcx, callee_expr.span, call_region,
|
link_region(rcx, callee_expr.span, call_region,
|
||||||
ty::UniqueImmBorrow, expr_cmt);
|
ty::UniqueImmBorrow, expr_cmt);
|
||||||
r
|
r
|
||||||
|
@ -1136,7 +1140,7 @@ fn constrain_autoderefs<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>,
|
||||||
};
|
};
|
||||||
{
|
{
|
||||||
let mc = mc::MemCategorizationContext::new(rcx.fcx);
|
let mc = mc::MemCategorizationContext::new(rcx.fcx);
|
||||||
let self_cmt = mc.cat_expr_autoderefd(deref_expr, i);
|
let self_cmt = ignore_err!(mc.cat_expr_autoderefd(deref_expr, i));
|
||||||
link_region(rcx, deref_expr.span, *r,
|
link_region(rcx, deref_expr.span, *r,
|
||||||
ty::BorrowKind::from_mutbl(m), self_cmt);
|
ty::BorrowKind::from_mutbl(m), self_cmt);
|
||||||
}
|
}
|
||||||
|
@ -1232,7 +1236,7 @@ fn link_addr_of(rcx: &mut Rcx, expr: &ast::Expr,
|
||||||
|
|
||||||
let cmt = {
|
let cmt = {
|
||||||
let mc = mc::MemCategorizationContext::new(rcx.fcx);
|
let mc = mc::MemCategorizationContext::new(rcx.fcx);
|
||||||
mc.cat_expr(base)
|
ignore_err!(mc.cat_expr(base))
|
||||||
};
|
};
|
||||||
link_region_from_node_type(rcx, expr.span, expr.id, mutability, cmt);
|
link_region_from_node_type(rcx, expr.span, expr.id, mutability, cmt);
|
||||||
}
|
}
|
||||||
|
@ -1247,7 +1251,7 @@ fn link_local(rcx: &Rcx, local: &ast::Local) {
|
||||||
Some(ref expr) => &**expr,
|
Some(ref expr) => &**expr,
|
||||||
};
|
};
|
||||||
let mc = mc::MemCategorizationContext::new(rcx.fcx);
|
let mc = mc::MemCategorizationContext::new(rcx.fcx);
|
||||||
let discr_cmt = mc.cat_expr(init_expr);
|
let discr_cmt = ignore_err!(mc.cat_expr(init_expr));
|
||||||
link_pattern(rcx, mc, discr_cmt, &*local.pat);
|
link_pattern(rcx, mc, discr_cmt, &*local.pat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1257,7 +1261,7 @@ fn link_local(rcx: &Rcx, local: &ast::Local) {
|
||||||
fn link_match(rcx: &Rcx, discr: &ast::Expr, arms: &[ast::Arm]) {
|
fn link_match(rcx: &Rcx, discr: &ast::Expr, arms: &[ast::Arm]) {
|
||||||
debug!("regionck::for_match()");
|
debug!("regionck::for_match()");
|
||||||
let mc = mc::MemCategorizationContext::new(rcx.fcx);
|
let mc = mc::MemCategorizationContext::new(rcx.fcx);
|
||||||
let discr_cmt = mc.cat_expr(discr);
|
let discr_cmt = ignore_err!(mc.cat_expr(discr));
|
||||||
debug!("discr_cmt={}", discr_cmt.repr(rcx.tcx()));
|
debug!("discr_cmt={}", discr_cmt.repr(rcx.tcx()));
|
||||||
for arm in arms.iter() {
|
for arm in arms.iter() {
|
||||||
for root_pat in arm.pats.iter() {
|
for root_pat in arm.pats.iter() {
|
||||||
|
@ -1303,12 +1307,15 @@ fn link_pattern<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>,
|
||||||
|
|
||||||
// `[_, ..slice, _]` pattern
|
// `[_, ..slice, _]` pattern
|
||||||
ast::PatVec(_, Some(ref slice_pat), _) => {
|
ast::PatVec(_, Some(ref slice_pat), _) => {
|
||||||
let (slice_cmt, slice_mutbl, slice_r) =
|
match mc.cat_slice_pattern(sub_cmt, &**slice_pat) {
|
||||||
mc.cat_slice_pattern(sub_cmt, &**slice_pat);
|
Ok((slice_cmt, slice_mutbl, slice_r)) => {
|
||||||
link_region(rcx, sub_pat.span, slice_r,
|
link_region(rcx, sub_pat.span, slice_r,
|
||||||
ty::BorrowKind::from_mutbl(slice_mutbl),
|
ty::BorrowKind::from_mutbl(slice_mutbl),
|
||||||
slice_cmt);
|
slice_cmt);
|
||||||
}
|
}
|
||||||
|
Err(()) => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -1323,7 +1330,7 @@ fn link_autoref(rcx: &Rcx,
|
||||||
|
|
||||||
debug!("link_autoref(autoref={})", autoref);
|
debug!("link_autoref(autoref={})", autoref);
|
||||||
let mc = mc::MemCategorizationContext::new(rcx.fcx);
|
let mc = mc::MemCategorizationContext::new(rcx.fcx);
|
||||||
let expr_cmt = mc.cat_expr_autoderefd(expr, autoderefs);
|
let expr_cmt = ignore_err!(mc.cat_expr_autoderefd(expr, autoderefs));
|
||||||
debug!("expr_cmt={}", expr_cmt.repr(rcx.tcx()));
|
debug!("expr_cmt={}", expr_cmt.repr(rcx.tcx()));
|
||||||
|
|
||||||
match *autoref {
|
match *autoref {
|
||||||
|
@ -1345,7 +1352,7 @@ fn link_by_ref(rcx: &Rcx,
|
||||||
debug!("link_by_ref(expr={}, callee_scope={})",
|
debug!("link_by_ref(expr={}, callee_scope={})",
|
||||||
expr.repr(tcx), callee_scope);
|
expr.repr(tcx), callee_scope);
|
||||||
let mc = mc::MemCategorizationContext::new(rcx.fcx);
|
let mc = mc::MemCategorizationContext::new(rcx.fcx);
|
||||||
let expr_cmt = mc.cat_expr(expr);
|
let expr_cmt = ignore_err!(mc.cat_expr(expr));
|
||||||
let borrow_region = ty::ReScope(callee_scope);
|
let borrow_region = ty::ReScope(callee_scope);
|
||||||
link_region(rcx, expr.span, borrow_region, ty::ImmBorrow, expr_cmt);
|
link_region(rcx, expr.span, borrow_region, ty::ImmBorrow, expr_cmt);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue