mirror of
https://github.com/rust-lang/rust.git
synced 2026-05-08 01:28:18 +03:00
regionck: rustfmt
This commit is contained in:
@@ -88,27 +88,32 @@
|
||||
use middle::mem_categorization::Categorization;
|
||||
use middle::region;
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc::ty::subst::Substs;
|
||||
use rustc::ty::{self, Ty};
|
||||
use rustc::infer;
|
||||
use rustc::infer::outlives::env::OutlivesEnvironment;
|
||||
use rustc::ty::adjustment;
|
||||
use rustc::ty::subst::Substs;
|
||||
use rustc::ty::{self, Ty};
|
||||
|
||||
use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
|
||||
use rustc::hir::{self, PatKind};
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use std::mem;
|
||||
use std::ops::Deref;
|
||||
use std::rc::Rc;
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use syntax::ast;
|
||||
use syntax_pos::Span;
|
||||
use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
|
||||
use rustc::hir::{self, PatKind};
|
||||
|
||||
// a variation on try that just returns unit
|
||||
macro_rules! ignore_err {
|
||||
($e:expr) => (match $e { Ok(e) => e, Err(_) => {
|
||||
debug!("ignoring mem-categorization error!");
|
||||
return ()
|
||||
}})
|
||||
($e:expr) => {
|
||||
match $e {
|
||||
Ok(e) => e,
|
||||
Err(_) => {
|
||||
debug!("ignoring mem-categorization error!");
|
||||
return ();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
@@ -118,11 +123,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
pub fn regionck_expr(&self, body: &'gcx hir::Body) {
|
||||
let subject = self.tcx.hir.body_owner_def_id(body.id());
|
||||
let id = body.value.id;
|
||||
let mut rcx = RegionCtxt::new(self,
|
||||
RepeatingScope(id),
|
||||
id,
|
||||
Subject(subject),
|
||||
self.param_env);
|
||||
let mut rcx = RegionCtxt::new(
|
||||
self,
|
||||
RepeatingScope(id),
|
||||
id,
|
||||
Subject(subject),
|
||||
self.param_env,
|
||||
);
|
||||
if self.err_count_since_creation() == 0 {
|
||||
// regionck assumes typeck succeeded
|
||||
rcx.visit_body(body);
|
||||
@@ -136,18 +143,18 @@ pub fn regionck_expr(&self, body: &'gcx hir::Body) {
|
||||
|
||||
/// Region checking during the WF phase for items. `wf_tys` are the
|
||||
/// types from which we should derive implied bounds, if any.
|
||||
pub fn regionck_item(&self,
|
||||
item_id: ast::NodeId,
|
||||
span: Span,
|
||||
wf_tys: &[Ty<'tcx>]) {
|
||||
pub fn regionck_item(&self, item_id: ast::NodeId, span: Span, wf_tys: &[Ty<'tcx>]) {
|
||||
debug!("regionck_item(item.id={:?}, wf_tys={:?})", item_id, wf_tys);
|
||||
let subject = self.tcx.hir.local_def_id(item_id);
|
||||
let mut rcx = RegionCtxt::new(self,
|
||||
RepeatingScope(item_id),
|
||||
item_id,
|
||||
Subject(subject),
|
||||
self.param_env);
|
||||
rcx.outlives_environment.add_implied_bounds(self, wf_tys, item_id, span);
|
||||
let mut rcx = RegionCtxt::new(
|
||||
self,
|
||||
RepeatingScope(item_id),
|
||||
item_id,
|
||||
Subject(subject),
|
||||
self.param_env,
|
||||
);
|
||||
rcx.outlives_environment
|
||||
.add_implied_bounds(self, wf_tys, item_id, span);
|
||||
rcx.visit_region_obligations(item_id);
|
||||
rcx.resolve_regions_and_report_errors();
|
||||
}
|
||||
@@ -160,17 +167,17 @@ pub fn regionck_item(&self,
|
||||
/// rest of type check and because sometimes we need type
|
||||
/// inference to have completed before we can determine which
|
||||
/// constraints to add.
|
||||
pub fn regionck_fn(&self,
|
||||
fn_id: ast::NodeId,
|
||||
body: &'gcx hir::Body) {
|
||||
pub fn regionck_fn(&self, fn_id: ast::NodeId, body: &'gcx hir::Body) {
|
||||
debug!("regionck_fn(id={})", fn_id);
|
||||
let subject = self.tcx.hir.body_owner_def_id(body.id());
|
||||
let node_id = body.value.id;
|
||||
let mut rcx = RegionCtxt::new(self,
|
||||
RepeatingScope(node_id),
|
||||
node_id,
|
||||
Subject(subject),
|
||||
self.param_env);
|
||||
let mut rcx = RegionCtxt::new(
|
||||
self,
|
||||
RepeatingScope(node_id),
|
||||
node_id,
|
||||
Subject(subject),
|
||||
self.param_env,
|
||||
);
|
||||
|
||||
if self.err_count_since_creation() == 0 {
|
||||
// regionck assumes typeck succeeded
|
||||
@@ -190,7 +197,7 @@ pub fn regionck_fn(&self,
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// INTERNALS
|
||||
|
||||
pub struct RegionCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
||||
pub struct RegionCtxt<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
|
||||
pub fcx: &'a FnCtxt<'a, 'gcx, 'tcx>,
|
||||
|
||||
pub region_scope_tree: Lrc<region::ScopeTree>,
|
||||
@@ -208,7 +215,6 @@ pub struct RegionCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
||||
|
||||
// id of AST node being analyzed (the subject of the analysis).
|
||||
subject_def_id: DefId,
|
||||
|
||||
}
|
||||
|
||||
impl<'a, 'gcx, 'tcx> Deref for RegionCtxt<'a, 'gcx, 'tcx> {
|
||||
@@ -222,12 +228,13 @@ fn deref(&self) -> &Self::Target {
|
||||
pub struct Subject(DefId);
|
||||
|
||||
impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
|
||||
pub fn new(fcx: &'a FnCtxt<'a, 'gcx, 'tcx>,
|
||||
RepeatingScope(initial_repeating_scope): RepeatingScope,
|
||||
initial_body_id: ast::NodeId,
|
||||
Subject(subject): Subject,
|
||||
param_env: ty::ParamEnv<'tcx>)
|
||||
-> RegionCtxt<'a, 'gcx, 'tcx> {
|
||||
pub fn new(
|
||||
fcx: &'a FnCtxt<'a, 'gcx, 'tcx>,
|
||||
RepeatingScope(initial_repeating_scope): RepeatingScope,
|
||||
initial_body_id: ast::NodeId,
|
||||
Subject(subject): Subject,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
) -> RegionCtxt<'a, 'gcx, 'tcx> {
|
||||
let region_scope_tree = fcx.tcx.region_scope_tree(subject);
|
||||
let outlives_environment = OutlivesEnvironment::new(param_env);
|
||||
RegionCtxt {
|
||||
@@ -296,11 +303,12 @@ pub fn resolve_expr_type_adjusted(&mut self, expr: &hir::Expr) -> Ty<'tcx> {
|
||||
/// closures, however, we save and restore any "scoped state"
|
||||
/// before we invoke this function. (See `visit_fn` in the
|
||||
/// `intravisit::Visitor` impl below.)
|
||||
fn visit_fn_body(&mut self,
|
||||
id: ast::NodeId, // the id of the fn itself
|
||||
body: &'gcx hir::Body,
|
||||
span: Span)
|
||||
{
|
||||
fn visit_fn_body(
|
||||
&mut self,
|
||||
id: ast::NodeId, // the id of the fn itself
|
||||
body: &'gcx hir::Body,
|
||||
span: Span,
|
||||
) {
|
||||
// When we enter a function, we can derive
|
||||
debug!("visit_fn_body(id={})", id);
|
||||
|
||||
@@ -309,7 +317,7 @@ fn visit_fn_body(&mut self,
|
||||
|
||||
let call_site = region::Scope {
|
||||
id: body.value.hir_id.local_id,
|
||||
data: region::ScopeData::CallSite
|
||||
data: region::ScopeData::CallSite,
|
||||
};
|
||||
self.call_site_scope = Some(call_site);
|
||||
|
||||
@@ -328,32 +336,39 @@ fn visit_fn_body(&mut self,
|
||||
// because it will have no effect.
|
||||
//
|
||||
// FIXME(#27579) return types should not be implied bounds
|
||||
let fn_sig_tys: Vec<_> =
|
||||
fn_sig.inputs().iter().cloned().chain(Some(fn_sig.output())).collect();
|
||||
let fn_sig_tys: Vec<_> = fn_sig
|
||||
.inputs()
|
||||
.iter()
|
||||
.cloned()
|
||||
.chain(Some(fn_sig.output()))
|
||||
.collect();
|
||||
|
||||
self.outlives_environment.add_implied_bounds(
|
||||
self.fcx,
|
||||
&fn_sig_tys[..],
|
||||
body_id.node_id,
|
||||
span);
|
||||
span,
|
||||
);
|
||||
self.link_fn_args(
|
||||
region::Scope {
|
||||
id: body.value.hir_id.local_id,
|
||||
data: region::ScopeData::Node
|
||||
data: region::ScopeData::Node,
|
||||
},
|
||||
&body.arguments);
|
||||
&body.arguments,
|
||||
);
|
||||
self.visit_body(body);
|
||||
self.visit_region_obligations(body_id.node_id);
|
||||
|
||||
let call_site_scope = self.call_site_scope.unwrap();
|
||||
debug!("visit_fn_body body.id {:?} call_site_scope: {:?}",
|
||||
body.id(), call_site_scope);
|
||||
debug!(
|
||||
"visit_fn_body body.id {:?} call_site_scope: {:?}",
|
||||
body.id(),
|
||||
call_site_scope
|
||||
);
|
||||
let call_site_region = self.tcx.mk_region(ty::ReScope(call_site_scope));
|
||||
|
||||
let body_hir_id = self.tcx.hir.node_to_hir_id(body_id.node_id);
|
||||
self.type_of_node_must_outlive(infer::CallReturn(span),
|
||||
body_hir_id,
|
||||
call_site_region);
|
||||
self.type_of_node_must_outlive(infer::CallReturn(span), body_hir_id, call_site_region);
|
||||
|
||||
self.constrain_opaque_types(
|
||||
&self.fcx.opaque_types.borrow(),
|
||||
@@ -361,8 +376,7 @@ fn visit_fn_body(&mut self,
|
||||
);
|
||||
}
|
||||
|
||||
fn visit_region_obligations(&mut self, node_id: ast::NodeId)
|
||||
{
|
||||
fn visit_region_obligations(&mut self, node_id: ast::NodeId) {
|
||||
debug!("visit_region_obligations: node_id={}", node_id);
|
||||
|
||||
// region checking can introduce new pending obligations
|
||||
@@ -374,19 +388,24 @@ fn visit_region_obligations(&mut self, node_id: ast::NodeId)
|
||||
self.outlives_environment.region_bound_pairs(),
|
||||
self.implicit_region_bound,
|
||||
self.param_env,
|
||||
self.body_id);
|
||||
self.body_id,
|
||||
);
|
||||
}
|
||||
|
||||
fn resolve_regions_and_report_errors(&self) {
|
||||
self.fcx.resolve_regions_and_report_errors(self.subject_def_id,
|
||||
&self.region_scope_tree,
|
||||
&self.outlives_environment);
|
||||
self.fcx.resolve_regions_and_report_errors(
|
||||
self.subject_def_id,
|
||||
&self.region_scope_tree,
|
||||
&self.outlives_environment,
|
||||
);
|
||||
}
|
||||
|
||||
fn resolve_regions_and_report_errors_unless_nll(&self) {
|
||||
self.fcx.resolve_regions_and_report_errors_unless_nll(self.subject_def_id,
|
||||
&self.region_scope_tree,
|
||||
&self.outlives_environment);
|
||||
self.fcx.resolve_regions_and_report_errors_unless_nll(
|
||||
self.subject_def_id,
|
||||
&self.region_scope_tree,
|
||||
&self.outlives_environment,
|
||||
);
|
||||
}
|
||||
|
||||
fn constrain_bindings_in_pat(&mut self, pat: &hir::Pat) {
|
||||
@@ -423,7 +442,8 @@ fn constrain_bindings_in_pat(&mut self, pat: &hir::Pat) {
|
||||
let typ = self.resolve_node_type(hir_id);
|
||||
let body_id = self.body_id;
|
||||
let _ = dropck::check_safety_of_destructor_if_necessary(
|
||||
self, typ, span, body_id, var_scope);
|
||||
self, typ, span, body_id, var_scope,
|
||||
);
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -441,14 +461,21 @@ fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'gcx> {
|
||||
NestedVisitorMap::None
|
||||
}
|
||||
|
||||
fn visit_fn(&mut self,
|
||||
fk: intravisit::FnKind<'gcx>,
|
||||
_: &'gcx hir::FnDecl,
|
||||
body_id: hir::BodyId,
|
||||
span: Span,
|
||||
id: ast::NodeId) {
|
||||
assert!(match fk { intravisit::FnKind::Closure(..) => true, _ => false },
|
||||
"visit_fn invoked for something other than a closure");
|
||||
fn visit_fn(
|
||||
&mut self,
|
||||
fk: intravisit::FnKind<'gcx>,
|
||||
_: &'gcx hir::FnDecl,
|
||||
body_id: hir::BodyId,
|
||||
span: Span,
|
||||
id: ast::NodeId,
|
||||
) {
|
||||
assert!(
|
||||
match fk {
|
||||
intravisit::FnKind::Closure(..) => true,
|
||||
_ => false,
|
||||
},
|
||||
"visit_fn invoked for something other than a closure"
|
||||
);
|
||||
|
||||
// Save state of current function before invoking
|
||||
// `visit_fn_body`. We will restore afterwards.
|
||||
@@ -460,7 +487,8 @@ fn visit_fn(&mut self,
|
||||
self.visit_fn_body(id, body, span);
|
||||
|
||||
// Restore state from previous function.
|
||||
self.outlives_environment.pop_snapshot_post_closure(env_snapshot);
|
||||
self.outlives_environment
|
||||
.pop_snapshot_post_closure(env_snapshot);
|
||||
self.call_site_scope = old_call_site_scope;
|
||||
self.body_id = old_body_id;
|
||||
}
|
||||
@@ -483,20 +511,24 @@ fn visit_local(&mut self, l: &'gcx hir::Local) {
|
||||
}
|
||||
|
||||
fn visit_expr(&mut self, expr: &'gcx hir::Expr) {
|
||||
debug!("regionck::visit_expr(e={:?}, repeating_scope={})",
|
||||
expr, self.repeating_scope);
|
||||
debug!(
|
||||
"regionck::visit_expr(e={:?}, repeating_scope={})",
|
||||
expr, self.repeating_scope
|
||||
);
|
||||
|
||||
// No matter what, the type of each expression must outlive the
|
||||
// scope of that expression. This also guarantees basic WF.
|
||||
let expr_ty = self.resolve_node_type(expr.hir_id);
|
||||
// the region corresponding to this expression
|
||||
let expr_region = self.tcx.mk_region(ty::ReScope(
|
||||
region::Scope {
|
||||
id: expr.hir_id.local_id,
|
||||
data: region::ScopeData::Node
|
||||
}));
|
||||
self.type_must_outlive(infer::ExprTypeIsNotInScope(expr_ty, expr.span),
|
||||
expr_ty, expr_region);
|
||||
let expr_region = self.tcx.mk_region(ty::ReScope(region::Scope {
|
||||
id: expr.hir_id.local_id,
|
||||
data: region::ScopeData::Node,
|
||||
}));
|
||||
self.type_must_outlive(
|
||||
infer::ExprTypeIsNotInScope(expr_ty, expr.span),
|
||||
expr_ty,
|
||||
expr_region,
|
||||
);
|
||||
|
||||
let is_method_call = self.tables.borrow().is_method_call(expr);
|
||||
|
||||
@@ -506,12 +538,11 @@ fn visit_expr(&mut self, expr: &'gcx hir::Expr) {
|
||||
// provided as arguments outlive the call.
|
||||
if is_method_call {
|
||||
let origin = match expr.node {
|
||||
hir::ExprKind::MethodCall(..) =>
|
||||
infer::ParameterOrigin::MethodCall,
|
||||
hir::ExprKind::Unary(op, _) if op == hir::UnDeref =>
|
||||
infer::ParameterOrigin::OverloadedDeref,
|
||||
_ =>
|
||||
infer::ParameterOrigin::OverloadedOperator
|
||||
hir::ExprKind::MethodCall(..) => infer::ParameterOrigin::MethodCall,
|
||||
hir::ExprKind::Unary(op, _) if op == hir::UnDeref => {
|
||||
infer::ParameterOrigin::OverloadedDeref
|
||||
}
|
||||
_ => infer::ParameterOrigin::OverloadedOperator,
|
||||
};
|
||||
|
||||
let substs = self.tables.borrow().node_substs(expr.hir_id);
|
||||
@@ -533,8 +564,10 @@ fn visit_expr(&mut self, expr: &'gcx hir::Expr) {
|
||||
}
|
||||
}
|
||||
|
||||
debug!("regionck::visit_expr(e={:?}, repeating_scope={}) - visiting subexprs",
|
||||
expr, self.repeating_scope);
|
||||
debug!(
|
||||
"regionck::visit_expr(e={:?}, repeating_scope={}) - visiting subexprs",
|
||||
expr, self.repeating_scope
|
||||
);
|
||||
match expr.node {
|
||||
hir::ExprKind::Path(_) => {
|
||||
let substs = self.tables.borrow().node_substs(expr.hir_id);
|
||||
@@ -571,7 +604,7 @@ fn visit_expr(&mut self, expr: &'gcx hir::Expr) {
|
||||
self.constrain_call(expr, Some(&lhs), Some(&**rhs).into_iter());
|
||||
|
||||
intravisit::walk_expr(self, expr);
|
||||
},
|
||||
}
|
||||
|
||||
hir::ExprKind::Binary(_, ref lhs, ref rhs) if is_method_call => {
|
||||
// As `ExprKind::MethodCall`, but the call is via an overloaded op.
|
||||
@@ -586,8 +619,7 @@ fn visit_expr(&mut self, expr: &'gcx hir::Expr) {
|
||||
let lhs_ty = self.resolve_expr_type_adjusted(&lhs);
|
||||
let rhs_ty = self.resolve_expr_type_adjusted(&rhs);
|
||||
for &ty in &[lhs_ty, rhs_ty] {
|
||||
self.type_must_outlive(infer::Operand(expr.span),
|
||||
ty, expr_region);
|
||||
self.type_must_outlive(infer::Operand(expr.span), ty, expr_region);
|
||||
}
|
||||
intravisit::walk_expr(self, expr);
|
||||
}
|
||||
@@ -674,12 +706,16 @@ fn visit_expr(&mut self, expr: &'gcx hir::Expr) {
|
||||
|
||||
hir::ExprKind::Ret(Some(ref ret_expr)) => {
|
||||
let call_site_scope = self.call_site_scope;
|
||||
debug!("visit_expr ExprKind::Ret ret_expr.id {} call_site_scope: {:?}",
|
||||
ret_expr.id, call_site_scope);
|
||||
debug!(
|
||||
"visit_expr ExprKind::Ret ret_expr.id {} call_site_scope: {:?}",
|
||||
ret_expr.id, call_site_scope
|
||||
);
|
||||
let call_site_region = self.tcx.mk_region(ty::ReScope(call_site_scope.unwrap()));
|
||||
self.type_of_node_must_outlive(infer::CallReturn(ret_expr.span),
|
||||
ret_expr.hir_id,
|
||||
call_site_region);
|
||||
self.type_of_node_must_outlive(
|
||||
infer::CallReturn(ret_expr.span),
|
||||
ret_expr.hir_id,
|
||||
call_site_region,
|
||||
);
|
||||
intravisit::walk_expr(self, expr);
|
||||
}
|
||||
|
||||
@@ -691,13 +727,11 @@ fn visit_expr(&mut self, expr: &'gcx hir::Expr) {
|
||||
}
|
||||
|
||||
impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
|
||||
fn constrain_cast(&mut self,
|
||||
cast_expr: &hir::Expr,
|
||||
source_expr: &hir::Expr)
|
||||
{
|
||||
debug!("constrain_cast(cast_expr={:?}, source_expr={:?})",
|
||||
cast_expr,
|
||||
source_expr);
|
||||
fn constrain_cast(&mut self, cast_expr: &hir::Expr, source_expr: &hir::Expr) {
|
||||
debug!(
|
||||
"constrain_cast(cast_expr={:?}, source_expr={:?})",
|
||||
cast_expr, source_expr
|
||||
);
|
||||
|
||||
let source_ty = self.resolve_node_type(source_expr.hir_id);
|
||||
let target_ty = self.resolve_node_type(cast_expr.hir_id);
|
||||
@@ -705,40 +739,35 @@ fn constrain_cast(&mut self,
|
||||
self.walk_cast(cast_expr, source_ty, target_ty);
|
||||
}
|
||||
|
||||
fn walk_cast(&mut self,
|
||||
cast_expr: &hir::Expr,
|
||||
from_ty: Ty<'tcx>,
|
||||
to_ty: Ty<'tcx>) {
|
||||
debug!("walk_cast(from_ty={:?}, to_ty={:?})",
|
||||
from_ty,
|
||||
to_ty);
|
||||
fn walk_cast(&mut self, cast_expr: &hir::Expr, from_ty: Ty<'tcx>, to_ty: Ty<'tcx>) {
|
||||
debug!("walk_cast(from_ty={:?}, to_ty={:?})", from_ty, to_ty);
|
||||
match (&from_ty.sty, &to_ty.sty) {
|
||||
/*From:*/ (&ty::Ref(from_r, from_ty, _),
|
||||
/*To: */ &ty::Ref(to_r, to_ty, _)) => {
|
||||
/*From:*/
|
||||
(&ty::Ref(from_r, from_ty, _), /*To: */ &ty::Ref(to_r, to_ty, _)) => {
|
||||
// Target cannot outlive source, naturally.
|
||||
self.sub_regions(infer::Reborrow(cast_expr.span), to_r, from_r);
|
||||
self.walk_cast(cast_expr, from_ty, to_ty);
|
||||
}
|
||||
|
||||
/*From:*/ (_,
|
||||
/*To: */ &ty::Dynamic(.., r)) => {
|
||||
/*From:*/
|
||||
(_, /*To: */ &ty::Dynamic(.., r)) => {
|
||||
// When T is existentially quantified as a trait
|
||||
// `Foo+'to`, it must outlive the region bound `'to`.
|
||||
self.type_must_outlive(infer::RelateObjectBound(cast_expr.span), from_ty, r);
|
||||
}
|
||||
|
||||
/*From:*/ (&ty::Adt(from_def, _),
|
||||
/*To: */ &ty::Adt(to_def, _)) if from_def.is_box() && to_def.is_box() => {
|
||||
/*From:*/
|
||||
(&ty::Adt(from_def, _), /*To: */ &ty::Adt(to_def, _))
|
||||
if from_def.is_box() && to_def.is_box() =>
|
||||
{
|
||||
self.walk_cast(cast_expr, from_ty.boxed_ty(), to_ty.boxed_ty());
|
||||
}
|
||||
|
||||
_ => { }
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn check_expr_fn_block(&mut self,
|
||||
expr: &'gcx hir::Expr,
|
||||
body_id: hir::BodyId) {
|
||||
fn check_expr_fn_block(&mut self, expr: &'gcx hir::Expr, body_id: hir::BodyId) {
|
||||
let repeating_scope = self.set_repeating_scope(body_id.node_id);
|
||||
intravisit::walk_expr(self, expr);
|
||||
self.set_repeating_scope(repeating_scope);
|
||||
@@ -747,7 +776,7 @@ fn check_expr_fn_block(&mut self,
|
||||
fn constrain_callee(&mut self, callee_expr: &hir::Expr) {
|
||||
let callee_ty = self.resolve_node_type(callee_expr.hir_id);
|
||||
match callee_ty.sty {
|
||||
ty::FnDef(..) | ty::FnPtr(_) => { }
|
||||
ty::FnDef(..) | ty::FnPtr(_) => {}
|
||||
_ => {
|
||||
// this should not happen, but it does if the program is
|
||||
// erroneous
|
||||
@@ -760,18 +789,21 @@ fn constrain_callee(&mut self, callee_expr: &hir::Expr) {
|
||||
}
|
||||
}
|
||||
|
||||
fn constrain_call<'b, I: Iterator<Item=&'b hir::Expr>>(&mut self,
|
||||
call_expr: &hir::Expr,
|
||||
receiver: Option<&hir::Expr>,
|
||||
arg_exprs: I) {
|
||||
fn constrain_call<'b, I: Iterator<Item = &'b hir::Expr>>(
|
||||
&mut self,
|
||||
call_expr: &hir::Expr,
|
||||
receiver: Option<&hir::Expr>,
|
||||
arg_exprs: I,
|
||||
) {
|
||||
//! Invoked on every call site (i.e., normal calls, method calls,
|
||||
//! and overloaded operators). Constrains the regions which appear
|
||||
//! in the type of the function. Also constrains the regions that
|
||||
//! appear in the arguments appropriately.
|
||||
|
||||
debug!("constrain_call(call_expr={:?}, receiver={:?})",
|
||||
call_expr,
|
||||
receiver);
|
||||
debug!(
|
||||
"constrain_call(call_expr={:?}, receiver={:?})",
|
||||
call_expr, receiver
|
||||
);
|
||||
|
||||
// `callee_region` is the scope representing the time in which the
|
||||
// call occurs.
|
||||
@@ -779,7 +811,7 @@ fn constrain_call<'b, I: Iterator<Item=&'b hir::Expr>>(&mut self,
|
||||
// FIXME(#6268) to support nested method calls, should be callee_id
|
||||
let callee_scope = region::Scope {
|
||||
id: call_expr.hir_id.local_id,
|
||||
data: region::ScopeData::Node
|
||||
data: region::ScopeData::Node,
|
||||
};
|
||||
let callee_region = self.tcx.mk_region(ty::ReScope(callee_scope));
|
||||
|
||||
@@ -790,27 +822,30 @@ fn constrain_call<'b, I: Iterator<Item=&'b hir::Expr>>(&mut self,
|
||||
|
||||
// ensure that any regions appearing in the argument type are
|
||||
// valid for at least the lifetime of the function:
|
||||
self.type_of_node_must_outlive(infer::CallArg(arg_expr.span),
|
||||
arg_expr.hir_id,
|
||||
callee_region);
|
||||
self.type_of_node_must_outlive(
|
||||
infer::CallArg(arg_expr.span),
|
||||
arg_expr.hir_id,
|
||||
callee_region,
|
||||
);
|
||||
}
|
||||
|
||||
// as loop above, but for receiver
|
||||
if let Some(r) = receiver {
|
||||
debug!("receiver: {:?}", r);
|
||||
self.type_of_node_must_outlive(infer::CallRcvr(r.span),
|
||||
r.hir_id,
|
||||
callee_region);
|
||||
self.type_of_node_must_outlive(infer::CallRcvr(r.span), r.hir_id, callee_region);
|
||||
}
|
||||
}
|
||||
|
||||
/// 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
|
||||
where
|
||||
F: for<'b> FnOnce(mc::MemCategorizationContext<'b, 'gcx, 'tcx>) -> R,
|
||||
{
|
||||
f(mc::MemCategorizationContext::with_infer(&self.infcx,
|
||||
&self.region_scope_tree,
|
||||
&self.tables.borrow()))
|
||||
f(mc::MemCategorizationContext::with_infer(
|
||||
&self.infcx,
|
||||
&self.region_scope_tree,
|
||||
&self.tables.borrow(),
|
||||
))
|
||||
}
|
||||
|
||||
/// Invoked on any adjustments that occur. Checks that if this is a region pointer being
|
||||
@@ -832,37 +867,46 @@ fn constrain_adjustments(&mut self, expr: &hir::Expr) -> mc::McResult<mc::cmt_<'
|
||||
// expression.
|
||||
self.check_safety_of_rvalue_destructor_if_necessary(&cmt, expr.span);
|
||||
|
||||
let expr_region = self.tcx.mk_region(ty::ReScope(
|
||||
region::Scope {
|
||||
id: expr.hir_id.local_id,
|
||||
data: region::ScopeData::Node
|
||||
}));
|
||||
let expr_region = self.tcx.mk_region(ty::ReScope(region::Scope {
|
||||
id: expr.hir_id.local_id,
|
||||
data: region::ScopeData::Node,
|
||||
}));
|
||||
for adjustment in adjustments {
|
||||
debug!("constrain_adjustments: adjustment={:?}, cmt={:?}",
|
||||
adjustment, cmt);
|
||||
debug!(
|
||||
"constrain_adjustments: adjustment={:?}, cmt={:?}",
|
||||
adjustment, cmt
|
||||
);
|
||||
|
||||
if let adjustment::Adjust::Deref(Some(deref)) = adjustment.kind {
|
||||
debug!("constrain_adjustments: overloaded deref: {:?}", deref);
|
||||
|
||||
// Treat overloaded autoderefs as if an AutoBorrow adjustment
|
||||
// was applied on the base type, as that is always the case.
|
||||
let input = self.tcx.mk_ref(deref.region, ty::TypeAndMut {
|
||||
ty: cmt.ty,
|
||||
mutbl: deref.mutbl,
|
||||
});
|
||||
let output = self.tcx.mk_ref(deref.region, ty::TypeAndMut {
|
||||
ty: adjustment.target,
|
||||
mutbl: deref.mutbl,
|
||||
});
|
||||
let input = self.tcx.mk_ref(
|
||||
deref.region,
|
||||
ty::TypeAndMut {
|
||||
ty: cmt.ty,
|
||||
mutbl: deref.mutbl,
|
||||
},
|
||||
);
|
||||
let output = self.tcx.mk_ref(
|
||||
deref.region,
|
||||
ty::TypeAndMut {
|
||||
ty: adjustment.target,
|
||||
mutbl: deref.mutbl,
|
||||
},
|
||||
);
|
||||
|
||||
self.link_region(expr.span, deref.region,
|
||||
ty::BorrowKind::from_mutbl(deref.mutbl), &cmt);
|
||||
self.link_region(
|
||||
expr.span,
|
||||
deref.region,
|
||||
ty::BorrowKind::from_mutbl(deref.mutbl),
|
||||
&cmt,
|
||||
);
|
||||
|
||||
// Specialized version of constrain_call.
|
||||
self.type_must_outlive(infer::CallRcvr(expr.span),
|
||||
input, expr_region);
|
||||
self.type_must_outlive(infer::CallReturn(expr.span),
|
||||
output, expr_region);
|
||||
self.type_must_outlive(infer::CallRcvr(expr.span), input, expr_region);
|
||||
self.type_must_outlive(infer::CallReturn(expr.span), output, expr_region);
|
||||
}
|
||||
|
||||
if let adjustment::Adjust::Borrow(ref autoref) = adjustment.kind {
|
||||
@@ -872,73 +916,84 @@ fn constrain_adjustments(&mut self, expr: &hir::Expr) -> mc::McResult<mc::cmt_<'
|
||||
// the current node.
|
||||
//
|
||||
// FIXME(#6268) remove to support nested method calls
|
||||
self.type_of_node_must_outlive(infer::AutoBorrow(expr.span),
|
||||
expr.hir_id,
|
||||
expr_region);
|
||||
self.type_of_node_must_outlive(
|
||||
infer::AutoBorrow(expr.span),
|
||||
expr.hir_id,
|
||||
expr_region,
|
||||
);
|
||||
}
|
||||
|
||||
cmt = self.with_mc(|mc| mc.cat_expr_adjusted(expr, cmt, &adjustment))?;
|
||||
|
||||
if let Categorization::Deref(_, mc::BorrowedPtr(_, r_ptr)) = cmt.cat {
|
||||
self.mk_subregion_due_to_dereference(expr.span,
|
||||
expr_region, r_ptr);
|
||||
self.mk_subregion_due_to_dereference(expr.span, expr_region, r_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(cmt)
|
||||
}
|
||||
|
||||
pub fn mk_subregion_due_to_dereference(&mut self,
|
||||
deref_span: Span,
|
||||
minimum_lifetime: ty::Region<'tcx>,
|
||||
maximum_lifetime: ty::Region<'tcx>) {
|
||||
self.sub_regions(infer::DerefPointer(deref_span),
|
||||
minimum_lifetime, maximum_lifetime)
|
||||
pub fn mk_subregion_due_to_dereference(
|
||||
&mut self,
|
||||
deref_span: Span,
|
||||
minimum_lifetime: ty::Region<'tcx>,
|
||||
maximum_lifetime: ty::Region<'tcx>,
|
||||
) {
|
||||
self.sub_regions(
|
||||
infer::DerefPointer(deref_span),
|
||||
minimum_lifetime,
|
||||
maximum_lifetime,
|
||||
)
|
||||
}
|
||||
|
||||
fn check_safety_of_rvalue_destructor_if_necessary(&mut self,
|
||||
cmt: &mc::cmt_<'tcx>,
|
||||
span: Span) {
|
||||
fn check_safety_of_rvalue_destructor_if_necessary(&mut self, cmt: &mc::cmt_<'tcx>, span: Span) {
|
||||
match cmt.cat {
|
||||
Categorization::Rvalue(region) => {
|
||||
match *region {
|
||||
ty::ReScope(rvalue_scope) => {
|
||||
let typ = self.resolve_type(cmt.ty);
|
||||
let body_id = self.body_id;
|
||||
let _ = dropck::check_safety_of_destructor_if_necessary(
|
||||
self, typ, span, body_id, rvalue_scope);
|
||||
}
|
||||
ty::ReStatic => {}
|
||||
_ => {
|
||||
span_bug!(span,
|
||||
"unexpected rvalue region in rvalue \
|
||||
destructor safety checking: `{:?}`",
|
||||
region);
|
||||
}
|
||||
Categorization::Rvalue(region) => match *region {
|
||||
ty::ReScope(rvalue_scope) => {
|
||||
let typ = self.resolve_type(cmt.ty);
|
||||
let body_id = self.body_id;
|
||||
let _ = dropck::check_safety_of_destructor_if_necessary(
|
||||
self,
|
||||
typ,
|
||||
span,
|
||||
body_id,
|
||||
rvalue_scope,
|
||||
);
|
||||
}
|
||||
}
|
||||
ty::ReStatic => {}
|
||||
_ => {
|
||||
span_bug!(
|
||||
span,
|
||||
"unexpected rvalue region in rvalue \
|
||||
destructor safety checking: `{:?}`",
|
||||
region
|
||||
);
|
||||
}
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
/// Invoked on any index expression that occurs. Checks that if this is a slice
|
||||
/// being indexed, the lifetime of the pointer includes the deref expr.
|
||||
fn constrain_index(&mut self,
|
||||
index_expr: &hir::Expr,
|
||||
indexed_ty: Ty<'tcx>)
|
||||
{
|
||||
debug!("constrain_index(index_expr=?, indexed_ty={}",
|
||||
self.ty_to_string(indexed_ty));
|
||||
fn constrain_index(&mut self, index_expr: &hir::Expr, indexed_ty: Ty<'tcx>) {
|
||||
debug!(
|
||||
"constrain_index(index_expr=?, indexed_ty={}",
|
||||
self.ty_to_string(indexed_ty)
|
||||
);
|
||||
|
||||
let r_index_expr = ty::ReScope(region::Scope {
|
||||
id: index_expr.hir_id.local_id,
|
||||
data: region::ScopeData::Node
|
||||
data: region::ScopeData::Node,
|
||||
});
|
||||
if let ty::Ref(r_ptr, r_ty, _) = indexed_ty.sty {
|
||||
match r_ty.sty {
|
||||
ty::Slice(_) | ty::Str => {
|
||||
self.sub_regions(infer::IndexSlice(index_expr.span),
|
||||
self.tcx.mk_region(r_index_expr), r_ptr);
|
||||
self.sub_regions(
|
||||
infer::IndexSlice(index_expr.span),
|
||||
self.tcx.mk_region(r_index_expr),
|
||||
r_ptr,
|
||||
);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
@@ -947,27 +1002,29 @@ fn constrain_index(&mut self,
|
||||
|
||||
/// Guarantees that any lifetimes which appear in the type of the node `id` (after applying
|
||||
/// adjustments) are valid for at least `minimum_lifetime`
|
||||
fn type_of_node_must_outlive(&mut self,
|
||||
fn type_of_node_must_outlive(
|
||||
&mut self,
|
||||
origin: infer::SubregionOrigin<'tcx>,
|
||||
hir_id: hir::HirId,
|
||||
minimum_lifetime: ty::Region<'tcx>)
|
||||
{
|
||||
minimum_lifetime: ty::Region<'tcx>,
|
||||
) {
|
||||
// Try to resolve the type. If we encounter an error, then typeck
|
||||
// is going to fail anyway, so just stop here and let typeck
|
||||
// report errors later on in the writeback phase.
|
||||
let ty0 = self.resolve_node_type(hir_id);
|
||||
|
||||
let ty = self.tables
|
||||
.borrow()
|
||||
.adjustments()
|
||||
.get(hir_id)
|
||||
.and_then(|adj| adj.last())
|
||||
.map_or(ty0, |adj| adj.target);
|
||||
.borrow()
|
||||
.adjustments()
|
||||
.get(hir_id)
|
||||
.and_then(|adj| adj.last())
|
||||
.map_or(ty0, |adj| adj.target);
|
||||
let ty = self.resolve_type(ty);
|
||||
debug!("constrain_regions_in_type_of_node(\
|
||||
ty={}, ty0={}, id={:?}, minimum_lifetime={:?})",
|
||||
ty, ty0,
|
||||
hir_id, minimum_lifetime);
|
||||
debug!(
|
||||
"constrain_regions_in_type_of_node(\
|
||||
ty={}, ty0={}, id={:?}, minimum_lifetime={:?})",
|
||||
ty, ty0, hir_id, minimum_lifetime
|
||||
);
|
||||
self.type_must_outlive(origin, ty, minimum_lifetime);
|
||||
}
|
||||
|
||||
@@ -979,23 +1036,25 @@ fn type_of_node_must_outlive(&mut self,
|
||||
/// - `origin`, the reason we need this constraint
|
||||
/// - `ty`, the type `T`
|
||||
/// - `region`, the region `'a`
|
||||
pub fn type_must_outlive(&self,
|
||||
origin: infer::SubregionOrigin<'tcx>,
|
||||
ty: Ty<'tcx>,
|
||||
region: ty::Region<'tcx>)
|
||||
{
|
||||
self.infcx.type_must_outlive(self.outlives_environment.region_bound_pairs(),
|
||||
self.implicit_region_bound,
|
||||
self.param_env,
|
||||
origin,
|
||||
ty,
|
||||
region);
|
||||
pub fn type_must_outlive(
|
||||
&self,
|
||||
origin: infer::SubregionOrigin<'tcx>,
|
||||
ty: Ty<'tcx>,
|
||||
region: ty::Region<'tcx>,
|
||||
) {
|
||||
self.infcx.type_must_outlive(
|
||||
self.outlives_environment.region_bound_pairs(),
|
||||
self.implicit_region_bound,
|
||||
self.param_env,
|
||||
origin,
|
||||
ty,
|
||||
region,
|
||||
);
|
||||
}
|
||||
|
||||
/// Computes the guarantor for an expression `&base` and then ensures that the lifetime of the
|
||||
/// resulting pointer is linked to the lifetime of its guarantor (if any).
|
||||
fn link_addr_of(&mut self, expr: &hir::Expr,
|
||||
mutability: hir::Mutability, base: &hir::Expr) {
|
||||
fn link_addr_of(&mut self, expr: &hir::Expr, mutability: hir::Mutability, base: &hir::Expr) {
|
||||
debug!("link_addr_of(expr={:?}, base={:?})", expr, base);
|
||||
|
||||
let cmt = ignore_err!(self.with_mc(|mc| mc.cat_expr(base)));
|
||||
@@ -1011,7 +1070,9 @@ fn link_addr_of(&mut self, expr: &hir::Expr,
|
||||
fn link_local(&self, local: &hir::Local) {
|
||||
debug!("regionck::for_local()");
|
||||
let init_expr = match local.init {
|
||||
None => { return; }
|
||||
None => {
|
||||
return;
|
||||
}
|
||||
Some(ref expr) => &**expr,
|
||||
};
|
||||
let discr_cmt = Rc::new(ignore_err!(self.with_mc(|mc| mc.cat_expr(init_expr))));
|
||||
@@ -1043,10 +1104,7 @@ fn link_fn_args(&self, body_scope: region::Scope, args: &[hir::Arg]) {
|
||||
let arg_cmt = self.with_mc(|mc| {
|
||||
Rc::new(mc.cat_rvalue(arg.hir_id, arg.pat.span, re_scope, arg_ty))
|
||||
});
|
||||
debug!("arg_ty={:?} arg_cmt={:?} arg={:?}",
|
||||
arg_ty,
|
||||
arg_cmt,
|
||||
arg);
|
||||
debug!("arg_ty={:?} arg_cmt={:?} arg={:?}", arg_ty, arg_cmt, arg);
|
||||
self.link_pattern(arg_cmt, &arg.pat);
|
||||
}
|
||||
}
|
||||
@@ -1054,9 +1112,10 @@ fn link_fn_args(&self, body_scope: region::Scope, args: &[hir::Arg]) {
|
||||
/// Link lifetimes of any ref bindings in `root_pat` to the pointers found
|
||||
/// in the discriminant, if needed.
|
||||
fn link_pattern(&self, discr_cmt: mc::cmt<'tcx>, root_pat: &hir::Pat) {
|
||||
debug!("link_pattern(discr_cmt={:?}, root_pat={:?})",
|
||||
discr_cmt,
|
||||
root_pat);
|
||||
debug!(
|
||||
"link_pattern(discr_cmt={:?}, root_pat={:?})",
|
||||
discr_cmt, root_pat
|
||||
);
|
||||
ignore_err!(self.with_mc(|mc| {
|
||||
mc.cat_pattern(discr_cmt, root_pat, |sub_cmt, sub_pat| {
|
||||
match sub_pat.node {
|
||||
@@ -1064,11 +1123,17 @@ fn link_pattern(&self, discr_cmt: mc::cmt<'tcx>, root_pat: &hir::Pat) {
|
||||
PatKind::Binding(..) => {
|
||||
if let Some(&bm) = mc.tables.pat_binding_modes().get(sub_pat.hir_id) {
|
||||
if let ty::BindByReference(mutbl) = bm {
|
||||
self.link_region_from_node_type(sub_pat.span, sub_pat.hir_id,
|
||||
mutbl, &sub_cmt);
|
||||
self.link_region_from_node_type(
|
||||
sub_pat.span,
|
||||
sub_pat.hir_id,
|
||||
mutbl,
|
||||
&sub_cmt,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
self.tcx.sess.delay_span_bug(sub_pat.span, "missing binding mode");
|
||||
self.tcx
|
||||
.sess
|
||||
.delay_span_bug(sub_pat.span, "missing binding mode");
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
@@ -1079,12 +1144,16 @@ fn link_pattern(&self, discr_cmt: mc::cmt<'tcx>, root_pat: &hir::Pat) {
|
||||
|
||||
/// Link lifetime of borrowed pointer resulting from autoref to lifetimes in the value being
|
||||
/// autoref'd.
|
||||
fn link_autoref(&self,
|
||||
expr: &hir::Expr,
|
||||
expr_cmt: &mc::cmt_<'tcx>,
|
||||
autoref: &adjustment::AutoBorrow<'tcx>)
|
||||
{
|
||||
debug!("link_autoref(autoref={:?}, expr_cmt={:?})", autoref, expr_cmt);
|
||||
fn link_autoref(
|
||||
&self,
|
||||
expr: &hir::Expr,
|
||||
expr_cmt: &mc::cmt_<'tcx>,
|
||||
autoref: &adjustment::AutoBorrow<'tcx>,
|
||||
) {
|
||||
debug!(
|
||||
"link_autoref(autoref={:?}, expr_cmt={:?})",
|
||||
autoref, expr_cmt
|
||||
);
|
||||
|
||||
match *autoref {
|
||||
adjustment::AutoBorrow::Ref(r, m) => {
|
||||
@@ -1094,7 +1163,7 @@ fn link_autoref(&self,
|
||||
adjustment::AutoBorrow::RawPtr(m) => {
|
||||
let r = self.tcx.mk_region(ty::ReScope(region::Scope {
|
||||
id: expr.hir_id.local_id,
|
||||
data: region::ScopeData::Node
|
||||
data: region::ScopeData::Node,
|
||||
}));
|
||||
self.link_region(expr.span, r, ty::BorrowKind::from_mutbl(m), expr_cmt);
|
||||
}
|
||||
@@ -1103,17 +1172,21 @@ fn link_autoref(&self,
|
||||
|
||||
/// Like `link_region()`, except that the region is extracted from the type of `id`,
|
||||
/// which must be some reference (`&T`, `&str`, etc).
|
||||
fn link_region_from_node_type(&self,
|
||||
span: Span,
|
||||
id: hir::HirId,
|
||||
mutbl: hir::Mutability,
|
||||
cmt_borrowed: &mc::cmt_<'tcx>) {
|
||||
debug!("link_region_from_node_type(id={:?}, mutbl={:?}, cmt_borrowed={:?})",
|
||||
id, mutbl, cmt_borrowed);
|
||||
fn link_region_from_node_type(
|
||||
&self,
|
||||
span: Span,
|
||||
id: hir::HirId,
|
||||
mutbl: hir::Mutability,
|
||||
cmt_borrowed: &mc::cmt_<'tcx>,
|
||||
) {
|
||||
debug!(
|
||||
"link_region_from_node_type(id={:?}, mutbl={:?}, cmt_borrowed={:?})",
|
||||
id, mutbl, cmt_borrowed
|
||||
);
|
||||
|
||||
let rptr_ty = self.resolve_node_type(id);
|
||||
if let ty::Ref(r, _, _) = rptr_ty.sty {
|
||||
debug!("rptr_ty={}", rptr_ty);
|
||||
debug!("rptr_ty={}", rptr_ty);
|
||||
self.link_region(span, r, ty::BorrowKind::from_mutbl(mutbl), cmt_borrowed);
|
||||
}
|
||||
}
|
||||
@@ -1122,11 +1195,13 @@ fn link_region_from_node_type(&self,
|
||||
/// kind `borrow_kind` and lifetime `borrow_region`.
|
||||
/// In order to ensure borrowck is satisfied, this may create constraints
|
||||
/// between regions, as explained in `link_reborrowed_region()`.
|
||||
fn link_region(&self,
|
||||
span: Span,
|
||||
borrow_region: ty::Region<'tcx>,
|
||||
borrow_kind: ty::BorrowKind,
|
||||
borrow_cmt: &mc::cmt_<'tcx>) {
|
||||
fn link_region(
|
||||
&self,
|
||||
span: Span,
|
||||
borrow_region: ty::Region<'tcx>,
|
||||
borrow_kind: ty::BorrowKind,
|
||||
borrow_cmt: &mc::cmt_<'tcx>,
|
||||
) {
|
||||
let origin = infer::DataBorrowed(borrow_cmt.ty, span);
|
||||
self.type_must_outlive(origin, borrow_cmt.ty, borrow_region);
|
||||
|
||||
@@ -1134,16 +1209,21 @@ fn link_region(&self,
|
||||
let mut borrow_cmt_cat = borrow_cmt.cat.clone();
|
||||
|
||||
loop {
|
||||
debug!("link_region(borrow_region={:?}, borrow_kind={:?}, borrow_cmt={:?})",
|
||||
borrow_region,
|
||||
borrow_kind,
|
||||
borrow_cmt);
|
||||
debug!(
|
||||
"link_region(borrow_region={:?}, borrow_kind={:?}, borrow_cmt={:?})",
|
||||
borrow_region, borrow_kind, borrow_cmt
|
||||
);
|
||||
match borrow_cmt_cat {
|
||||
Categorization::Deref(ref_cmt, mc::BorrowedPtr(ref_kind, ref_region)) => {
|
||||
match self.link_reborrowed_region(span,
|
||||
borrow_region, borrow_kind,
|
||||
ref_cmt, ref_region, ref_kind,
|
||||
borrow_cmt.note) {
|
||||
match self.link_reborrowed_region(
|
||||
span,
|
||||
borrow_region,
|
||||
borrow_kind,
|
||||
ref_cmt,
|
||||
ref_region,
|
||||
ref_kind,
|
||||
borrow_cmt.note,
|
||||
) {
|
||||
Some((c, k)) => {
|
||||
borrow_cmt_cat = c.cat.clone();
|
||||
borrow_kind = k;
|
||||
@@ -1154,20 +1234,20 @@ fn link_region(&self,
|
||||
}
|
||||
}
|
||||
|
||||
Categorization::Downcast(cmt_base, _) |
|
||||
Categorization::Deref(cmt_base, mc::Unique) |
|
||||
Categorization::Interior(cmt_base, _) => {
|
||||
Categorization::Downcast(cmt_base, _)
|
||||
| Categorization::Deref(cmt_base, mc::Unique)
|
||||
| Categorization::Interior(cmt_base, _) => {
|
||||
// Borrowing interior or owned data requires the base
|
||||
// to be valid and borrowable in the same fashion.
|
||||
borrow_cmt_cat = cmt_base.cat.clone();
|
||||
borrow_kind = borrow_kind;
|
||||
}
|
||||
|
||||
Categorization::Deref(_, mc::UnsafePtr(..)) |
|
||||
Categorization::StaticItem |
|
||||
Categorization::Upvar(..) |
|
||||
Categorization::Local(..) |
|
||||
Categorization::Rvalue(..) => {
|
||||
Categorization::Deref(_, mc::UnsafePtr(..))
|
||||
| Categorization::StaticItem
|
||||
| Categorization::Upvar(..)
|
||||
| Categorization::Local(..)
|
||||
| Categorization::Rvalue(..) => {
|
||||
// These are all "base cases" with independent lifetimes
|
||||
// that are not subject to inference
|
||||
return;
|
||||
@@ -1218,16 +1298,16 @@ fn link_region(&self,
|
||||
///
|
||||
/// The return value of this function indicates whether we need to
|
||||
/// recurse and process `ref_cmt` (see case 2 above).
|
||||
fn link_reborrowed_region(&self,
|
||||
span: Span,
|
||||
borrow_region: ty::Region<'tcx>,
|
||||
borrow_kind: ty::BorrowKind,
|
||||
ref_cmt: mc::cmt<'tcx>,
|
||||
ref_region: ty::Region<'tcx>,
|
||||
mut ref_kind: ty::BorrowKind,
|
||||
note: mc::Note)
|
||||
-> Option<(mc::cmt<'tcx>, ty::BorrowKind)>
|
||||
{
|
||||
fn link_reborrowed_region(
|
||||
&self,
|
||||
span: Span,
|
||||
borrow_region: ty::Region<'tcx>,
|
||||
borrow_kind: ty::BorrowKind,
|
||||
ref_cmt: mc::cmt<'tcx>,
|
||||
ref_region: ty::Region<'tcx>,
|
||||
mut ref_kind: ty::BorrowKind,
|
||||
note: mc::Note,
|
||||
) -> Option<(mc::cmt<'tcx>, ty::BorrowKind)> {
|
||||
// Possible upvar ID we may need later to create an entry in the
|
||||
// maybe link map.
|
||||
|
||||
@@ -1243,7 +1323,7 @@ fn link_reborrowed_region(&self,
|
||||
infer::ReborrowUpvar(span, *upvar_id)
|
||||
}
|
||||
_ => {
|
||||
span_bug!( span, "Illegal upvar id: {:?}", upvar_id);
|
||||
span_bug!(span, "Illegal upvar id: {:?}", upvar_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1253,14 +1333,13 @@ fn link_reborrowed_region(&self,
|
||||
// link
|
||||
infer::ReborrowUpvar(span, *upvar_id)
|
||||
}
|
||||
_ => {
|
||||
infer::Reborrow(span)
|
||||
}
|
||||
_ => infer::Reborrow(span),
|
||||
};
|
||||
|
||||
debug!("link_reborrowed_region: {:?} <= {:?}",
|
||||
borrow_region,
|
||||
ref_region);
|
||||
debug!(
|
||||
"link_reborrowed_region: {:?} <= {:?}",
|
||||
borrow_region, ref_region
|
||||
);
|
||||
self.sub_regions(cause, borrow_region, ref_region);
|
||||
|
||||
// If we end up needing to recurse and establish a region link
|
||||
@@ -1272,10 +1351,8 @@ fn link_reborrowed_region(&self,
|
||||
// borrowck requires a unique path to the `&mut` reference but not
|
||||
// necessarily a *mutable* path.
|
||||
let new_borrow_kind = match borrow_kind {
|
||||
ty::ImmBorrow =>
|
||||
ty::ImmBorrow,
|
||||
ty::MutBorrow | ty::UniqueImmBorrow =>
|
||||
ty::UniqueImmBorrow
|
||||
ty::ImmBorrow => ty::ImmBorrow,
|
||||
ty::MutBorrow | ty::UniqueImmBorrow => ty::UniqueImmBorrow,
|
||||
};
|
||||
|
||||
// Decide whether we need to recurse and link any regions within
|
||||
@@ -1329,16 +1406,20 @@ fn link_reborrowed_region(&self,
|
||||
|
||||
/// Checks that the values provided for type/region arguments in a given
|
||||
/// expression are well-formed and in-scope.
|
||||
fn substs_wf_in_scope(&mut self,
|
||||
origin: infer::ParameterOrigin,
|
||||
substs: &Substs<'tcx>,
|
||||
expr_span: Span,
|
||||
expr_region: ty::Region<'tcx>) {
|
||||
debug!("substs_wf_in_scope(substs={:?}, \
|
||||
expr_region={:?}, \
|
||||
origin={:?}, \
|
||||
expr_span={:?})",
|
||||
substs, expr_region, origin, expr_span);
|
||||
fn substs_wf_in_scope(
|
||||
&mut self,
|
||||
origin: infer::ParameterOrigin,
|
||||
substs: &Substs<'tcx>,
|
||||
expr_span: Span,
|
||||
expr_region: ty::Region<'tcx>,
|
||||
) {
|
||||
debug!(
|
||||
"substs_wf_in_scope(substs={:?}, \
|
||||
expr_region={:?}, \
|
||||
origin={:?}, \
|
||||
expr_span={:?})",
|
||||
substs, expr_region, origin, expr_span
|
||||
);
|
||||
|
||||
let origin = infer::ParameterInScope(origin, expr_span);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user