Use ObligationCtxt in custom type ops
This commit is contained in:
parent
70db836922
commit
521a0bcd1f
5 changed files with 66 additions and 60 deletions
|
@ -1,32 +1,31 @@
|
|||
use crate::infer::canonical::query_response;
|
||||
use crate::infer::{InferCtxt, InferOk};
|
||||
use crate::infer::InferCtxt;
|
||||
use crate::traits::query::type_op::TypeOpOutput;
|
||||
use crate::traits::query::Fallible;
|
||||
use crate::traits::ObligationCtxt;
|
||||
use rustc_infer::infer::region_constraints::RegionConstraintData;
|
||||
use rustc_middle::traits::query::NoSolution;
|
||||
use rustc_span::source_map::DUMMY_SP;
|
||||
|
||||
use std::fmt;
|
||||
|
||||
pub struct CustomTypeOp<F, G> {
|
||||
pub struct CustomTypeOp<F> {
|
||||
closure: F,
|
||||
description: G,
|
||||
description: &'static str,
|
||||
}
|
||||
|
||||
impl<F, G> CustomTypeOp<F, G> {
|
||||
pub fn new<'tcx, R>(closure: F, description: G) -> Self
|
||||
impl<F> CustomTypeOp<F> {
|
||||
pub fn new<'tcx, R>(closure: F, description: &'static str) -> Self
|
||||
where
|
||||
F: FnOnce(&InferCtxt<'tcx>) -> Fallible<InferOk<'tcx, R>>,
|
||||
G: Fn() -> String,
|
||||
F: FnOnce(&ObligationCtxt<'_, 'tcx>) -> Fallible<R>,
|
||||
{
|
||||
CustomTypeOp { closure, description }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, F, R: fmt::Debug, G> super::TypeOp<'tcx> for CustomTypeOp<F, G>
|
||||
impl<'tcx, F, R: fmt::Debug> super::TypeOp<'tcx> for CustomTypeOp<F>
|
||||
where
|
||||
F: for<'a, 'cx> FnOnce(&'a InferCtxt<'tcx>) -> Fallible<InferOk<'tcx, R>>,
|
||||
G: Fn() -> String,
|
||||
F: FnOnce(&ObligationCtxt<'_, 'tcx>) -> Fallible<R>,
|
||||
{
|
||||
type Output = R;
|
||||
/// We can't do any custom error reporting for `CustomTypeOp`, so
|
||||
|
@ -41,16 +40,13 @@ where
|
|||
info!("fully_perform({:?})", self);
|
||||
}
|
||||
|
||||
Ok(scrape_region_constraints(infcx, || (self.closure)(infcx))?.0)
|
||||
Ok(scrape_region_constraints(infcx, self.closure)?.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl<F, G> fmt::Debug for CustomTypeOp<F, G>
|
||||
where
|
||||
G: Fn() -> String,
|
||||
{
|
||||
impl<F> fmt::Debug for CustomTypeOp<F> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{}", (self.description)())
|
||||
self.description.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -58,7 +54,7 @@ where
|
|||
/// constraints that result, creating query-region-constraints.
|
||||
pub fn scrape_region_constraints<'tcx, Op: super::TypeOp<'tcx, Output = R>, R>(
|
||||
infcx: &InferCtxt<'tcx>,
|
||||
op: impl FnOnce() -> Fallible<InferOk<'tcx, R>>,
|
||||
op: impl FnOnce(&ObligationCtxt<'_, 'tcx>) -> Fallible<R>,
|
||||
) -> Fallible<(TypeOpOutput<'tcx, Op>, RegionConstraintData<'tcx>)> {
|
||||
// During NLL, we expect that nobody will register region
|
||||
// obligations **except** as part of a custom type op (and, at the
|
||||
|
@ -72,16 +68,20 @@ pub fn scrape_region_constraints<'tcx, Op: super::TypeOp<'tcx, Output = R>, R>(
|
|||
pre_obligations,
|
||||
);
|
||||
|
||||
let InferOk { value, obligations } = infcx.commit_if_ok(|_| op())?;
|
||||
let ocx = ObligationCtxt::new(infcx);
|
||||
ocx.register_obligations(obligations);
|
||||
let errors = ocx.select_all_or_error();
|
||||
if !errors.is_empty() {
|
||||
infcx.tcx.sess.diagnostic().delay_span_bug(
|
||||
DUMMY_SP,
|
||||
format!("errors selecting obligation during MIR typeck: {:?}", errors),
|
||||
);
|
||||
}
|
||||
let value = infcx.commit_if_ok(|_| {
|
||||
let ocx = ObligationCtxt::new_in_snapshot(infcx);
|
||||
let value = op(&ocx)?;
|
||||
let errors = ocx.select_all_or_error();
|
||||
if errors.is_empty() {
|
||||
Ok(value)
|
||||
} else {
|
||||
infcx.tcx.sess.delay_span_bug(
|
||||
DUMMY_SP,
|
||||
format!("errors selecting obligation during MIR typeck: {:?}", errors),
|
||||
);
|
||||
Err(NoSolution)
|
||||
}
|
||||
})?;
|
||||
|
||||
let region_obligations = infcx.take_registered_region_obligations();
|
||||
let region_constraint_data = infcx.take_and_reset_region_constraints();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue