Skip to content

Commit 2fd8a31

Browse files
committed
extract out query boilerplate and use for Eq
1 parent 188ad38 commit 2fd8a31

File tree

2 files changed

+48
-28
lines changed

2 files changed

+48
-28
lines changed

src/librustc/infer/canonical/query_result.rs

Lines changed: 43 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,24 +18,54 @@
1818
//! [c]: https://rust-lang-nursery.github.io/rustc-guide/traits/canonicalization.html
1919
2020
use infer::canonical::substitute::substitute_value;
21-
use infer::canonical::{
22-
Canonical, CanonicalVarKind, CanonicalVarValues, CanonicalizedQueryResult, Certainty,
23-
QueryRegionConstraint, QueryResult,
24-
};
21+
use infer::canonical::{Canonical, CanonicalVarKind, CanonicalVarValues, CanonicalizedQueryResult,
22+
Certainty, QueryRegionConstraint, QueryResult};
2523
use infer::region_constraints::{Constraint, RegionConstraintData};
24+
use infer::InferCtxtBuilder;
2625
use infer::{InferCtxt, InferOk, InferResult, RegionObligation};
2726
use rustc_data_structures::indexed_vec::Idx;
2827
use rustc_data_structures::indexed_vec::IndexVec;
2928
use rustc_data_structures::sync::Lrc;
3029
use std::fmt::Debug;
3130
use syntax::ast;
32-
use traits::query::NoSolution;
31+
use syntax_pos::DUMMY_SP;
32+
use traits::query::{Fallible, NoSolution};
3333
use traits::{FulfillmentContext, TraitEngine};
3434
use traits::{Obligation, ObligationCause, PredicateObligation};
3535
use ty::fold::TypeFoldable;
3636
use ty::subst::{Kind, UnpackedKind};
3737
use ty::{self, CanonicalVar, Lift, TyCtxt};
3838

39+
impl<'cx, 'gcx, 'tcx> InferCtxtBuilder<'cx, 'gcx, 'tcx> {
40+
/// The "main method" for a canonicalized trait query. Given the
41+
/// canonical key `canonical_key`, this method will create a new
42+
/// inference context, instantiate the key, and run your operation
43+
/// `op`. The operation should yield up a result (of type `R`) as
44+
/// well as a set of trait obligations that must be fully
45+
/// satisfied. These obligations will be processed and the
46+
/// canonical result created.
47+
///
48+
/// Returns `NoSolution` in the event of any error.
49+
pub fn enter_canonical_trait_query<K, R>(
50+
&'tcx mut self,
51+
canonical_key: &Canonical<'tcx, K>,
52+
op: impl FnOnce(&InferCtxt<'_, 'gcx, 'tcx>, K) -> Fallible<InferOk<'tcx, R>>,
53+
) -> Fallible<CanonicalizedQueryResult<'gcx, R>>
54+
where
55+
K: TypeFoldable<'tcx>,
56+
R: Debug + Lift<'gcx> + TypeFoldable<'tcx>,
57+
{
58+
self.enter(|ref infcx| {
59+
let (key, canonical_inference_vars) =
60+
infcx.instantiate_canonical_with_fresh_inference_vars(DUMMY_SP, &canonical_key);
61+
let InferOk { value, obligations } = op(infcx, key)?;
62+
let fulfill_cx = &mut FulfillmentContext::new();
63+
fulfill_cx.register_predicate_obligations(infcx, obligations);
64+
infcx.make_canonicalized_query_result(canonical_inference_vars, value, fulfill_cx)
65+
})
66+
}
67+
}
68+
3969
impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
4070
/// This method is meant to be invoked as the final step of a canonical query
4171
/// implementation. It is given:
@@ -61,7 +91,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
6191
inference_vars: CanonicalVarValues<'tcx>,
6292
answer: T,
6393
fulfill_cx: &mut FulfillmentContext<'tcx>,
64-
) -> Result<CanonicalizedQueryResult<'gcx, T>, NoSolution>
94+
) -> Fallible<CanonicalizedQueryResult<'gcx, T>>
6595
where
6696
T: Debug + Lift<'gcx> + TypeFoldable<'tcx>,
6797
{
@@ -293,14 +323,13 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
293323
let result_subst =
294324
self.query_result_substitution_guess(cause, original_values, query_result);
295325

296-
let obligations = self
297-
.unify_query_result_substitution_guess(
298-
cause,
299-
param_env,
300-
original_values,
301-
&result_subst,
302-
query_result,
303-
)?
326+
let obligations = self.unify_query_result_substitution_guess(
327+
cause,
328+
param_env,
329+
original_values,
330+
&result_subst,
331+
query_result,
332+
)?
304333
.into_obligations();
305334

306335
Ok(InferOk {

src/librustc_traits/type_op_eq.rs

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,25 +11,16 @@
1111
use rustc::infer::canonical::{Canonical, QueryResult};
1212
use rustc::traits::query::type_op::eq::Eq;
1313
use rustc::traits::query::NoSolution;
14-
use rustc::traits::{FulfillmentContext, ObligationCause};
14+
use rustc::traits::ObligationCause;
1515
use rustc::ty::TyCtxt;
1616
use rustc_data_structures::sync::Lrc;
17-
use syntax::codemap::DUMMY_SP;
1817

1918
crate fn type_op_eq<'tcx>(
2019
tcx: TyCtxt<'_, 'tcx, 'tcx>,
2120
canonicalized: Canonical<'tcx, Eq<'tcx>>,
2221
) -> Result<Lrc<Canonical<'tcx, QueryResult<'tcx, ()>>>, NoSolution> {
23-
let tcx = tcx.global_tcx();
24-
tcx.infer_ctxt().enter(|ref infcx| {
25-
let (Eq { param_env, a, b }, canonical_inference_vars) =
26-
infcx.instantiate_canonical_with_fresh_inference_vars(DUMMY_SP, &canonicalized);
27-
let fulfill_cx = &mut FulfillmentContext::new();
28-
let obligations = match infcx.at(&ObligationCause::dummy(), param_env).eq(a, b) {
29-
Ok(v) => v.into_obligations(),
30-
Err(_) => return Err(NoSolution),
31-
};
32-
fulfill_cx.register_predicate_obligations(infcx, obligations);
33-
infcx.make_canonicalized_query_result(canonical_inference_vars, (), fulfill_cx)
34-
})
22+
tcx.infer_ctxt()
23+
.enter_canonical_trait_query(&canonicalized, |infcx, Eq { param_env, a, b }| {
24+
Ok(infcx.at(&ObligationCause::dummy(), param_env).eq(a, b)?)
25+
})
3526
}

0 commit comments

Comments
 (0)