Add LpDowncast
, LoanPath
variant tracking downcasts in match arms.
`LpDowncast` carries the `DefId` of the variant itself. To support this, added the enum variant `DefId` to the `cat_downcast` variant in `mem_categorization::categorization`. (updated to fix mem_categorization to handle downcast of enum struct-variants properly.)
This commit is contained in:
parent
e31fc9dd4f
commit
d6c8f3b726
11 changed files with 105 additions and 48 deletions
|
@ -52,6 +52,7 @@ fn owned_ptr_base_path<'a>(loan_path: &'a LoanPath) -> &'a LoanPath {
|
||||||
None => Some(&**lp_base)
|
None => Some(&**lp_base)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
LpDowncast(ref lp_base, _) |
|
||||||
LpExtend(ref lp_base, _, _) => owned_ptr_base_path_helper(&**lp_base)
|
LpExtend(ref lp_base, _, _) => owned_ptr_base_path_helper(&**lp_base)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -75,6 +76,7 @@ fn owned_ptr_base_path_rc(loan_path: &Rc<LoanPath>) -> Rc<LoanPath> {
|
||||||
None => Some(lp_base.clone())
|
None => Some(lp_base.clone())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
LpDowncast(ref lp_base, _) |
|
||||||
LpExtend(ref lp_base, _, _) => owned_ptr_base_path_helper(lp_base)
|
LpExtend(ref lp_base, _, _) => owned_ptr_base_path_helper(lp_base)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -298,6 +300,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
|
||||||
LpVar(_) | LpUpvar(_) => {
|
LpVar(_) | LpUpvar(_) => {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
LpDowncast(ref lp_base, _) |
|
||||||
LpExtend(ref lp_base, _, _) => {
|
LpExtend(ref lp_base, _, _) => {
|
||||||
loan_path = &**lp_base;
|
loan_path = &**lp_base;
|
||||||
}
|
}
|
||||||
|
@ -726,6 +729,11 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
|
||||||
LpVar(_) | LpUpvar(_) => {
|
LpVar(_) | LpUpvar(_) => {
|
||||||
// assigning to `x` does not require that `x` is initialized
|
// assigning to `x` does not require that `x` is initialized
|
||||||
}
|
}
|
||||||
|
LpDowncast(ref lp_base, _) => {
|
||||||
|
// assigning to `(P->Variant).f` is ok if assigning to `P` is ok
|
||||||
|
self.check_if_assigned_path_is_moved(id, span,
|
||||||
|
use_kind, lp_base);
|
||||||
|
}
|
||||||
LpExtend(ref lp_base, _, LpInterior(_)) => {
|
LpExtend(ref lp_base, _, LpInterior(_)) => {
|
||||||
// assigning to `P.f` is ok if assigning to `P` is ok
|
// assigning to `P.f` is ok if assigning to `P` is ok
|
||||||
self.check_if_assigned_path_is_moved(id, span,
|
self.check_if_assigned_path_is_moved(id, span,
|
||||||
|
@ -864,7 +872,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
|
||||||
cmt = b;
|
cmt = b;
|
||||||
}
|
}
|
||||||
|
|
||||||
mc::cat_downcast(b) |
|
mc::cat_downcast(b, _) |
|
||||||
mc::cat_interior(b, _) => {
|
mc::cat_interior(b, _) => {
|
||||||
assert_eq!(cmt.mutbl, mc::McInherited);
|
assert_eq!(cmt.mutbl, mc::McInherited);
|
||||||
cmt = b;
|
cmt = b;
|
||||||
|
|
|
@ -144,7 +144,7 @@ fn check_and_get_illegal_move_origin<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
mc::cat_downcast(ref b) |
|
mc::cat_downcast(ref b, _) |
|
||||||
mc::cat_interior(ref b, _) => {
|
mc::cat_interior(ref b, _) => {
|
||||||
match b.ty.sty {
|
match b.ty.sty {
|
||||||
ty::ty_struct(did, _) | ty::ty_enum(did, _) => {
|
ty::ty_struct(did, _) | ty::ty_enum(did, _) => {
|
||||||
|
|
|
@ -85,7 +85,7 @@ impl<'a, 'tcx> GuaranteeLifetimeContext<'a, 'tcx> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
mc::cat_downcast(ref base) |
|
mc::cat_downcast(ref base, _) |
|
||||||
mc::cat_deref(ref base, _, mc::OwnedPtr) | // L-Deref-Send
|
mc::cat_deref(ref base, _, mc::OwnedPtr) | // L-Deref-Send
|
||||||
mc::cat_interior(ref base, _) => { // L-Field
|
mc::cat_interior(ref base, _) => { // L-Field
|
||||||
self.check(base, discr_scope)
|
self.check(base, discr_scope)
|
||||||
|
@ -130,7 +130,7 @@ impl<'a, 'tcx> GuaranteeLifetimeContext<'a, 'tcx> {
|
||||||
mc::cat_deref(_, _, mc::Implicit(_, r)) => {
|
mc::cat_deref(_, _, mc::Implicit(_, r)) => {
|
||||||
r
|
r
|
||||||
}
|
}
|
||||||
mc::cat_downcast(ref cmt) |
|
mc::cat_downcast(ref cmt, _) |
|
||||||
mc::cat_deref(ref cmt, _, mc::OwnedPtr) |
|
mc::cat_deref(ref cmt, _, mc::OwnedPtr) |
|
||||||
mc::cat_interior(ref cmt, _) => {
|
mc::cat_interior(ref cmt, _) => {
|
||||||
self.scope(cmt)
|
self.scope(cmt)
|
||||||
|
|
|
@ -400,6 +400,7 @@ impl<'a, 'tcx> GatherLoanCtxt<'a, 'tcx> {
|
||||||
LpUpvar(ty::UpvarId{ var_id: local_id, closure_expr_id: _ }) => {
|
LpUpvar(ty::UpvarId{ var_id: local_id, closure_expr_id: _ }) => {
|
||||||
self.tcx().used_mut_nodes.borrow_mut().insert(local_id);
|
self.tcx().used_mut_nodes.borrow_mut().insert(local_id);
|
||||||
}
|
}
|
||||||
|
LpDowncast(ref base, _) |
|
||||||
LpExtend(ref base, mc::McInherited, _) |
|
LpExtend(ref base, mc::McInherited, _) |
|
||||||
LpExtend(ref base, mc::McDeclared, _) => {
|
LpExtend(ref base, mc::McDeclared, _) => {
|
||||||
self.mark_loan_path_as_mutated(&**base);
|
self.mark_loan_path_as_mutated(&**base);
|
||||||
|
|
|
@ -124,7 +124,7 @@ fn report_cannot_move_out_of<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
|
||||||
bccx.cmt_to_string(&*move_from)).as_slice());
|
bccx.cmt_to_string(&*move_from)).as_slice());
|
||||||
}
|
}
|
||||||
|
|
||||||
mc::cat_downcast(ref b) |
|
mc::cat_downcast(ref b, _) |
|
||||||
mc::cat_interior(ref b, _) => {
|
mc::cat_interior(ref b, _) => {
|
||||||
match b.ty.sty {
|
match b.ty.sty {
|
||||||
ty::ty_struct(did, _)
|
ty::ty_struct(did, _)
|
||||||
|
|
|
@ -82,7 +82,7 @@ impl<'a, 'tcx> RestrictionsContext<'a, 'tcx> {
|
||||||
SafeIf(lp.clone(), vec![lp])
|
SafeIf(lp.clone(), vec![lp])
|
||||||
}
|
}
|
||||||
|
|
||||||
mc::cat_downcast(cmt_base) => {
|
mc::cat_downcast(cmt_base, _) => {
|
||||||
// When we borrow the interior of an enum, we have to
|
// When we borrow the interior of an enum, we have to
|
||||||
// ensure the enum itself is not mutated, because that
|
// ensure the enum itself is not mutated, because that
|
||||||
// could cause the type of the memory to change.
|
// could cause the type of the memory to change.
|
||||||
|
|
|
@ -284,11 +284,27 @@ impl Loan {
|
||||||
|
|
||||||
#[deriving(PartialEq, Eq, Hash, Show)]
|
#[deriving(PartialEq, Eq, Hash, Show)]
|
||||||
pub enum LoanPath {
|
pub enum LoanPath {
|
||||||
LpVar(ast::NodeId), // `x` in doc.rs
|
LpVar(ast::NodeId), // `x` in doc.rs
|
||||||
LpUpvar(ty::UpvarId), // `x` captured by-value into closure
|
LpUpvar(ty::UpvarId), // `x` captured by-value into closure
|
||||||
|
LpDowncast(Rc<LoanPath>, ast::DefId), // `x` downcast to particular enum variant
|
||||||
LpExtend(Rc<LoanPath>, mc::MutabilityCategory, LoanPathElem)
|
LpExtend(Rc<LoanPath>, mc::MutabilityCategory, LoanPathElem)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl LoanPath {
|
||||||
|
fn kill_id(&self, tcx: &ty::ctxt) -> ast::NodeId {
|
||||||
|
//! Returns the lifetime of the local variable that forms the
|
||||||
|
//! base of this path. (See move_data::add_gen_kills.)
|
||||||
|
match *self {
|
||||||
|
LpVar(id) =>
|
||||||
|
tcx.region_maps.var_scope(id),
|
||||||
|
LpUpvar(ty::UpvarId { var_id: _, closure_expr_id }) =>
|
||||||
|
closure_to_block(closure_expr_id, tcx),
|
||||||
|
LpDowncast(ref base_lp, _) | LpExtend(ref base_lp, _, _) =>
|
||||||
|
base_lp.kill_id(tcx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[deriving(PartialEq, Eq, Hash, Show)]
|
#[deriving(PartialEq, Eq, Hash, Show)]
|
||||||
pub enum LoanPathElem {
|
pub enum LoanPathElem {
|
||||||
LpDeref(mc::PointerKind), // `*LV` in doc.rs
|
LpDeref(mc::PointerKind), // `*LV` in doc.rs
|
||||||
|
@ -319,6 +335,7 @@ impl LoanPath {
|
||||||
let block_id = closure_to_block(upvar_id.closure_expr_id, tcx);
|
let block_id = closure_to_block(upvar_id.closure_expr_id, tcx);
|
||||||
region::CodeExtent::from_node_id(block_id)
|
region::CodeExtent::from_node_id(block_id)
|
||||||
}
|
}
|
||||||
|
LpDowncast(ref base, _) |
|
||||||
LpExtend(ref base, _, _) => base.kill_scope(tcx),
|
LpExtend(ref base, _, _) => base.kill_scope(tcx),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -402,9 +419,12 @@ pub fn opt_loan_path(cmt: &mc::cmt) -> Option<Rc<LoanPath>> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
mc::cat_downcast(ref cmt_base) => {
|
mc::cat_downcast(ref cmt_base, variant_def_id) =>
|
||||||
opt_loan_path(cmt_base)
|
opt_loan_path(cmt_base)
|
||||||
}
|
.map(|lp| {
|
||||||
|
Rc::new(LpDowncast(lp, variant_def_id))
|
||||||
|
}),
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -862,6 +882,15 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
|
||||||
out.push_str(ty::local_var_name_str(self.tcx, id).get());
|
out.push_str(ty::local_var_name_str(self.tcx, id).get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LpDowncast(ref lp_base, variant_def_id) => {
|
||||||
|
out.push('(');
|
||||||
|
self.append_loan_path_to_string(&**lp_base, out);
|
||||||
|
out.push_str("->");
|
||||||
|
out.push_str(ty::item_path_str(self.tcx, variant_def_id).as_slice());
|
||||||
|
out.push(')');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
LpExtend(ref lp_base, _, LpInterior(mc::InteriorField(fname))) => {
|
LpExtend(ref lp_base, _, LpInterior(mc::InteriorField(fname))) => {
|
||||||
self.append_autoderefd_loan_path_to_string(&**lp_base, out);
|
self.append_autoderefd_loan_path_to_string(&**lp_base, out);
|
||||||
match fname {
|
match fname {
|
||||||
|
@ -899,6 +928,14 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
|
||||||
self.append_autoderefd_loan_path_to_string(&**lp_base, out)
|
self.append_autoderefd_loan_path_to_string(&**lp_base, out)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LpDowncast(ref lp_base, variant_def_id) => {
|
||||||
|
out.push('(');
|
||||||
|
self.append_autoderefd_loan_path_to_string(&**lp_base, out);
|
||||||
|
out.push(':');
|
||||||
|
out.push_str(ty::item_path_str(self.tcx, variant_def_id).as_slice());
|
||||||
|
out.push(')');
|
||||||
|
}
|
||||||
|
|
||||||
LpVar(..) | LpUpvar(..) | LpExtend(_, _, LpInterior(..)) => {
|
LpVar(..) | LpUpvar(..) | LpExtend(_, _, LpInterior(..)) => {
|
||||||
self.append_loan_path_to_string(loan_path, out)
|
self.append_loan_path_to_string(loan_path, out)
|
||||||
}
|
}
|
||||||
|
@ -966,6 +1003,15 @@ impl<'tcx> Repr<'tcx> for LoanPath {
|
||||||
format!("$({} captured by id={})", s, closure_expr_id)
|
format!("$({} captured by id={})", s, closure_expr_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&LpDowncast(ref lp, variant_def_id) => {
|
||||||
|
let variant_str = if variant_def_id.krate == ast::LOCAL_CRATE {
|
||||||
|
ty::item_path_str(tcx, variant_def_id)
|
||||||
|
} else {
|
||||||
|
variant_def_id.repr(tcx)
|
||||||
|
};
|
||||||
|
format!("({}->{})", lp.repr(tcx), variant_str)
|
||||||
|
}
|
||||||
|
|
||||||
&LpExtend(ref lp, _, LpDeref(_)) => {
|
&LpExtend(ref lp, _, LpDeref(_)) => {
|
||||||
format!("{}.*", lp.repr(tcx))
|
format!("{}.*", lp.repr(tcx))
|
||||||
}
|
}
|
||||||
|
|
|
@ -175,6 +175,7 @@ fn loan_path_is_precise(loan_path: &LoanPath) -> bool {
|
||||||
// location, as there is no accurate tracking of the indices.
|
// location, as there is no accurate tracking of the indices.
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
LpDowncast(ref lp_base, _) |
|
||||||
LpExtend(ref lp_base, _, _) => {
|
LpExtend(ref lp_base, _, _) => {
|
||||||
loan_path_is_precise(&**lp_base)
|
loan_path_is_precise(&**lp_base)
|
||||||
}
|
}
|
||||||
|
@ -266,6 +267,7 @@ impl MoveData {
|
||||||
index
|
index
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LpDowncast(ref base, _) |
|
||||||
LpExtend(ref base, _, _) => {
|
LpExtend(ref base, _, _) => {
|
||||||
let parent_index = self.move_path(tcx, base.clone());
|
let parent_index = self.move_path(tcx, base.clone());
|
||||||
|
|
||||||
|
@ -324,6 +326,7 @@ impl MoveData {
|
||||||
None => {
|
None => {
|
||||||
match **lp {
|
match **lp {
|
||||||
LpVar(..) | LpUpvar(..) => { }
|
LpVar(..) | LpUpvar(..) => { }
|
||||||
|
LpDowncast(ref b, _) |
|
||||||
LpExtend(ref b, _, _) => {
|
LpExtend(ref b, _, _) => {
|
||||||
self.add_existing_base_paths(b, result);
|
self.add_existing_base_paths(b, result);
|
||||||
}
|
}
|
||||||
|
@ -434,16 +437,11 @@ impl MoveData {
|
||||||
// of scope:
|
// of scope:
|
||||||
for path in self.paths.borrow().iter() {
|
for path in self.paths.borrow().iter() {
|
||||||
match *path.loan_path {
|
match *path.loan_path {
|
||||||
LpVar(id) => {
|
LpVar(..) | LpUpvar(..) | LpDowncast(..) => {
|
||||||
let kill_scope = tcx.region_maps.var_scope(id);
|
let kill_scope = path.loan_path.kill_scope(tcx);
|
||||||
let path = (*self.path_map.borrow())[path.loan_path];
|
let path = *self.path_map.borrow().get(&path.loan_path);
|
||||||
self.kill_moves(path, kill_scope.node_id(), dfcx_moves);
|
self.kill_moves(path, kill_scope.node_id(), dfcx_moves);
|
||||||
}
|
}
|
||||||
LpUpvar(ty::UpvarId { var_id: _, closure_expr_id }) => {
|
|
||||||
let kill_id = closure_to_block(closure_expr_id, tcx);
|
|
||||||
let path = (*self.path_map.borrow())[path.loan_path];
|
|
||||||
self.kill_moves(path, kill_id, dfcx_moves);
|
|
||||||
}
|
|
||||||
LpExtend(..) => {}
|
LpExtend(..) => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -451,15 +449,12 @@ impl MoveData {
|
||||||
// Kill all assignments when the variable goes out of scope:
|
// Kill all assignments when the variable goes out of scope:
|
||||||
for (assignment_index, assignment) in
|
for (assignment_index, assignment) in
|
||||||
self.var_assignments.borrow().iter().enumerate() {
|
self.var_assignments.borrow().iter().enumerate() {
|
||||||
match *self.path_loan_path(assignment.path) {
|
let lp = self.path_loan_path(assignment.path);
|
||||||
LpVar(id) => {
|
match *lp {
|
||||||
let kill_scope = tcx.region_maps.var_scope(id);
|
LpVar(..) | LpUpvar(..) | LpDowncast(..) => {
|
||||||
|
let kill_scope = lp.kill_scope(tcx);
|
||||||
dfcx_assign.add_kill(kill_scope.node_id(), assignment_index);
|
dfcx_assign.add_kill(kill_scope.node_id(), assignment_index);
|
||||||
}
|
}
|
||||||
LpUpvar(ty::UpvarId { var_id: _, closure_expr_id }) => {
|
|
||||||
let kill_id = closure_to_block(closure_expr_id, tcx);
|
|
||||||
dfcx_assign.add_kill(kill_id, assignment_index);
|
|
||||||
}
|
|
||||||
LpExtend(..) => {
|
LpExtend(..) => {
|
||||||
tcx.sess.bug("var assignment for non var path");
|
tcx.sess.bug("var assignment for non var path");
|
||||||
}
|
}
|
||||||
|
|
|
@ -270,7 +270,7 @@ impl<'tcx> euv::Delegate<'tcx> for GlobalChecker {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
mc::cat_deref(ref cmt, _, _) |
|
mc::cat_deref(ref cmt, _, _) |
|
||||||
mc::cat_downcast(ref cmt) |
|
mc::cat_downcast(ref cmt, _) |
|
||||||
mc::cat_interior(ref cmt, _) => cur = cmt,
|
mc::cat_interior(ref cmt, _) => cur = cmt,
|
||||||
|
|
||||||
mc::cat_rvalue(..) |
|
mc::cat_rvalue(..) |
|
||||||
|
|
|
@ -98,7 +98,7 @@ pub enum categorization<'tcx> {
|
||||||
cat_local(ast::NodeId), // local variable
|
cat_local(ast::NodeId), // local variable
|
||||||
cat_deref(cmt<'tcx>, uint, PointerKind), // deref of a ptr
|
cat_deref(cmt<'tcx>, uint, PointerKind), // deref of a ptr
|
||||||
cat_interior(cmt<'tcx>, InteriorKind), // something interior: field, tuple, etc
|
cat_interior(cmt<'tcx>, InteriorKind), // something interior: field, tuple, etc
|
||||||
cat_downcast(cmt<'tcx>), // selects a particular enum variant (*1)
|
cat_downcast(cmt, ast::DefId), // selects a particular enum variant (*1)
|
||||||
|
|
||||||
// (*1) downcast is only required if the enum has more than one variant
|
// (*1) downcast is only required if the enum has more than one variant
|
||||||
}
|
}
|
||||||
|
@ -1102,13 +1102,14 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
|
||||||
pub fn cat_downcast<N:ast_node>(&self,
|
pub fn cat_downcast<N:ast_node>(&self,
|
||||||
node: &N,
|
node: &N,
|
||||||
base_cmt: cmt<'tcx>,
|
base_cmt: cmt<'tcx>,
|
||||||
downcast_ty: Ty<'tcx>)
|
downcast_ty: Ty<'tcx>,
|
||||||
|
variant_did: ast::DefId)
|
||||||
-> cmt<'tcx> {
|
-> cmt<'tcx> {
|
||||||
Rc::new(cmt_ {
|
Rc::new(cmt_ {
|
||||||
id: node.id(),
|
id: node.id(),
|
||||||
span: node.span(),
|
span: node.span(),
|
||||||
mutbl: base_cmt.mutbl.inherit(),
|
mutbl: base_cmt.mutbl.inherit(),
|
||||||
cat: cat_downcast(base_cmt),
|
cat: cat_downcast(base_cmt, variant_did),
|
||||||
ty: downcast_ty,
|
ty: downcast_ty,
|
||||||
note: NoteNone
|
note: NoteNone
|
||||||
})
|
})
|
||||||
|
@ -1172,6 +1173,21 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
|
||||||
|
|
||||||
op(self, cmt.clone(), pat);
|
op(self, cmt.clone(), pat);
|
||||||
|
|
||||||
|
let def_map = self.tcx().def_map.borrow();
|
||||||
|
let opt_def = def_map.get(&pat.id);
|
||||||
|
|
||||||
|
// Note: This goes up here (rather than within the PatEnum arm
|
||||||
|
// alone) because struct patterns can refer to struct types or
|
||||||
|
// to struct variants within enums.
|
||||||
|
let cmt = match opt_def {
|
||||||
|
Some(&def::DefVariant(enum_did, variant_did, _))
|
||||||
|
// univariant enums do not need downcasts
|
||||||
|
if !ty::enum_is_univariant(self.tcx(), enum_did) => {
|
||||||
|
self.cat_downcast(pat, cmt.clone(), cmt.ty, variant_did)
|
||||||
|
}
|
||||||
|
_ => cmt
|
||||||
|
};
|
||||||
|
|
||||||
match pat.node {
|
match pat.node {
|
||||||
ast::PatWild(_) => {
|
ast::PatWild(_) => {
|
||||||
// _
|
// _
|
||||||
|
@ -1181,24 +1197,15 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
|
||||||
// variant(..)
|
// variant(..)
|
||||||
}
|
}
|
||||||
ast::PatEnum(_, Some(ref subpats)) => {
|
ast::PatEnum(_, Some(ref subpats)) => {
|
||||||
match self.tcx().def_map.borrow().get(&pat.id) {
|
match opt_def {
|
||||||
Some(&def::DefVariant(enum_did, _, _)) => {
|
Some(&def::DefVariant(..)) => {
|
||||||
// variant(x, y, z)
|
// variant(x, y, z)
|
||||||
|
|
||||||
let downcast_cmt = {
|
|
||||||
if ty::enum_is_univariant(self.tcx(), enum_did) {
|
|
||||||
cmt // univariant, no downcast needed
|
|
||||||
} else {
|
|
||||||
self.cat_downcast(pat, cmt.clone(), cmt.ty)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
for (i, subpat) in subpats.iter().enumerate() {
|
for (i, subpat) in subpats.iter().enumerate() {
|
||||||
let subpat_ty = if_ok!(self.pat_ty(&**subpat)); // see (*2)
|
let subpat_ty = if_ok!(self.pat_ty(&**subpat)); // see (*2)
|
||||||
|
|
||||||
let subcmt =
|
let subcmt =
|
||||||
self.cat_imm_interior(
|
self.cat_imm_interior(
|
||||||
pat, downcast_cmt.clone(), subpat_ty,
|
pat, cmt.clone(), subpat_ty,
|
||||||
InteriorField(PositionalField(i)));
|
InteriorField(PositionalField(i)));
|
||||||
|
|
||||||
if_ok!(self.cat_pattern(subcmt, &**subpat, |x,y,z| op(x,y,z)));
|
if_ok!(self.cat_pattern(subcmt, &**subpat, |x,y,z| op(x,y,z)));
|
||||||
|
@ -1356,7 +1363,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
|
||||||
cat_upvar(ref var) => {
|
cat_upvar(ref var) => {
|
||||||
upvar_to_string(var, true)
|
upvar_to_string(var, true)
|
||||||
}
|
}
|
||||||
cat_downcast(ref cmt) => {
|
cat_downcast(ref cmt, _) => {
|
||||||
self.cmt_to_string(&**cmt)
|
self.cmt_to_string(&**cmt)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1392,7 +1399,7 @@ impl<'tcx> cmt_<'tcx> {
|
||||||
cat_upvar(..) => {
|
cat_upvar(..) => {
|
||||||
Rc::new((*self).clone())
|
Rc::new((*self).clone())
|
||||||
}
|
}
|
||||||
cat_downcast(ref b) |
|
cat_downcast(ref b, _) |
|
||||||
cat_interior(ref b, _) |
|
cat_interior(ref b, _) |
|
||||||
cat_deref(ref b, _, OwnedPtr) => {
|
cat_deref(ref b, _, OwnedPtr) => {
|
||||||
b.guarantor()
|
b.guarantor()
|
||||||
|
@ -1416,7 +1423,7 @@ impl<'tcx> cmt_<'tcx> {
|
||||||
cat_deref(ref b, _, Implicit(ty::MutBorrow, _)) |
|
cat_deref(ref b, _, Implicit(ty::MutBorrow, _)) |
|
||||||
cat_deref(ref b, _, BorrowedPtr(ty::UniqueImmBorrow, _)) |
|
cat_deref(ref b, _, BorrowedPtr(ty::UniqueImmBorrow, _)) |
|
||||||
cat_deref(ref b, _, Implicit(ty::UniqueImmBorrow, _)) |
|
cat_deref(ref b, _, Implicit(ty::UniqueImmBorrow, _)) |
|
||||||
cat_downcast(ref b) |
|
cat_downcast(ref b, _) |
|
||||||
cat_deref(ref b, _, OwnedPtr) |
|
cat_deref(ref b, _, OwnedPtr) |
|
||||||
cat_interior(ref b, _) => {
|
cat_interior(ref b, _) => {
|
||||||
// Aliasability depends on base cmt
|
// Aliasability depends on base cmt
|
||||||
|
@ -1500,7 +1507,7 @@ impl<'tcx> Repr<'tcx> for categorization<'tcx> {
|
||||||
cat_interior(ref cmt, interior) => {
|
cat_interior(ref cmt, interior) => {
|
||||||
format!("{}.{}", cmt.cat.repr(tcx), interior.repr(tcx))
|
format!("{}.{}", cmt.cat.repr(tcx), interior.repr(tcx))
|
||||||
}
|
}
|
||||||
cat_downcast(ref cmt) => {
|
cat_downcast(ref cmt, _) => {
|
||||||
format!("{}->(enum)", cmt.cat.repr(tcx))
|
format!("{}->(enum)", cmt.cat.repr(tcx))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1503,7 +1503,7 @@ fn link_region<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mc::cat_downcast(cmt_base) |
|
mc::cat_downcast(cmt_base, _) |
|
||||||
mc::cat_deref(cmt_base, _, mc::OwnedPtr) |
|
mc::cat_deref(cmt_base, _, mc::OwnedPtr) |
|
||||||
mc::cat_interior(cmt_base, _) => {
|
mc::cat_interior(cmt_base, _) => {
|
||||||
// Borrowing interior or owned data requires the base
|
// Borrowing interior or owned data requires the base
|
||||||
|
@ -1744,7 +1744,7 @@ fn adjust_upvar_borrow_kind_for_mut<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>,
|
||||||
match cmt.cat.clone() {
|
match cmt.cat.clone() {
|
||||||
mc::cat_deref(base, _, mc::OwnedPtr) |
|
mc::cat_deref(base, _, mc::OwnedPtr) |
|
||||||
mc::cat_interior(base, _) |
|
mc::cat_interior(base, _) |
|
||||||
mc::cat_downcast(base) => {
|
mc::cat_downcast(base, _) => {
|
||||||
// Interior or owned data is mutable if base is
|
// Interior or owned data is mutable if base is
|
||||||
// mutable, so iterate to the base.
|
// mutable, so iterate to the base.
|
||||||
cmt = base;
|
cmt = base;
|
||||||
|
@ -1795,7 +1795,7 @@ fn adjust_upvar_borrow_kind_for_unique<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>, cmt: mc::c
|
||||||
match cmt.cat.clone() {
|
match cmt.cat.clone() {
|
||||||
mc::cat_deref(base, _, mc::OwnedPtr) |
|
mc::cat_deref(base, _, mc::OwnedPtr) |
|
||||||
mc::cat_interior(base, _) |
|
mc::cat_interior(base, _) |
|
||||||
mc::cat_downcast(base) => {
|
mc::cat_downcast(base, _) => {
|
||||||
// Interior or owned data is unique if base is
|
// Interior or owned data is unique if base is
|
||||||
// unique.
|
// unique.
|
||||||
cmt = base;
|
cmt = base;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue