about summary refs log tree commit diff
diff options
context:
space:
mode:
authorManish Goregaokar <manishsmail@gmail.com>2016-05-09 15:00:14 -0700
committerManish Goregaokar <manishsmail@gmail.com>2016-05-09 15:00:20 -0700
commit52f48bdcb5260fa82df840c8224338dd28b7b818 (patch)
treebba6328b56f6a5e4086c4fb73ae57d55c20c3c31
parent433f907050432af6396a317525f60579c604b3e0 (diff)
parent84843b73dc8e54f1e8c1e4418b7d56dbd513dd65 (diff)
Rollup merge of #33493 - Manishearth:more-diag, r=Manishearth
 r? @GuillaumeGomez
-rw-r--r--src/librustc_resolve/diagnostics.rs90
-rw-r--r--src/librustc_resolve/lib.rs25
2 files changed, 94 insertions, 21 deletions
diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs
index fda7c7aeb33..35148622052 100644
--- a/src/librustc_resolve/diagnostics.rs
+++ b/src/librustc_resolve/diagnostics.rs
@@ -497,6 +497,91 @@ impl Bar {
 ```
 "##,
 
+E0408: r##"
+An "or" pattern was used where the variable bindings are not consistently bound
+across patterns.
+
+Example of erroneous code:
+
+```compile_fail
+match x {
+    Some(y) | None => { /* use y */ } // error: variable `y` from pattern #1 is
+                                      //        not bound in pattern #2
+    _ => ()
+}
+```
+
+Here, `y` is bound to the contents of the `Some` and can be used within the
+block corresponding to the match arm. However, in case `x` is `None`, we have
+not specified what `y` is, and the block will use a nonexistent variable.
+
+To fix this error, either split into multiple match arms:
+
+```
+let x = Some(1);
+match x {
+    Some(y) => { /* use y */ }
+    None => { /* ... */ }
+}
+```
+
+or, bind the variable to a field of the same type in all sub-patterns of the
+or pattern:
+
+```
+let x = (0, 2);
+match x {
+    (0, y) | (y, 0) => { /* use y */}
+    _ => {}
+}
+```
+
+In this example, if `x` matches the pattern `(0, _)`, the second field is set
+to `y`. If it matches `(_, 0)`, the first field is set to `y`; so in all
+cases `y` is set to some value.
+"##,
+
+E0409: r##"
+An "or" pattern was used where the variable bindings are not consistently bound
+across patterns.
+
+Example of erroneous code:
+
+```compile_fail
+let x = (0, 2);
+match x {
+    (0, ref y) | (y, 0) => { /* use y */} // error: variable `y` is bound with
+                                          //        different mode in pattern #2
+                                          //        than in pattern #1
+    _ => ()
+}
+```
+
+Here, `y` is bound by-value in one case and by-reference in the other.
+
+To fix this error, just use the same mode in both cases.
+Generally using `ref` or `ref mut` where not already used will fix this:
+
+```ignore
+let x = (0, 2);
+match x {
+    (0, ref y) | (ref y, 0) => { /* use y */}
+    _ => ()
+}
+```
+
+Alternatively, split the pattern:
+
+```
+let x = (0, 2);
+match x {
+    (y, 0) => { /* use y */ }
+    (0, ref y) => { /* use y */}
+    _ => ()
+}
+```
+"##,
+
 E0411: r##"
 The `Self` keyword was used outside an impl or a trait. Erroneous code example:
 
@@ -1145,10 +1230,7 @@ register_diagnostics! {
 //  E0258,
     E0402, // cannot use an outer type parameter in this context
     E0406, // undeclared associated type
-    E0408, // variable from pattern #1 is not bound in pattern #
-    E0409, // variable is bound with different mode in pattern # than in
-           // pattern #1
-    E0410, // variable from pattern is not bound in pattern 1
+//  E0410, merged into 408
     E0418, // is not an enum variant, struct or const
     E0420, // is not an associated const
     E0421, // unresolved associated const
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index 7c6c76f130e..e3c2a9300ba 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -126,12 +126,10 @@ enum ResolutionError<'a> {
     TypeNotMemberOfTrait(Name, &'a str),
     /// error E0438: const is not a member of trait
     ConstNotMemberOfTrait(Name, &'a str),
-    /// error E0408: variable `{}` from pattern #1 is not bound in pattern
-    VariableNotBoundInPattern(Name, usize),
+    /// error E0408: variable `{}` from pattern #{} is not bound in pattern #{}
+    VariableNotBoundInPattern(Name, usize, usize),
     /// error E0409: variable is bound with different mode in pattern #{} than in pattern #1
     VariableBoundWithDifferentMode(Name, usize),
-    /// error E0410: variable from pattern is not bound in pattern #1
-    VariableNotBoundInParentPattern(Name, usize),
     /// error E0411: use of `Self` outside of an impl or trait
     SelfUsedOutsideImplOrTrait,
     /// error E0412: use of undeclared
@@ -272,13 +270,14 @@ fn resolve_struct_error<'b, 'a: 'b, 'tcx: 'a>(resolver: &'b Resolver<'a, 'tcx>,
                              const_,
                              trait_)
         }
-        ResolutionError::VariableNotBoundInPattern(variable_name, pattern_number) => {
+        ResolutionError::VariableNotBoundInPattern(variable_name, from, to) => {
             struct_span_err!(resolver.session,
                              span,
                              E0408,
-                             "variable `{}` from pattern #1 is not bound in pattern #{}",
+                             "variable `{}` from pattern #{} is not bound in pattern #{}",
                              variable_name,
-                             pattern_number)
+                             from,
+                             to)
         }
         ResolutionError::VariableBoundWithDifferentMode(variable_name, pattern_number) => {
             struct_span_err!(resolver.session,
@@ -289,14 +288,6 @@ fn resolve_struct_error<'b, 'a: 'b, 'tcx: 'a>(resolver: &'b Resolver<'a, 'tcx>,
                              variable_name,
                              pattern_number)
         }
-        ResolutionError::VariableNotBoundInParentPattern(variable_name, pattern_number) => {
-            struct_span_err!(resolver.session,
-                             span,
-                             E0410,
-                             "variable `{}` from pattern #{} is not bound in pattern #1",
-                             variable_name,
-                             pattern_number)
-        }
         ResolutionError::SelfUsedOutsideImplOrTrait => {
             struct_span_err!(resolver.session,
                              span,
@@ -2038,7 +2029,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                     None => {
                         resolve_error(self,
                                       p.span,
-                                      ResolutionError::VariableNotBoundInPattern(key, i + 1));
+                                      ResolutionError::VariableNotBoundInPattern(key, 1, i + 1));
                     }
                     Some(binding_i) => {
                         if binding_0.binding_mode != binding_i.binding_mode {
@@ -2055,7 +2046,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                 if !map_0.contains_key(&key) {
                     resolve_error(self,
                                   binding.span,
-                                  ResolutionError::VariableNotBoundInParentPattern(key, i + 1));
+                                  ResolutionError::VariableNotBoundInPattern(key, i + 1, 1));
                 }
             }
         }