519: support ref-patterns r=matklad a=matklad



Co-authored-by: Aleksey Kladov <aleksey.kladov@gmail.com>
This commit is contained in:
bors[bot] 2019-01-13 10:36:30 +00:00
commit ff3d91bb0c
5 changed files with 46 additions and 11 deletions

View File

@ -422,6 +422,9 @@ fn foo(x: String) {
fn do_check_local_name(code: &str, expected_offset: u32) {
let (off, code) = extract_offset(code);
let file = SourceFile::parse(&code);
let expected_name = find_node_at_offset::<ast::Name>(file.syntax(), expected_offset.into())
.expect("failed to find a name at the target offset");
let fn_def: &ast::FnDef = find_node_at_offset(file.syntax(), off).unwrap();
let name_ref: &ast::NameRef = find_node_at_offset(file.syntax(), off).unwrap();
@ -431,11 +434,8 @@ fn do_check_local_name(code: &str, expected_offset: u32) {
scopes: Arc::new(scopes),
syntax_mapping: Arc::new(body_hir),
};
let local_name_entry = scopes.resolve_local_name(name_ref).unwrap();
let local_name = local_name_entry.ptr();
let expected_name =
find_node_at_offset::<ast::Name>(file.syntax(), expected_offset.into()).unwrap();
assert_eq!(local_name.range(), expected_name.syntax().range());
}
@ -470,11 +470,26 @@ fn foo(x: String) {
fn test_resolve_local_name_shadow() {
do_check_local_name(
r"
fn foo(x: String) {
let x : &str = &x;
x<|>
}",
46,
fn foo(x: String) {
let x : &str = &x;
x<|>
}
",
53,
);
}
#[test]
fn ref_patterns_contribute_bindings() {
do_check_local_name(
r"
fn foo() {
if let Some(&from) = bar() {
from<|>;
}
}
",
53,
);
}
}

View File

@ -315,15 +315,20 @@ pub enum Pat {
path: Option<Path>,
args: Vec<PatId>,
},
Ref {
pat: PatId,
mutability: Mutability,
},
}
impl Pat {
pub fn walk_child_pats(&self, f: impl FnMut(PatId)) {
pub fn walk_child_pats(&self, mut f: impl FnMut(PatId)) {
match self {
Pat::Missing | Pat::Bind { .. } => {}
Pat::TupleStruct { args, .. } => {
args.iter().map(|pat| *pat).for_each(f);
}
Pat::Ref { pat, .. } => f(*pat),
}
}
}
@ -684,6 +689,11 @@ fn collect_pat(&mut self, pat: &ast::Pat) -> PatId {
let args = p.args().map(|p| self.collect_pat(p)).collect();
self.alloc_pat(Pat::TupleStruct { path, args }, syntax_ptr)
}
ast::PatKind::RefPat(p) => {
let pat = self.collect_pat_opt(p.pat());
let mutability = Mutability::from_mutable(p.is_mut());
self.alloc_pat(Pat::Ref { pat, mutability }, syntax_ptr)
}
_ => {
// TODO
self.alloc_pat(Pat::Missing, syntax_ptr)

View File

@ -348,6 +348,12 @@ pub fn parent_use_tree(&self) -> &UseTree {
}
}
impl RefPat {
pub fn is_mut(&self) -> bool {
self.syntax().children().any(|n| n.kind() == MUT_KW)
}
}
fn child_opt<P: AstNode, C: AstNode>(parent: &P) -> Option<&C> {
children(parent).next()
}

View File

@ -2456,7 +2456,11 @@ fn to_owned(&self) -> TreeArc<RefPat> { TreeArc::cast(self.syntax.to_owned()) }
}
impl RefPat {}
impl RefPat {
pub fn pat(&self) -> Option<&Pat> {
super::child_opt(self)
}
}
// ReferenceType
#[derive(Debug, PartialEq, Eq, Hash)]

View File

@ -462,7 +462,7 @@ Grammar(
],
),
"RefPat": (),
"RefPat": ( options: [ "Pat" ]),
"BindPat": ( traits: ["NameOwner"] ),
"PlaceholderPat": (),
"PathPat": (),