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>
This commit is contained in:
parent
b6e334d873
commit
e8910440a2
@ -3,7 +3,9 @@ use rustc_infer::infer::type_variable::Diverging;
|
||||
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;
|
||||
@ -50,6 +52,8 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
|
||||
|
||||
// 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.
|
||||
|
@ -446,11 +446,12 @@ fn typeck_with_fallback<'tcx>(
|
||||
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.
|
||||
|
@ -243,7 +243,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
|
||||
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
|
||||
@ -290,7 +290,13 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
|
||||
// examined
|
||||
}
|
||||
}
|
||||
}));
|
||||
}) {
|
||||
Ok(_) => (),
|
||||
Err(_) => {
|
||||
// If typeck failed, assume borrow is needed.
|
||||
needs_to_be_read = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if needs_to_be_read {
|
||||
|
14
src/test/ui/closures/2229_closure_analysis/issue_88118.rs
Normal file
14
src/test/ui/closures/2229_closure_analysis/issue_88118.rs
Normal file
@ -0,0 +1,14 @@
|
||||
// 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() {}
|
8
src/test/ui/closures/issue-87814-1.rs
Normal file
8
src/test/ui/closures/issue-87814-1.rs
Normal file
@ -0,0 +1,8 @@
|
||||
// check-pass
|
||||
fn main() {
|
||||
let mut schema_all = vec![];
|
||||
(0..42).for_each(|_x| match Err(()) as Result<(), _> {
|
||||
Ok(()) => schema_all.push(()),
|
||||
Err(_) => (),
|
||||
});
|
||||
}
|
11
src/test/ui/closures/issue-87814-2.rs
Normal file
11
src/test/ui/closures/issue-87814-2.rs
Normal file
@ -0,0 +1,11 @@
|
||||
// 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(_) => (),
|
||||
};
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user