]> git.lizzy.rs Git - rust.git/blob - src/librustc/traits/query/type_op/custom.rs
Rollup merge of #61273 - RalfJung:maybe-uninit, r=Centril
[rust.git] / src / librustc / traits / query / type_op / custom.rs
1 use crate::infer::{InferCtxt, InferOk};
2 use std::fmt;
3 use crate::traits::query::Fallible;
4
5 use crate::infer::canonical::query_response;
6 use crate::infer::canonical::QueryRegionConstraint;
7 use std::rc::Rc;
8 use syntax::source_map::DUMMY_SP;
9 use crate::traits::{ObligationCause, TraitEngine, TraitEngineExt};
10
11 pub struct CustomTypeOp<F, G> {
12     closure: F,
13     description: G,
14 }
15
16 impl<F, G> CustomTypeOp<F, G> {
17     pub fn new<'gcx, 'tcx, R>(closure: F, description: G) -> Self
18     where
19         F: FnOnce(&InferCtxt<'_, 'gcx, 'tcx>) -> Fallible<InferOk<'tcx, R>>,
20         G: Fn() -> String,
21     {
22         CustomTypeOp {
23             closure,
24             description,
25         }
26     }
27 }
28
29 impl<'gcx, 'tcx, F, R, G> super::TypeOp<'gcx, 'tcx> for CustomTypeOp<F, G>
30 where
31     F: for<'a, 'cx> FnOnce(&'a InferCtxt<'cx, 'gcx, 'tcx>) -> Fallible<InferOk<'tcx, R>>,
32     G: Fn() -> String,
33 {
34     type Output = R;
35
36     /// Processes the operation and all resulting obligations,
37     /// returning the final result along with any region constraints
38     /// (they will be given over to the NLL region solver).
39     fn fully_perform(
40         self,
41         infcx: &InferCtxt<'_, 'gcx, 'tcx>,
42     ) -> Fallible<(Self::Output, Option<Rc<Vec<QueryRegionConstraint<'tcx>>>>)> {
43         if cfg!(debug_assertions) {
44             info!("fully_perform({:?})", self);
45         }
46
47         scrape_region_constraints(infcx, || Ok((self.closure)(infcx)?))
48     }
49 }
50
51 impl<F, G> fmt::Debug for CustomTypeOp<F, G>
52 where
53     G: Fn() -> String,
54 {
55     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
56         write!(f, "{}", (self.description)())
57     }
58 }
59
60 /// Executes `op` and then scrapes out all the "old style" region
61 /// constraints that result, creating query-region-constraints.
62 fn scrape_region_constraints<'gcx, 'tcx, R>(
63     infcx: &InferCtxt<'_, 'gcx, 'tcx>,
64     op: impl FnOnce() -> Fallible<InferOk<'tcx, R>>,
65 ) -> Fallible<(R, Option<Rc<Vec<QueryRegionConstraint<'tcx>>>>)> {
66     let mut fulfill_cx = TraitEngine::new(infcx.tcx);
67     let dummy_body_id = ObligationCause::dummy().body_id;
68
69     // During NLL, we expect that nobody will register region
70     // obligations **except** as part of a custom type op (and, at the
71     // end of each custom type op, we scrape out the region
72     // obligations that resulted). So this vector should be empty on
73     // entry.
74     let pre_obligations = infcx.take_registered_region_obligations();
75     assert!(
76         pre_obligations.is_empty(),
77         "scrape_region_constraints: incoming region obligations = {:#?}",
78         pre_obligations,
79     );
80
81     let InferOk { value, obligations } = infcx.commit_if_ok(|_| op())?;
82     debug_assert!(obligations.iter().all(|o| o.cause.body_id == dummy_body_id));
83     fulfill_cx.register_predicate_obligations(infcx, obligations);
84     if let Err(e) = fulfill_cx.select_all_or_error(infcx) {
85         infcx.tcx.sess.diagnostic().delay_span_bug(
86             DUMMY_SP,
87             &format!("errors selecting obligation during MIR typeck: {:?}", e),
88         );
89     }
90
91     let region_obligations = infcx.take_registered_region_obligations();
92
93     let region_constraint_data = infcx.take_and_reset_region_constraints();
94
95     let outlives = query_response::make_query_outlives(
96         infcx.tcx,
97         region_obligations
98             .iter()
99             .map(|(_, r_o)| (r_o.sup_type, r_o.sub_region))
100             .map(|(ty, r)| (infcx.resolve_vars_if_possible(&ty), r)),
101         &region_constraint_data,
102     );
103
104     if outlives.is_empty() {
105         Ok((value, None))
106     } else {
107         Ok((value, Some(Rc::new(outlives))))
108     }
109 }