]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #54269 - PramodBisht:issue/53840, r=estebank
authorPietro Albini <pietro@pietroalbini.org>
Tue, 2 Oct 2018 20:54:27 +0000 (22:54 +0200)
committerGitHub <noreply@github.com>
Tue, 2 Oct 2018 20:54:27 +0000 (22:54 +0200)
#53840: Consolidate pattern check errors

#53840  on this PR we are aggregating `cannot bind by-move and by-ref in the same pattern` message present on the different lines into one diagnostic message. Here we are first gathering those `spans` on `vector` then we are throwing them with the help of `MultiSpan`
r? @estebank

Addresses: #53480

src/librustc_mir/hair/pattern/check_match.rs
src/test/ui/issue-53840.rs [new file with mode: 0644]
src/test/ui/issue-53840.stderr [new file with mode: 0644]

index 6187e091319e0f03fcd44ce8b2a3ed2fe62ce40f..f2ae5774da875f8eb014635cbcef5e05ba42f894 100644 (file)
@@ -35,7 +35,7 @@
 
 use syntax::ast;
 use syntax::ptr::P;
-use syntax_pos::{Span, DUMMY_SP};
+use syntax_pos::{Span, DUMMY_SP, MultiSpan};
 
 struct OuterVisitor<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx> }
 
@@ -527,8 +527,8 @@ fn check_legality_of_move_bindings(cx: &MatchVisitor,
             }
         })
     }
-
-    let check_move = |p: &Pat, sub: Option<&Pat>| {
+    let span_vec = &mut Vec::new();
+    let check_move = |p: &Pat, sub: Option<&Pat>, span_vec: &mut Vec<Span>| {
         // check legality of moving out of the enum
 
         // x @ Foo(..) is legal, but x @ Foo(y) isn't.
@@ -546,16 +546,8 @@ fn check_legality_of_move_bindings(cx: &MatchVisitor,
                           crate attributes to enable");
             }
             err.emit();
-        } else if let Some(by_ref_span) = by_ref_span {
-            struct_span_err!(
-                cx.tcx.sess,
-                p.span,
-                E0009,
-                "cannot bind by-move and by-ref in the same pattern",
-            )
-            .span_label(p.span, "by-move pattern here")
-            .span_label(by_ref_span, "both by-ref and by-move used")
-            .emit();
+        } else if let Some(_by_ref_span) = by_ref_span {
+            span_vec.push(p.span);
         }
     };
 
@@ -567,7 +559,7 @@ fn check_legality_of_move_bindings(cx: &MatchVisitor,
                         ty::BindByValue(..) => {
                             let pat_ty = cx.tables.node_id_to_type(p.hir_id);
                             if pat_ty.moves_by_default(cx.tcx, cx.param_env, pat.span) {
-                                check_move(p, sub.as_ref().map(|p| &**p));
+                                check_move(p, sub.as_ref().map(|p| &**p), span_vec);
                             }
                         }
                         _ => {}
@@ -579,6 +571,20 @@ fn check_legality_of_move_bindings(cx: &MatchVisitor,
             true
         });
     }
+    if !span_vec.is_empty(){
+        let span = MultiSpan::from_spans(span_vec.clone());
+        let mut err = struct_span_err!(
+            cx.tcx.sess,
+            span,
+            E0009,
+            "cannot bind by-move and by-ref in the same pattern",
+        );
+        err.span_label(by_ref_span.unwrap(), "both by-ref and by-move used");
+        for span in span_vec.iter(){
+            err.span_label(*span, "by-move pattern here");
+        }
+        err.emit();
+    }
 }
 
 /// Ensures that a pattern guard doesn't borrow by mutable reference or
diff --git a/src/test/ui/issue-53840.rs b/src/test/ui/issue-53840.rs
new file mode 100644 (file)
index 0000000..ece3caf
--- /dev/null
@@ -0,0 +1,27 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+enum E {
+    Foo(String, String, String),
+}
+
+struct Bar {
+    a: String,
+    b: String,
+}
+
+fn main() {
+    let bar = Bar { a: "1".to_string(), b: "2".to_string() };
+    match E::Foo("".into(), "".into(), "".into()) {
+        E::Foo(a, b, ref c) => {}
+    }
+    match bar {
+        Bar {a, ref b} => {}
+    }
+}
diff --git a/src/test/ui/issue-53840.stderr b/src/test/ui/issue-53840.stderr
new file mode 100644 (file)
index 0000000..961e4c0
--- /dev/null
@@ -0,0 +1,20 @@
+error[E0009]: cannot bind by-move and by-ref in the same pattern
+  --> $DIR/issue-53840.rs:22:16
+   |
+LL |         E::Foo(a, b, ref c) => {}
+   |                ^  ^  ----- both by-ref and by-move used
+   |                |  |
+   |                |  by-move pattern here
+   |                by-move pattern here
+
+error[E0009]: cannot bind by-move and by-ref in the same pattern
+  --> $DIR/issue-53840.rs:25:14
+   |
+LL |         Bar {a, ref b} => {}
+   |              ^  ----- both by-ref and by-move used
+   |              |
+   |              by-move pattern here
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0009`.