use rustc_middle::ty::{self, Ty};
impl<'tcx> FnCtxt<'_, 'tcx> {
- pub(super) fn type_inference_fallback(&self) {
+ /// Performs type inference fallback, returning true if any fallback
+ /// occurs.
+ pub(super) fn type_inference_fallback(&self) -> bool {
// All type checking constraints were added, try to fallback unsolved variables.
self.select_obligations_where_possible(false, |_| {});
let mut fallback_has_occurred = false;
// See if we can make any more progress.
self.select_obligations_where_possible(fallback_has_occurred, |_| {});
+
+ fallback_has_occurred
}
// Tries to apply a fallback to `ty` if it is an unsolved variable.
fcx
};
- fcx.type_inference_fallback();
+ let fallback_has_occurred = fcx.type_inference_fallback();
// Even though coercion casts provide type hints, we check casts after fallback for
// backwards compatibility. This makes fallback a stronger type hint than a cast coercion.
fcx.check_casts();
+ fcx.select_obligations_where_possible(fallback_has_occurred, |_| {});
// Closure and generator analysis may run after fallback
// because they don't constrain other type variables.
let ExprUseVisitor { ref mc, body_owner: _, delegate: _ } = *self;
let mut needs_to_be_read = false;
for arm in arms.iter() {
- return_if_err!(mc.cat_pattern(discr_place.clone(), &arm.pat, |place, pat| {
+ match mc.cat_pattern(discr_place.clone(), &arm.pat, |place, pat| {
match &pat.kind {
PatKind::Binding(.., opt_sub_pat) => {
// If the opt_sub_pat is None, than the binding does not count as
// examined
}
}
- }));
+ }) {
+ Ok(_) => (),
+ Err(_) => {
+ // If typeck failed, assume borrow is needed.
+ needs_to_be_read = true;
+ }
+ }
}
if needs_to_be_read {
--- /dev/null
+// Regression test for #88118. Used to ICE.
+//
+// check-pass
+
+#![feature(capture_disjoint_fields)]
+
+fn foo<MsU>(handler: impl FnOnce() -> MsU + Clone + 'static) {
+ Box::new(move |value| {
+ (|_| handler.clone()())(value);
+ None
+ }) as Box<dyn Fn(i32) -> Option<i32>>;
+}
+
+fn main() {}
\ No newline at end of file
--- /dev/null
+// check-pass
+fn main() {
+ let mut schema_all = vec![];
+ (0..42).for_each(|_x| match Err(()) as Result<(), _> {
+ Ok(()) => schema_all.push(()),
+ Err(_) => (),
+ });
+}
--- /dev/null
+// check-pass
+#![feature(try_reserve)]
+
+fn main() {
+ let mut schema_all: (Vec<String>, Vec<String>) = (vec![], vec![]);
+
+ let _c = || match schema_all.0.try_reserve(1) as Result<(), _> {
+ Ok(()) => (),
+ Err(_) => (),
+ };
+}