Skip to content

Commit e891044

Browse files
ldm0nikomatsakis
andcommitted
select obligations after check_casts
Otherwise, we can get into a situation where you have a subtype obligation `#1 <: #2` pending, #1 is constrained by `check_casts`, but #2` is unaffected. Co-authored-by: Niko Matsakis <niko@alum.mit.edu>
1 parent b6e334d commit e891044

File tree

6 files changed

+48
-4
lines changed

6 files changed

+48
-4
lines changed

compiler/rustc_typeck/src/check/fallback.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ use rustc_infer::infer::type_variable::Diverging;
33
use rustc_middle::ty::{self, Ty};
44

55
impl<'tcx> FnCtxt<'_, 'tcx> {
6-
pub(super) fn type_inference_fallback(&self) {
6+
/// Performs type inference fallback, returning true if any fallback
7+
/// occurs.
8+
pub(super) fn type_inference_fallback(&self) -> bool {
79
// All type checking constraints were added, try to fallback unsolved variables.
810
self.select_obligations_where_possible(false, |_| {});
911
let mut fallback_has_occurred = false;
@@ -50,6 +52,8 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
5052

5153
// See if we can make any more progress.
5254
self.select_obligations_where_possible(fallback_has_occurred, |_| {});
55+
56+
fallback_has_occurred
5357
}
5458

5559
// Tries to apply a fallback to `ty` if it is an unsolved variable.

compiler/rustc_typeck/src/check/mod.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -446,11 +446,12 @@ fn typeck_with_fallback<'tcx>(
446446
fcx
447447
};
448448

449-
fcx.type_inference_fallback();
449+
let fallback_has_occurred = fcx.type_inference_fallback();
450450

451451
// Even though coercion casts provide type hints, we check casts after fallback for
452452
// backwards compatibility. This makes fallback a stronger type hint than a cast coercion.
453453
fcx.check_casts();
454+
fcx.select_obligations_where_possible(fallback_has_occurred, |_| {});
454455

455456
// Closure and generator analysis may run after fallback
456457
// because they don't constrain other type variables.

compiler/rustc_typeck/src/expr_use_visitor.rs

+8-2
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
243243
let ExprUseVisitor { ref mc, body_owner: _, delegate: _ } = *self;
244244
let mut needs_to_be_read = false;
245245
for arm in arms.iter() {
246-
return_if_err!(mc.cat_pattern(discr_place.clone(), &arm.pat, |place, pat| {
246+
match mc.cat_pattern(discr_place.clone(), &arm.pat, |place, pat| {
247247
match &pat.kind {
248248
PatKind::Binding(.., opt_sub_pat) => {
249249
// If the opt_sub_pat is None, than the binding does not count as
@@ -290,7 +290,13 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
290290
// examined
291291
}
292292
}
293-
}));
293+
}) {
294+
Ok(_) => (),
295+
Err(_) => {
296+
// If typeck failed, assume borrow is needed.
297+
needs_to_be_read = true;
298+
}
299+
}
294300
}
295301

296302
if needs_to_be_read {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Regression test for #88118. Used to ICE.
2+
//
3+
// check-pass
4+
5+
#![feature(capture_disjoint_fields)]
6+
7+
fn foo<MsU>(handler: impl FnOnce() -> MsU + Clone + 'static) {
8+
Box::new(move |value| {
9+
(|_| handler.clone()())(value);
10+
None
11+
}) as Box<dyn Fn(i32) -> Option<i32>>;
12+
}
13+
14+
fn main() {}

src/test/ui/closures/issue-87814-1.rs

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// check-pass
2+
fn main() {
3+
let mut schema_all = vec![];
4+
(0..42).for_each(|_x| match Err(()) as Result<(), _> {
5+
Ok(()) => schema_all.push(()),
6+
Err(_) => (),
7+
});
8+
}

src/test/ui/closures/issue-87814-2.rs

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// check-pass
2+
#![feature(try_reserve)]
3+
4+
fn main() {
5+
let mut schema_all: (Vec<String>, Vec<String>) = (vec![], vec![]);
6+
7+
let _c = || match schema_all.0.try_reserve(1) as Result<(), _> {
8+
Ok(()) => (),
9+
Err(_) => (),
10+
};
11+
}

0 commit comments

Comments
 (0)