diff --git a/src/parser/grammar/patterns.rs b/src/parser/grammar/patterns.rs index 6e4f2236bfd..a5d13a12468 100644 --- a/src/parser/grammar/patterns.rs +++ b/src/parser/grammar/patterns.rs @@ -4,7 +4,7 @@ pub(super) fn pattern(p: &mut Parser) { match p.current() { UNDERSCORE => placeholder_pat(p), AMPERSAND => ref_pat(p), - IDENT | REF_KW => bind_pat(p), + IDENT | REF_KW | MUT_KW => bind_pat(p), _ => p.err_and_bump("expected pattern"), } } @@ -35,14 +35,18 @@ fn ref_pat(p: &mut Parser) { // test bind_pat // fn main() { // let a = (); -// let ref b = (); -// let ref mut c = (); -// let d @ _ = (); +// let mut b = (); +// let ref c = (); +// let ref mut d = (); +// let e @ _ = (); +// let ref mut f @ g @ _ = (); // } fn bind_pat(p: &mut Parser) { let m = p.start(); if p.eat(REF_KW) { p.eat(MUT_KW); + } else { + p.eat(MUT_KW); } name(p); if p.eat(AT) { diff --git a/tests/data/parser/inline/0034_bind_pat.rs b/tests/data/parser/inline/0034_bind_pat.rs index 604db24079b..820a9e72ce5 100644 --- a/tests/data/parser/inline/0034_bind_pat.rs +++ b/tests/data/parser/inline/0034_bind_pat.rs @@ -1,6 +1,8 @@ fn main() { let a = (); - let ref b = (); - let ref mut c = (); - let d @ _ = (); + let mut b = (); + let ref c = (); + let ref mut d = (); + let e @ _ = (); + let ref mut f @ g @ _ = (); } diff --git a/tests/data/parser/inline/0034_bind_pat.txt b/tests/data/parser/inline/0034_bind_pat.txt index c799a560c73..f4eb8bc4d1e 100644 --- a/tests/data/parser/inline/0034_bind_pat.txt +++ b/tests/data/parser/inline/0034_bind_pat.txt @@ -1,5 +1,5 @@ -FILE@[0; 94) - FN_ITEM@[0; 94) +FILE@[0; 146) + FN_ITEM@[0; 146) FN_KW@[0; 2) NAME@[2; 7) WHITESPACE@[2; 3) @@ -8,7 +8,7 @@ FILE@[0; 94) L_PAREN@[7; 8) R_PAREN@[8; 9) WHITESPACE@[9; 10) - BLOCK@[10; 94) + BLOCK@[10; 146) L_CURLY@[10; 11) LET_STMT@[11; 32) WHITESPACE@[11; 16) @@ -29,7 +29,7 @@ FILE@[0; 94) LET_KW@[32; 35) BIND_PAT@[35; 42) WHITESPACE@[35; 36) - REF_KW@[36; 39) + MUT_KW@[36; 39) NAME@[39; 42) WHITESPACE@[39; 40) IDENT@[40; 41) "b" @@ -41,35 +41,32 @@ FILE@[0; 94) R_PAREN@[45; 46) SEMI@[46; 47) WHITESPACE@[47; 52) - LET_STMT@[52; 76) + LET_STMT@[52; 72) LET_KW@[52; 55) - BIND_PAT@[55; 66) + BIND_PAT@[55; 62) WHITESPACE@[55; 56) REF_KW@[56; 59) - WHITESPACE@[59; 60) - MUT_KW@[60; 63) - NAME@[63; 66) - WHITESPACE@[63; 64) - IDENT@[64; 65) "c" - WHITESPACE@[65; 66) - EQ@[66; 67) - TUPLE_EXPR@[67; 70) - WHITESPACE@[67; 68) - L_PAREN@[68; 69) - R_PAREN@[69; 70) - SEMI@[70; 71) - WHITESPACE@[71; 76) - LET_STMT@[76; 92) - LET_KW@[76; 79) - BIND_PAT@[79; 86) - NAME@[79; 82) - WHITESPACE@[79; 80) - IDENT@[80; 81) "d" - WHITESPACE@[81; 82) - AT@[82; 83) - PLACEHOLDER_PAT@[83; 86) + NAME@[59; 62) + WHITESPACE@[59; 60) + IDENT@[60; 61) "c" + WHITESPACE@[61; 62) + EQ@[62; 63) + TUPLE_EXPR@[63; 66) + WHITESPACE@[63; 64) + L_PAREN@[64; 65) + R_PAREN@[65; 66) + SEMI@[66; 67) + WHITESPACE@[67; 72) + LET_STMT@[72; 96) + LET_KW@[72; 75) + BIND_PAT@[75; 86) + WHITESPACE@[75; 76) + REF_KW@[76; 79) + WHITESPACE@[79; 80) + MUT_KW@[80; 83) + NAME@[83; 86) WHITESPACE@[83; 84) - UNDERSCORE@[84; 85) + IDENT@[84; 85) "d" WHITESPACE@[85; 86) EQ@[86; 87) TUPLE_EXPR@[87; 90) @@ -77,6 +74,54 @@ FILE@[0; 94) L_PAREN@[88; 89) R_PAREN@[89; 90) SEMI@[90; 91) - WHITESPACE@[91; 92) - R_CURLY@[92; 93) - WHITESPACE@[93; 94) + WHITESPACE@[91; 96) + LET_STMT@[96; 116) + LET_KW@[96; 99) + BIND_PAT@[99; 106) + NAME@[99; 102) + WHITESPACE@[99; 100) + IDENT@[100; 101) "e" + WHITESPACE@[101; 102) + AT@[102; 103) + PLACEHOLDER_PAT@[103; 106) + WHITESPACE@[103; 104) + UNDERSCORE@[104; 105) + WHITESPACE@[105; 106) + EQ@[106; 107) + TUPLE_EXPR@[107; 110) + WHITESPACE@[107; 108) + L_PAREN@[108; 109) + R_PAREN@[109; 110) + SEMI@[110; 111) + WHITESPACE@[111; 116) + LET_STMT@[116; 144) + LET_KW@[116; 119) + BIND_PAT@[119; 138) + WHITESPACE@[119; 120) + REF_KW@[120; 123) + WHITESPACE@[123; 124) + MUT_KW@[124; 127) + NAME@[127; 130) + WHITESPACE@[127; 128) + IDENT@[128; 129) "f" + WHITESPACE@[129; 130) + AT@[130; 131) + BIND_PAT@[131; 138) + NAME@[131; 134) + WHITESPACE@[131; 132) + IDENT@[132; 133) "g" + WHITESPACE@[133; 134) + AT@[134; 135) + PLACEHOLDER_PAT@[135; 138) + WHITESPACE@[135; 136) + UNDERSCORE@[136; 137) + WHITESPACE@[137; 138) + EQ@[138; 139) + TUPLE_EXPR@[139; 142) + WHITESPACE@[139; 140) + L_PAREN@[140; 141) + R_PAREN@[141; 142) + SEMI@[142; 143) + WHITESPACE@[143; 144) + R_CURLY@[144; 145) + WHITESPACE@[145; 146) diff --git a/tools/src/lib.rs b/tools/src/lib.rs index 7a0de3e3c80..21a9468bcab 100644 --- a/tools/src/lib.rs +++ b/tools/src/lib.rs @@ -3,24 +3,12 @@ extern crate itertools; use std::hash; use itertools::Itertools; -#[derive(Debug, Eq)] +#[derive(Debug)] pub struct Test { pub name: String, pub text: String, } -impl PartialEq for Test { - fn eq(&self, other: &Test) -> bool { - self.name.eq(&other.name) - } -} - -impl hash::Hash for Test { - fn hash(&self, state: &mut H) { - self.name.hash(state) - } -} - pub fn collect_tests(s: &str) -> Vec<(usize, Test)> { let mut res = vec![]; let prefix = "// "; diff --git a/tools/src/main.rs b/tools/src/main.rs index 84a0cf1b6e8..3acb6e7ed08 100644 --- a/tools/src/main.rs +++ b/tools/src/main.rs @@ -8,7 +8,7 @@ extern crate tools; #[macro_use] extern crate commandspec; -use std::{collections::{HashSet, HashMap}, fs, path::Path}; +use std::{collections::{HashMap}, fs, path::{Path, PathBuf}}; use clap::{App, Arg, SubCommand}; use tools::{collect_tests, Test}; @@ -104,21 +104,27 @@ fn gen_tests(verify: bool) -> Result<()> { } let existing = existing_tests(inline_tests_dir)?; - for t in existing.difference(&tests) { - panic!("Test is deleted: {}\n{}", t.name, t.text); + for t in existing.keys().filter(|&t| !tests.contains_key(t)) { + panic!("Test is deleted: {}", t); } - let new_tests = tests.difference(&existing); - for (i, t) in new_tests.enumerate() { - let name = format!("{:04}_{}.rs", existing.len() + i + 1, t.name); - let path = inline_tests_dir.join(name); - update(&path, &t.text, verify)?; + let mut new_idx = existing.len() + 2; + for (name, test) in tests { + let path = match existing.get(&name) { + Some((path, _test)) => path.clone(), + None => { + let file_name = format!("{:04}_{}.rs", new_idx, name); + new_idx += 1; + inline_tests_dir.join(file_name) + } + }; + update(&path, &test.text, verify)?; } Ok(()) } -fn tests_from_dir(dir: &Path) -> Result> { - let mut res = HashSet::new(); +fn tests_from_dir(dir: &Path) -> Result> { + let mut res = HashMap::new(); for entry in ::walkdir::WalkDir::new(dir) { let entry = entry.unwrap(); if !entry.file_type().is_file() { @@ -130,7 +136,7 @@ fn tests_from_dir(dir: &Path) -> Result> { let text = fs::read_to_string(entry.path())?; for (_, test) in collect_tests(&text) { - if let Some(old_test) = res.replace(test) { + if let Some(old_test) = res.insert(test.name.clone(), test) { bail!("Duplicate test: {}", old_test.name) } } @@ -138,18 +144,24 @@ fn tests_from_dir(dir: &Path) -> Result> { Ok(res) } -fn existing_tests(dir: &Path) -> Result> { - let mut res = HashSet::new(); +fn existing_tests(dir: &Path) -> Result> { + let mut res = HashMap::new(); for file in fs::read_dir(dir)? { let file = file?; let path = file.path(); if path.extension().unwrap_or_default() != "rs" { continue; } - let name = path.file_name().unwrap().to_str().unwrap(); - let name = name["0000_".len()..name.len() - 3].to_string(); + let name = { + let file_name = path.file_name().unwrap().to_str().unwrap(); + file_name[5..file_name.len() - 3].to_string() + }; let text = fs::read_to_string(&path)?; - res.insert(Test { name, text }); + let test = Test { name: name.clone(), text }; + match res.insert(name, (path, test)) { + Some(old) => println!("Duplicate test: {:?}", old), + None => (), + } } Ok(res) }