Merge #519
519: support ref-patterns r=matklad a=matklad Co-authored-by: Aleksey Kladov <aleksey.kladov@gmail.com>
This commit is contained in:
commit
ff3d91bb0c
@ -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,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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()
|
||||
}
|
||||
|
@ -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)]
|
||||
|
@ -462,7 +462,7 @@ Grammar(
|
||||
],
|
||||
),
|
||||
|
||||
"RefPat": (),
|
||||
"RefPat": ( options: [ "Pat" ]),
|
||||
"BindPat": ( traits: ["NameOwner"] ),
|
||||
"PlaceholderPat": (),
|
||||
"PathPat": (),
|
||||
|
Loading…
Reference in New Issue
Block a user