Skip to content

Commit 36840bd

Browse files
bors[bot]matklad
andauthored
Merge #4036
4036: Fix a bunch of unresovled references r=matklad a=matklad bors r+ 🤖 Co-authored-by: Aleksey Kladov <[email protected]>
2 parents 7a59cd4 + b79fd82 commit 36840bd

File tree

9 files changed

+87
-6
lines changed

9 files changed

+87
-6
lines changed

crates/ra_hir/src/semantics.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,10 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
195195
self.analyze(field.syntax()).resolve_record_field(self.db, field)
196196
}
197197

198+
pub fn resolve_record_field_pat(&self, field: &ast::RecordFieldPat) -> Option<StructField> {
199+
self.analyze(field.syntax()).resolve_record_field_pat(self.db, field)
200+
}
201+
198202
pub fn resolve_macro_call(&self, macro_call: &ast::MacroCall) -> Option<MacroDef> {
199203
let sa = self.analyze(macro_call.syntax());
200204
let macro_call = self.find_file(macro_call.syntax().clone()).with_value(macro_call);

crates/ra_hir/src/source_analyzer.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ impl SourceAnalyzer {
9595
}
9696

9797
fn pat_id(&self, pat: &ast::Pat) -> Option<PatId> {
98+
// FIXME: macros, see `expr_id`
9899
let src = InFile { file_id: self.file_id, value: pat };
99100
self.body_source_map.as_ref()?.node_pat(src)
100101
}
@@ -167,6 +168,16 @@ impl SourceAnalyzer {
167168
Some((struct_field.into(), local))
168169
}
169170

171+
pub(crate) fn resolve_record_field_pat(
172+
&self,
173+
_db: &dyn HirDatabase,
174+
field: &ast::RecordFieldPat,
175+
) -> Option<StructField> {
176+
let pat_id = self.pat_id(&field.pat()?)?;
177+
let struct_field = self.infer.as_ref()?.record_field_pat_resolution(pat_id)?;
178+
Some(struct_field.into())
179+
}
180+
170181
pub(crate) fn resolve_macro_call(
171182
&self,
172183
db: &dyn HirDatabase,

crates/ra_hir_def/src/body/scope.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,10 @@ fn compute_expr_scopes(expr: ExprId, body: &Body, scopes: &mut ExprScopes, scope
157157
for arm in arms {
158158
let scope = scopes.new_scope(scope);
159159
scopes.add_bindings(body, scope, arm.pat);
160+
if let Some(guard) = arm.guard {
161+
scopes.set_scope(guard, scope);
162+
compute_expr_scopes(guard, body, scopes, scope);
163+
}
160164
scopes.set_scope(arm.expr, scope);
161165
compute_expr_scopes(arm.expr, body, scopes, scope);
162166
}

crates/ra_hir_ty/src/infer.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ pub struct InferenceResult {
127127
field_resolutions: FxHashMap<ExprId, StructFieldId>,
128128
/// For each field in record literal, records the field it resolves to.
129129
record_field_resolutions: FxHashMap<ExprId, StructFieldId>,
130+
record_field_pat_resolutions: FxHashMap<PatId, StructFieldId>,
130131
/// For each struct literal, records the variant it resolves to.
131132
variant_resolutions: FxHashMap<ExprOrPatId, VariantId>,
132133
/// For each associated item record what it resolves to
@@ -147,6 +148,9 @@ impl InferenceResult {
147148
pub fn record_field_resolution(&self, expr: ExprId) -> Option<StructFieldId> {
148149
self.record_field_resolutions.get(&expr).copied()
149150
}
151+
pub fn record_field_pat_resolution(&self, pat: PatId) -> Option<StructFieldId> {
152+
self.record_field_pat_resolutions.get(&pat).copied()
153+
}
150154
pub fn variant_resolution_for_expr(&self, id: ExprId) -> Option<VariantId> {
151155
self.variant_resolutions.get(&id.into()).copied()
152156
}

crates/ra_hir_ty/src/infer/pat.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use hir_def::{
77
expr::{BindingAnnotation, Pat, PatId, RecordFieldPat},
88
path::Path,
99
type_ref::Mutability,
10+
StructFieldId,
1011
};
1112
use hir_expand::name::Name;
1213
use test_utils::tested_by;
@@ -67,6 +68,11 @@ impl<'a> InferenceContext<'a> {
6768
let field_tys = def.map(|it| self.db.field_types(it)).unwrap_or_default();
6869
for subpat in subpats {
6970
let matching_field = var_data.as_ref().and_then(|it| it.field(&subpat.name));
71+
if let Some(local_id) = matching_field {
72+
let field_def = StructFieldId { parent: def.unwrap(), local_id };
73+
self.result.record_field_pat_resolutions.insert(subpat.pat, field_def);
74+
}
75+
7076
let expected_ty =
7177
matching_field.map_or(Ty::Unknown, |field| field_tys[field].clone().subst(&substs));
7278
let expected_ty = self.normalize_associated_types_in(expected_ty);

crates/ra_hir_ty/src/tests/patterns.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -455,3 +455,29 @@ fn test() {
455455
"###
456456
);
457457
}
458+
459+
#[test]
460+
fn infer_guard() {
461+
assert_snapshot!(
462+
infer(r#"
463+
struct S;
464+
impl S { fn foo(&self) -> bool { false } }
465+
466+
fn main() {
467+
match S {
468+
s if s.foo() => (),
469+
}
470+
}
471+
"#), @"
472+
[28; 32) 'self': &S
473+
[42; 51) '{ false }': bool
474+
[44; 49) 'false': bool
475+
[65; 116) '{ ... } }': ()
476+
[71; 114) 'match ... }': ()
477+
[77; 78) 'S': S
478+
[89; 90) 's': S
479+
[94; 95) 's': S
480+
[94; 101) 's.foo()': bool
481+
[105; 107) '()': ()
482+
")
483+
}

crates/ra_ide/src/goto_definition.rs

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,9 @@ pub(crate) enum ReferenceResult {
6262

6363
impl ReferenceResult {
6464
fn to_vec(self) -> Vec<NavigationTarget> {
65-
use self::ReferenceResult::*;
6665
match self {
67-
Exact(target) => vec![target],
68-
Approximate(vec) => vec,
66+
ReferenceResult::Exact(target) => vec![target],
67+
ReferenceResult::Approximate(vec) => vec,
6968
}
7069
}
7170
}
@@ -74,8 +73,6 @@ pub(crate) fn reference_definition(
7473
sema: &Semantics<RootDatabase>,
7574
name_ref: &ast::NameRef,
7675
) -> ReferenceResult {
77-
use self::ReferenceResult::*;
78-
7976
let name_kind = classify_name_ref(sema, name_ref);
8077
if let Some(def) = name_kind {
8178
let def = def.definition();
@@ -91,7 +88,7 @@ pub(crate) fn reference_definition(
9188
.into_iter()
9289
.map(|s| s.to_nav(sema.db))
9390
.collect();
94-
Approximate(navs)
91+
ReferenceResult::Approximate(navs)
9592
}
9693

9794
#[cfg(test)]
@@ -398,6 +395,25 @@ mod tests {
398395
);
399396
}
400397

398+
#[test]
399+
fn goto_def_for_record_pat_fields() {
400+
covers!(ra_ide_db::goto_def_for_record_field_pats);
401+
check_goto(
402+
r"
403+
//- /lib.rs
404+
struct Foo {
405+
spam: u32,
406+
}
407+
408+
fn bar(foo: Foo) -> Foo {
409+
let Foo { spam<|>: _, } = foo
410+
}
411+
",
412+
"spam RECORD_FIELD_DEF FileId(1) [17; 26) [17; 21)",
413+
"spam: u32|spam",
414+
);
415+
}
416+
401417
#[test]
402418
fn goto_def_for_record_fields_macros() {
403419
check_goto(

crates/ra_ide_db/src/defs.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@ fn classify_name_inner(sema: &Semantics<RootDatabase>, name: &ast::Name) -> Opti
180180
}
181181
}
182182

183+
#[derive(Debug)]
183184
pub enum NameRefClass {
184185
Definition(Definition),
185186
FieldShorthand { local: Local, field: Definition },
@@ -229,6 +230,14 @@ pub fn classify_name_ref(
229230
}
230231
}
231232

233+
if let Some(record_field_pat) = ast::RecordFieldPat::cast(parent.clone()) {
234+
tested_by!(goto_def_for_record_field_pats; force);
235+
if let Some(field) = sema.resolve_record_field_pat(&record_field_pat) {
236+
let field = Definition::StructField(field);
237+
return Some(NameRefClass::Definition(field));
238+
}
239+
}
240+
232241
if let Some(macro_call) = parent.ancestors().find_map(ast::MacroCall::cast) {
233242
tested_by!(goto_def_for_macros; force);
234243
if let Some(macro_def) = sema.resolve_macro_call(&macro_call) {

crates/ra_ide_db/src/marks.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,6 @@ test_utils::marks![
66
goto_def_for_fields
77
goto_def_for_record_fields
88
goto_def_for_field_init_shorthand
9+
goto_def_for_record_field_pats
910
search_filters_by_range
1011
];

0 commit comments

Comments
 (0)