Skip to content

Commit

Permalink
select obligations after check_casts
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
ldm0 and nikomatsakis committed Aug 23, 2021
1 parent b6e334d commit e891044
Show file tree
Hide file tree
Showing 6 changed files with 48 additions and 4 deletions.
6 changes: 5 additions & 1 deletion compiler/rustc_typeck/src/check/fallback.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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.
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_typeck/src/check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
10 changes: 8 additions & 2 deletions compiler/rustc_typeck/src/expr_use_visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 {
Expand Down
14 changes: 14 additions & 0 deletions src/test/ui/closures/2229_closure_analysis/issue_88118.rs
Original file line number Diff line number Diff line change
@@ -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 changes: 8 additions & 0 deletions src/test/ui/closures/issue-87814-1.rs
Original file line number Diff line number Diff line change
@@ -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 changes: 11 additions & 0 deletions src/test/ui/closures/issue-87814-2.rs
Original file line number Diff line number Diff line change
@@ -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(_) => (),
};
}

0 comments on commit e891044

Please sign in to comment.