diff options
| author | Niko Matsakis <niko@alum.mit.edu> | 2018-06-06 10:33:07 -0400 |
|---|---|---|
| committer | Niko Matsakis <niko@alum.mit.edu> | 2018-06-26 10:31:49 -0400 |
| commit | 846cc263cf4aee40064598c8a9c1d26c50daa7c2 (patch) | |
| tree | 483c7293c99562646686c9aeceb4d7082a5d1398 | |
| parent | f998628e5c661f07bf0db7985b2949411a23064c (diff) | |
| download | rust-846cc263cf4aee40064598c8a9c1d26c50daa7c2.tar.gz rust-846cc263cf4aee40064598c8a9c1d26c50daa7c2.zip | |
make normalize into an op
| -rw-r--r-- | src/librustc_mir/borrow_check/nll/type_check/mod.rs | 32 | ||||
| -rw-r--r-- | src/librustc_mir/borrow_check/nll/type_check/type_op.rs | 53 |
2 files changed, 58 insertions, 27 deletions
diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index e6211c4ed7f..99d8ed85af3 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -15,7 +15,6 @@ use borrow_check::location::LocationTable; use borrow_check::nll::facts::AllFacts; use borrow_check::nll::region_infer::Cause; use borrow_check::nll::region_infer::{ClosureRegionRequirementsExt, OutlivesConstraint, TypeTest}; -use borrow_check::nll::type_check::type_op::{CustomTypeOp, TypeOp}; use borrow_check::nll::universal_regions::UniversalRegions; use dataflow::move_paths::MoveData; use dataflow::FlowAtLocation; @@ -27,8 +26,7 @@ use rustc::mir::interpret::EvalErrorKind::BoundsCheck; use rustc::mir::tcx::PlaceTy; use rustc::mir::visit::{PlaceContext, Visitor}; use rustc::mir::*; -use rustc::traits::query::NoSolution; -use rustc::traits::{ObligationCause, Normalized, TraitEngine}; +use rustc::traits::{ObligationCause, TraitEngine}; use rustc::ty::error::TypeError; use rustc::ty::fold::TypeFoldable; use rustc::ty::{self, ToPolyTraitRef, Ty, TyCtxt, TypeVariants}; @@ -734,7 +732,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { &mut self, locations: Locations, describe_op: impl Fn() -> String, - op: impl TypeOp<'gcx, 'tcx, Output = R>, + op: impl type_op::TypeOp<'gcx, 'tcx, Output = R>, ) -> Result<R, TypeError<'tcx>> { match op.trivial_noop() { Ok(r) => Ok(r), @@ -784,7 +782,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { fn fully_perform_op_and_get_region_constraint_data<R>( &mut self, describe_op: impl Fn() -> String, - op: impl TypeOp<'gcx, 'tcx, Output = R>, + op: impl type_op::TypeOp<'gcx, 'tcx, Output = R>, ) -> Result<(R, Option<Rc<RegionConstraintData<'tcx>>>), TypeError<'tcx>> { if cfg!(debug_assertions) { info!( @@ -1649,30 +1647,12 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { where T: fmt::Debug + TypeFoldable<'tcx>, { - // Micro-optimization: avoid work when we don't have to - if !value.has_projections() { - return value.clone(); - } - debug!("normalize(value={:?}, location={:?})", value, location); + let value1 = value.clone(); // FIXME move describe into type_op self.fully_perform_op( location.to_locations(), - || format!("normalize(value={:?})", value), - CustomTypeOp::new(|this| { - let Normalized { value, obligations } = this - .infcx - .at(&ObligationCause::dummy(), this.param_env) - .normalize(&value) - .unwrap_or_else(|NoSolution| { - span_bug!( - this.last_span, - "normalization of `{:?}` failed at {:?}", - value, - location, - ); - }); - Ok(InferOk { value, obligations }) - }), + || format!("normalize(value={:?})", value1), + type_op::Normalize::new(value), ).unwrap() } } diff --git a/src/librustc_mir/borrow_check/nll/type_check/type_op.rs b/src/librustc_mir/borrow_check/nll/type_check/type_op.rs index d85a83ac3fc..43c11c61eff 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/type_op.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/type_op.rs @@ -10,8 +10,11 @@ use borrow_check::nll::type_check::TypeChecker; use rustc::infer::{InferOk, InferResult}; -use rustc::traits::{Obligation, ObligationCause, PredicateObligation}; +use rustc::traits::{Normalized, Obligation, ObligationCause, PredicateObligation}; +use rustc::traits::query::NoSolution; use rustc::ty::{ParamEnv, Predicate, Ty}; +use rustc::ty::fold::TypeFoldable; +use std::fmt; pub(super) trait TypeOp<'gcx, 'tcx>: Sized { type Output; @@ -160,3 +163,51 @@ impl<'gcx, 'tcx> TypeOp<'gcx, 'tcx> for ProvePredicates<'tcx> { }) } } + +pub(super) struct Normalize<T> { + value: T +} + +impl<'tcx, T> Normalize<T> +where + T: fmt::Debug + TypeFoldable<'tcx>, +{ + pub(super) fn new( + value: T + ) -> Self { + Self { value } + } +} + +impl<'gcx, 'tcx, T> TypeOp<'gcx, 'tcx> for Normalize<T> +where + T: fmt::Debug + TypeFoldable<'tcx>, +{ + type Output = T; + + fn trivial_noop(self) -> Result<Self::Output, Self> { + if !self.value.has_projections() { + Ok(self.value) + } else { + Err(self) + } + } + + fn perform( + self, + type_checker: &mut TypeChecker<'_, 'gcx, 'tcx>, + ) -> InferResult<'tcx, Self::Output> { + let Normalized { value, obligations } = type_checker + .infcx + .at(&ObligationCause::dummy(), type_checker.param_env) + .normalize(&self.value) + .unwrap_or_else(|NoSolution| { + span_bug!( + type_checker.last_span, + "normalization of `{:?}` failed", + self.value, + ); + }); + Ok(InferOk { value, obligations }) + } +} |
