about summary refs log tree commit diff
path: root/src/librustc_mir
diff options
context:
space:
mode:
authorEsteban Küber <esteban@kuber.com.ar>2019-10-09 12:25:48 -0700
committerEsteban Küber <esteban@kuber.com.ar>2019-10-09 12:25:48 -0700
commit4bb1592402003184cd73c6ee5b135df084ea5abc (patch)
tree7653b07f00f3f4d9a901bd1ae6852a2013ef0f81 /src/librustc_mir
parentec557aa8180ca08ff749793b3d42383618b96044 (diff)
downloadrust-4bb1592402003184cd73c6ee5b135df084ea5abc.tar.gz
rust-4bb1592402003184cd73c6ee5b135df084ea5abc.zip
Suggest `if let` on `let` refutable binding
Diffstat (limited to 'src/librustc_mir')
-rw-r--r--src/librustc_mir/hair/pattern/check_match.rs36
1 files changed, 27 insertions, 9 deletions
diff --git a/src/librustc_mir/hair/pattern/check_match.rs b/src/librustc_mir/hair/pattern/check_match.rs
index c521b735221..9bed4fb66ea 100644
--- a/src/librustc_mir/hair/pattern/check_match.rs
+++ b/src/librustc_mir/hair/pattern/check_match.rs
@@ -62,12 +62,13 @@ impl<'tcx> Visitor<'tcx> for MatchVisitor<'_, 'tcx> {
     fn visit_local(&mut self, loc: &'tcx hir::Local) {
         intravisit::walk_local(self, loc);
 
-        self.check_irrefutable(&loc.pat, match loc.source {
-            hir::LocalSource::Normal => "local binding",
-            hir::LocalSource::ForLoopDesugar => "`for` loop binding",
-            hir::LocalSource::AsyncFn => "async fn binding",
-            hir::LocalSource::AwaitDesugar => "`await` future binding",
-        });
+        let (msg, sp) = match loc.source {
+            hir::LocalSource::Normal => ("local binding", Some(loc.span)),
+            hir::LocalSource::ForLoopDesugar => ("`for` loop binding", None),
+            hir::LocalSource::AsyncFn => ("async fn binding", None),
+            hir::LocalSource::AwaitDesugar => ("`await` future binding", None),
+        };
+        self.check_irrefutable(&loc.pat, msg, sp);
 
         // Check legality of move bindings and `@` patterns.
         self.check_patterns(false, &loc.pat);
@@ -77,7 +78,7 @@ impl<'tcx> Visitor<'tcx> for MatchVisitor<'_, 'tcx> {
         intravisit::walk_body(self, body);
 
         for param in &body.params {
-            self.check_irrefutable(&param.pat, "function argument");
+            self.check_irrefutable(&param.pat, "function argument", None);
             self.check_patterns(false, &param.pat);
         }
     }
@@ -242,7 +243,7 @@ impl<'tcx> MatchVisitor<'_, 'tcx> {
         })
     }
 
-    fn check_irrefutable(&self, pat: &'tcx Pat, origin: &str) {
+    fn check_irrefutable(&self, pat: &'tcx Pat, origin: &str, sp: Option<Span>) {
         let module = self.tcx.hir().get_module_parent(pat.hir_id);
         MatchCheckCtxt::create_and_enter(self.tcx, self.param_env, module, |ref mut cx| {
             let mut patcx = PatCtxt::new(self.tcx,
@@ -266,18 +267,35 @@ impl<'tcx> MatchVisitor<'_, 'tcx> {
                 "refutable pattern in {}: {} not covered",
                 origin, joined_patterns
             );
-            match &pat.kind {
+            let suggest_if_let = match &pat.kind {
                 hir::PatKind::Path(hir::QPath::Resolved(None, path))
                     if path.segments.len() == 1 && path.segments[0].args.is_none() =>
                 {
                     const_not_var(&mut err, cx.tcx, pat, path);
+                    false
                 }
                 _ => {
                     err.span_label(
                         pat.span,
                         pattern_not_covered_label(&witnesses, &joined_patterns),
                     );
+                    true
+                }
+            };
+
+            if let (Some(span), true) = (sp, suggest_if_let) {
+                err.note("`let` bindings require an \"irrefutable pattern\", like a `struct` or \
+                          an `enum` with only one variant");
+                if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
+                    err.span_suggestion(
+                        span,
+                        "you might want to use `if let` to ignore the variant that isn't matched",
+                        format!("if {} {{ /* */ }}", &snippet[..snippet.len() - 1]),
+                        Applicability::HasPlaceholders,
+                    );
                 }
+                err.note("for more information, visit \
+                          https://doc.rust-lang.org/book/ch18-02-refutability.html");
             }
 
             adt_defined_here(cx, &mut err, pattern_ty, &witnesses);