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