Rollup merge of #114454 - Nilstrieb:no-evil-sorting, r=cjgillot

Replace `HashMap` with `IndexMap` in pattern binding resolve

fixes https://github.com/rust-lang/rust/pull/114332#discussion_r1284189179
This commit is contained in:
Tyler Mandry 2023-10-02 16:09:42 -04:00 committed by GitHub
commit af77806bee
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 98 additions and 100 deletions

View file

@ -41,9 +41,6 @@ type Res = def::Res<NodeId>;
type IdentMap<T> = FxHashMap<Ident, T>; type IdentMap<T> = FxHashMap<Ident, T>;
/// Map from the name in a pattern to its binding mode.
type BindingMap = IdentMap<BindingInfo>;
use diagnostics::{ use diagnostics::{
ElisionFnParameter, LifetimeElisionCandidate, MissingLifetime, MissingLifetimeKind, ElisionFnParameter, LifetimeElisionCandidate, MissingLifetime, MissingLifetimeKind,
}; };
@ -3164,8 +3161,8 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
/// this is done hygienically. This could arise for a macro /// this is done hygienically. This could arise for a macro
/// that expands into an or-pattern where one 'x' was from the /// that expands into an or-pattern where one 'x' was from the
/// user and one 'x' came from the macro. /// user and one 'x' came from the macro.
fn binding_mode_map(&mut self, pat: &Pat) -> BindingMap { fn binding_mode_map(&mut self, pat: &Pat) -> FxIndexMap<Ident, BindingInfo> {
let mut binding_map = FxHashMap::default(); let mut binding_map = FxIndexMap::default();
pat.walk(&mut |pat| { pat.walk(&mut |pat| {
match pat.kind { match pat.kind {
@ -3200,22 +3197,28 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
/// Checks that all of the arms in an or-pattern have exactly the /// Checks that all of the arms in an or-pattern have exactly the
/// same set of bindings, with the same binding modes for each. /// same set of bindings, with the same binding modes for each.
fn check_consistent_bindings(&mut self, pats: &[P<Pat>]) -> Vec<BindingMap> { fn check_consistent_bindings(
let mut missing_vars = FxHashMap::default(); &mut self,
let mut inconsistent_vars = FxHashMap::default(); pats: &[P<Pat>],
) -> Vec<FxIndexMap<Ident, BindingInfo>> {
// pats is consistent.
let mut missing_vars = FxIndexMap::default();
let mut inconsistent_vars = FxIndexMap::default();
// 1) Compute the binding maps of all arms. // 1) Compute the binding maps of all arms.
let maps = pats.iter().map(|pat| self.binding_mode_map(pat)).collect::<Vec<_>>(); let maps = pats.iter().map(|pat| self.binding_mode_map(pat)).collect::<Vec<_>>();
// 2) Record any missing bindings or binding mode inconsistencies. // 2) Record any missing bindings or binding mode inconsistencies.
for (map_outer, pat_outer) in pats.iter().enumerate().map(|(idx, pat)| (&maps[idx], pat)) { for (map_outer, pat_outer) in maps.iter().zip(pats.iter()) {
// Check against all arms except for the same pattern which is always self-consistent. // Check against all arms except for the same pattern which is always self-consistent.
let inners = pats let inners = maps
.iter() .iter()
.enumerate() .zip(pats.iter())
.filter(|(_, pat)| pat.id != pat_outer.id) .filter(|(_, pat)| pat.id != pat_outer.id)
.flat_map(|(idx, _)| maps[idx].iter()) .flat_map(|(map, _)| map)
.map(|(key, binding)| (key.name, map_outer.get(&key), binding)); .map(|(key, binding)| (key.name, map_outer.get(key), binding));
let inners = inners.collect::<Vec<_>>();
for (name, info, &binding_inner) in inners { for (name, info, &binding_inner) in inners {
match info { match info {
@ -3244,10 +3247,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
} }
// 3) Report all missing variables we found. // 3) Report all missing variables we found.
let mut missing_vars = missing_vars.into_iter().collect::<Vec<_>>(); for (name, mut v) in missing_vars {
missing_vars.sort_by_key(|&(sym, ref _err)| sym);
for (name, mut v) in missing_vars.into_iter() {
if inconsistent_vars.contains_key(&name) { if inconsistent_vars.contains_key(&name) {
v.could_be_path = false; v.could_be_path = false;
} }
@ -3258,10 +3258,8 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
} }
// 4) Report all inconsistencies in binding modes we found. // 4) Report all inconsistencies in binding modes we found.
let mut inconsistent_vars = inconsistent_vars.iter().collect::<Vec<_>>();
inconsistent_vars.sort();
for (name, v) in inconsistent_vars { for (name, v) in inconsistent_vars {
self.report_error(v.0, ResolutionError::VariableBoundWithDifferentMode(*name, v.1)); self.report_error(v.0, ResolutionError::VariableBoundWithDifferentMode(name, v.1));
} }
// 5) Finally bubble up all the binding maps. // 5) Finally bubble up all the binding maps.

View file

@ -103,22 +103,6 @@ LL | let (A(A(a, b) | B(c), d) | B(e)) = Y;
| | | |
| variable not in all patterns | variable not in all patterns
error[E0408]: variable `c` is not bound in all patterns
--> $DIR/missing-bindings.rs:45:33
|
LL | let (A(A(a, b) | B(c), d) | B(e)) = Y;
| - ^^^^ pattern doesn't bind `c`
| |
| variable not in all patterns
error[E0408]: variable `d` is not bound in all patterns
--> $DIR/missing-bindings.rs:45:33
|
LL | let (A(A(a, b) | B(c), d) | B(e)) = Y;
| - ^^^^ pattern doesn't bind `d`
| |
| variable not in all patterns
error[E0408]: variable `e` is not bound in all patterns error[E0408]: variable `e` is not bound in all patterns
--> $DIR/missing-bindings.rs:45:10 --> $DIR/missing-bindings.rs:45:10
| |
@ -143,6 +127,22 @@ LL | let (A(A(a, b) | B(c), d) | B(e)) = Y;
| | | |
| variable not in all patterns | variable not in all patterns
error[E0408]: variable `c` is not bound in all patterns
--> $DIR/missing-bindings.rs:45:33
|
LL | let (A(A(a, b) | B(c), d) | B(e)) = Y;
| - ^^^^ pattern doesn't bind `c`
| |
| variable not in all patterns
error[E0408]: variable `d` is not bound in all patterns
--> $DIR/missing-bindings.rs:45:33
|
LL | let (A(A(a, b) | B(c), d) | B(e)) = Y;
| - ^^^^ pattern doesn't bind `d`
| |
| variable not in all patterns
error[E0408]: variable `a` is not bound in all patterns error[E0408]: variable `a` is not bound in all patterns
--> $DIR/missing-bindings.rs:61:29 --> $DIR/missing-bindings.rs:61:29
| |
@ -151,14 +151,6 @@ LL | Ok(a) | Err(_),
| | | |
| variable not in all patterns | variable not in all patterns
error[E0408]: variable `a` is not bound in all patterns
--> $DIR/missing-bindings.rs:69:21
|
LL | A(_, a) |
| - variable not in all patterns
LL | B(b),
| ^^^^ pattern doesn't bind `a`
error[E0408]: variable `b` is not bound in all patterns error[E0408]: variable `b` is not bound in all patterns
--> $DIR/missing-bindings.rs:68:21 --> $DIR/missing-bindings.rs:68:21
| |
@ -167,6 +159,14 @@ LL | A(_, a) |
LL | B(b), LL | B(b),
| - variable not in all patterns | - variable not in all patterns
error[E0408]: variable `a` is not bound in all patterns
--> $DIR/missing-bindings.rs:69:21
|
LL | A(_, a) |
| - variable not in all patterns
LL | B(b),
| ^^^^ pattern doesn't bind `a`
error[E0408]: variable `a` is not bound in all patterns error[E0408]: variable `a` is not bound in all patterns
--> $DIR/missing-bindings.rs:72:17 --> $DIR/missing-bindings.rs:72:17
| |
@ -185,6 +185,24 @@ LL | B(b),
LL | B(_) LL | B(_)
| ^^^^ pattern doesn't bind `b` | ^^^^ pattern doesn't bind `b`
error[E0408]: variable `b` is not bound in all patterns
--> $DIR/missing-bindings.rs:57:13
|
LL | / V1(
LL | |
LL | |
LL | | A(
... |
LL | | B(Ok(a) | Err(a))
LL | | ) |
| |_____________^ pattern doesn't bind `b`
...
LL | B(b),
| - variable not in all patterns
...
LL | V3(c),
| ^^^^^ pattern doesn't bind `b`
error[E0408]: variable `c` is not bound in all patterns error[E0408]: variable `c` is not bound in all patterns
--> $DIR/missing-bindings.rs:57:13 --> $DIR/missing-bindings.rs:57:13
| |
@ -219,24 +237,6 @@ LL | A(_, a) |
LL | V3(c), LL | V3(c),
| ^^^^^ pattern doesn't bind `a` | ^^^^^ pattern doesn't bind `a`
error[E0408]: variable `b` is not bound in all patterns
--> $DIR/missing-bindings.rs:57:13
|
LL | / V1(
LL | |
LL | |
LL | | A(
... |
LL | | B(Ok(a) | Err(a))
LL | | ) |
| |_____________^ pattern doesn't bind `b`
...
LL | B(b),
| - variable not in all patterns
...
LL | V3(c),
| ^^^^^ pattern doesn't bind `b`
error: aborting due to 26 previous errors error: aborting due to 26 previous errors
For more information about this error, try `rustc --explain E0408`. For more information about this error, try `rustc --explain E0408`.

View file

@ -1,11 +1,3 @@
error[E0408]: variable `a` is not bound in all patterns
--> $DIR/resolve-inconsistent-names.rs:13:12
|
LL | a | b => {}
| - ^ pattern doesn't bind `a`
| |
| variable not in all patterns
error[E0408]: variable `b` is not bound in all patterns error[E0408]: variable `b` is not bound in all patterns
--> $DIR/resolve-inconsistent-names.rs:13:8 --> $DIR/resolve-inconsistent-names.rs:13:8
| |
@ -14,6 +6,14 @@ LL | a | b => {}
| | | |
| pattern doesn't bind `b` | pattern doesn't bind `b`
error[E0408]: variable `a` is not bound in all patterns
--> $DIR/resolve-inconsistent-names.rs:13:12
|
LL | a | b => {}
| - ^ pattern doesn't bind `a`
| |
| variable not in all patterns
error[E0408]: variable `c` is not bound in all patterns error[E0408]: variable `c` is not bound in all patterns
--> $DIR/resolve-inconsistent-names.rs:19:9 --> $DIR/resolve-inconsistent-names.rs:19:9
| |
@ -54,6 +54,19 @@ LL | (A, B) | (ref B, c) | (c, A) => ()
| | | |
| first binding | first binding
error[E0408]: variable `Const2` is not bound in all patterns
--> $DIR/resolve-inconsistent-names.rs:31:9
|
LL | (CONST1, _) | (_, Const2) => ()
| ^^^^^^^^^^^ ------ variable not in all patterns
| |
| pattern doesn't bind `Const2`
|
help: if you meant to match on constant `m::Const2`, use the full path in the pattern
|
LL | (CONST1, _) | (_, m::Const2) => ()
| ~~~~~~~~~
error[E0408]: variable `CONST1` is not bound in all patterns error[E0408]: variable `CONST1` is not bound in all patterns
--> $DIR/resolve-inconsistent-names.rs:31:23 --> $DIR/resolve-inconsistent-names.rs:31:23
| |
@ -68,19 +81,6 @@ note: you might have meant to match on constant `m::CONST1`, which exists but is
LL | const CONST1: usize = 10; LL | const CONST1: usize = 10;
| ^^^^^^^^^^^^^^^^^^^^^^^^^ not accessible | ^^^^^^^^^^^^^^^^^^^^^^^^^ not accessible
error[E0408]: variable `Const2` is not bound in all patterns
--> $DIR/resolve-inconsistent-names.rs:31:9
|
LL | (CONST1, _) | (_, Const2) => ()
| ^^^^^^^^^^^ ------ variable not in all patterns
| |
| pattern doesn't bind `Const2`
|
help: if you meant to match on constant `m::Const2`, use the full path in the pattern
|
LL | (CONST1, _) | (_, m::Const2) => ()
| ~~~~~~~~~
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/resolve-inconsistent-names.rs:19:19 --> $DIR/resolve-inconsistent-names.rs:19:19
| |

View file

@ -1,3 +1,13 @@
error[E0408]: variable `b` is not bound in all patterns
--> $DIR/issue-39698.rs:10:9
|
LL | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^^^^^^^^^^^ - ^^^^^^^^ ^^^^^^^^ pattern doesn't bind `b`
| | | |
| | | pattern doesn't bind `b`
| | variable not in all patterns
| pattern doesn't bind `b`
error[E0408]: variable `c` is not bound in all patterns error[E0408]: variable `c` is not bound in all patterns
--> $DIR/issue-39698.rs:10:9 --> $DIR/issue-39698.rs:10:9
| |
@ -8,16 +18,6 @@ LL | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}
| | pattern doesn't bind `c` | | pattern doesn't bind `c`
| pattern doesn't bind `c` | pattern doesn't bind `c`
error[E0408]: variable `d` is not bound in all patterns
--> $DIR/issue-39698.rs:10:37
|
LL | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| - - ^^^^^^^^ ^^^^^^^^ pattern doesn't bind `d`
| | | |
| | | pattern doesn't bind `d`
| | variable not in all patterns
| variable not in all patterns
error[E0408]: variable `a` is not bound in all patterns error[E0408]: variable `a` is not bound in all patterns
--> $DIR/issue-39698.rs:10:23 --> $DIR/issue-39698.rs:10:23
| |
@ -28,15 +28,15 @@ LL | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}
| | pattern doesn't bind `a` | | pattern doesn't bind `a`
| variable not in all patterns | variable not in all patterns
error[E0408]: variable `b` is not bound in all patterns error[E0408]: variable `d` is not bound in all patterns
--> $DIR/issue-39698.rs:10:9 --> $DIR/issue-39698.rs:10:37
| |
LL | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); } LL | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^^^^^^^^^^^ - ^^^^^^^^ ^^^^^^^^ pattern doesn't bind `b` | - - ^^^^^^^^ ^^^^^^^^ pattern doesn't bind `d`
| | | | | | | |
| | | pattern doesn't bind `b` | | | pattern doesn't bind `d`
| | variable not in all patterns | | variable not in all patterns
| pattern doesn't bind `b` | variable not in all patterns
error: aborting due to 4 previous errors error: aborting due to 4 previous errors