about summary refs log tree commit diff
diff options
context:
space:
mode:
authorLin Yihai <linyihai@huawei.com>2024-06-11 17:31:06 +0800
committerLin Yihai <linyihai@huawei.com>2024-06-12 11:11:02 +0800
commit5d8f40a63afe3999df61c2487555a540b6ff30ea (patch)
tree5a89373d596fed4bddbd7f7b822f20a02e412a4c
parentb5b13568fb5da4ac988bde370008d6134d3dfe6c (diff)
downloadrust-5d8f40a63afe3999df61c2487555a540b6ff30ea.tar.gz
rust-5d8f40a63afe3999df61c2487555a540b6ff30ea.zip
No uninitalized report in a pre-returned match arm
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs21
-rw-r--r--tests/ui/borrowck/uninitalized-in-match-arm-issue-126133.rs22
-rw-r--r--tests/ui/borrowck/uninitalized-in-match-arm-issue-126133.stderr15
3 files changed, 54 insertions, 4 deletions
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index 821a9036654..f32ff57fe88 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -557,8 +557,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         // for the branching codepaths that aren't covered, to point at them.
         let map = self.infcx.tcx.hir();
         let body = map.body_owned_by(self.mir_def_id());
-
-        let mut visitor = ConditionVisitor { spans: &spans, name: &name, errors: vec![] };
+        let mut visitor =
+            ConditionVisitor { tcx: self.infcx.tcx, spans: &spans, name: &name, errors: vec![] };
         visitor.visit_body(&body);
 
         let mut show_assign_sugg = false;
@@ -4372,13 +4372,14 @@ impl<'hir> Visitor<'hir> for BreakFinder {
 
 /// Given a set of spans representing statements initializing the relevant binding, visit all the
 /// function expressions looking for branching code paths that *do not* initialize the binding.
-struct ConditionVisitor<'b> {
+struct ConditionVisitor<'b, 'tcx> {
+    tcx: TyCtxt<'tcx>,
     spans: &'b [Span],
     name: &'b str,
     errors: Vec<(Span, String)>,
 }
 
-impl<'b, 'v> Visitor<'v> for ConditionVisitor<'b> {
+impl<'b, 'v, 'tcx> Visitor<'v> for ConditionVisitor<'b, 'tcx> {
     fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) {
         match ex.kind {
             hir::ExprKind::If(cond, body, None) => {
@@ -4464,6 +4465,12 @@ impl<'b, 'v> Visitor<'v> for ConditionVisitor<'b> {
                                     ),
                                 ));
                             } else if let Some(guard) = &arm.guard {
+                                if matches!(
+                                    self.tcx.hir_node(arm.body.hir_id),
+                                    hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Ret(_), .. })
+                                ) {
+                                    continue;
+                                }
                                 self.errors.push((
                                     arm.pat.span.to(guard.span),
                                     format!(
@@ -4473,6 +4480,12 @@ impl<'b, 'v> Visitor<'v> for ConditionVisitor<'b> {
                                     ),
                                 ));
                             } else {
+                                if matches!(
+                                    self.tcx.hir_node(arm.body.hir_id),
+                                    hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Ret(_), .. })
+                                ) {
+                                    continue;
+                                }
                                 self.errors.push((
                                     arm.pat.span,
                                     format!(
diff --git a/tests/ui/borrowck/uninitalized-in-match-arm-issue-126133.rs b/tests/ui/borrowck/uninitalized-in-match-arm-issue-126133.rs
new file mode 100644
index 00000000000..1974bbf9fe7
--- /dev/null
+++ b/tests/ui/borrowck/uninitalized-in-match-arm-issue-126133.rs
@@ -0,0 +1,22 @@
+enum E {
+    A,
+    B,
+    C,
+}
+
+fn foo(e: E) {
+    let bar;
+
+    match e {
+        E::A if true => return,
+        E::A => return,
+        E::B => {}
+        E::C => {
+            bar = 5;
+        }
+    }
+
+    let _baz = bar; //~ ERROR E0381
+}
+
+fn main() {}
diff --git a/tests/ui/borrowck/uninitalized-in-match-arm-issue-126133.stderr b/tests/ui/borrowck/uninitalized-in-match-arm-issue-126133.stderr
new file mode 100644
index 00000000000..eb7d0f8b204
--- /dev/null
+++ b/tests/ui/borrowck/uninitalized-in-match-arm-issue-126133.stderr
@@ -0,0 +1,15 @@
+error[E0381]: used binding `bar` is possibly-uninitialized
+  --> $DIR/uninitalized-in-match-arm-issue-126133.rs:19:16
+   |
+LL |     let bar;
+   |         --- binding declared here but left uninitialized
+...
+LL |         E::B => {}
+   |         ---- if this pattern is matched, `bar` is not initialized
+...
+LL |     let _baz = bar;
+   |                ^^^ `bar` used here but it is possibly-uninitialized
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0381`.