about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_hir_typeck/src/expr_use_visitor.rs17
-rw-r--r--compiler/rustc_hir_typeck/src/upvar.rs2
-rw-r--r--src/test/ui/inference/issue-104649.rs32
-rw-r--r--src/test/ui/inference/issue-104649.stderr14
4 files changed, 58 insertions, 7 deletions
diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
index 275f7d12148..e5e798f4b93 100644
--- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
+++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
@@ -252,11 +252,11 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
 
             hir::ExprKind::Match(ref discr, arms, _) => {
                 let discr_place = return_if_err!(self.mc.cat_expr(discr));
-                self.maybe_read_scrutinee(
+                return_if_err!(self.maybe_read_scrutinee(
                     discr,
                     discr_place.clone(),
                     arms.iter().map(|arm| arm.pat),
-                );
+                ));
 
                 // treatment of the discriminant is handled while walking the arms.
                 for arm in arms {
@@ -390,7 +390,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
         discr: &Expr<'_>,
         discr_place: PlaceWithHirId<'tcx>,
         pats: impl Iterator<Item = &'t hir::Pat<'t>>,
-    ) {
+    ) -> Result<(), ()> {
         // Matching should not always be considered a use of the place, hence
         // discr does not necessarily need to be borrowed.
         // We only want to borrow discr if the pattern contain something other
@@ -398,7 +398,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
         let ExprUseVisitor { ref mc, body_owner: _, delegate: _ } = *self;
         let mut needs_to_be_read = false;
         for pat in pats {
-            return_if_err!(mc.cat_pattern(discr_place.clone(), pat, |place, pat| {
+            mc.cat_pattern(discr_place.clone(), 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
@@ -453,7 +453,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
                         // examined
                     }
                 }
-            }));
+            })?
         }
 
         if needs_to_be_read {
@@ -474,6 +474,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
             // that the discriminant has been initialized.
             self.walk_expr(discr);
         }
+        Ok(())
     }
 
     fn walk_local<F>(
@@ -490,7 +491,11 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
         f(self);
         if let Some(els) = els {
             // borrowing because we need to test the discriminant
-            self.maybe_read_scrutinee(expr, expr_place.clone(), from_ref(pat).iter());
+            return_if_err!(self.maybe_read_scrutinee(
+                expr,
+                expr_place.clone(),
+                from_ref(pat).iter()
+            ));
             self.walk_block(els)
         }
         self.walk_irrefutable_pat(&expr_place, &pat);
diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs
index 68f119adc7a..0f46972019e 100644
--- a/compiler/rustc_hir_typeck/src/upvar.rs
+++ b/compiler/rustc_hir_typeck/src/upvar.rs
@@ -2168,7 +2168,7 @@ fn determine_place_ancestry_relation<'tcx>(
     place_a: &Place<'tcx>,
     place_b: &Place<'tcx>,
 ) -> PlaceAncestryRelation {
-    // If Place A and Place B, don't start off from the same root variable, they are divergent.
+    // If Place A and Place B don't start off from the same root variable, they are divergent.
     if place_a.base != place_b.base {
         return PlaceAncestryRelation::Divergent;
     }
diff --git a/src/test/ui/inference/issue-104649.rs b/src/test/ui/inference/issue-104649.rs
new file mode 100644
index 00000000000..4637b884d44
--- /dev/null
+++ b/src/test/ui/inference/issue-104649.rs
@@ -0,0 +1,32 @@
+type Result<T, E = Error> = ::std::result::Result<T, E>;
+struct Error;
+
+trait ForEach {
+    type Input;
+    fn for_each<F, U>(self, f: F)
+    where
+        F: FnOnce(Self::Input) -> U;
+}
+
+impl<T> ForEach for A<T> {
+    type Input = T;
+    fn for_each<F, U>(self, f: F)
+    where
+        F: FnOnce(Self::Input) -> U,
+    {
+        todo!()
+    }
+}
+
+struct A<T>(T);
+
+fn main() {
+    let a = A(Result::Ok(Result::Ok(()))); //~ ERROR type annotations needed
+    a.for_each(|a: Result<_>| {
+        let f = || match a {
+            Ok(Ok(a)) => {}
+            Ok(Err(a)) => {}
+            Err(a) => {}
+        };
+    });
+}
diff --git a/src/test/ui/inference/issue-104649.stderr b/src/test/ui/inference/issue-104649.stderr
new file mode 100644
index 00000000000..4962b21f9fd
--- /dev/null
+++ b/src/test/ui/inference/issue-104649.stderr
@@ -0,0 +1,14 @@
+error[E0282]: type annotations needed for `A<std::result::Result<std::result::Result<(), E>, Error>>`
+  --> $DIR/issue-104649.rs:24:9
+   |
+LL |     let a = A(Result::Ok(Result::Ok(())));
+   |         ^
+   |
+help: consider giving `a` an explicit type, where the type for type parameter `E` is specified
+   |
+LL |     let a: A<std::result::Result<std::result::Result<(), E>, Error>> = A(Result::Ok(Result::Ok(())));
+   |          +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.