rustc: do not depend on infcx.tables in MemCategorizationContext.
This commit is contained in:
parent
5175bc18b5
commit
1f874ded52
13 changed files with 146 additions and 240 deletions
|
@ -19,11 +19,8 @@ pub use self::freshen::TypeFreshener;
|
||||||
pub use self::region_inference::{GenericKind, VerifyBound};
|
pub use self::region_inference::{GenericKind, VerifyBound};
|
||||||
|
|
||||||
use hir::def_id::DefId;
|
use hir::def_id::DefId;
|
||||||
use hir;
|
|
||||||
use middle::free_region::{FreeRegionMap, RegionRelations};
|
use middle::free_region::{FreeRegionMap, RegionRelations};
|
||||||
use middle::region::RegionMaps;
|
use middle::region::RegionMaps;
|
||||||
use middle::mem_categorization as mc;
|
|
||||||
use middle::mem_categorization::McResult;
|
|
||||||
use middle::lang_items;
|
use middle::lang_items;
|
||||||
use mir::tcx::LvalueTy;
|
use mir::tcx::LvalueTy;
|
||||||
use ty::subst::{Kind, Subst, Substs};
|
use ty::subst::{Kind, Subst, Substs};
|
||||||
|
@ -36,7 +33,6 @@ use traits::{self, ObligationCause, PredicateObligations, Reveal};
|
||||||
use rustc_data_structures::unify::{self, UnificationTable};
|
use rustc_data_structures::unify::{self, UnificationTable};
|
||||||
use std::cell::{Cell, RefCell, Ref, RefMut};
|
use std::cell::{Cell, RefCell, Ref, RefMut};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::ops::Deref;
|
|
||||||
use syntax::ast;
|
use syntax::ast;
|
||||||
use errors::DiagnosticBuilder;
|
use errors::DiagnosticBuilder;
|
||||||
use syntax_pos::{self, Span, DUMMY_SP};
|
use syntax_pos::{self, Span, DUMMY_SP};
|
||||||
|
@ -80,55 +76,23 @@ pub type FixupResult<T> = Result<T, FixupError>; // "fixup result"
|
||||||
/// `InProgress` (during typeck) or `Interned` (result of typeck).
|
/// `InProgress` (during typeck) or `Interned` (result of typeck).
|
||||||
/// Only the `InProgress` version supports `borrow_mut`.
|
/// Only the `InProgress` version supports `borrow_mut`.
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub enum InferTables<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
pub enum InferTables<'a, 'tcx: 'a> {
|
||||||
Interned(&'a ty::TypeckTables<'gcx>),
|
|
||||||
InProgress(&'a RefCell<ty::TypeckTables<'tcx>>),
|
InProgress(&'a RefCell<ty::TypeckTables<'tcx>>),
|
||||||
Missing
|
Missing
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum InferTablesRef<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
impl<'a, 'tcx> InferTables<'a, 'tcx> {
|
||||||
Interned(&'a ty::TypeckTables<'gcx>),
|
pub fn borrow(self) -> Ref<'a, ty::TypeckTables<'tcx>> {
|
||||||
InProgress(Ref<'a, ty::TypeckTables<'tcx>>)
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, 'gcx, 'tcx> Deref for InferTablesRef<'a, 'gcx, 'tcx> {
|
|
||||||
type Target = ty::TypeckTables<'tcx>;
|
|
||||||
fn deref(&self) -> &Self::Target {
|
|
||||||
match *self {
|
|
||||||
InferTablesRef::Interned(tables) => tables,
|
|
||||||
InferTablesRef::InProgress(ref tables) => tables
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, 'gcx, 'tcx> InferTables<'a, 'gcx, 'tcx> {
|
|
||||||
pub fn borrow(self) -> InferTablesRef<'a, 'gcx, 'tcx> {
|
|
||||||
match self {
|
match self {
|
||||||
InferTables::Interned(tables) => InferTablesRef::Interned(tables),
|
InferTables::InProgress(tables) => tables.borrow(),
|
||||||
InferTables::InProgress(tables) => InferTablesRef::InProgress(tables.borrow()),
|
|
||||||
InferTables::Missing => {
|
InferTables::Missing => {
|
||||||
bug!("InferTables: infcx.tables.borrow() with no tables")
|
bug!("InferTables: infcx.tables.borrow() with no tables")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn expect_interned(self) -> &'a ty::TypeckTables<'gcx> {
|
|
||||||
match self {
|
|
||||||
InferTables::Interned(tables) => tables,
|
|
||||||
InferTables::InProgress(_) => {
|
|
||||||
bug!("InferTables: infcx.tables.expect_interned() during type-checking");
|
|
||||||
}
|
|
||||||
InferTables::Missing => {
|
|
||||||
bug!("InferTables: infcx.tables.expect_interned() with no tables")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn borrow_mut(self) -> RefMut<'a, ty::TypeckTables<'tcx>> {
|
pub fn borrow_mut(self) -> RefMut<'a, ty::TypeckTables<'tcx>> {
|
||||||
match self {
|
match self {
|
||||||
InferTables::Interned(_) => {
|
|
||||||
bug!("InferTables: infcx.tables.borrow_mut() outside of type-checking");
|
|
||||||
}
|
|
||||||
InferTables::InProgress(tables) => tables.borrow_mut(),
|
InferTables::InProgress(tables) => tables.borrow_mut(),
|
||||||
InferTables::Missing => {
|
InferTables::Missing => {
|
||||||
bug!("InferTables: infcx.tables.borrow_mut() with no tables")
|
bug!("InferTables: infcx.tables.borrow_mut() with no tables")
|
||||||
|
@ -140,7 +104,7 @@ impl<'a, 'gcx, 'tcx> InferTables<'a, 'gcx, 'tcx> {
|
||||||
pub struct InferCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
pub struct InferCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
||||||
pub tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
pub tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||||
|
|
||||||
pub tables: InferTables<'a, 'gcx, 'tcx>,
|
pub tables: InferTables<'a, 'tcx>,
|
||||||
|
|
||||||
// Cache for projections. This cache is snapshotted along with the
|
// Cache for projections. This cache is snapshotted along with the
|
||||||
// infcx.
|
// infcx.
|
||||||
|
@ -397,41 +361,18 @@ impl fmt::Display for FixupError {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait InferEnv<'a, 'tcx> {
|
pub trait InferEnv<'a, 'tcx> {
|
||||||
fn to_parts(self, tcx: TyCtxt<'a, 'tcx, 'tcx>)
|
fn fresh_tables(self) -> Option<ty::TypeckTables<'tcx>>;
|
||||||
-> (Option<&'a ty::TypeckTables<'tcx>>,
|
|
||||||
Option<ty::TypeckTables<'tcx>>);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> InferEnv<'a, 'tcx> for () {
|
impl<'a, 'tcx> InferEnv<'a, 'tcx> for () {
|
||||||
fn to_parts(self, _: TyCtxt<'a, 'tcx, 'tcx>)
|
fn fresh_tables(self) -> Option<ty::TypeckTables<'tcx>> {
|
||||||
-> (Option<&'a ty::TypeckTables<'tcx>>,
|
None
|
||||||
Option<ty::TypeckTables<'tcx>>) {
|
|
||||||
(None, None)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, 'tcx> InferEnv<'a, 'tcx> for &'a ty::TypeckTables<'tcx> {
|
|
||||||
fn to_parts(self, _: TyCtxt<'a, 'tcx, 'tcx>)
|
|
||||||
-> (Option<&'a ty::TypeckTables<'tcx>>,
|
|
||||||
Option<ty::TypeckTables<'tcx>>) {
|
|
||||||
(Some(self), None)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> InferEnv<'a, 'tcx> for ty::TypeckTables<'tcx> {
|
impl<'a, 'tcx> InferEnv<'a, 'tcx> for ty::TypeckTables<'tcx> {
|
||||||
fn to_parts(self, _: TyCtxt<'a, 'tcx, 'tcx>)
|
fn fresh_tables(self) -> Option<ty::TypeckTables<'tcx>> {
|
||||||
-> (Option<&'a ty::TypeckTables<'tcx>>,
|
Some(self)
|
||||||
Option<ty::TypeckTables<'tcx>>) {
|
|
||||||
(None, Some(self))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, 'tcx> InferEnv<'a, 'tcx> for hir::BodyId {
|
|
||||||
fn to_parts(self, tcx: TyCtxt<'a, 'tcx, 'tcx>)
|
|
||||||
-> (Option<&'a ty::TypeckTables<'tcx>>,
|
|
||||||
Option<ty::TypeckTables<'tcx>>) {
|
|
||||||
let def_id = tcx.hir.body_owner_def_id(self);
|
|
||||||
(Some(tcx.typeck_tables_of(def_id)), None)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -442,29 +383,24 @@ pub struct InferCtxtBuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
||||||
global_tcx: TyCtxt<'a, 'gcx, 'gcx>,
|
global_tcx: TyCtxt<'a, 'gcx, 'gcx>,
|
||||||
arena: DroplessArena,
|
arena: DroplessArena,
|
||||||
fresh_tables: Option<RefCell<ty::TypeckTables<'tcx>>>,
|
fresh_tables: Option<RefCell<ty::TypeckTables<'tcx>>>,
|
||||||
tables: Option<&'a ty::TypeckTables<'gcx>>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'gcx> {
|
impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'gcx> {
|
||||||
pub fn infer_ctxt<E: InferEnv<'a, 'gcx>>(self, env: E) -> InferCtxtBuilder<'a, 'gcx, 'tcx> {
|
pub fn infer_ctxt<E: InferEnv<'a, 'gcx>>(self, env: E) -> InferCtxtBuilder<'a, 'gcx, 'tcx> {
|
||||||
let (tables, fresh_tables) = env.to_parts(self);
|
|
||||||
InferCtxtBuilder {
|
InferCtxtBuilder {
|
||||||
global_tcx: self,
|
global_tcx: self,
|
||||||
arena: DroplessArena::new(),
|
arena: DroplessArena::new(),
|
||||||
fresh_tables: fresh_tables.map(RefCell::new),
|
fresh_tables: env.fresh_tables().map(RefCell::new),
|
||||||
tables: tables,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Fake InferCtxt with the global tcx. Used by pre-MIR borrowck
|
/// Fake InferCtxt with the global tcx. Used by pre-MIR borrowck
|
||||||
/// for MemCategorizationContext/ExprUseVisitor.
|
/// for MemCategorizationContext/ExprUseVisitor.
|
||||||
/// If any inference functionality is used, ICEs will occur.
|
/// If any inference functionality is used, ICEs will occur.
|
||||||
pub fn borrowck_fake_infer_ctxt(self, body: hir::BodyId)
|
pub fn borrowck_fake_infer_ctxt(self) -> InferCtxt<'a, 'gcx, 'gcx> {
|
||||||
-> InferCtxt<'a, 'gcx, 'gcx> {
|
|
||||||
let (tables, _) = body.to_parts(self);
|
|
||||||
InferCtxt {
|
InferCtxt {
|
||||||
tcx: self,
|
tcx: self,
|
||||||
tables: InferTables::Interned(tables.unwrap()),
|
tables: InferTables::Missing,
|
||||||
type_variables: RefCell::new(type_variable::TypeVariableTable::new()),
|
type_variables: RefCell::new(type_variable::TypeVariableTable::new()),
|
||||||
int_unification_table: RefCell::new(UnificationTable::new()),
|
int_unification_table: RefCell::new(UnificationTable::new()),
|
||||||
float_unification_table: RefCell::new(UnificationTable::new()),
|
float_unification_table: RefCell::new(UnificationTable::new()),
|
||||||
|
@ -488,11 +424,9 @@ impl<'a, 'gcx, 'tcx> InferCtxtBuilder<'a, 'gcx, 'tcx> {
|
||||||
global_tcx,
|
global_tcx,
|
||||||
ref arena,
|
ref arena,
|
||||||
ref fresh_tables,
|
ref fresh_tables,
|
||||||
tables,
|
|
||||||
} = *self;
|
} = *self;
|
||||||
let tables = tables.map(InferTables::Interned).unwrap_or_else(|| {
|
let tables = fresh_tables.as_ref()
|
||||||
fresh_tables.as_ref().map_or(InferTables::Missing, InferTables::InProgress)
|
.map_or(InferTables::Missing, InferTables::InProgress);
|
||||||
});
|
|
||||||
global_tcx.enter_local(arena, |tcx| f(InferCtxt {
|
global_tcx.enter_local(arena, |tcx| f(InferCtxt {
|
||||||
tcx: tcx,
|
tcx: tcx,
|
||||||
tables: tables,
|
tables: tables,
|
||||||
|
@ -1190,28 +1124,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||||
self.tainted_by_errors_flag.set(true)
|
self.tainted_by_errors_flag.set(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn node_type(&self, id: ast::NodeId) -> Ty<'tcx> {
|
|
||||||
match self.tables.borrow().node_types.get(&id) {
|
|
||||||
Some(&t) => t,
|
|
||||||
// FIXME
|
|
||||||
None if self.is_tainted_by_errors() =>
|
|
||||||
self.tcx.types.err,
|
|
||||||
None => {
|
|
||||||
bug!("no type for node {}: {} in fcx",
|
|
||||||
id, self.tcx.hir.node_to_string(id));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn expr_ty(&self, ex: &hir::Expr) -> Ty<'tcx> {
|
|
||||||
match self.tables.borrow().node_types.get(&ex.id) {
|
|
||||||
Some(&t) => t,
|
|
||||||
None => {
|
|
||||||
bug!("no type for expr in fcx");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn resolve_regions_and_report_errors(&self,
|
pub fn resolve_regions_and_report_errors(&self,
|
||||||
region_context: DefId,
|
region_context: DefId,
|
||||||
region_map: &RegionMaps,
|
region_map: &RegionMaps,
|
||||||
|
@ -1310,21 +1222,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||||
value.fold_with(&mut r)
|
value.fold_with(&mut r)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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 ty = self.resolve_type_vars_if_possible(t);
|
|
||||||
if ty.references_error() || ty.is_ty_var() {
|
|
||||||
debug!("resolve_type_vars_or_error: error from {:?}", ty);
|
|
||||||
Err(())
|
|
||||||
} else {
|
|
||||||
Ok(ty)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn fully_resolve<T:TypeFoldable<'tcx>>(&self, value: &T) -> FixupResult<T> {
|
pub fn fully_resolve<T:TypeFoldable<'tcx>>(&self, value: &T) -> FixupResult<T> {
|
||||||
/*!
|
/*!
|
||||||
* Attempts to resolve all type/region variables in
|
* Attempts to resolve all type/region variables in
|
||||||
|
@ -1484,16 +1381,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||||
self.region_vars.verify_generic_bound(origin, kind, a, bound);
|
self.region_vars.verify_generic_bound(origin, kind, a, bound);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn node_ty(&self, id: ast::NodeId) -> McResult<Ty<'tcx>> {
|
|
||||||
let ty = self.node_type(id);
|
|
||||||
self.resolve_type_vars_or_error(&ty)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn expr_ty_adjusted(&self, expr: &hir::Expr) -> McResult<Ty<'tcx>> {
|
|
||||||
let ty = self.tables.borrow().expr_ty_adjusted(expr);
|
|
||||||
self.resolve_type_vars_or_error(&ty)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn type_moves_by_default(&self,
|
pub fn type_moves_by_default(&self,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
ty: Ty<'tcx>,
|
ty: Ty<'tcx>,
|
||||||
|
|
|
@ -235,17 +235,14 @@ impl OverloadedCallType {
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// The ExprUseVisitor type
|
// The ExprUseVisitor type
|
||||||
//
|
//
|
||||||
// This is the code that actually walks the tree. Like
|
// This is the code that actually walks the tree.
|
||||||
// mem_categorization, it requires a TYPER, which is a type that
|
|
||||||
// supplies types from the tree. After type checking is complete, you
|
|
||||||
// can just use the tcx as the typer.
|
|
||||||
pub struct ExprUseVisitor<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
pub struct ExprUseVisitor<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
||||||
mc: mc::MemCategorizationContext<'a, 'gcx, 'tcx>,
|
mc: mc::MemCategorizationContext<'a, 'gcx, 'tcx>,
|
||||||
delegate: &'a mut Delegate<'tcx>,
|
delegate: &'a mut Delegate<'tcx>,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the TYPER results in an error, it's because the type check
|
// If the MC results in an error, it's because the type check
|
||||||
// failed (or will fail, when the error is uncovered and reported
|
// failed (or will fail, when the error is uncovered and reported
|
||||||
// during writeback). In this case, we just ignore this part of the
|
// during writeback). In this case, we just ignore this part of the
|
||||||
// code.
|
// code.
|
||||||
|
@ -266,13 +263,14 @@ macro_rules! return_if_err {
|
||||||
|
|
||||||
impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
|
impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
|
||||||
pub fn new(delegate: &'a mut (Delegate<'tcx>+'a),
|
pub fn new(delegate: &'a mut (Delegate<'tcx>+'a),
|
||||||
region_maps: &'a RegionMaps,
|
|
||||||
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
|
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
|
||||||
param_env: ty::ParamEnv<'tcx>)
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
|
region_maps: &'a RegionMaps,
|
||||||
|
tables: &'a ty::TypeckTables<'tcx>)
|
||||||
-> Self
|
-> Self
|
||||||
{
|
{
|
||||||
ExprUseVisitor {
|
ExprUseVisitor {
|
||||||
mc: mc::MemCategorizationContext::new(infcx, region_maps),
|
mc: mc::MemCategorizationContext::new(infcx, region_maps, tables),
|
||||||
delegate,
|
delegate,
|
||||||
param_env,
|
param_env,
|
||||||
}
|
}
|
||||||
|
@ -282,7 +280,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
|
||||||
debug!("consume_body(body={:?})", body);
|
debug!("consume_body(body={:?})", body);
|
||||||
|
|
||||||
for arg in &body.arguments {
|
for arg in &body.arguments {
|
||||||
let arg_ty = return_if_err!(self.mc.infcx.node_ty(arg.pat.id));
|
let arg_ty = return_if_err!(self.mc.node_ty(arg.pat.id));
|
||||||
|
|
||||||
let fn_body_scope_r = self.tcx().node_scope_region(body.value.id);
|
let fn_body_scope_r = self.tcx().node_scope_region(body.value.id);
|
||||||
let arg_cmt = self.mc.cat_rvalue(
|
let arg_cmt = self.mc.cat_rvalue(
|
||||||
|
@ -427,7 +425,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
|
||||||
hir::ExprAddrOf(m, ref base) => { // &base
|
hir::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 = return_if_err!(self.mc.infcx.node_ty(expr.id));
|
let expr_ty = return_if_err!(self.mc.expr_ty(expr));
|
||||||
if let ty::TyRef(r, _) = expr_ty.sty {
|
if let ty::TyRef(r, _) = expr_ty.sty {
|
||||||
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);
|
||||||
|
@ -491,7 +489,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
hir::ExprAssignOp(_, ref lhs, ref rhs) => {
|
hir::ExprAssignOp(_, ref lhs, ref rhs) => {
|
||||||
if self.mc.infcx.tables.borrow().is_method_call(expr) {
|
if self.mc.tables.is_method_call(expr) {
|
||||||
self.consume_expr(lhs);
|
self.consume_expr(lhs);
|
||||||
} else {
|
} else {
|
||||||
self.mutate_expr(expr, &lhs, MutateMode::WriteAndRead);
|
self.mutate_expr(expr, &lhs, MutateMode::WriteAndRead);
|
||||||
|
@ -514,7 +512,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn walk_callee(&mut self, call: &hir::Expr, callee: &hir::Expr) {
|
fn walk_callee(&mut self, call: &hir::Expr, callee: &hir::Expr) {
|
||||||
let callee_ty = return_if_err!(self.mc.infcx.expr_ty_adjusted(callee));
|
let callee_ty = return_if_err!(self.mc.expr_ty_adjusted(callee));
|
||||||
debug!("walk_callee: callee={:?} callee_ty={:?}",
|
debug!("walk_callee: callee={:?} callee_ty={:?}",
|
||||||
callee, callee_ty);
|
callee, callee_ty);
|
||||||
match callee_ty.sty {
|
match callee_ty.sty {
|
||||||
|
@ -523,7 +521,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
ty::TyError => { }
|
ty::TyError => { }
|
||||||
_ => {
|
_ => {
|
||||||
let def_id = self.mc.infcx.tables.borrow().type_dependent_defs[&call.id].def_id();
|
let def_id = self.mc.tables.type_dependent_defs[&call.id].def_id();
|
||||||
match OverloadedCallType::from_method_id(self.tcx(), def_id) {
|
match OverloadedCallType::from_method_id(self.tcx(), def_id) {
|
||||||
FnMutOverloadedCall => {
|
FnMutOverloadedCall => {
|
||||||
let call_scope_r = self.tcx().node_scope_region(call.id);
|
let call_scope_r = self.tcx().node_scope_region(call.id);
|
||||||
|
@ -664,8 +662,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
|
||||||
// consumed or borrowed as part of the automatic adjustment
|
// consumed or borrowed as part of the automatic adjustment
|
||||||
// process.
|
// process.
|
||||||
fn walk_adjustment(&mut self, expr: &hir::Expr) {
|
fn walk_adjustment(&mut self, expr: &hir::Expr) {
|
||||||
let tables = self.mc.infcx.tables.borrow();
|
let adjustments = self.mc.tables.expr_adjustments(expr);
|
||||||
let adjustments = tables.expr_adjustments(expr);
|
|
||||||
let mut cmt = return_if_err!(self.mc.cat_expr_unadjusted(expr));
|
let mut cmt = return_if_err!(self.mc.cat_expr_unadjusted(expr));
|
||||||
for adjustment in adjustments {
|
for adjustment in adjustments {
|
||||||
debug!("walk_adjustment expr={:?} adj={:?}", expr, adjustment);
|
debug!("walk_adjustment expr={:?} adj={:?}", expr, adjustment);
|
||||||
|
@ -782,7 +779,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
|
||||||
mode: &mut TrackMatchMode) {
|
mode: &mut TrackMatchMode) {
|
||||||
debug!("determine_pat_move_mode cmt_discr={:?} pat={:?}", cmt_discr,
|
debug!("determine_pat_move_mode cmt_discr={:?} pat={:?}", cmt_discr,
|
||||||
pat);
|
pat);
|
||||||
return_if_err!(self.mc.cat_pattern(cmt_discr, pat, |_mc, cmt_pat, pat| {
|
return_if_err!(self.mc.cat_pattern(cmt_discr, pat, |cmt_pat, pat| {
|
||||||
match pat.node {
|
match pat.node {
|
||||||
PatKind::Binding(hir::BindByRef(..), ..) =>
|
PatKind::Binding(hir::BindByRef(..), ..) =>
|
||||||
mode.lub(BorrowingMatch),
|
mode.lub(BorrowingMatch),
|
||||||
|
@ -806,12 +803,12 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
|
||||||
let tcx = self.tcx();
|
let tcx = self.tcx();
|
||||||
let infcx = self.mc.infcx;
|
let infcx = self.mc.infcx;
|
||||||
let ExprUseVisitor { ref mc, ref mut delegate, param_env } = *self;
|
let ExprUseVisitor { ref mc, ref mut delegate, param_env } = *self;
|
||||||
return_if_err!(mc.cat_pattern(cmt_discr.clone(), pat, |mc, cmt_pat, pat| {
|
return_if_err!(mc.cat_pattern(cmt_discr.clone(), pat, |cmt_pat, pat| {
|
||||||
if let PatKind::Binding(bmode, def_id, ..) = pat.node {
|
if let PatKind::Binding(bmode, def_id, ..) = pat.node {
|
||||||
debug!("binding cmt_pat={:?} pat={:?} match_mode={:?}", cmt_pat, pat, match_mode);
|
debug!("binding cmt_pat={:?} pat={:?} match_mode={:?}", cmt_pat, pat, match_mode);
|
||||||
|
|
||||||
// pat_ty: the type of the binding being produced.
|
// pat_ty: the type of the binding being produced.
|
||||||
let pat_ty = return_if_err!(infcx.node_ty(pat.id));
|
let pat_ty = return_if_err!(mc.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.
|
||||||
|
@ -841,14 +838,14 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
|
||||||
// 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.
|
||||||
return_if_err!(mc.cat_pattern(cmt_discr, pat, |mc, cmt_pat, pat| {
|
return_if_err!(mc.cat_pattern(cmt_discr, pat, |cmt_pat, pat| {
|
||||||
let qpath = match pat.node {
|
let qpath = match pat.node {
|
||||||
PatKind::Path(ref qpath) |
|
PatKind::Path(ref qpath) |
|
||||||
PatKind::TupleStruct(ref qpath, ..) |
|
PatKind::TupleStruct(ref qpath, ..) |
|
||||||
PatKind::Struct(ref qpath, ..) => qpath,
|
PatKind::Struct(ref qpath, ..) => qpath,
|
||||||
_ => return
|
_ => return
|
||||||
};
|
};
|
||||||
let def = infcx.tables.borrow().qpath_def(qpath, pat.id);
|
let def = mc.tables.qpath_def(qpath, pat.id);
|
||||||
match def {
|
match def {
|
||||||
Def::Variant(variant_did) |
|
Def::Variant(variant_did) |
|
||||||
Def::VariantCtor(variant_did, ..) => {
|
Def::VariantCtor(variant_did, ..) => {
|
||||||
|
@ -882,7 +879,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
|
||||||
let id_var = self.tcx().hir.as_local_node_id(def_id).unwrap();
|
let id_var = self.tcx().hir.as_local_node_id(def_id).unwrap();
|
||||||
let upvar_id = ty::UpvarId { var_id: id_var,
|
let upvar_id = ty::UpvarId { var_id: id_var,
|
||||||
closure_expr_id: closure_expr.id };
|
closure_expr_id: closure_expr.id };
|
||||||
let upvar_capture = self.mc.infcx.tables.borrow().upvar_capture(upvar_id);
|
let upvar_capture = self.mc.tables.upvar_capture(upvar_id);
|
||||||
let cmt_var = return_if_err!(self.cat_captured_var(closure_expr.id,
|
let cmt_var = return_if_err!(self.cat_captured_var(closure_expr.id,
|
||||||
fn_decl_span,
|
fn_decl_span,
|
||||||
freevar.def));
|
freevar.def));
|
||||||
|
@ -915,7 +912,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, '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 = self.tcx().hir.as_local_node_id(upvar_def.def_id()).unwrap();
|
let var_id = self.tcx().hir.as_local_node_id(upvar_def.def_id()).unwrap();
|
||||||
let var_ty = self.mc.infcx.node_ty(var_id)?;
|
let var_ty = self.mc.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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,6 +76,7 @@ use infer::InferCtxt;
|
||||||
use hir::def::{Def, CtorKind};
|
use hir::def::{Def, CtorKind};
|
||||||
use ty::adjustment;
|
use ty::adjustment;
|
||||||
use ty::{self, Ty, TyCtxt};
|
use ty::{self, Ty, TyCtxt};
|
||||||
|
use ty::fold::TypeFoldable;
|
||||||
|
|
||||||
use hir::{MutImmutable, MutMutable, PatKind};
|
use hir::{MutImmutable, MutMutable, PatKind};
|
||||||
use hir::pat_util::EnumerateAndAdjustIterator;
|
use hir::pat_util::EnumerateAndAdjustIterator;
|
||||||
|
@ -283,6 +284,7 @@ impl ast_node for hir::Pat {
|
||||||
pub struct MemCategorizationContext<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
pub struct MemCategorizationContext<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
||||||
pub infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
|
pub infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
|
||||||
pub region_maps: &'a RegionMaps,
|
pub region_maps: &'a RegionMaps,
|
||||||
|
pub tables: &'a ty::TypeckTables<'tcx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type McResult<T> = Result<T, ()>;
|
pub type McResult<T> = Result<T, ()>;
|
||||||
|
@ -386,35 +388,63 @@ impl MutabilityCategory {
|
||||||
impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
|
impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
|
||||||
/// Context should be the `DefId` we use to fetch region-maps.
|
/// Context should be the `DefId` we use to fetch region-maps.
|
||||||
pub fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
|
pub fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
|
||||||
region_maps: &'a RegionMaps)
|
region_maps: &'a RegionMaps,
|
||||||
|
tables: &'a ty::TypeckTables<'tcx>)
|
||||||
-> MemCategorizationContext<'a, 'gcx, 'tcx> {
|
-> MemCategorizationContext<'a, 'gcx, 'tcx> {
|
||||||
MemCategorizationContext { infcx, region_maps }
|
MemCategorizationContext { infcx, region_maps, tables }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> {
|
fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> {
|
||||||
self.infcx.tcx
|
self.infcx.tcx
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expr_ty(&self, expr: &hir::Expr) -> McResult<Ty<'tcx>> {
|
fn resolve_type_vars_if_possible<T>(&self, value: &T) -> T
|
||||||
match self.infcx.node_ty(expr.id) {
|
where T: TypeFoldable<'tcx>
|
||||||
Ok(t) => Ok(t),
|
{
|
||||||
Err(()) => {
|
self.infcx.resolve_type_vars_if_possible(value)
|
||||||
debug!("expr_ty({:?}) yielded Err", expr);
|
}
|
||||||
|
|
||||||
|
fn is_tainted_by_errors(&self) -> bool {
|
||||||
|
self.infcx.is_tainted_by_errors()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn resolve_type_vars_or_error(&self,
|
||||||
|
id: ast::NodeId,
|
||||||
|
ty: Option<Ty<'tcx>>)
|
||||||
|
-> McResult<Ty<'tcx>> {
|
||||||
|
match ty {
|
||||||
|
Some(ty) => {
|
||||||
|
let ty = self.resolve_type_vars_if_possible(&ty);
|
||||||
|
if ty.references_error() || ty.is_ty_var() {
|
||||||
|
debug!("resolve_type_vars_or_error: error from {:?}", ty);
|
||||||
Err(())
|
Err(())
|
||||||
|
} else {
|
||||||
|
Ok(ty)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// FIXME
|
||||||
|
None if self.is_tainted_by_errors() => Err(()),
|
||||||
|
None => {
|
||||||
|
bug!("no type for node {}: {} in mem_categorization",
|
||||||
|
id, self.tcx().hir.node_to_string(id));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expr_ty_adjusted(&self, expr: &hir::Expr) -> McResult<Ty<'tcx>> {
|
pub fn node_ty(&self, id: ast::NodeId) -> McResult<Ty<'tcx>> {
|
||||||
self.infcx.expr_ty_adjusted(expr)
|
self.resolve_type_vars_or_error(id, self.tables.node_id_to_type_opt(id))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn node_ty(&self, id: ast::NodeId) -> McResult<Ty<'tcx>> {
|
pub fn expr_ty(&self, expr: &hir::Expr) -> McResult<Ty<'tcx>> {
|
||||||
self.infcx.node_ty(id)
|
self.resolve_type_vars_or_error(expr.id, self.tables.expr_ty_opt(expr))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn expr_ty_adjusted(&self, expr: &hir::Expr) -> McResult<Ty<'tcx>> {
|
||||||
|
self.resolve_type_vars_or_error(expr.id, self.tables.expr_ty_adjusted_opt(expr))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pat_ty(&self, pat: &hir::Pat) -> McResult<Ty<'tcx>> {
|
fn pat_ty(&self, pat: &hir::Pat) -> McResult<Ty<'tcx>> {
|
||||||
let base_ty = self.infcx.node_ty(pat.id)?;
|
let base_ty = self.node_ty(pat.id)?;
|
||||||
// FIXME (Issue #18207): This code detects whether we are
|
// FIXME (Issue #18207): This code detects whether we are
|
||||||
// looking at a `ref x`, and if so, figures out what the type
|
// looking at a `ref x`, and if so, figures out what the type
|
||||||
// *being borrowed* is. But ideally we would put in a more
|
// *being borrowed* is. But ideally we would put in a more
|
||||||
|
@ -454,7 +484,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
helper(self, expr, self.infcx.tables.borrow().expr_adjustments(expr))
|
helper(self, expr, self.tables.expr_adjustments(expr))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cat_expr_adjusted(&self, expr: &hir::Expr,
|
pub fn cat_expr_adjusted(&self, expr: &hir::Expr,
|
||||||
|
@ -471,7 +501,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
|
||||||
where F: FnOnce() -> McResult<cmt<'tcx>>
|
where F: FnOnce() -> McResult<cmt<'tcx>>
|
||||||
{
|
{
|
||||||
debug!("cat_expr_adjusted_with({:?}): {:?}", adjustment, expr);
|
debug!("cat_expr_adjusted_with({:?}): {:?}", adjustment, expr);
|
||||||
let target = self.infcx.resolve_type_vars_if_possible(&adjustment.target);
|
let target = self.resolve_type_vars_if_possible(&adjustment.target);
|
||||||
match adjustment.kind {
|
match adjustment.kind {
|
||||||
adjustment::Adjust::Deref(overloaded) => {
|
adjustment::Adjust::Deref(overloaded) => {
|
||||||
// Equivalent to *expr or something similar.
|
// Equivalent to *expr or something similar.
|
||||||
|
@ -506,7 +536,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
|
||||||
let expr_ty = self.expr_ty(expr)?;
|
let expr_ty = self.expr_ty(expr)?;
|
||||||
match expr.node {
|
match expr.node {
|
||||||
hir::ExprUnary(hir::UnDeref, ref e_base) => {
|
hir::ExprUnary(hir::UnDeref, ref e_base) => {
|
||||||
if self.infcx.tables.borrow().is_method_call(expr) {
|
if self.tables.is_method_call(expr) {
|
||||||
self.cat_overloaded_lvalue(expr, e_base, false)
|
self.cat_overloaded_lvalue(expr, e_base, false)
|
||||||
} else {
|
} else {
|
||||||
let base_cmt = self.cat_expr(&e_base)?;
|
let base_cmt = self.cat_expr(&e_base)?;
|
||||||
|
@ -529,7 +559,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
hir::ExprIndex(ref base, _) => {
|
hir::ExprIndex(ref base, _) => {
|
||||||
if self.infcx.tables.borrow().is_method_call(expr) {
|
if self.tables.is_method_call(expr) {
|
||||||
// If this is an index implemented by a method call, then it
|
// If this is an index implemented by a method call, then it
|
||||||
// will include an implicit deref of the result.
|
// will include an implicit deref of the result.
|
||||||
// The call to index() returns a `&T` value, which
|
// The call to index() returns a `&T` value, which
|
||||||
|
@ -543,7 +573,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
hir::ExprPath(ref qpath) => {
|
hir::ExprPath(ref qpath) => {
|
||||||
let def = self.infcx.tables.borrow().qpath_def(qpath, expr.id);
|
let def = self.tables.qpath_def(qpath, expr.id);
|
||||||
self.cat_def(expr.id, expr.span, expr_ty, def)
|
self.cat_def(expr.id, expr.span, expr_ty, def)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -595,15 +625,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
|
||||||
|
|
||||||
Def::Upvar(def_id, _, fn_node_id) => {
|
Def::Upvar(def_id, _, fn_node_id) => {
|
||||||
let var_id = self.tcx().hir.as_local_node_id(def_id).unwrap();
|
let var_id = self.tcx().hir.as_local_node_id(def_id).unwrap();
|
||||||
let closure_id = self.tcx().hir.local_def_id(fn_node_id);
|
self.cat_upvar(id, span, var_id, fn_node_id)
|
||||||
match self.infcx.closure_kind(closure_id) {
|
|
||||||
Some(kind) => {
|
|
||||||
self.cat_upvar(id, span, var_id, fn_node_id, kind)
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
span_bug!(span, "No closure kind for {:?}", closure_id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Def::Local(def_id) => {
|
Def::Local(def_id) => {
|
||||||
|
@ -628,8 +650,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
|
||||||
id: ast::NodeId,
|
id: ast::NodeId,
|
||||||
span: Span,
|
span: Span,
|
||||||
var_id: ast::NodeId,
|
var_id: ast::NodeId,
|
||||||
fn_node_id: ast::NodeId,
|
fn_node_id: ast::NodeId)
|
||||||
kind: ty::ClosureKind)
|
|
||||||
-> McResult<cmt<'tcx>>
|
-> McResult<cmt<'tcx>>
|
||||||
{
|
{
|
||||||
// An upvar can have up to 3 components. We translate first to a
|
// An upvar can have up to 3 components. We translate first to a
|
||||||
|
@ -655,6 +676,11 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
|
||||||
// FnMut | copied -> &'env mut | upvar -> &'env mut -> &'up bk
|
// FnMut | copied -> &'env mut | upvar -> &'env mut -> &'up bk
|
||||||
// FnOnce | copied | upvar -> &'up bk
|
// FnOnce | copied | upvar -> &'up bk
|
||||||
|
|
||||||
|
let kind = match self.tables.closure_kinds.get(&fn_node_id) {
|
||||||
|
Some(&(kind, _)) => kind,
|
||||||
|
None => span_bug!(span, "missing closure kind")
|
||||||
|
};
|
||||||
|
|
||||||
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 };
|
||||||
let var_ty = self.node_ty(var_id)?;
|
let var_ty = self.node_ty(var_id)?;
|
||||||
|
@ -694,7 +720,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
|
||||||
// for that.
|
// for that.
|
||||||
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 };
|
||||||
let upvar_capture = self.infcx.tables.borrow().upvar_capture(upvar_id);
|
let upvar_capture = self.tables.upvar_capture(upvar_id);
|
||||||
let cmt_result = match upvar_capture {
|
let cmt_result = match upvar_capture {
|
||||||
ty::UpvarCapture::ByValue => {
|
ty::UpvarCapture::ByValue => {
|
||||||
cmt_result
|
cmt_result
|
||||||
|
@ -1000,14 +1026,14 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cat_pattern<F>(&self, cmt: cmt<'tcx>, pat: &hir::Pat, mut op: F) -> McResult<()>
|
pub fn cat_pattern<F>(&self, cmt: cmt<'tcx>, pat: &hir::Pat, mut op: F) -> McResult<()>
|
||||||
where F: FnMut(&MemCategorizationContext<'a, 'gcx, 'tcx>, cmt<'tcx>, &hir::Pat),
|
where F: FnMut(cmt<'tcx>, &hir::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: &hir::Pat, op: &mut F) -> McResult<()>
|
fn cat_pattern_<F>(&self, cmt: cmt<'tcx>, pat: &hir::Pat, op: &mut F) -> McResult<()>
|
||||||
where F : FnMut(&MemCategorizationContext<'a, 'gcx, 'tcx>, cmt<'tcx>, &hir::Pat)
|
where F : FnMut(cmt<'tcx>, &hir::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.
|
||||||
|
@ -1056,7 +1082,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
|
||||||
|
|
||||||
debug!("cat_pattern: {:?} cmt={:?}", pat, cmt);
|
debug!("cat_pattern: {:?} cmt={:?}", pat, cmt);
|
||||||
|
|
||||||
op(self, cmt.clone(), pat);
|
op(cmt.clone(), pat);
|
||||||
|
|
||||||
// Note: This goes up here (rather than within the PatKind::TupleStruct arm
|
// Note: This goes up here (rather than within the PatKind::TupleStruct arm
|
||||||
// alone) because PatKind::Struct can also refer to variants.
|
// alone) because PatKind::Struct can also refer to variants.
|
||||||
|
@ -1087,7 +1113,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
|
||||||
|
|
||||||
match pat.node {
|
match pat.node {
|
||||||
PatKind::TupleStruct(ref qpath, ref subpats, ddpos) => {
|
PatKind::TupleStruct(ref qpath, ref subpats, ddpos) => {
|
||||||
let def = self.infcx.tables.borrow().qpath_def(qpath, pat.id);
|
let def = self.tables.qpath_def(qpath, pat.id);
|
||||||
let expected_len = match def {
|
let expected_len = match def {
|
||||||
Def::VariantCtor(def_id, CtorKind::Fn) => {
|
Def::VariantCtor(def_id, CtorKind::Fn) => {
|
||||||
let enum_def = self.tcx().parent_def_id(def_id).unwrap();
|
let enum_def = self.tcx().parent_def_id(def_id).unwrap();
|
||||||
|
|
|
@ -29,7 +29,7 @@ use hir::{self, intravisit, Local, Pat, Body};
|
||||||
use hir::intravisit::{Visitor, NestedVisitorMap};
|
use hir::intravisit::{Visitor, NestedVisitorMap};
|
||||||
use hir::map::NodeExpr;
|
use hir::map::NodeExpr;
|
||||||
use hir::def_id::DefId;
|
use hir::def_id::DefId;
|
||||||
use infer::{self, InferCtxt, InferTables, InferTablesRef};
|
use infer::{self, InferCtxt, InferTables};
|
||||||
use infer::type_variable::TypeVariableOrigin;
|
use infer::type_variable::TypeVariableOrigin;
|
||||||
use rustc::lint::builtin::EXTRA_REQUIREMENT_IN_IMPL;
|
use rustc::lint::builtin::EXTRA_REQUIREMENT_IN_IMPL;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
@ -652,18 +652,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||||
obligation.cause.span,
|
obligation.cause.span,
|
||||||
format!("the requirement to implement `{}` derives from here", kind));
|
format!("the requirement to implement `{}` derives from here", kind));
|
||||||
|
|
||||||
let infer_tables = match self.tables {
|
|
||||||
InferTables::Interned(tables) =>
|
|
||||||
Some(InferTablesRef::Interned(tables)),
|
|
||||||
InferTables::InProgress(tables) =>
|
|
||||||
Some(InferTablesRef::InProgress(tables.borrow())),
|
|
||||||
InferTables::Missing => None,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Additional context information explaining why the closure only implements
|
// Additional context information explaining why the closure only implements
|
||||||
// a particular trait.
|
// a particular trait.
|
||||||
if let Some(tables) = infer_tables {
|
if let InferTables::InProgress(tables) = self.tables {
|
||||||
match tables.closure_kinds.get(&node_id) {
|
match tables.borrow().closure_kinds.get(&node_id) {
|
||||||
Some(&(ty::ClosureKind::FnOnce, Some((span, name)))) => {
|
Some(&(ty::ClosureKind::FnOnce, Some((span, name)))) => {
|
||||||
err.span_note(span, &format!(
|
err.span_note(span, &format!(
|
||||||
"closure is `FnOnce` because it moves the \
|
"closure is `FnOnce` because it moves the \
|
||||||
|
|
|
@ -192,7 +192,6 @@ pub fn check_loans<'a, 'b, 'c, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
|
||||||
debug!("check_loans(body id={})", body.value.id);
|
debug!("check_loans(body id={})", body.value.id);
|
||||||
|
|
||||||
let def_id = bccx.tcx.hir.body_owner_def_id(body.id());
|
let def_id = bccx.tcx.hir.body_owner_def_id(body.id());
|
||||||
let infcx = bccx.tcx.borrowck_fake_infer_ctxt(body.id());
|
|
||||||
let param_env = bccx.tcx.param_env(def_id);
|
let param_env = bccx.tcx.param_env(def_id);
|
||||||
let mut clcx = CheckLoanCtxt {
|
let mut clcx = CheckLoanCtxt {
|
||||||
bccx: bccx,
|
bccx: bccx,
|
||||||
|
@ -201,7 +200,9 @@ pub fn check_loans<'a, 'b, 'c, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
|
||||||
all_loans: all_loans,
|
all_loans: all_loans,
|
||||||
param_env,
|
param_env,
|
||||||
};
|
};
|
||||||
euv::ExprUseVisitor::new(&mut clcx, &bccx.region_maps, &infcx, param_env).consume_body(body);
|
let infcx = bccx.tcx.borrowck_fake_infer_ctxt();
|
||||||
|
euv::ExprUseVisitor::new(&mut clcx, &infcx, param_env, &bccx.region_maps, bccx.tables)
|
||||||
|
.consume_body(body);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq)]
|
#[derive(PartialEq)]
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
|
|
||||||
use borrowck::*;
|
use borrowck::*;
|
||||||
use borrowck::move_data::MoveData;
|
use borrowck::move_data::MoveData;
|
||||||
use rustc::infer::InferCtxt;
|
|
||||||
use rustc::middle::expr_use_visitor as euv;
|
use rustc::middle::expr_use_visitor as euv;
|
||||||
use rustc::middle::mem_categorization as mc;
|
use rustc::middle::mem_categorization as mc;
|
||||||
use rustc::middle::mem_categorization::Categorization;
|
use rustc::middle::mem_categorization::Categorization;
|
||||||
|
@ -40,11 +39,9 @@ pub fn gather_loans_in_fn<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
|
||||||
body: hir::BodyId)
|
body: hir::BodyId)
|
||||||
-> (Vec<Loan<'tcx>>, move_data::MoveData<'tcx>) {
|
-> (Vec<Loan<'tcx>>, move_data::MoveData<'tcx>) {
|
||||||
let def_id = bccx.tcx.hir.body_owner_def_id(body);
|
let def_id = bccx.tcx.hir.body_owner_def_id(body);
|
||||||
let infcx = bccx.tcx.borrowck_fake_infer_ctxt(body);
|
|
||||||
let param_env = bccx.tcx.param_env(def_id);
|
let param_env = bccx.tcx.param_env(def_id);
|
||||||
let mut glcx = GatherLoanCtxt {
|
let mut glcx = GatherLoanCtxt {
|
||||||
bccx: bccx,
|
bccx: bccx,
|
||||||
infcx: &infcx,
|
|
||||||
all_loans: Vec::new(),
|
all_loans: Vec::new(),
|
||||||
item_ub: region::CodeExtent::Misc(body.node_id),
|
item_ub: region::CodeExtent::Misc(body.node_id),
|
||||||
move_data: MoveData::new(),
|
move_data: MoveData::new(),
|
||||||
|
@ -52,7 +49,9 @@ pub fn gather_loans_in_fn<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
|
||||||
};
|
};
|
||||||
|
|
||||||
let body = glcx.bccx.tcx.hir.body(body);
|
let body = glcx.bccx.tcx.hir.body(body);
|
||||||
euv::ExprUseVisitor::new(&mut glcx, &bccx.region_maps, &infcx, param_env).consume_body(body);
|
let infcx = bccx.tcx.borrowck_fake_infer_ctxt();
|
||||||
|
euv::ExprUseVisitor::new(&mut glcx, &infcx, param_env, &bccx.region_maps, bccx.tables)
|
||||||
|
.consume_body(body);
|
||||||
|
|
||||||
glcx.report_potential_errors();
|
glcx.report_potential_errors();
|
||||||
let GatherLoanCtxt { all_loans, move_data, .. } = glcx;
|
let GatherLoanCtxt { all_loans, move_data, .. } = glcx;
|
||||||
|
@ -61,7 +60,6 @@ pub fn gather_loans_in_fn<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
|
||||||
|
|
||||||
struct GatherLoanCtxt<'a, 'tcx: 'a> {
|
struct GatherLoanCtxt<'a, 'tcx: 'a> {
|
||||||
bccx: &'a BorrowckCtxt<'a, 'tcx>,
|
bccx: &'a BorrowckCtxt<'a, 'tcx>,
|
||||||
infcx: &'a InferCtxt<'a, 'tcx, 'tcx>,
|
|
||||||
move_data: move_data::MoveData<'tcx>,
|
move_data: move_data::MoveData<'tcx>,
|
||||||
move_error_collector: move_error::MoveErrorCollector<'tcx>,
|
move_error_collector: move_error::MoveErrorCollector<'tcx>,
|
||||||
all_loans: Vec<Loan<'tcx>>,
|
all_loans: Vec<Loan<'tcx>>,
|
||||||
|
@ -158,7 +156,7 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for GatherLoanCtxt<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn decl_without_init(&mut self, id: ast::NodeId, _span: Span) {
|
fn decl_without_init(&mut self, id: ast::NodeId, _span: Span) {
|
||||||
let ty = self.infcx.tables.borrow().node_id_to_type(id);
|
let ty = self.bccx.tables.node_id_to_type(id);
|
||||||
gather_moves::gather_decl(self.bccx, &self.move_data, id, ty);
|
gather_moves::gather_decl(self.bccx, &self.move_data, id, ty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -493,11 +493,12 @@ fn check_legality_of_move_bindings(cx: &MatchVisitor,
|
||||||
///
|
///
|
||||||
/// FIXME: this should be done by borrowck.
|
/// FIXME: this should be done by borrowck.
|
||||||
fn check_for_mutation_in_guard(cx: &MatchVisitor, guard: &hir::Expr) {
|
fn check_for_mutation_in_guard(cx: &MatchVisitor, guard: &hir::Expr) {
|
||||||
cx.tcx.infer_ctxt(cx.tables).enter(|infcx| {
|
cx.tcx.infer_ctxt(()).enter(|infcx| {
|
||||||
let mut checker = MutationChecker {
|
let mut checker = MutationChecker {
|
||||||
cx: cx,
|
cx: cx,
|
||||||
};
|
};
|
||||||
ExprUseVisitor::new(&mut checker, cx.region_maps, &infcx, cx.param_env).walk_expr(guard);
|
ExprUseVisitor::new(&mut checker, &infcx, cx.param_env, cx.region_maps, cx.tables)
|
||||||
|
.walk_expr(guard);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -83,7 +83,7 @@ pub fn mir_build<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Mir<'t
|
||||||
};
|
};
|
||||||
|
|
||||||
let src = MirSource::from_node(tcx, id);
|
let src = MirSource::from_node(tcx, id);
|
||||||
tcx.infer_ctxt(body_id).enter(|infcx| {
|
tcx.infer_ctxt(()).enter(|infcx| {
|
||||||
let cx = Cx::new(&infcx, src);
|
let cx = Cx::new(&infcx, src);
|
||||||
let mut mir = if cx.tables().tainted_by_errors {
|
let mut mir = if cx.tables().tainted_by_errors {
|
||||||
build::construct_error(cx, body_id)
|
build::construct_error(cx, body_id)
|
||||||
|
|
|
@ -37,6 +37,7 @@ pub struct Cx<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
|
||||||
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
|
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
|
||||||
pub param_env: ty::ParamEnv<'tcx>,
|
pub param_env: ty::ParamEnv<'tcx>,
|
||||||
pub region_maps: Rc<RegionMaps>,
|
pub region_maps: Rc<RegionMaps>,
|
||||||
|
pub tables: &'a ty::TypeckTables<'gcx>,
|
||||||
|
|
||||||
/// This is `Constness::Const` if we are compiling a `static`,
|
/// This is `Constness::Const` if we are compiling a `static`,
|
||||||
/// `const`, or the body of a `const fn`.
|
/// `const`, or the body of a `const fn`.
|
||||||
|
@ -67,6 +68,7 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
|
||||||
|
|
||||||
let param_env = tcx.param_env(src_def_id);
|
let param_env = tcx.param_env(src_def_id);
|
||||||
let region_maps = tcx.region_maps(src_def_id);
|
let region_maps = tcx.region_maps(src_def_id);
|
||||||
|
let tables = tcx.typeck_tables_of(src_def_id);
|
||||||
|
|
||||||
let attrs = tcx.hir.attrs(src_id);
|
let attrs = tcx.hir.attrs(src_id);
|
||||||
|
|
||||||
|
@ -82,7 +84,7 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
|
||||||
// Constants and const fn's always need overflow checks.
|
// Constants and const fn's always need overflow checks.
|
||||||
check_overflow |= constness == hir::Constness::Const;
|
check_overflow |= constness == hir::Constness::Const;
|
||||||
|
|
||||||
Cx { tcx, infcx, param_env, region_maps, constness, src, check_overflow }
|
Cx { tcx, infcx, param_env, region_maps, tables, constness, src, check_overflow }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -184,7 +186,7 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn tables(&self) -> &'a ty::TypeckTables<'gcx> {
|
pub fn tables(&self) -> &'a ty::TypeckTables<'gcx> {
|
||||||
self.infcx.tables.expect_interned()
|
self.tables
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn check_overflow(&self) -> bool {
|
pub fn check_overflow(&self) -> bool {
|
||||||
|
|
|
@ -138,11 +138,12 @@ impl<'a, 'tcx> Visitor<'tcx> for CheckCrateVisitor<'a, 'tcx> {
|
||||||
self.check_const_eval(&body.value);
|
self.check_const_eval(&body.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
let outer_penv = self.tcx.infer_ctxt(body_id).enter(|infcx| {
|
let outer_penv = self.tcx.infer_ctxt(()).enter(|infcx| {
|
||||||
let param_env = self.tcx.param_env(item_def_id);
|
let param_env = self.tcx.param_env(item_def_id);
|
||||||
let outer_penv = mem::replace(&mut self.param_env, param_env);
|
let outer_penv = mem::replace(&mut self.param_env, param_env);
|
||||||
let region_maps = &self.tcx.region_maps(item_def_id);
|
let region_maps = &self.tcx.region_maps(item_def_id);
|
||||||
euv::ExprUseVisitor::new(self, region_maps, &infcx, param_env).consume_body(body);
|
euv::ExprUseVisitor::new(self, &infcx, param_env, region_maps, self.tables)
|
||||||
|
.consume_body(body);
|
||||||
outer_penv
|
outer_penv
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -4186,7 +4186,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
hir::StmtSemi(ref e, _) => e,
|
hir::StmtSemi(ref e, _) => e,
|
||||||
_ => return,
|
_ => return,
|
||||||
};
|
};
|
||||||
let last_expr_ty = self.expr_ty(last_expr);
|
let last_expr_ty = self.node_ty(last_expr.id);
|
||||||
if self.can_sub(self.param_env, last_expr_ty, expected_ty).is_err() {
|
if self.can_sub(self.param_env, last_expr_ty, expected_ty).is_err() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -824,15 +824,21 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Create a temporary `MemCategorizationContext` and pass it to the closure.
|
||||||
|
fn with_mc<F, R>(&self, f: F) -> R
|
||||||
|
where F: for<'b> FnOnce(mc::MemCategorizationContext<'b, 'gcx, 'tcx>) -> R
|
||||||
|
{
|
||||||
|
f(mc::MemCategorizationContext::new(&self.infcx,
|
||||||
|
&self.region_maps,
|
||||||
|
&self.tables.borrow()))
|
||||||
|
}
|
||||||
|
|
||||||
/// Invoked on any adjustments that occur. Checks that if this is a region pointer being
|
/// Invoked on any adjustments that occur. Checks that if this is a region pointer being
|
||||||
/// dereferenced, the lifetime of the pointer includes the deref expr.
|
/// dereferenced, the lifetime of the pointer includes the deref expr.
|
||||||
fn constrain_adjustments(&mut self, expr: &hir::Expr) -> mc::McResult<mc::cmt<'tcx>> {
|
fn constrain_adjustments(&mut self, expr: &hir::Expr) -> mc::McResult<mc::cmt<'tcx>> {
|
||||||
debug!("constrain_adjustments(expr={:?})", expr);
|
debug!("constrain_adjustments(expr={:?})", expr);
|
||||||
|
|
||||||
let mut cmt = {
|
let mut cmt = self.with_mc(|mc| mc.cat_expr_unadjusted(expr))?;
|
||||||
let mc = mc::MemCategorizationContext::new(self, &self.region_maps);
|
|
||||||
mc.cat_expr_unadjusted(expr)?
|
|
||||||
};
|
|
||||||
|
|
||||||
let tables = self.tables.borrow();
|
let tables = self.tables.borrow();
|
||||||
let adjustments = tables.expr_adjustments(&expr);
|
let adjustments = tables.expr_adjustments(&expr);
|
||||||
|
@ -886,10 +892,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
|
||||||
expr.id, expr_region);
|
expr.id, expr_region);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
cmt = self.with_mc(|mc| mc.cat_expr_adjusted(expr, cmt, &adjustment))?;
|
||||||
let mc = mc::MemCategorizationContext::new(self, &self.region_maps);
|
|
||||||
cmt = mc.cat_expr_adjusted(expr, cmt, &adjustment)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Categorization::Deref(_, mc::BorrowedPtr(_, r_ptr)) = cmt.cat {
|
if let Categorization::Deref(_, mc::BorrowedPtr(_, r_ptr)) = cmt.cat {
|
||||||
self.mk_subregion_due_to_dereference(expr.span,
|
self.mk_subregion_due_to_dereference(expr.span,
|
||||||
|
@ -981,10 +984,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
|
||||||
mutability: hir::Mutability, base: &hir::Expr) {
|
mutability: hir::Mutability, base: &hir::Expr) {
|
||||||
debug!("link_addr_of(expr={:?}, base={:?})", expr, base);
|
debug!("link_addr_of(expr={:?}, base={:?})", expr, base);
|
||||||
|
|
||||||
let cmt = {
|
let cmt = ignore_err!(self.with_mc(|mc| mc.cat_expr(base)));
|
||||||
let mc = mc::MemCategorizationContext::new(self, &self.region_maps);
|
|
||||||
ignore_err!(mc.cat_expr(base))
|
|
||||||
};
|
|
||||||
|
|
||||||
debug!("link_addr_of: cmt={:?}", cmt);
|
debug!("link_addr_of: cmt={:?}", cmt);
|
||||||
|
|
||||||
|
@ -1000,9 +1000,8 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
|
||||||
None => { return; }
|
None => { return; }
|
||||||
Some(ref expr) => &**expr,
|
Some(ref expr) => &**expr,
|
||||||
};
|
};
|
||||||
let mc = &mc::MemCategorizationContext::new(self, &self.region_maps);
|
let discr_cmt = ignore_err!(self.with_mc(|mc| mc.cat_expr(init_expr)));
|
||||||
let discr_cmt = ignore_err!(mc.cat_expr(init_expr));
|
self.link_pattern(discr_cmt, &local.pat);
|
||||||
self.link_pattern(mc, discr_cmt, &local.pat);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Computes the guarantors for any ref bindings in a match and
|
/// Computes the guarantors for any ref bindings in a match and
|
||||||
|
@ -1010,12 +1009,11 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
|
||||||
/// linked to the lifetime of its guarantor (if any).
|
/// linked to the lifetime of its guarantor (if any).
|
||||||
fn link_match(&self, discr: &hir::Expr, arms: &[hir::Arm]) {
|
fn link_match(&self, discr: &hir::Expr, arms: &[hir::Arm]) {
|
||||||
debug!("regionck::for_match()");
|
debug!("regionck::for_match()");
|
||||||
let mc = &mc::MemCategorizationContext::new(self, &self.region_maps);
|
let discr_cmt = ignore_err!(self.with_mc(|mc| mc.cat_expr(discr)));
|
||||||
let discr_cmt = ignore_err!(mc.cat_expr(discr));
|
|
||||||
debug!("discr_cmt={:?}", discr_cmt);
|
debug!("discr_cmt={:?}", discr_cmt);
|
||||||
for arm in arms {
|
for arm in arms {
|
||||||
for root_pat in &arm.pats {
|
for root_pat in &arm.pats {
|
||||||
self.link_pattern(mc, discr_cmt.clone(), &root_pat);
|
self.link_pattern(discr_cmt.clone(), &root_pat);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1025,30 +1023,28 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
|
||||||
/// linked to the lifetime of its guarantor (if any).
|
/// linked to the lifetime of its guarantor (if any).
|
||||||
fn link_fn_args(&self, body_scope: CodeExtent, args: &[hir::Arg]) {
|
fn link_fn_args(&self, body_scope: CodeExtent, args: &[hir::Arg]) {
|
||||||
debug!("regionck::link_fn_args(body_scope={:?})", body_scope);
|
debug!("regionck::link_fn_args(body_scope={:?})", body_scope);
|
||||||
let mc = &mc::MemCategorizationContext::new(self, &self.region_maps);
|
|
||||||
for arg in args {
|
for arg in args {
|
||||||
let arg_ty = self.node_ty(arg.id);
|
let arg_ty = self.node_ty(arg.id);
|
||||||
let re_scope = self.tcx.mk_region(ty::ReScope(body_scope));
|
let re_scope = self.tcx.mk_region(ty::ReScope(body_scope));
|
||||||
let arg_cmt = mc.cat_rvalue(
|
let arg_cmt = self.with_mc(|mc| {
|
||||||
arg.id, arg.pat.span, re_scope, arg_ty);
|
mc.cat_rvalue(arg.id, arg.pat.span, re_scope, arg_ty)
|
||||||
|
});
|
||||||
debug!("arg_ty={:?} arg_cmt={:?} arg={:?}",
|
debug!("arg_ty={:?} arg_cmt={:?} arg={:?}",
|
||||||
arg_ty,
|
arg_ty,
|
||||||
arg_cmt,
|
arg_cmt,
|
||||||
arg);
|
arg);
|
||||||
self.link_pattern(mc, arg_cmt, &arg.pat);
|
self.link_pattern(arg_cmt, &arg.pat);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Link lifetimes of any ref bindings in `root_pat` to the pointers found
|
/// Link lifetimes of any ref bindings in `root_pat` to the pointers found
|
||||||
/// in the discriminant, if needed.
|
/// in the discriminant, if needed.
|
||||||
fn link_pattern<'t>(&self,
|
fn link_pattern(&self, discr_cmt: mc::cmt<'tcx>, root_pat: &hir::Pat) {
|
||||||
mc: &mc::MemCategorizationContext<'a, 'gcx, 'tcx>,
|
|
||||||
discr_cmt: mc::cmt<'tcx>,
|
|
||||||
root_pat: &hir::Pat) {
|
|
||||||
debug!("link_pattern(discr_cmt={:?}, root_pat={:?})",
|
debug!("link_pattern(discr_cmt={:?}, root_pat={:?})",
|
||||||
discr_cmt,
|
discr_cmt,
|
||||||
root_pat);
|
root_pat);
|
||||||
let _ = mc.cat_pattern(discr_cmt, root_pat, |_, sub_cmt, sub_pat| {
|
let _ = self.with_mc(|mc| {
|
||||||
|
mc.cat_pattern(discr_cmt, root_pat, |sub_cmt, sub_pat| {
|
||||||
match sub_pat.node {
|
match sub_pat.node {
|
||||||
// `ref x` pattern
|
// `ref x` pattern
|
||||||
PatKind::Binding(hir::BindByRef(mutbl), ..) => {
|
PatKind::Binding(hir::BindByRef(mutbl), ..) => {
|
||||||
|
@ -1057,6 +1053,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
})
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -142,7 +142,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
adjust_closure_kinds: NodeMap(),
|
adjust_closure_kinds: NodeMap(),
|
||||||
adjust_upvar_captures: ty::UpvarCaptureMap::default(),
|
adjust_upvar_captures: ty::UpvarCaptureMap::default(),
|
||||||
};
|
};
|
||||||
euv::ExprUseVisitor::new(&mut delegate, region_maps, self, self.param_env)
|
euv::ExprUseVisitor::new(&mut delegate,
|
||||||
|
&self.infcx,
|
||||||
|
self.param_env,
|
||||||
|
region_maps,
|
||||||
|
&self.tables.borrow())
|
||||||
.consume_body(body);
|
.consume_body(body);
|
||||||
|
|
||||||
// Write the adjusted values back into the main tables.
|
// Write the adjusted values back into the main tables.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue