diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index fda7c7aeb3306..adaf48f60b87a 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -497,6 +497,90 @@ 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: + +``` +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 +1229,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 7c6c76f130efe..e3c2a9300baf8 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)); } } }