More · rust-lang/rust@f943f73 (original) (raw)
1
1
`use std::assert_matches::assert_matches;
`
2
2
`use std::fmt::Debug;
`
3
``
`-
use std:📑:PhantomData;
`
4
3
``
5
4
`use rustc_data_structures::stack::ensure_sufficient_stack;
`
6
5
`use rustc_infer::infer::InferCtxt;
`
60
59
`` /// entered before passing value
to the function. This is currently needed for
``
61
60
`` /// normalize_erasing_regions
, which skips binders as it walks through a type.
``
62
61
`///
`
63
``
`-
/// TODO: doc
`
``
62
`+
/// This returns a set of stalled obligations if the typing mode of the underlying infcx
`
``
63
`+
/// has any stalled coroutine def ids.
`
64
64
`pub fn deeply_normalize_with_skipped_universes_and_ambiguous_goals<'tcx, T, E>(
`
65
65
`at: At<'_, 'tcx>,
`
66
66
`value: T,
`
`@@ -72,24 +72,18 @@ where
`
72
72
`{
`
73
73
`let fulfill_cx = FulfillmentCtxt::new(at.infcx);
`
74
74
`let mut folder =
`
75
``
`-
NormalizationFolder { at, fulfill_cx, depth: 0, universes, _errors: PhantomData };
`
``
75
`+
NormalizationFolder { at, fulfill_cx, depth: 0, universes, stalled_goals: vec![] };
`
76
76
`let value = value.try_fold_with(&mut folder)?;
`
77
``
`-
let goals = folder
`
78
``
`-
.fulfill_cx
`
79
``
`-
.drain_stalled_obligations_for_coroutines(at.infcx)
`
80
``
`-
.into_iter()
`
81
``
`-
.map(|obl| obl.as_goal())
`
82
``
`-
.collect();
`
83
77
`let errors = folder.fulfill_cx.select_all_or_error(at.infcx);
`
84
``
`-
if errors.is_empty() { Ok((value, goals)) } else { Err(errors) }
`
``
78
`+
if errors.is_empty() { Ok((value, folder.stalled_goals)) } else { Err(errors) }
`
85
79
`}
`
86
80
``
87
81
`struct NormalizationFolder<'me, 'tcx, E> {
`
88
82
`at: At<'me, 'tcx>,
`
89
83
`fulfill_cx: FulfillmentCtxt<'tcx, E>,
`
90
84
`depth: usize,
`
91
85
`universes: Vec<Option>,
`
92
``
`-
_errors: PhantomData,
`
``
86
`+
stalled_goals: Vec<Goal<'tcx, ty::Predicate<'tcx>>>,
`
93
87
`}
`
94
88
``
95
89
`impl<'tcx, E> NormalizationFolder<'_, 'tcx, E>
`
`@@ -130,10 +124,7 @@ where
`
130
124
`);
`
131
125
``
132
126
`self.fulfill_cx.register_predicate_obligation(infcx, obligation);
`
133
``
`-
let errors = self.fulfill_cx.select_where_possible(infcx);
`
134
``
`-
if !errors.is_empty() {
`
135
``
`-
return Err(errors);
`
136
``
`-
}
`
``
127
`+
self.select_all_and_stall_coroutine_predicates()?;
`
137
128
``
138
129
`// Alias is guaranteed to be fully structurally resolved,
`
139
130
`// so we can super fold here.
`
`@@ -184,6 +175,27 @@ where
`
184
175
`self.depth -= 1;
`
185
176
`Ok(result)
`
186
177
`}
`
``
178
+
``
179
`+
fn select_all_and_stall_coroutine_predicates(&mut self) -> Result<(), Vec> {
`
``
180
`+
let errors = self.fulfill_cx.select_where_possible(self.at.infcx);
`
``
181
`+
if !errors.is_empty() {
`
``
182
`+
return Err(errors);
`
``
183
`+
}
`
``
184
+
``
185
`+
self.stalled_goals.extend(
`
``
186
`+
self.fulfill_cx
`
``
187
`+
.drain_stalled_obligations_for_coroutines(self.at.infcx)
`
``
188
`+
.into_iter()
`
``
189
`+
.map(|obl| obl.as_goal()),
`
``
190
`+
);
`
``
191
+
``
192
`+
let errors = self.fulfill_cx.collect_remaining_errors(self.at.infcx);
`
``
193
`+
if !errors.is_empty() {
`
``
194
`+
return Err(errors);
`
``
195
`+
}
`
``
196
+
``
197
`+
Ok(())
`
``
198
`+
}
`
187
199
`}
`
188
200
``
189
201
`impl<'tcx, E> FallibleTypeFolder<TyCtxt<'tcx>> for NormalizationFolder<'_, 'tcx, E>
`