pub use self::MutabilityCategory::*;
pub use self::AliasableReason::*;
pub use self::Note::*;
-pub use self::deref_kind::*;
use self::Aliasability::*;
use hir::map as ast_map;
use infer::InferCtxt;
use middle::const_qualif::ConstQualif;
-use hir::def::Def;
+use hir::def::{Def, CtorKind};
use ty::adjustment;
use ty::{self, Ty, TyCtxt};
#[derive(Clone, PartialEq)]
pub enum Categorization<'tcx> {
- Rvalue(ty::Region), // temporary val, argument is its scope
+ Rvalue(&'tcx ty::Region), // temporary val, argument is its scope
StaticItem,
Upvar(Upvar), // upvar referenced by closure env
Local(ast::NodeId), // local variable
- Deref(cmt<'tcx>, usize, PointerKind), // deref of a ptr
+ Deref(cmt<'tcx>, usize, PointerKind<'tcx>), // deref of a ptr
Interior(cmt<'tcx>, InteriorKind), // something interior: field, tuple, etc
Downcast(cmt<'tcx>, DefId), // selects a particular enum variant (*1)
// different kinds of pointers:
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
-pub enum PointerKind {
+pub enum PointerKind<'tcx> {
/// `Box<T>`
Unique,
/// `&T`
- BorrowedPtr(ty::BorrowKind, ty::Region),
+ BorrowedPtr(ty::BorrowKind, &'tcx ty::Region),
/// `*T`
UnsafePtr(hir::Mutability),
/// Implicit deref of the `&T` that results from an overloaded index `[]`.
- Implicit(ty::BorrowKind, ty::Region),
+ Implicit(ty::BorrowKind, &'tcx ty::Region),
}
// We use the term "interior" to mean "something reachable from the
pub type cmt<'tcx> = Rc<cmt_<'tcx>>;
-// We pun on *T to mean both actual deref of a ptr as well
-// as accessing of components:
-#[derive(Copy, Clone)]
-pub enum deref_kind {
- deref_ptr(PointerKind),
- deref_interior(InteriorKind),
-}
-
-type DerefKindContext = Option<InteriorOffsetKind>;
-
-// Categorizes a derefable type. Note that we include vectors and strings as
-// derefable (we model an index as the combination of a deref and then a
-// pointer adjustment).
-fn deref_kind(t: Ty, context: DerefKindContext) -> McResult<deref_kind> {
- match t.sty {
- ty::TyBox(_) => {
- Ok(deref_ptr(Unique))
- }
-
- ty::TyRef(r, mt) => {
- let kind = ty::BorrowKind::from_mutbl(mt.mutbl);
- Ok(deref_ptr(BorrowedPtr(kind, *r)))
- }
-
- ty::TyRawPtr(ref mt) => {
- Ok(deref_ptr(UnsafePtr(mt.mutbl)))
- }
-
- ty::TyEnum(..) |
- ty::TyStruct(..) => { // newtype
- Ok(deref_interior(InteriorField(PositionalField(0))))
- }
-
- ty::TyArray(_, _) | ty::TySlice(_) => {
- // no deref of indexed content without supplying InteriorOffsetKind
- if let Some(context) = context {
- Ok(deref_interior(InteriorElement(context, ElementKind::VecElement)))
- } else {
- Err(())
- }
- }
-
- _ => Err(()),
- }
-}
-
pub trait ast_node {
fn id(&self) -> ast::NodeId;
fn span(&self) -> Span;
fn from_local(tcx: TyCtxt, id: ast::NodeId) -> MutabilityCategory {
let ret = match tcx.map.get(id) {
ast_map::NodeLocal(p) => match p.node {
- PatKind::Binding(bind_mode, _, _) => {
+ PatKind::Binding(bind_mode, ..) => {
if bind_mode == hir::BindByValue(hir::MutMutable) {
McDeclared
} else {
}
fn expr_ty_adjusted(&self, expr: &hir::Expr) -> McResult<Ty<'tcx>> {
- let unadjusted_ty = self.expr_ty(expr)?;
- Ok(unadjusted_ty.adjust(
- self.tcx(), expr.span, expr.id,
- self.infcx.adjustments().get(&expr.id),
- |method_call| self.infcx.node_method_ty(method_call)))
+ self.infcx.expr_ty_adjusted(expr)
}
fn node_ty(&self, id: ast::NodeId) -> McResult<Ty<'tcx>> {
// *being borrowed* is. But ideally we would put in a more
// fundamental fix to this conflated use of the node id.
let ret_ty = match pat.node {
- PatKind::Binding(hir::BindByRef(_), _, _) => {
+ PatKind::Binding(hir::BindByRef(_), ..) => {
// a bind-by-ref means that the base_ty will be the type of the ident itself,
// but what we want here is the type of the underlying value being borrowed.
// So peel off one-level, turning the &T into T.
}
Some(adjustment) => {
- match *adjustment {
- adjustment::AdjustDerefRef(
- adjustment::AutoDerefRef {
- autoref: None, unsize: None, autoderefs, ..}) => {
+ match adjustment.kind {
+ adjustment::Adjust::DerefRef {
+ autoderefs,
+ autoref: None,
+ unsize: false
+ } => {
// Equivalent to *expr or something similar.
self.cat_expr_autoderefd(expr, autoderefs)
}
- adjustment::AdjustNeverToAny(..) |
- adjustment::AdjustReifyFnPointer |
- adjustment::AdjustUnsafeFnPointer |
- adjustment::AdjustMutToConstPointer |
- adjustment::AdjustDerefRef(_) => {
+ adjustment::Adjust::NeverToAny |
+ adjustment::Adjust::ReifyFnPointer |
+ adjustment::Adjust::UnsafeFnPointer |
+ adjustment::Adjust::MutToConstPointer |
+ adjustment::Adjust::DerefRef {..} => {
debug!("cat_expr({:?}): {:?}",
adjustment,
expr);
autoderefs,
cmt);
for deref in 1..autoderefs + 1 {
- cmt = self.cat_deref(expr, cmt, deref, None)?;
+ cmt = self.cat_deref(expr, cmt, deref)?;
}
return Ok(cmt);
}
match expr.node {
hir::ExprUnary(hir::UnDeref, ref e_base) => {
let base_cmt = self.cat_expr(&e_base)?;
- self.cat_deref(expr, base_cmt, 0, None)
+ self.cat_deref(expr, base_cmt, 0)
}
hir::ExprField(ref base, f_name) => {
hir::ExprIndex(ref base, _) => {
let method_call = ty::MethodCall::expr(expr.id());
- let context = InteriorOffsetKind::Index;
match self.infcx.node_method_ty(method_call) {
Some(method_ty) => {
// If this is an index implemented by a method call, then it
// is an rvalue. That is what we will be
// dereferencing.
let base_cmt = self.cat_rvalue_node(expr.id(), expr.span(), ret_ty);
- self.cat_deref_common(expr, base_cmt, 1, elem_ty, Some(context), true)
+ Ok(self.cat_deref_common(expr, base_cmt, 1, elem_ty, true))
}
None => {
- self.cat_index(expr, self.cat_expr(&base)?, context)
+ self.cat_index(expr, self.cat_expr(&base)?, InteriorOffsetKind::Index)
}
}
}
hir::ExprClosure(..) | hir::ExprRet(..) |
hir::ExprUnary(..) |
hir::ExprMethodCall(..) | hir::ExprCast(..) |
- hir::ExprVec(..) | hir::ExprTup(..) | hir::ExprIf(..) |
+ hir::ExprArray(..) | hir::ExprTup(..) | hir::ExprIf(..) |
hir::ExprBinary(..) | hir::ExprWhile(..) |
hir::ExprBlock(..) | hir::ExprLoop(..) | hir::ExprMatch(..) |
hir::ExprLit(..) | hir::ExprBreak(..) |
id, expr_ty, def);
match def {
- Def::Struct(..) | Def::Variant(..) | Def::Const(..) |
+ Def::StructCtor(..) | Def::VariantCtor(..) | Def::Const(..) |
Def::AssociatedConst(..) | Def::Fn(..) | Def::Method(..) => {
Ok(self.cat_rvalue_node(id, span, expr_ty))
}
- Def::Mod(_) | Def::ForeignMod(_) |
- Def::Trait(_) | Def::Enum(..) | Def::TyAlias(..) | Def::PrimTy(_) |
- Def::TyParam(..) |
- Def::Label(_) | Def::SelfTy(..) |
- Def::AssociatedTy(..) => {
- span_bug!(span, "Unexpected definition in \
- memory categorization: {:?}", def);
- }
-
Def::Static(_, mutbl) => {
Ok(Rc::new(cmt_ {
id:id,
}))
}
- Def::Upvar(_, var_id, _, fn_node_id) => {
+ Def::Upvar(def_id, _, fn_node_id) => {
+ let var_id = self.tcx().map.as_local_node_id(def_id).unwrap();
let ty = self.node_ty(fn_node_id)?;
match ty.sty {
ty::TyClosure(closure_id, _) => {
}
}
- Def::Local(_, vid) => {
+ Def::Local(def_id) => {
+ let vid = self.tcx().map.as_local_node_id(def_id).unwrap();
Ok(Rc::new(cmt_ {
id: id,
span: span,
}))
}
- Def::Err => bug!("Def::Err in memory categorization")
+ def => span_bug!(span, "unexpected definition in memory categorization: {:?}", def)
}
}
};
match fn_expr.node {
- hir::ExprClosure(_, _, ref body, _) => body.id,
+ hir::ExprClosure(.., ref body, _) => body.id,
_ => bug!()
}
};
// Region of environment pointer
- let env_region = ty::ReFree(ty::FreeRegion {
+ let env_region = self.tcx().mk_region(ty::ReFree(ty::FreeRegion {
// The environment of a closure is guaranteed to
// outlive any bindings introduced in the body of the
// closure itself.
scope: self.tcx().region_maps.item_extent(fn_body_id),
bound_region: ty::BrEnv
- });
+ }));
let env_ptr = BorrowedPtr(env_borrow_kind, env_region);
/// Returns the lifetime of a temporary created by expr with id `id`.
/// This could be `'static` if `id` is part of a constant expression.
- pub fn temporary_scope(&self, id: ast::NodeId) -> ty::Region {
- match self.infcx.temporary_scope(id) {
+ pub fn temporary_scope(&self, id: ast::NodeId) -> &'tcx ty::Region {
+ self.tcx().mk_region(match self.infcx.temporary_scope(id) {
Some(scope) => ty::ReScope(scope),
None => ty::ReStatic
- }
+ })
}
pub fn cat_rvalue_node(&self,
let re = if qualif.intersects(ConstQualif::NON_STATIC_BORROWS) {
self.temporary_scope(id)
} else {
- ty::ReStatic
+ self.tcx().mk_region(ty::ReStatic)
};
let ret = self.cat_rvalue(id, span, re, expr_ty);
debug!("cat_rvalue_node ret {:?}", ret);
pub fn cat_rvalue(&self,
cmt_id: ast::NodeId,
span: Span,
- temp_scope: ty::Region,
+ temp_scope: &'tcx ty::Region,
expr_ty: Ty<'tcx>) -> cmt<'tcx> {
let ret = Rc::new(cmt_ {
id:cmt_id,
fn cat_deref<N:ast_node>(&self,
node: &N,
base_cmt: cmt<'tcx>,
- deref_cnt: usize,
- deref_context: DerefKindContext)
+ deref_cnt: usize)
-> McResult<cmt<'tcx>> {
let method_call = ty::MethodCall {
expr_id: node.id(),
let base_cmt_ty = base_cmt.ty;
match base_cmt_ty.builtin_deref(true, ty::NoPreference) {
Some(mt) => {
- let ret = self.cat_deref_common(node, base_cmt, deref_cnt,
- mt.ty,
- deref_context,
- /* implicit: */ false);
+ let ret = self.cat_deref_common(node, base_cmt, deref_cnt, mt.ty, false);
debug!("cat_deref ret {:?}", ret);
- ret
+ Ok(ret)
}
None => {
debug!("Explicit deref of non-derefable type: {:?}",
base_cmt: cmt<'tcx>,
deref_cnt: usize,
deref_ty: Ty<'tcx>,
- deref_context: DerefKindContext,
implicit: bool)
- -> McResult<cmt<'tcx>>
+ -> cmt<'tcx>
{
- let (m, cat) = match deref_kind(base_cmt.ty, deref_context)? {
- deref_ptr(ptr) => {
- let ptr = if implicit {
- match ptr {
- BorrowedPtr(bk, r) => Implicit(bk, r),
- _ => span_bug!(node.span(),
- "Implicit deref of non-borrowed pointer")
- }
- } else {
- ptr
- };
- // for unique ptrs, we inherit mutability from the
- // owning reference.
- (MutabilityCategory::from_pointer_kind(base_cmt.mutbl, ptr),
- Categorization::Deref(base_cmt, deref_cnt, ptr))
- }
- deref_interior(interior) => {
- (base_cmt.mutbl.inherit(), Categorization::Interior(base_cmt, interior))
+ let ptr = match base_cmt.ty.sty {
+ ty::TyBox(..) => Unique,
+ ty::TyRawPtr(ref mt) => UnsafePtr(mt.mutbl),
+ ty::TyRef(r, mt) => {
+ let bk = ty::BorrowKind::from_mutbl(mt.mutbl);
+ if implicit { Implicit(bk, r) } else { BorrowedPtr(bk, r) }
}
+ ref ty => bug!("unexpected type in cat_deref_common: {:?}", ty)
};
let ret = Rc::new(cmt_ {
id: node.id(),
span: node.span(),
- cat: cat,
- mutbl: m,
+ // For unique ptrs, we inherit mutability from the owning reference.
+ mutbl: MutabilityCategory::from_pointer_kind(base_cmt.mutbl, ptr),
+ cat: Categorization::Deref(base_cmt, deref_cnt, ptr),
ty: deref_ty,
note: NoteNone
});
debug!("cat_deref_common ret {:?}", ret);
- Ok(ret)
+ ret
}
pub fn cat_index<N:ast_node>(&self,
// alone) because PatKind::Struct can also refer to variants.
let cmt = match self.tcx().expect_def_or_none(pat.id) {
Some(Def::Err) => return Err(()),
- Some(Def::Variant(enum_did, variant_did))
+ Some(Def::Variant(variant_did)) |
+ Some(Def::VariantCtor(variant_did, ..)) => {
// univariant enums do not need downcasts
- if !self.tcx().lookup_adt_def(enum_did).is_univariant() => {
+ let enum_did = self.tcx().parent_def_id(variant_did).unwrap();
+ if !self.tcx().lookup_adt_def(enum_did).is_univariant() {
self.cat_downcast(pat, cmt.clone(), cmt.ty, variant_did)
+ } else {
+ cmt
}
+ }
_ => cmt
};
match pat.node {
PatKind::TupleStruct(_, ref subpats, ddpos) => {
let expected_len = match self.tcx().expect_def(pat.id) {
- Def::Variant(enum_def, def_id) => {
+ Def::VariantCtor(def_id, CtorKind::Fn) => {
+ let enum_def = self.tcx().parent_def_id(def_id).unwrap();
self.tcx().lookup_adt_def(enum_def).variant_with_id(def_id).fields.len()
}
- Def::Struct(..) => {
+ Def::StructCtor(_, CtorKind::Fn) => {
match self.pat_ty(&pat)?.sty {
- ty::TyStruct(adt_def, _) => {
+ ty::TyAdt(adt_def, _) => {
adt_def.struct_variant().fields.len()
}
ref ty => {
}
}
- PatKind::Binding(_, _, Some(ref subpat)) => {
+ PatKind::Binding(.., Some(ref subpat)) => {
self.cat_pattern_(cmt, &subpat, op)?;
}
// box p1, &p1, &mut p1. we can ignore the mutability of
// PatKind::Ref since that information is already contained
// in the type.
- let subcmt = self.cat_deref(pat, cmt, 0, None)?;
+ let subcmt = self.cat_deref(pat, cmt, 0)?;
self.cat_pattern_(subcmt, &subpat, op)?;
}
- PatKind::Vec(ref before, ref slice, ref after) => {
+ PatKind::Slice(ref before, ref slice, ref after) => {
let context = InteriorOffsetKind::Pattern;
let elt_cmt = self.cat_index(pat, cmt, context)?;
for before_pat in before {
}
}
- PatKind::Path(..) | PatKind::Binding(_, _, None) |
+ PatKind::Path(..) | PatKind::Binding(.., None) |
PatKind::Lit(..) | PatKind::Range(..) | PatKind::Wild => {
// always ok
}
Categorization::Rvalue(..) |
Categorization::StaticItem |
Categorization::Local(..) |
- Categorization::Deref(_, _, UnsafePtr(..)) |
- Categorization::Deref(_, _, BorrowedPtr(..)) |
- Categorization::Deref(_, _, Implicit(..)) |
+ Categorization::Deref(.., UnsafePtr(..)) |
+ Categorization::Deref(.., BorrowedPtr(..)) |
+ Categorization::Deref(.., Implicit(..)) |
Categorization::Upvar(..) => {
Rc::new((*self).clone())
}
Categorization::Rvalue(..) |
Categorization::Local(..) |
Categorization::Upvar(..) |
- Categorization::Deref(_, _, UnsafePtr(..)) => { // yes, it's aliasable, but...
+ Categorization::Deref(.., UnsafePtr(..)) => { // yes, it's aliasable, but...
NonAliasable
}
match self.note {
NoteClosureEnv(..) | NoteUpvarRef(..) => {
Some(match self.cat {
- Categorization::Deref(ref inner, _, _) => {
+ Categorization::Deref(ref inner, ..) => {
match inner.cat {
- Categorization::Deref(ref inner, _, _) => inner.clone(),
+ Categorization::Deref(ref inner, ..) => inner.clone(),
Categorization::Upvar(..) => inner.clone(),
_ => bug!()
}
"local variable".to_string()
}
}
- Categorization::Deref(_, _, pk) => {
+ Categorization::Deref(.., pk) => {
let upvar = self.upvar();
match upvar.as_ref().map(|i| &i.cat) {
Some(&Categorization::Upvar(ref var)) => {
}
}
-impl fmt::Debug for PointerKind {
+impl<'tcx> fmt::Debug for PointerKind<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Unique => write!(f, "Box"),