diff options
| author | liudingming <liudingming@bytedance.com> | 2021-08-09 20:25:57 +0800 |
|---|---|---|
| committer | Niko Matsakis <niko@alum.mit.edu> | 2021-08-23 19:16:16 +0000 |
| commit | e8910440a24ecb2ddb08b4dbe170488ddf61fc87 (patch) | |
| tree | 7b574ec36f695dd6346584fcb7850cafbbc98794 | |
| parent | b6e334d87349502766be70d649e6fe4a73573482 (diff) | |
| download | rust-e8910440a24ecb2ddb08b4dbe170488ddf61fc87.tar.gz rust-e8910440a24ecb2ddb08b4dbe170488ddf61fc87.zip | |
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>
| -rw-r--r-- | compiler/rustc_typeck/src/check/fallback.rs | 6 | ||||
| -rw-r--r-- | compiler/rustc_typeck/src/check/mod.rs | 3 | ||||
| -rw-r--r-- | compiler/rustc_typeck/src/expr_use_visitor.rs | 10 | ||||
| -rw-r--r-- | src/test/ui/closures/2229_closure_analysis/issue_88118.rs | 14 | ||||
| -rw-r--r-- | src/test/ui/closures/issue-87814-1.rs | 8 | ||||
| -rw-r--r-- | src/test/ui/closures/issue-87814-2.rs | 11 |
6 files changed, 48 insertions, 4 deletions
diff --git a/compiler/rustc_typeck/src/check/fallback.rs b/compiler/rustc_typeck/src/check/fallback.rs index 69a8970ae09..8f6cdc7bb12 100644 --- a/compiler/rustc_typeck/src/check/fallback.rs +++ b/compiler/rustc_typeck/src/check/fallback.rs @@ -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. diff --git a/compiler/rustc_typeck/src/check/mod.rs b/compiler/rustc_typeck/src/check/mod.rs index ad7e96e2833..ff6cb35a752 100644 --- a/compiler/rustc_typeck/src/check/mod.rs +++ b/compiler/rustc_typeck/src/check/mod.rs @@ -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. diff --git a/compiler/rustc_typeck/src/expr_use_visitor.rs b/compiler/rustc_typeck/src/expr_use_visitor.rs index b0c95939bb7..8d401b7f444 100644 --- a/compiler/rustc_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_typeck/src/expr_use_visitor.rs @@ -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 { diff --git a/src/test/ui/closures/2229_closure_analysis/issue_88118.rs b/src/test/ui/closures/2229_closure_analysis/issue_88118.rs new file mode 100644 index 00000000000..15c6ae4906c --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/issue_88118.rs @@ -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() {} \ No newline at end of file diff --git a/src/test/ui/closures/issue-87814-1.rs b/src/test/ui/closures/issue-87814-1.rs new file mode 100644 index 00000000000..5cf01ddf5d7 --- /dev/null +++ b/src/test/ui/closures/issue-87814-1.rs @@ -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(_) => (), + }); +} diff --git a/src/test/ui/closures/issue-87814-2.rs b/src/test/ui/closures/issue-87814-2.rs new file mode 100644 index 00000000000..7a5facdac58 --- /dev/null +++ b/src/test/ui/closures/issue-87814-2.rs @@ -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(_) => (), + }; +} |
