rustc_mir: don't rely on mir::UpvarDecl in the MIR borrowck.
This commit is contained in:
parent
3bee49f42b
commit
61fcbfcd59
12 changed files with 159 additions and 91 deletions
|
@ -133,41 +133,6 @@ impl<'tcx> Place<'tcx> {
|
||||||
proj.base.ty(local_decls, tcx).projection_ty(tcx, &proj.elem),
|
proj.base.ty(local_decls, tcx).projection_ty(tcx, &proj.elem),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// If this is a field projection, and the field is being projected from a closure type,
|
|
||||||
/// then returns the index of the field being projected. Note that this closure will always
|
|
||||||
/// be `self` in the current MIR, because that is the only time we directly access the fields
|
|
||||||
/// of a closure type.
|
|
||||||
pub fn is_upvar_field_projection<'cx, 'gcx>(&self, mir: &'cx Mir<'tcx>,
|
|
||||||
tcx: &TyCtxt<'cx, 'gcx, 'tcx>) -> Option<Field> {
|
|
||||||
let (place, by_ref) = if let Place::Projection(ref proj) = self {
|
|
||||||
if let ProjectionElem::Deref = proj.elem {
|
|
||||||
(&proj.base, true)
|
|
||||||
} else {
|
|
||||||
(self, false)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
(self, false)
|
|
||||||
};
|
|
||||||
|
|
||||||
match place {
|
|
||||||
Place::Projection(ref proj) => match proj.elem {
|
|
||||||
ProjectionElem::Field(field, _ty) => {
|
|
||||||
let base_ty = proj.base.ty(mir, *tcx).ty;
|
|
||||||
|
|
||||||
if (base_ty.is_closure() || base_ty.is_generator()) &&
|
|
||||||
(!by_ref || mir.upvar_decls[field.index()].by_ref)
|
|
||||||
{
|
|
||||||
Some(field)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
},
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum RvalueInitializationState {
|
pub enum RvalueInitializationState {
|
||||||
|
|
|
@ -1088,7 +1088,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
| LocalKind::Temp => bug!("temporary or return pointer with a name"),
|
| LocalKind::Temp => bug!("temporary or return pointer with a name"),
|
||||||
LocalKind::Var => "local variable ",
|
LocalKind::Var => "local variable ",
|
||||||
LocalKind::Arg
|
LocalKind::Arg
|
||||||
if !self.mir.upvar_decls.is_empty()
|
if !self.upvars.is_empty()
|
||||||
&& local == Local::new(1) => {
|
&& local == Local::new(1) => {
|
||||||
"variable captured by `move` "
|
"variable captured by `move` "
|
||||||
}
|
}
|
||||||
|
@ -1632,11 +1632,11 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
match proj.elem {
|
match proj.elem {
|
||||||
ProjectionElem::Deref => {
|
ProjectionElem::Deref => {
|
||||||
let upvar_field_projection =
|
let upvar_field_projection =
|
||||||
place.is_upvar_field_projection(self.mir, &self.infcx.tcx);
|
self.is_upvar_field_projection(place);
|
||||||
if let Some(field) = upvar_field_projection {
|
if let Some(field) = upvar_field_projection {
|
||||||
let var_index = field.index();
|
let var_index = field.index();
|
||||||
let name = self.mir.upvar_decls[var_index].debug_name.to_string();
|
let name = self.upvars[var_index].name.to_string();
|
||||||
if self.mir.upvar_decls[var_index].by_ref {
|
if self.upvars[var_index].by_ref {
|
||||||
buf.push_str(&name);
|
buf.push_str(&name);
|
||||||
} else {
|
} else {
|
||||||
buf.push_str(&format!("*{}", &name));
|
buf.push_str(&format!("*{}", &name));
|
||||||
|
@ -1694,10 +1694,10 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
autoderef = true;
|
autoderef = true;
|
||||||
|
|
||||||
let upvar_field_projection =
|
let upvar_field_projection =
|
||||||
place.is_upvar_field_projection(self.mir, &self.infcx.tcx);
|
self.is_upvar_field_projection(place);
|
||||||
if let Some(field) = upvar_field_projection {
|
if let Some(field) = upvar_field_projection {
|
||||||
let var_index = field.index();
|
let var_index = field.index();
|
||||||
let name = self.mir.upvar_decls[var_index].debug_name.to_string();
|
let name = self.upvars[var_index].name.to_string();
|
||||||
buf.push_str(&name);
|
buf.push_str(&name);
|
||||||
} else {
|
} else {
|
||||||
let field_name = self.describe_field(&proj.base, field);
|
let field_name = self.describe_field(&proj.base, field);
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
//! This query borrow-checks the MIR to (further) ensure it is not broken.
|
//! This query borrow-checks the MIR to (further) ensure it is not broken.
|
||||||
|
|
||||||
use crate::borrow_check::nll::region_infer::RegionInferenceContext;
|
use crate::borrow_check::nll::region_infer::RegionInferenceContext;
|
||||||
use rustc::hir;
|
use rustc::hir::{self, HirId};
|
||||||
use rustc::hir::Node;
|
use rustc::hir::Node;
|
||||||
use rustc::hir::def_id::DefId;
|
use rustc::hir::def_id::DefId;
|
||||||
use rustc::infer::InferCtxt;
|
use rustc::infer::InferCtxt;
|
||||||
|
@ -27,6 +27,7 @@ use std::collections::BTreeMap;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
use syntax::ast::Name;
|
||||||
use syntax_pos::{Span, DUMMY_SP};
|
use syntax_pos::{Span, DUMMY_SP};
|
||||||
|
|
||||||
use crate::dataflow::indexes::{BorrowIndex, InitIndex, MoveOutIndex, MovePathIndex};
|
use crate::dataflow::indexes::{BorrowIndex, InitIndex, MoveOutIndex, MovePathIndex};
|
||||||
|
@ -63,6 +64,19 @@ mod used_muts;
|
||||||
|
|
||||||
pub(crate) mod nll;
|
pub(crate) mod nll;
|
||||||
|
|
||||||
|
// FIXME(eddyb) perhaps move this somewhere more centrally.
|
||||||
|
#[derive(Debug)]
|
||||||
|
crate struct Upvar {
|
||||||
|
name: Name,
|
||||||
|
|
||||||
|
var_hir_id: HirId,
|
||||||
|
|
||||||
|
/// If true, the capture is behind a reference.
|
||||||
|
by_ref: bool,
|
||||||
|
|
||||||
|
mutability: Mutability,
|
||||||
|
}
|
||||||
|
|
||||||
pub fn provide(providers: &mut Providers<'_>) {
|
pub fn provide(providers: &mut Providers<'_>) {
|
||||||
*providers = Providers {
|
*providers = Providers {
|
||||||
mir_borrowck,
|
mir_borrowck,
|
||||||
|
@ -126,6 +140,36 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
|
||||||
.as_local_hir_id(def_id)
|
.as_local_hir_id(def_id)
|
||||||
.expect("do_mir_borrowck: non-local DefId");
|
.expect("do_mir_borrowck: non-local DefId");
|
||||||
|
|
||||||
|
// Gather the upvars of a closure, if any.
|
||||||
|
let tables = tcx.typeck_tables_of(def_id);
|
||||||
|
let upvars: Vec<_> = tables
|
||||||
|
.upvar_list
|
||||||
|
.get(&def_id)
|
||||||
|
.into_iter()
|
||||||
|
.flatten()
|
||||||
|
.map(|upvar_id| {
|
||||||
|
let var_hir_id = upvar_id.var_path.hir_id;
|
||||||
|
let var_node_id = tcx.hir().hir_to_node_id(var_hir_id);
|
||||||
|
let capture = tables.upvar_capture(*upvar_id);
|
||||||
|
let by_ref = match capture {
|
||||||
|
ty::UpvarCapture::ByValue => false,
|
||||||
|
ty::UpvarCapture::ByRef(..) => true,
|
||||||
|
};
|
||||||
|
let mut upvar = Upvar {
|
||||||
|
name: tcx.hir().name(var_node_id),
|
||||||
|
var_hir_id,
|
||||||
|
by_ref,
|
||||||
|
mutability: Mutability::Not,
|
||||||
|
};
|
||||||
|
let bm = *tables.pat_binding_modes().get(var_hir_id)
|
||||||
|
.expect("missing binding mode");
|
||||||
|
if bm == ty::BindByValue(hir::MutMutable) {
|
||||||
|
upvar.mutability = Mutability::Mut;
|
||||||
|
}
|
||||||
|
upvar
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
// Replace all regions with fresh inference variables. This
|
// Replace all regions with fresh inference variables. This
|
||||||
// requires first making our own copy of the MIR. This copy will
|
// requires first making our own copy of the MIR. This copy will
|
||||||
// be modified (in place) to contain non-lexical lifetimes. It
|
// be modified (in place) to contain non-lexical lifetimes. It
|
||||||
|
@ -168,6 +212,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
|
||||||
def_id,
|
def_id,
|
||||||
free_regions,
|
free_regions,
|
||||||
mir,
|
mir,
|
||||||
|
&upvars,
|
||||||
location_table,
|
location_table,
|
||||||
param_env,
|
param_env,
|
||||||
&mut flow_inits,
|
&mut flow_inits,
|
||||||
|
@ -240,6 +285,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
|
||||||
used_mut_upvars: SmallVec::new(),
|
used_mut_upvars: SmallVec::new(),
|
||||||
borrow_set,
|
borrow_set,
|
||||||
dominators,
|
dominators,
|
||||||
|
upvars,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut state = Flows::new(
|
let mut state = Flows::new(
|
||||||
|
@ -475,6 +521,9 @@ pub struct MirBorrowckCtxt<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
|
||||||
|
|
||||||
/// Dominators for MIR
|
/// Dominators for MIR
|
||||||
dominators: Dominators<BasicBlock>,
|
dominators: Dominators<BasicBlock>,
|
||||||
|
|
||||||
|
/// Information about upvars not necessarily preserved in types or MIR
|
||||||
|
upvars: Vec<Upvar>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that:
|
// Check that:
|
||||||
|
@ -1287,8 +1336,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
let propagate_closure_used_mut_place = |this: &mut Self, place: &Place<'tcx>| {
|
let propagate_closure_used_mut_place = |this: &mut Self, place: &Place<'tcx>| {
|
||||||
match *place {
|
match *place {
|
||||||
Place::Projection { .. } => {
|
Place::Projection { .. } => {
|
||||||
if let Some(field) = place.is_upvar_field_projection(
|
if let Some(field) = this.is_upvar_field_projection(place) {
|
||||||
this.mir, &this.infcx.tcx) {
|
|
||||||
this.used_mut_upvars.push(field);
|
this.used_mut_upvars.push(field);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2057,7 +2105,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
place: place @ Place::Projection(_),
|
place: place @ Place::Projection(_),
|
||||||
is_local_mutation_allowed: _,
|
is_local_mutation_allowed: _,
|
||||||
} => {
|
} => {
|
||||||
if let Some(field) = place.is_upvar_field_projection(self.mir, &self.infcx.tcx) {
|
if let Some(field) = self.is_upvar_field_projection(place) {
|
||||||
self.used_mut_upvars.push(field);
|
self.used_mut_upvars.push(field);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2127,13 +2175,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
// Mutably borrowed data is mutable, but only if we have a
|
// Mutably borrowed data is mutable, but only if we have a
|
||||||
// unique path to the `&mut`
|
// unique path to the `&mut`
|
||||||
hir::MutMutable => {
|
hir::MutMutable => {
|
||||||
let mode = match place.is_upvar_field_projection(
|
let mode = match self.is_upvar_field_projection(place) {
|
||||||
self.mir, &self.infcx.tcx)
|
|
||||||
{
|
|
||||||
Some(field)
|
Some(field)
|
||||||
if {
|
if self.upvars[field.index()].by_ref =>
|
||||||
self.mir.upvar_decls[field.index()].by_ref
|
|
||||||
} =>
|
|
||||||
{
|
{
|
||||||
is_local_mutation_allowed
|
is_local_mutation_allowed
|
||||||
}
|
}
|
||||||
|
@ -2173,15 +2217,14 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
| ProjectionElem::ConstantIndex { .. }
|
| ProjectionElem::ConstantIndex { .. }
|
||||||
| ProjectionElem::Subslice { .. }
|
| ProjectionElem::Subslice { .. }
|
||||||
| ProjectionElem::Downcast(..) => {
|
| ProjectionElem::Downcast(..) => {
|
||||||
let upvar_field_projection = place.is_upvar_field_projection(
|
let upvar_field_projection = self.is_upvar_field_projection(place);
|
||||||
self.mir, &self.infcx.tcx);
|
|
||||||
if let Some(field) = upvar_field_projection {
|
if let Some(field) = upvar_field_projection {
|
||||||
let decl = &self.mir.upvar_decls[field.index()];
|
let upvar = &self.upvars[field.index()];
|
||||||
debug!(
|
debug!(
|
||||||
"decl.mutability={:?} local_mutation_is_allowed={:?} place={:?}",
|
"upvar.mutability={:?} local_mutation_is_allowed={:?} place={:?}",
|
||||||
decl, is_local_mutation_allowed, place
|
upvar, is_local_mutation_allowed, place
|
||||||
);
|
);
|
||||||
match (decl.mutability, is_local_mutation_allowed) {
|
match (upvar.mutability, is_local_mutation_allowed) {
|
||||||
(Mutability::Not, LocalMutationIsAllowed::No)
|
(Mutability::Not, LocalMutationIsAllowed::No)
|
||||||
| (Mutability::Not, LocalMutationIsAllowed::ExceptUpvars) => {
|
| (Mutability::Not, LocalMutationIsAllowed::ExceptUpvars) => {
|
||||||
Err(place)
|
Err(place)
|
||||||
|
@ -2229,6 +2272,41 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// If `place` is a field projection, and the field is being projected from a closure type,
|
||||||
|
/// then returns the index of the field being projected. Note that this closure will always
|
||||||
|
/// be `self` in the current MIR, because that is the only time we directly access the fields
|
||||||
|
/// of a closure type.
|
||||||
|
pub fn is_upvar_field_projection(&self, place: &Place<'tcx>) -> Option<Field> {
|
||||||
|
let (place, by_ref) = if let Place::Projection(ref proj) = place {
|
||||||
|
if let ProjectionElem::Deref = proj.elem {
|
||||||
|
(&proj.base, true)
|
||||||
|
} else {
|
||||||
|
(place, false)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
(place, false)
|
||||||
|
};
|
||||||
|
|
||||||
|
match place {
|
||||||
|
Place::Projection(ref proj) => match proj.elem {
|
||||||
|
ProjectionElem::Field(field, _ty) => {
|
||||||
|
let tcx = self.infcx.tcx;
|
||||||
|
let base_ty = proj.base.ty(self.mir, tcx).ty;
|
||||||
|
|
||||||
|
if (base_ty.is_closure() || base_ty.is_generator()) &&
|
||||||
|
(!by_ref || self.upvars[field.index()].by_ref)
|
||||||
|
{
|
||||||
|
Some(field)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||||
|
|
|
@ -256,7 +256,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
|
||||||
let origin = Origin::Mir;
|
let origin = Origin::Mir;
|
||||||
debug!("report: original_path={:?} span={:?}, kind={:?} \
|
debug!("report: original_path={:?} span={:?}, kind={:?} \
|
||||||
original_path.is_upvar_field_projection={:?}", original_path, span, kind,
|
original_path.is_upvar_field_projection={:?}", original_path, span, kind,
|
||||||
original_path.is_upvar_field_projection(self.mir, &self.infcx.tcx));
|
self.is_upvar_field_projection(original_path));
|
||||||
(
|
(
|
||||||
match kind {
|
match kind {
|
||||||
IllegalMoveOriginKind::Static => {
|
IllegalMoveOriginKind::Static => {
|
||||||
|
@ -269,8 +269,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
|
||||||
let ty = place.ty(self.mir, self.infcx.tcx).ty;
|
let ty = place.ty(self.mir, self.infcx.tcx).ty;
|
||||||
let is_upvar_field_projection =
|
let is_upvar_field_projection =
|
||||||
self.prefixes(&original_path, PrefixSet::All)
|
self.prefixes(&original_path, PrefixSet::All)
|
||||||
.any(|p| p.is_upvar_field_projection(self.mir, &self.infcx.tcx)
|
.any(|p| self.is_upvar_field_projection(p).is_some());
|
||||||
.is_some());
|
|
||||||
debug!("report: ty={:?}", ty);
|
debug!("report: ty={:?}", ty);
|
||||||
match ty.sty {
|
match ty.sty {
|
||||||
ty::Array(..) | ty::Slice(..) =>
|
ty::Array(..) | ty::Slice(..) =>
|
||||||
|
@ -278,7 +277,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
|
||||||
span, ty, None, origin
|
span, ty, None, origin
|
||||||
),
|
),
|
||||||
ty::Closure(def_id, closure_substs)
|
ty::Closure(def_id, closure_substs)
|
||||||
if !self.mir.upvar_decls.is_empty() && is_upvar_field_projection
|
if def_id == self.mir_def_id && is_upvar_field_projection
|
||||||
=> {
|
=> {
|
||||||
let closure_kind_ty =
|
let closure_kind_ty =
|
||||||
closure_substs.closure_kind_ty(def_id, self.infcx.tcx);
|
closure_substs.closure_kind_ty(def_id, self.infcx.tcx);
|
||||||
|
@ -303,11 +302,8 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
|
||||||
span, place_description, origin);
|
span, place_description, origin);
|
||||||
|
|
||||||
for prefix in self.prefixes(&original_path, PrefixSet::All) {
|
for prefix in self.prefixes(&original_path, PrefixSet::All) {
|
||||||
if let Some(field) = prefix.is_upvar_field_projection(
|
if let Some(field) = self.is_upvar_field_projection(prefix) {
|
||||||
self.mir, &self.infcx.tcx) {
|
let upvar_hir_id = self.upvars[field.index()].var_hir_id;
|
||||||
let upvar_decl = &self.mir.upvar_decls[field.index()];
|
|
||||||
let upvar_hir_id =
|
|
||||||
upvar_decl.var_hir_id.assert_crate_local();
|
|
||||||
let upvar_span = self.infcx.tcx.hir().span_by_hir_id(
|
let upvar_span = self.infcx.tcx.hir().span_by_hir_id(
|
||||||
upvar_hir_id);
|
upvar_hir_id);
|
||||||
diag.span_label(upvar_span, "captured outer variable");
|
diag.span_label(upvar_span, "captured outer variable");
|
||||||
|
|
|
@ -68,10 +68,10 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
|
||||||
));
|
));
|
||||||
|
|
||||||
item_msg = format!("`{}`", access_place_desc.unwrap());
|
item_msg = format!("`{}`", access_place_desc.unwrap());
|
||||||
if access_place.is_upvar_field_projection(self.mir, &self.infcx.tcx).is_some() {
|
if self.is_upvar_field_projection(access_place).is_some() {
|
||||||
reason = ", as it is not declared as mutable".to_string();
|
reason = ", as it is not declared as mutable".to_string();
|
||||||
} else {
|
} else {
|
||||||
let name = self.mir.upvar_decls[upvar_index.index()].debug_name;
|
let name = self.upvars[upvar_index.index()].name;
|
||||||
reason = format!(", as `{}` is not declared as mutable", name);
|
reason = format!(", as `{}` is not declared as mutable", name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -81,15 +81,14 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
|
||||||
elem: ProjectionElem::Deref,
|
elem: ProjectionElem::Deref,
|
||||||
}) => {
|
}) => {
|
||||||
if *base == Place::Base(PlaceBase::Local(Local::new(1))) &&
|
if *base == Place::Base(PlaceBase::Local(Local::new(1))) &&
|
||||||
!self.mir.upvar_decls.is_empty() {
|
!self.upvars.is_empty() {
|
||||||
item_msg = format!("`{}`", access_place_desc.unwrap());
|
item_msg = format!("`{}`", access_place_desc.unwrap());
|
||||||
debug_assert!(self.mir.local_decls[Local::new(1)].ty.is_region_ptr());
|
debug_assert!(self.mir.local_decls[Local::new(1)].ty.is_region_ptr());
|
||||||
debug_assert!(is_closure_or_generator(
|
debug_assert!(is_closure_or_generator(
|
||||||
the_place_err.ty(self.mir, self.infcx.tcx).ty
|
the_place_err.ty(self.mir, self.infcx.tcx).ty
|
||||||
));
|
));
|
||||||
|
|
||||||
reason = if access_place.is_upvar_field_projection(self.mir,
|
reason = if self.is_upvar_field_projection(access_place).is_some() {
|
||||||
&self.infcx.tcx).is_some() {
|
|
||||||
", as it is a captured variable in a `Fn` closure".to_string()
|
", as it is a captured variable in a `Fn` closure".to_string()
|
||||||
} else {
|
} else {
|
||||||
", as `Fn` closures cannot mutate their captured variables".to_string()
|
", as `Fn` closures cannot mutate their captured variables".to_string()
|
||||||
|
@ -309,9 +308,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
|
||||||
|
|
||||||
err.span_label(span, format!("cannot {ACT}", ACT = act));
|
err.span_label(span, format!("cannot {ACT}", ACT = act));
|
||||||
|
|
||||||
let upvar_hir_id = self.mir.upvar_decls[upvar_index.index()]
|
let upvar_hir_id = self.upvars[upvar_index.index()].var_hir_id;
|
||||||
.var_hir_id
|
|
||||||
.assert_crate_local();
|
|
||||||
let upvar_node_id = self.infcx.tcx.hir().hir_to_node_id(upvar_hir_id);
|
let upvar_node_id = self.infcx.tcx.hir().hir_to_node_id(upvar_hir_id);
|
||||||
if let Some(Node::Binding(pat)) = self.infcx.tcx.hir().find(upvar_node_id) {
|
if let Some(Node::Binding(pat)) = self.infcx.tcx.hir().find(upvar_node_id) {
|
||||||
if let hir::PatKind::Binding(
|
if let hir::PatKind::Binding(
|
||||||
|
@ -452,7 +449,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
|
||||||
base,
|
base,
|
||||||
elem: ProjectionElem::Deref,
|
elem: ProjectionElem::Deref,
|
||||||
}) if *base == Place::Base(PlaceBase::Local(Local::new(1))) &&
|
}) if *base == Place::Base(PlaceBase::Local(Local::new(1))) &&
|
||||||
!self.mir.upvar_decls.is_empty() =>
|
!self.upvars.is_empty() =>
|
||||||
{
|
{
|
||||||
err.span_label(span, format!("cannot {ACT}", ACT = act));
|
err.span_label(span, format!("cannot {ACT}", ACT = act));
|
||||||
err.span_help(
|
err.span_help(
|
||||||
|
|
|
@ -298,6 +298,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
let (category, from_closure, span, region_name) =
|
let (category, from_closure, span, region_name) =
|
||||||
self.nonlexical_regioncx.free_region_constraint_info(
|
self.nonlexical_regioncx.free_region_constraint_info(
|
||||||
self.mir,
|
self.mir,
|
||||||
|
&self.upvars,
|
||||||
self.mir_def_id,
|
self.mir_def_id,
|
||||||
self.infcx,
|
self.infcx,
|
||||||
borrow_region_vid,
|
borrow_region_vid,
|
||||||
|
|
|
@ -8,6 +8,7 @@ use crate::dataflow::move_paths::MoveData;
|
||||||
use crate::dataflow::FlowAtLocation;
|
use crate::dataflow::FlowAtLocation;
|
||||||
use crate::dataflow::MaybeInitializedPlaces;
|
use crate::dataflow::MaybeInitializedPlaces;
|
||||||
use crate::transform::MirSource;
|
use crate::transform::MirSource;
|
||||||
|
use crate::borrow_check::Upvar;
|
||||||
use rustc::hir::def_id::DefId;
|
use rustc::hir::def_id::DefId;
|
||||||
use rustc::infer::InferCtxt;
|
use rustc::infer::InferCtxt;
|
||||||
use rustc::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, Mir};
|
use rustc::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, Mir};
|
||||||
|
@ -72,6 +73,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
|
||||||
def_id: DefId,
|
def_id: DefId,
|
||||||
universal_regions: UniversalRegions<'tcx>,
|
universal_regions: UniversalRegions<'tcx>,
|
||||||
mir: &Mir<'tcx>,
|
mir: &Mir<'tcx>,
|
||||||
|
upvars: &[Upvar],
|
||||||
location_table: &LocationTable,
|
location_table: &LocationTable,
|
||||||
param_env: ty::ParamEnv<'gcx>,
|
param_env: ty::ParamEnv<'gcx>,
|
||||||
flow_inits: &mut FlowAtLocation<'tcx, MaybeInitializedPlaces<'cx, 'gcx, 'tcx>>,
|
flow_inits: &mut FlowAtLocation<'tcx, MaybeInitializedPlaces<'cx, 'gcx, 'tcx>>,
|
||||||
|
@ -187,7 +189,8 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
|
||||||
});
|
});
|
||||||
|
|
||||||
// Solve the region constraints.
|
// Solve the region constraints.
|
||||||
let closure_region_requirements = regioncx.solve(infcx, &mir, def_id, errors_buffer);
|
let closure_region_requirements =
|
||||||
|
regioncx.solve(infcx, &mir, upvars, def_id, errors_buffer);
|
||||||
|
|
||||||
// Dump MIR results into a file, if that is enabled. This let us
|
// Dump MIR results into a file, if that is enabled. This let us
|
||||||
// write unit-tests, as well as helping with debugging.
|
// write unit-tests, as well as helping with debugging.
|
||||||
|
|
|
@ -4,6 +4,7 @@ use crate::borrow_check::nll::type_check::Locations;
|
||||||
use crate::borrow_check::nll::universal_regions::DefiningTy;
|
use crate::borrow_check::nll::universal_regions::DefiningTy;
|
||||||
use crate::borrow_check::nll::ConstraintDescription;
|
use crate::borrow_check::nll::ConstraintDescription;
|
||||||
use crate::util::borrowck_errors::{BorrowckErrors, Origin};
|
use crate::util::borrowck_errors::{BorrowckErrors, Origin};
|
||||||
|
use crate::borrow_check::Upvar;
|
||||||
use rustc::hir::def_id::DefId;
|
use rustc::hir::def_id::DefId;
|
||||||
use rustc::infer::error_reporting::nice_region_error::NiceRegionError;
|
use rustc::infer::error_reporting::nice_region_error::NiceRegionError;
|
||||||
use rustc::infer::InferCtxt;
|
use rustc::infer::InferCtxt;
|
||||||
|
@ -237,6 +238,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||||
pub(super) fn report_error(
|
pub(super) fn report_error(
|
||||||
&self,
|
&self,
|
||||||
mir: &Mir<'tcx>,
|
mir: &Mir<'tcx>,
|
||||||
|
upvars: &[Upvar],
|
||||||
infcx: &InferCtxt<'_, '_, 'tcx>,
|
infcx: &InferCtxt<'_, '_, 'tcx>,
|
||||||
mir_def_id: DefId,
|
mir_def_id: DefId,
|
||||||
fr: RegionVid,
|
fr: RegionVid,
|
||||||
|
@ -273,6 +275,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||||
(ConstraintCategory::Return, true, false) if self.is_closure_fn_mut(infcx, fr) => {
|
(ConstraintCategory::Return, true, false) if self.is_closure_fn_mut(infcx, fr) => {
|
||||||
self.report_fnmut_error(
|
self.report_fnmut_error(
|
||||||
mir,
|
mir,
|
||||||
|
upvars,
|
||||||
infcx,
|
infcx,
|
||||||
mir_def_id,
|
mir_def_id,
|
||||||
fr,
|
fr,
|
||||||
|
@ -284,6 +287,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||||
(ConstraintCategory::Assignment, true, false)
|
(ConstraintCategory::Assignment, true, false)
|
||||||
| (ConstraintCategory::CallArgument, true, false) => self.report_escaping_data_error(
|
| (ConstraintCategory::CallArgument, true, false) => self.report_escaping_data_error(
|
||||||
mir,
|
mir,
|
||||||
|
upvars,
|
||||||
infcx,
|
infcx,
|
||||||
mir_def_id,
|
mir_def_id,
|
||||||
fr,
|
fr,
|
||||||
|
@ -294,6 +298,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||||
),
|
),
|
||||||
_ => self.report_general_error(
|
_ => self.report_general_error(
|
||||||
mir,
|
mir,
|
||||||
|
upvars,
|
||||||
infcx,
|
infcx,
|
||||||
mir_def_id,
|
mir_def_id,
|
||||||
fr,
|
fr,
|
||||||
|
@ -353,6 +358,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||||
fn report_fnmut_error(
|
fn report_fnmut_error(
|
||||||
&self,
|
&self,
|
||||||
mir: &Mir<'tcx>,
|
mir: &Mir<'tcx>,
|
||||||
|
upvars: &[Upvar],
|
||||||
infcx: &InferCtxt<'_, '_, 'tcx>,
|
infcx: &InferCtxt<'_, '_, 'tcx>,
|
||||||
mir_def_id: DefId,
|
mir_def_id: DefId,
|
||||||
_fr: RegionVid,
|
_fr: RegionVid,
|
||||||
|
@ -377,7 +383,9 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||||
|
|
||||||
diag.span_label(span, message);
|
diag.span_label(span, message);
|
||||||
|
|
||||||
match self.give_region_a_name(infcx, mir, mir_def_id, outlived_fr, &mut 1).unwrap().source {
|
match self.give_region_a_name(infcx, mir, upvars, mir_def_id, outlived_fr, &mut 1)
|
||||||
|
.unwrap().source
|
||||||
|
{
|
||||||
RegionNameSource::NamedEarlyBoundRegion(fr_span)
|
RegionNameSource::NamedEarlyBoundRegion(fr_span)
|
||||||
| RegionNameSource::NamedFreeRegion(fr_span)
|
| RegionNameSource::NamedFreeRegion(fr_span)
|
||||||
| RegionNameSource::SynthesizedFreeEnvRegion(fr_span, _)
|
| RegionNameSource::SynthesizedFreeEnvRegion(fr_span, _)
|
||||||
|
@ -415,6 +423,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||||
fn report_escaping_data_error(
|
fn report_escaping_data_error(
|
||||||
&self,
|
&self,
|
||||||
mir: &Mir<'tcx>,
|
mir: &Mir<'tcx>,
|
||||||
|
upvars: &[Upvar],
|
||||||
infcx: &InferCtxt<'_, '_, 'tcx>,
|
infcx: &InferCtxt<'_, '_, 'tcx>,
|
||||||
mir_def_id: DefId,
|
mir_def_id: DefId,
|
||||||
fr: RegionVid,
|
fr: RegionVid,
|
||||||
|
@ -423,9 +432,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||||
span: Span,
|
span: Span,
|
||||||
errors_buffer: &mut Vec<Diagnostic>,
|
errors_buffer: &mut Vec<Diagnostic>,
|
||||||
) {
|
) {
|
||||||
let fr_name_and_span = self.get_var_name_and_span_for_region(infcx.tcx, mir, fr);
|
let fr_name_and_span =
|
||||||
|
self.get_var_name_and_span_for_region(infcx.tcx, mir, upvars, fr);
|
||||||
let outlived_fr_name_and_span =
|
let outlived_fr_name_and_span =
|
||||||
self.get_var_name_and_span_for_region(infcx.tcx, mir, outlived_fr);
|
self.get_var_name_and_span_for_region(infcx.tcx, mir, upvars, outlived_fr);
|
||||||
|
|
||||||
let escapes_from = match self.universal_regions.defining_ty {
|
let escapes_from = match self.universal_regions.defining_ty {
|
||||||
DefiningTy::Closure(..) => "closure",
|
DefiningTy::Closure(..) => "closure",
|
||||||
|
@ -442,6 +452,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||||
{
|
{
|
||||||
return self.report_general_error(
|
return self.report_general_error(
|
||||||
mir,
|
mir,
|
||||||
|
upvars,
|
||||||
infcx,
|
infcx,
|
||||||
mir_def_id,
|
mir_def_id,
|
||||||
fr,
|
fr,
|
||||||
|
@ -504,6 +515,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||||
fn report_general_error(
|
fn report_general_error(
|
||||||
&self,
|
&self,
|
||||||
mir: &Mir<'tcx>,
|
mir: &Mir<'tcx>,
|
||||||
|
upvars: &[Upvar],
|
||||||
infcx: &InferCtxt<'_, '_, 'tcx>,
|
infcx: &InferCtxt<'_, '_, 'tcx>,
|
||||||
mir_def_id: DefId,
|
mir_def_id: DefId,
|
||||||
fr: RegionVid,
|
fr: RegionVid,
|
||||||
|
@ -520,10 +532,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||||
);
|
);
|
||||||
|
|
||||||
let counter = &mut 1;
|
let counter = &mut 1;
|
||||||
let fr_name = self.give_region_a_name(infcx, mir, mir_def_id, fr, counter).unwrap();
|
let fr_name = self.give_region_a_name(infcx, mir, upvars, mir_def_id, fr, counter).unwrap();
|
||||||
fr_name.highlight_region_name(&mut diag);
|
fr_name.highlight_region_name(&mut diag);
|
||||||
let outlived_fr_name =
|
let outlived_fr_name =
|
||||||
self.give_region_a_name(infcx, mir, mir_def_id, outlived_fr, counter).unwrap();
|
self.give_region_a_name(infcx, mir, upvars, mir_def_id, outlived_fr, counter).unwrap();
|
||||||
outlived_fr_name.highlight_region_name(&mut diag);
|
outlived_fr_name.highlight_region_name(&mut diag);
|
||||||
|
|
||||||
let mir_def_name = if infcx.tcx.is_closure(mir_def_id) {
|
let mir_def_name = if infcx.tcx.is_closure(mir_def_id) {
|
||||||
|
@ -656,6 +668,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||||
crate fn free_region_constraint_info(
|
crate fn free_region_constraint_info(
|
||||||
&self,
|
&self,
|
||||||
mir: &Mir<'tcx>,
|
mir: &Mir<'tcx>,
|
||||||
|
upvars: &[Upvar],
|
||||||
mir_def_id: DefId,
|
mir_def_id: DefId,
|
||||||
infcx: &InferCtxt<'_, '_, 'tcx>,
|
infcx: &InferCtxt<'_, '_, 'tcx>,
|
||||||
borrow_region: RegionVid,
|
borrow_region: RegionVid,
|
||||||
|
@ -664,7 +677,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||||
let (category, from_closure, span) =
|
let (category, from_closure, span) =
|
||||||
self.best_blame_constraint(mir, borrow_region, |r| r == outlived_region);
|
self.best_blame_constraint(mir, borrow_region, |r| r == outlived_region);
|
||||||
let outlived_fr_name =
|
let outlived_fr_name =
|
||||||
self.give_region_a_name(infcx, mir, mir_def_id, outlived_region, &mut 1);
|
self.give_region_a_name(infcx, mir, upvars, mir_def_id, outlived_region, &mut 1);
|
||||||
(category, from_closure, span, outlived_fr_name)
|
(category, from_closure, span, outlived_fr_name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@ use std::fmt::{self, Display};
|
||||||
use crate::borrow_check::nll::region_infer::RegionInferenceContext;
|
use crate::borrow_check::nll::region_infer::RegionInferenceContext;
|
||||||
use crate::borrow_check::nll::universal_regions::DefiningTy;
|
use crate::borrow_check::nll::universal_regions::DefiningTy;
|
||||||
use crate::borrow_check::nll::ToRegionVid;
|
use crate::borrow_check::nll::ToRegionVid;
|
||||||
|
use crate::borrow_check::Upvar;
|
||||||
use rustc::hir;
|
use rustc::hir;
|
||||||
use rustc::hir::def_id::DefId;
|
use rustc::hir::def_id::DefId;
|
||||||
use rustc::infer::InferCtxt;
|
use rustc::infer::InferCtxt;
|
||||||
|
@ -144,6 +145,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||||
&self,
|
&self,
|
||||||
infcx: &InferCtxt<'_, '_, 'tcx>,
|
infcx: &InferCtxt<'_, '_, 'tcx>,
|
||||||
mir: &Mir<'tcx>,
|
mir: &Mir<'tcx>,
|
||||||
|
upvars: &[Upvar],
|
||||||
mir_def_id: DefId,
|
mir_def_id: DefId,
|
||||||
fr: RegionVid,
|
fr: RegionVid,
|
||||||
counter: &mut usize,
|
counter: &mut usize,
|
||||||
|
@ -160,7 +162,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||||
})
|
})
|
||||||
.or_else(|| {
|
.or_else(|| {
|
||||||
self.give_name_if_anonymous_region_appears_in_upvars(
|
self.give_name_if_anonymous_region_appears_in_upvars(
|
||||||
infcx.tcx, mir, fr, counter,
|
infcx.tcx, upvars, fr, counter,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.or_else(|| {
|
.or_else(|| {
|
||||||
|
@ -639,13 +641,13 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||||
fn give_name_if_anonymous_region_appears_in_upvars(
|
fn give_name_if_anonymous_region_appears_in_upvars(
|
||||||
&self,
|
&self,
|
||||||
tcx: TyCtxt<'_, '_, 'tcx>,
|
tcx: TyCtxt<'_, '_, 'tcx>,
|
||||||
mir: &Mir<'tcx>,
|
upvars: &[Upvar],
|
||||||
fr: RegionVid,
|
fr: RegionVid,
|
||||||
counter: &mut usize,
|
counter: &mut usize,
|
||||||
) -> Option<RegionName> {
|
) -> Option<RegionName> {
|
||||||
let upvar_index = self.get_upvar_index_for_region(tcx, fr)?;
|
let upvar_index = self.get_upvar_index_for_region(tcx, fr)?;
|
||||||
let (upvar_name, upvar_span) =
|
let (upvar_name, upvar_span) =
|
||||||
self.get_upvar_name_and_span_for_region(tcx, mir, upvar_index);
|
self.get_upvar_name_and_span_for_region(tcx, upvars, upvar_index);
|
||||||
let region_name = self.synthesize_region_name(counter);
|
let region_name = self.synthesize_region_name(counter);
|
||||||
|
|
||||||
Some(RegionName {
|
Some(RegionName {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use crate::borrow_check::nll::region_infer::RegionInferenceContext;
|
use crate::borrow_check::nll::region_infer::RegionInferenceContext;
|
||||||
use crate::borrow_check::nll::ToRegionVid;
|
use crate::borrow_check::nll::ToRegionVid;
|
||||||
|
use crate::borrow_check::Upvar;
|
||||||
use rustc::mir::{Local, Mir};
|
use rustc::mir::{Local, Mir};
|
||||||
use rustc::ty::{RegionVid, TyCtxt};
|
use rustc::ty::{RegionVid, TyCtxt};
|
||||||
use rustc_data_structures::indexed_vec::Idx;
|
use rustc_data_structures::indexed_vec::Idx;
|
||||||
|
@ -11,6 +12,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||||
&self,
|
&self,
|
||||||
tcx: TyCtxt<'_, '_, 'tcx>,
|
tcx: TyCtxt<'_, '_, 'tcx>,
|
||||||
mir: &Mir<'tcx>,
|
mir: &Mir<'tcx>,
|
||||||
|
upvars: &[Upvar],
|
||||||
fr: RegionVid,
|
fr: RegionVid,
|
||||||
) -> Option<(Option<Symbol>, Span)> {
|
) -> Option<(Option<Symbol>, Span)> {
|
||||||
debug!("get_var_name_and_span_for_region(fr={:?})", fr);
|
debug!("get_var_name_and_span_for_region(fr={:?})", fr);
|
||||||
|
@ -19,7 +21,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||||
debug!("get_var_name_and_span_for_region: attempting upvar");
|
debug!("get_var_name_and_span_for_region: attempting upvar");
|
||||||
self.get_upvar_index_for_region(tcx, fr)
|
self.get_upvar_index_for_region(tcx, fr)
|
||||||
.map(|index| {
|
.map(|index| {
|
||||||
let (name, span) = self.get_upvar_name_and_span_for_region(tcx, mir, index);
|
let (name, span) =
|
||||||
|
self.get_upvar_name_and_span_for_region(tcx, upvars, index);
|
||||||
(Some(name), span)
|
(Some(name), span)
|
||||||
})
|
})
|
||||||
.or_else(|| {
|
.or_else(|| {
|
||||||
|
@ -67,10 +70,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||||
crate fn get_upvar_name_and_span_for_region(
|
crate fn get_upvar_name_and_span_for_region(
|
||||||
&self,
|
&self,
|
||||||
tcx: TyCtxt<'_, '_, 'tcx>,
|
tcx: TyCtxt<'_, '_, 'tcx>,
|
||||||
mir: &Mir<'tcx>,
|
upvars: &[Upvar],
|
||||||
upvar_index: usize,
|
upvar_index: usize,
|
||||||
) -> (Symbol, Span) {
|
) -> (Symbol, Span) {
|
||||||
let upvar_hir_id = mir.upvar_decls[upvar_index].var_hir_id.assert_crate_local();
|
let upvar_hir_id = upvars[upvar_index].var_hir_id;
|
||||||
debug!("get_upvar_name_and_span_for_region: upvar_hir_id={:?}", upvar_hir_id);
|
debug!("get_upvar_name_and_span_for_region: upvar_hir_id={:?}", upvar_hir_id);
|
||||||
|
|
||||||
let upvar_name = tcx.hir().name_by_hir_id(upvar_hir_id);
|
let upvar_name = tcx.hir().name_by_hir_id(upvar_hir_id);
|
||||||
|
|
|
@ -4,6 +4,7 @@ use crate::borrow_check::nll::constraints::{ConstraintSccIndex, ConstraintSet, O
|
||||||
use crate::borrow_check::nll::region_infer::values::{
|
use crate::borrow_check::nll::region_infer::values::{
|
||||||
PlaceholderIndices, RegionElement, ToElementIndex
|
PlaceholderIndices, RegionElement, ToElementIndex
|
||||||
};
|
};
|
||||||
|
use crate::borrow_check::Upvar;
|
||||||
use crate::borrow_check::nll::type_check::free_region_relations::UniversalRegionRelations;
|
use crate::borrow_check::nll::type_check::free_region_relations::UniversalRegionRelations;
|
||||||
use crate::borrow_check::nll::type_check::Locations;
|
use crate::borrow_check::nll::type_check::Locations;
|
||||||
use rustc::hir::def_id::DefId;
|
use rustc::hir::def_id::DefId;
|
||||||
|
@ -400,6 +401,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||||
&mut self,
|
&mut self,
|
||||||
infcx: &InferCtxt<'_, 'gcx, 'tcx>,
|
infcx: &InferCtxt<'_, 'gcx, 'tcx>,
|
||||||
mir: &Mir<'tcx>,
|
mir: &Mir<'tcx>,
|
||||||
|
upvars: &[Upvar],
|
||||||
mir_def_id: DefId,
|
mir_def_id: DefId,
|
||||||
errors_buffer: &mut Vec<Diagnostic>,
|
errors_buffer: &mut Vec<Diagnostic>,
|
||||||
) -> Option<ClosureRegionRequirements<'gcx>> {
|
) -> Option<ClosureRegionRequirements<'gcx>> {
|
||||||
|
@ -407,7 +409,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||||
infcx.tcx.sess.time_extended(),
|
infcx.tcx.sess.time_extended(),
|
||||||
Some(infcx.tcx.sess),
|
Some(infcx.tcx.sess),
|
||||||
&format!("solve_nll_region_constraints({:?})", mir_def_id),
|
&format!("solve_nll_region_constraints({:?})", mir_def_id),
|
||||||
|| self.solve_inner(infcx, mir, mir_def_id, errors_buffer),
|
|| self.solve_inner(infcx, mir, upvars, mir_def_id, errors_buffer),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -415,6 +417,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||||
&mut self,
|
&mut self,
|
||||||
infcx: &InferCtxt<'_, 'gcx, 'tcx>,
|
infcx: &InferCtxt<'_, 'gcx, 'tcx>,
|
||||||
mir: &Mir<'tcx>,
|
mir: &Mir<'tcx>,
|
||||||
|
upvars: &[Upvar],
|
||||||
mir_def_id: DefId,
|
mir_def_id: DefId,
|
||||||
errors_buffer: &mut Vec<Diagnostic>,
|
errors_buffer: &mut Vec<Diagnostic>,
|
||||||
) -> Option<ClosureRegionRequirements<'gcx>> {
|
) -> Option<ClosureRegionRequirements<'gcx>> {
|
||||||
|
@ -442,6 +445,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||||
self.check_universal_regions(
|
self.check_universal_regions(
|
||||||
infcx,
|
infcx,
|
||||||
mir,
|
mir,
|
||||||
|
upvars,
|
||||||
mir_def_id,
|
mir_def_id,
|
||||||
outlives_requirements.as_mut(),
|
outlives_requirements.as_mut(),
|
||||||
errors_buffer,
|
errors_buffer,
|
||||||
|
@ -1102,6 +1106,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||||
&self,
|
&self,
|
||||||
infcx: &InferCtxt<'_, 'gcx, 'tcx>,
|
infcx: &InferCtxt<'_, 'gcx, 'tcx>,
|
||||||
mir: &Mir<'tcx>,
|
mir: &Mir<'tcx>,
|
||||||
|
upvars: &[Upvar],
|
||||||
mir_def_id: DefId,
|
mir_def_id: DefId,
|
||||||
mut propagated_outlives_requirements: Option<&mut Vec<ClosureOutlivesRequirement<'gcx>>>,
|
mut propagated_outlives_requirements: Option<&mut Vec<ClosureOutlivesRequirement<'gcx>>>,
|
||||||
errors_buffer: &mut Vec<Diagnostic>,
|
errors_buffer: &mut Vec<Diagnostic>,
|
||||||
|
@ -1115,6 +1120,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||||
self.check_universal_region(
|
self.check_universal_region(
|
||||||
infcx,
|
infcx,
|
||||||
mir,
|
mir,
|
||||||
|
upvars,
|
||||||
mir_def_id,
|
mir_def_id,
|
||||||
fr,
|
fr,
|
||||||
&mut propagated_outlives_requirements,
|
&mut propagated_outlives_requirements,
|
||||||
|
@ -1145,6 +1151,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||||
&self,
|
&self,
|
||||||
infcx: &InferCtxt<'_, 'gcx, 'tcx>,
|
infcx: &InferCtxt<'_, 'gcx, 'tcx>,
|
||||||
mir: &Mir<'tcx>,
|
mir: &Mir<'tcx>,
|
||||||
|
upvars: &[Upvar],
|
||||||
mir_def_id: DefId,
|
mir_def_id: DefId,
|
||||||
longer_fr: RegionVid,
|
longer_fr: RegionVid,
|
||||||
propagated_outlives_requirements: &mut Option<&mut Vec<ClosureOutlivesRequirement<'gcx>>>,
|
propagated_outlives_requirements: &mut Option<&mut Vec<ClosureOutlivesRequirement<'gcx>>>,
|
||||||
|
@ -1177,6 +1184,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||||
representative,
|
representative,
|
||||||
infcx,
|
infcx,
|
||||||
mir,
|
mir,
|
||||||
|
upvars,
|
||||||
mir_def_id,
|
mir_def_id,
|
||||||
propagated_outlives_requirements,
|
propagated_outlives_requirements,
|
||||||
errors_buffer,
|
errors_buffer,
|
||||||
|
@ -1192,6 +1200,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||||
shorter_fr,
|
shorter_fr,
|
||||||
infcx,
|
infcx,
|
||||||
mir,
|
mir,
|
||||||
|
upvars,
|
||||||
mir_def_id,
|
mir_def_id,
|
||||||
propagated_outlives_requirements,
|
propagated_outlives_requirements,
|
||||||
errors_buffer,
|
errors_buffer,
|
||||||
|
@ -1208,6 +1217,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||||
shorter_fr: RegionVid,
|
shorter_fr: RegionVid,
|
||||||
infcx: &InferCtxt<'_, 'gcx, 'tcx>,
|
infcx: &InferCtxt<'_, 'gcx, 'tcx>,
|
||||||
mir: &Mir<'tcx>,
|
mir: &Mir<'tcx>,
|
||||||
|
upvars: &[Upvar],
|
||||||
mir_def_id: DefId,
|
mir_def_id: DefId,
|
||||||
propagated_outlives_requirements: &mut Option<&mut Vec<ClosureOutlivesRequirement<'gcx>>>,
|
propagated_outlives_requirements: &mut Option<&mut Vec<ClosureOutlivesRequirement<'gcx>>>,
|
||||||
errors_buffer: &mut Vec<Diagnostic>,
|
errors_buffer: &mut Vec<Diagnostic>,
|
||||||
|
@ -1265,7 +1275,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||||
//
|
//
|
||||||
// Note: in this case, we use the unapproximated regions to report the
|
// Note: in this case, we use the unapproximated regions to report the
|
||||||
// error. This gives better error messages in some cases.
|
// error. This gives better error messages in some cases.
|
||||||
self.report_error(mir, infcx, mir_def_id, longer_fr, shorter_fr, errors_buffer);
|
self.report_error(mir, upvars, infcx, mir_def_id, longer_fr, shorter_fr, errors_buffer);
|
||||||
Some(ErrorReported)
|
Some(ErrorReported)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -105,7 +105,7 @@ impl<'tcx> DefiningTy<'tcx> {
|
||||||
/// Returns a list of all the upvar types for this MIR. If this is
|
/// Returns a list of all the upvar types for this MIR. If this is
|
||||||
/// not a closure or generator, there are no upvars, and hence it
|
/// not a closure or generator, there are no upvars, and hence it
|
||||||
/// will be an empty list. The order of types in this list will
|
/// will be an empty list. The order of types in this list will
|
||||||
/// match up with the `upvar_decls` field of `Mir`.
|
/// match up with the upvar order in the HIR, typesystem, and MIR.
|
||||||
pub fn upvar_tys(self, tcx: TyCtxt<'_, '_, 'tcx>) -> impl Iterator<Item = Ty<'tcx>> + 'tcx {
|
pub fn upvar_tys(self, tcx: TyCtxt<'_, '_, 'tcx>) -> impl Iterator<Item = Ty<'tcx>> + 'tcx {
|
||||||
match self {
|
match self {
|
||||||
DefiningTy::Closure(def_id, substs) => Either::Left(substs.upvar_tys(def_id, tcx)),
|
DefiningTy::Closure(def_id, substs) => Either::Left(substs.upvar_tys(def_id, tcx)),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue