]> git.lizzy.rs Git - rust.git/commitdiff
select obligations after `check_casts`
authorliudingming <liudingming@bytedance.com>
Mon, 9 Aug 2021 12:25:57 +0000 (20:25 +0800)
committerNiko Matsakis <niko@alum.mit.edu>
Mon, 23 Aug 2021 19:16:16 +0000 (19:16 +0000)
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>
compiler/rustc_typeck/src/check/fallback.rs
compiler/rustc_typeck/src/check/mod.rs
compiler/rustc_typeck/src/expr_use_visitor.rs
src/test/ui/closures/2229_closure_analysis/issue_88118.rs [new file with mode: 0644]
src/test/ui/closures/issue-87814-1.rs [new file with mode: 0644]
src/test/ui/closures/issue-87814-2.rs [new file with mode: 0644]

index 69a8970ae094e8c4cdca183a83eb0fe7e08677f8..8f6cdc7bb12a7243ab97820e956a4e185c43330d 100644 (file)
@@ -3,7 +3,9 @@
 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 @@ pub(super) fn type_inference_fallback(&self) {
 
         // 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.
index ad7e96e2833b84b65fb00e28fa918532d8740e43..ff6cb35a752565b2d5374dfdbc9e796f1af41a13 100644 (file)
@@ -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.
index b0c95939bb77dd9e71ae826cf7ff0b27cb219dac..8d401b7f4444257d7071f5a2b2da411dcbc6bbe8 100644 (file)
@@ -243,7 +243,7 @@ pub fn walk_expr(&mut self, expr: &hir::Expr<'_>) {
                 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 @@ pub fn walk_expr(&mut self, expr: &hir::Expr<'_>) {
                                 // 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 (file)
index 0000000..15c6ae4
--- /dev/null
@@ -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 (file)
index 0000000..5cf01dd
--- /dev/null
@@ -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 (file)
index 0000000..7a5facd
--- /dev/null
@@ -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(_) => (),
+    };
+}