make TypeOp implement debug instead of carrying a closure

This allows us to avoid some silly clones etc.
This commit is contained in:
Niko Matsakis 2018-06-07 05:29:25 -04:00
parent e7a9e7aef2
commit 7a641cb145
5 changed files with 96 additions and 98 deletions

View File

@ -12,7 +12,7 @@ use borrow_check::location::{LocationIndex, LocationTable};
use dataflow::indexes::BorrowIndex;
use polonius_engine::AllFacts as PoloniusAllFacts;
use polonius_engine::Atom;
use rustc::ty::RegionVid;
use rustc::ty::{RegionVid, TyCtxt};
use rustc_data_structures::indexed_vec::Idx;
use std::error::Error;
use std::fmt::Debug;

View File

@ -80,63 +80,66 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
let anon_type_map =
self.fully_perform_op(
Locations::All,
|| format!("input_output"),
CustomTypeOp::new(|cx| {
let mut obligations = ObligationAccumulator::default();
CustomTypeOp::new(
|cx| {
let mut obligations = ObligationAccumulator::default();
let dummy_body_id = ObligationCause::dummy().body_id;
let (output_ty, anon_type_map) = obligations.add(infcx.instantiate_anon_types(
mir_def_id,
dummy_body_id,
cx.param_env,
&output_ty,
));
debug!(
"equate_inputs_and_outputs: instantiated output_ty={:?}",
output_ty
);
debug!(
"equate_inputs_and_outputs: anon_type_map={:#?}",
anon_type_map
);
debug!(
"equate_inputs_and_outputs: mir_output_ty={:?}",
mir_output_ty
);
obligations.add(
infcx
.at(&ObligationCause::dummy(), cx.param_env)
.eq(output_ty, mir_output_ty)?,
);
for (&anon_def_id, anon_decl) in &anon_type_map {
let anon_defn_ty = tcx.type_of(anon_def_id);
let anon_defn_ty = anon_defn_ty.subst(tcx, anon_decl.substs);
let anon_defn_ty = renumber::renumber_regions(
cx.infcx,
TyContext::Location(Location::START),
&anon_defn_ty,
let dummy_body_id = ObligationCause::dummy().body_id;
let (output_ty, anon_type_map) =
obligations.add(infcx.instantiate_anon_types(
mir_def_id,
dummy_body_id,
cx.param_env,
&output_ty,
));
debug!(
"equate_inputs_and_outputs: instantiated output_ty={:?}",
output_ty
);
debug!(
"equate_inputs_and_outputs: concrete_ty={:?}",
anon_decl.concrete_ty
"equate_inputs_and_outputs: anon_type_map={:#?}",
anon_type_map
);
debug!(
"equate_inputs_and_outputs: mir_output_ty={:?}",
mir_output_ty
);
debug!("equate_inputs_and_outputs: anon_defn_ty={:?}", anon_defn_ty);
obligations.add(
infcx
.at(&ObligationCause::dummy(), cx.param_env)
.eq(anon_decl.concrete_ty, anon_defn_ty)?,
.eq(output_ty, mir_output_ty)?,
);
}
debug!("equate_inputs_and_outputs: equated");
for (&anon_def_id, anon_decl) in &anon_type_map {
let anon_defn_ty = tcx.type_of(anon_def_id);
let anon_defn_ty = anon_defn_ty.subst(tcx, anon_decl.substs);
let anon_defn_ty = renumber::renumber_regions(
cx.infcx,
TyContext::Location(Location::START),
&anon_defn_ty,
);
debug!(
"equate_inputs_and_outputs: concrete_ty={:?}",
anon_decl.concrete_ty
);
debug!("equate_inputs_and_outputs: anon_defn_ty={:?}", anon_defn_ty);
obligations.add(
infcx
.at(&ObligationCause::dummy(), cx.param_env)
.eq(anon_decl.concrete_ty, anon_defn_ty)?,
);
}
Ok(InferOk {
value: Some(anon_type_map),
obligations: obligations.into_vec(),
})
}),
debug!("equate_inputs_and_outputs: equated");
Ok(InferOk {
value: Some(anon_type_map),
obligations: obligations.into_vec(),
})
},
|| format!("input_output"),
),
).unwrap_or_else(|terr| {
span_mirbug!(
self,
@ -156,14 +159,16 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
if let Some(anon_type_map) = anon_type_map {
self.fully_perform_op(
Locations::All,
|| format!("anon_type_map"),
CustomTypeOp::new(|_cx| {
infcx.constrain_anon_types(&anon_type_map, universal_regions);
Ok(InferOk {
value: (),
obligations: vec![],
})
}),
CustomTypeOp::new(
|_cx| {
infcx.constrain_anon_types(&anon_type_map, universal_regions);
Ok(InferOk {
value: (),
obligations: vec![],
})
},
|| format!("anon_type_map"),
),
).unwrap();
}
}

View File

@ -9,8 +9,8 @@
// except according to those terms.
use borrow_check::nll::region_infer::Cause;
use borrow_check::nll::type_check::AtLocation;
use borrow_check::nll::type_check::type_op::CustomTypeOp;
use borrow_check::nll::type_check::AtLocation;
use dataflow::move_paths::{HasMoveData, MoveData};
use dataflow::MaybeInitializedPlaces;
use dataflow::{FlowAtLocation, FlowsAtLocation};
@ -171,8 +171,7 @@ impl<'gen, 'typeck, 'flow, 'gcx, 'tcx> TypeLivenessGenerator<'gen, 'typeck, 'flo
);
cx.tcx().for_each_free_region(&value, |live_region| {
cx
.constraints
cx.constraints
.liveness_set
.push((live_region, location, cause.clone()));
});
@ -219,15 +218,15 @@ impl<'gen, 'typeck, 'flow, 'gcx, 'tcx> TypeLivenessGenerator<'gen, 'typeck, 'flo
debug!("compute_drop_data(dropped_ty={:?})", dropped_ty,);
let (dropped_kinds, region_constraint_data) =
cx.fully_perform_op_and_get_region_constraint_data(
|| format!("compute_drop_data(dropped_ty={:?})", dropped_ty),
CustomTypeOp::new(|cx| {
cx.fully_perform_op_and_get_region_constraint_data(CustomTypeOp::new(
|cx| {
Ok(cx
.infcx
.at(&ObligationCause::dummy(), cx.param_env)
.dropck_outlives(dropped_ty))
}),
).unwrap();
},
|| format!("compute_drop_data(dropped_ty={:?})", dropped_ty),
)).unwrap();
DropData {
dropped_kinds,

View File

@ -731,16 +731,12 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
fn fully_perform_op<R>(
&mut self,
locations: Locations,
describe_op: impl Fn() -> String,
op: impl type_op::TypeOp<'gcx, 'tcx, Output = R>,
) -> Result<R, TypeError<'tcx>> {
match op.trivial_noop() {
Ok(r) => Ok(r),
Err(op) => {
let (r, opt_data) = self.fully_perform_op_and_get_region_constraint_data(
|| format!("{} at {:?}", describe_op(), locations),
op,
)?;
let (r, opt_data) = self.fully_perform_op_and_get_region_constraint_data(op)?;
if let Some(data) = opt_data {
self.push_region_constraints(locations, data);
@ -781,14 +777,10 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
/// be generated there, so this can be useful for caching.
fn fully_perform_op_and_get_region_constraint_data<R>(
&mut self,
describe_op: impl Fn() -> String,
op: impl type_op::TypeOp<'gcx, 'tcx, Output = R>,
) -> Result<(R, Option<Rc<RegionConstraintData<'tcx>>>), TypeError<'tcx>> {
if cfg!(debug_assertions) {
info!(
"fully_perform_op_and_get_region_constraint_data({})",
describe_op(),
);
info!("fully_perform_op_and_get_region_constraint_data({:?})", op,);
}
let mut fulfill_cx = TraitEngine::new(self.infcx.tcx);
@ -822,20 +814,12 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
locations: Locations,
) -> UnitResult<'tcx> {
let param_env = self.param_env;
self.fully_perform_op(
locations,
|| format!("sub_types({:?} <: {:?})", sub, sup),
type_op::Subtype::new(param_env, sub, sup),
)
self.fully_perform_op(locations, type_op::Subtype::new(param_env, sub, sup))
}
fn eq_types(&mut self, a: Ty<'tcx>, b: Ty<'tcx>, locations: Locations) -> UnitResult<'tcx> {
let param_env = self.param_env;
self.fully_perform_op(
locations,
|| format!("eq_types({:?} = {:?})", a, b),
type_op::Eq::new(param_env, b, a),
)
self.fully_perform_op(locations, type_op::Eq::new(param_env, b, a))
}
fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> {
@ -1614,7 +1598,6 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
let param_env = self.param_env;
self.fully_perform_op(
location.at_self(),
|| format!("prove_predicates({:?})", predicates_vec),
type_op::ProvePredicates::new(param_env, predicates),
).unwrap()
}
@ -1651,10 +1634,8 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
{
debug!("normalize(value={:?}, location={:?})", value, location);
let param_env = self.param_env;
let value1 = value.clone(); // FIXME move describe into type_op
self.fully_perform_op(
location.to_locations(),
|| format!("normalize(value={:?})", value1),
type_op::Normalize::new(param_env, value),
).unwrap()
}

View File

@ -16,7 +16,7 @@ use rustc::ty::fold::TypeFoldable;
use rustc::ty::{ParamEnv, Predicate, Ty};
use std::fmt;
pub(super) trait TypeOp<'gcx, 'tcx>: Sized {
pub(super) trait TypeOp<'gcx, 'tcx>: Sized + fmt::Debug {
type Output;
/// Micro-optimization: returns `Ok(x)` if we can trivially
@ -30,22 +30,25 @@ pub(super) trait TypeOp<'gcx, 'tcx>: Sized {
) -> InferResult<'tcx, Self::Output>;
}
pub(super) struct CustomTypeOp<F> {
pub(super) struct CustomTypeOp<F, G> {
closure: F,
description: G,
}
impl<F> CustomTypeOp<F> {
pub(super) fn new<'gcx, 'tcx, R>(closure: F) -> Self
impl<F, G> CustomTypeOp<F, G> {
pub(super) fn new<'gcx, 'tcx, R>(closure: F, description: G) -> Self
where
F: FnOnce(&mut TypeChecker<'_, 'gcx, 'tcx>) -> InferResult<'tcx, R>,
G: Fn() -> String,
{
CustomTypeOp { closure }
CustomTypeOp { closure, description }
}
}
impl<'gcx, 'tcx, F, R> TypeOp<'gcx, 'tcx> for CustomTypeOp<F>
impl<'gcx, 'tcx, F, R, G> TypeOp<'gcx, 'tcx> for CustomTypeOp<F, G>
where
F: FnOnce(&mut TypeChecker<'_, 'gcx, 'tcx>) -> InferResult<'tcx, R>,
G: Fn() -> String,
{
type Output = R;
@ -58,7 +61,16 @@ where
}
}
pub(super) trait InfcxTypeOp<'gcx, 'tcx>: Sized {
impl<F, G> fmt::Debug for CustomTypeOp<F, G>
where
G: Fn() -> String,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", (self.description)())
}
}
pub(super) trait InfcxTypeOp<'gcx, 'tcx>: Sized + fmt::Debug {
type Output;
/// Micro-optimization: returns `Ok(x)` if we can trivially
@ -87,6 +99,7 @@ where
}
}
#[derive(Debug)]
pub(super) struct Subtype<'tcx> {
param_env: ParamEnv<'tcx>,
sub: Ty<'tcx>,
@ -121,6 +134,7 @@ impl<'gcx, 'tcx> InfcxTypeOp<'gcx, 'tcx> for Subtype<'tcx> {
}
}
#[derive(Debug)]
pub(super) struct Eq<'tcx> {
param_env: ParamEnv<'tcx>,
a: Ty<'tcx>,
@ -151,6 +165,7 @@ impl<'gcx, 'tcx> InfcxTypeOp<'gcx, 'tcx> for Eq<'tcx> {
}
}
#[derive(Debug)]
pub(super) struct ProvePredicates<'tcx> {
obligations: Vec<PredicateObligation<'tcx>>,
}
@ -188,6 +203,7 @@ impl<'gcx, 'tcx> InfcxTypeOp<'gcx, 'tcx> for ProvePredicates<'tcx> {
}
}
#[derive(Debug)]
pub(super) struct Normalize<'tcx, T> {
param_env: ParamEnv<'tcx>,
value: T,
@ -221,10 +237,7 @@ where
.at(&ObligationCause::dummy(), self.param_env)
.normalize(&self.value)
.unwrap_or_else(|NoSolution| {
bug!(
"normalization of `{:?}` failed",
self.value,
);
bug!("normalization of `{:?}` failed", self.value,);
});
Ok(InferOk { value, obligations })
}