Skip to content

Commit 6b55d2f

Browse files
bors[bot]Veykril
andauthored
Merge #11540
11540: fix: Resolve private fields in type inference r=flodiebold a=Veykril Fixes #10253 (comment) (the same issue probably exists for method calls, but I think fixing that might be trickier) Visibility checks were introduced in #7841 for autoderef to work properly, so now we just record the first field we find unconditionally, and then overwrite it if autoderef manages to find another field in a later cycle. Co-authored-by: Lukas Wirth <[email protected]>
2 parents 6fa525f + 41b6b37 commit 6b55d2f

File tree

3 files changed

+63
-65
lines changed

3 files changed

+63
-65
lines changed

crates/hir_ty/src/infer.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@
1313
//! to certain types. To record this, we use the union-find implementation from
1414
//! the `ena` crate, which is extracted from rustc.
1515
16-
use std::ops::Index;
1716
use std::sync::Arc;
17+
use std::{collections::hash_map::Entry, ops::Index};
1818

1919
use chalk_ir::{cast::Cast, DebruijnIndex, Mutability, Safety, Scalar, TypeFlags};
2020
use hir_def::{
@@ -459,6 +459,12 @@ impl<'a> InferenceContext<'a> {
459459
self.result.field_resolutions.insert(expr, field);
460460
}
461461

462+
fn write_field_resolution_if_empty(&mut self, expr: ExprId, field: FieldId) {
463+
if let Entry::Vacant(entry) = self.result.field_resolutions.entry(expr) {
464+
entry.insert(field);
465+
}
466+
}
467+
462468
fn write_variant_resolution(&mut self, id: ExprOrPatId, variant: VariantId) {
463469
self.result.variant_resolutions.insert(id, variant);
464470
}

crates/hir_ty/src/infer/expr.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -532,6 +532,11 @@ impl<'a> InferenceContext<'a> {
532532
.substitute(Interner, &parameters),
533533
)
534534
} else {
535+
// Write down the first field resolution even if it is not visible
536+
// This aids IDE features for private fields like goto def and in
537+
// case of autoderef finding an applicable field, this will be
538+
// overwritten in a following cycle
539+
self.write_field_resolution_if_empty(tgt_expr, field);
535540
None
536541
}
537542
}
@@ -546,6 +551,11 @@ impl<'a> InferenceContext<'a> {
546551
.substitute(Interner, &parameters),
547552
)
548553
} else {
554+
// Write down the first field resolution even if it is not visible
555+
// This aids IDE features for private fields like goto def and in
556+
// case of autoderef finding an applicable field, this will be
557+
// overwritten in a following cycle
558+
self.write_field_resolution_if_empty(tgt_expr, field);
549559
None
550560
}
551561
}

crates/ide_db/src/defs.rs

Lines changed: 46 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -206,8 +206,23 @@ impl NameClass {
206206

207207
let parent = name.syntax().parent()?;
208208

209-
let def = if let Some(item) = ast::Item::cast(parent.clone()) {
210-
match item {
209+
let definition = match_ast! {
210+
match parent {
211+
ast::Item(it) => classify_item(sema, it)?,
212+
ast::IdentPat(it) => return classify_ident_pat(sema, it),
213+
ast::Rename(it) => classify_rename(sema, it)?,
214+
ast::SelfParam(it) => Definition::Local(sema.to_def(&it)?),
215+
ast::RecordField(it) => Definition::Field(sema.to_def(&it)?),
216+
ast::Variant(it) => Definition::Variant(sema.to_def(&it)?),
217+
ast::TypeParam(it) => Definition::GenericParam(sema.to_def(&it)?.into()),
218+
ast::ConstParam(it) => Definition::GenericParam(sema.to_def(&it)?.into()),
219+
_ => return None,
220+
}
221+
};
222+
return Some(NameClass::Definition(definition));
223+
224+
fn classify_item(sema: &Semantics<RootDatabase>, item: ast::Item) -> Option<Definition> {
225+
let definition = match item {
211226
ast::Item::MacroRules(it) => {
212227
Definition::Macro(sema.to_def(&ast::Macro::MacroRules(it))?)
213228
}
@@ -229,14 +244,20 @@ impl NameClass {
229244
ast::Item::Struct(it) => Definition::Adt(hir::Adt::Struct(sema.to_def(&it)?)),
230245
ast::Item::Union(it) => Definition::Adt(hir::Adt::Union(sema.to_def(&it)?)),
231246
_ => return None,
232-
}
233-
} else if let Some(it) = ast::IdentPat::cast(parent.clone()) {
234-
if let Some(def) = sema.resolve_bind_pat_to_const(&it) {
247+
};
248+
Some(definition)
249+
}
250+
251+
fn classify_ident_pat(
252+
sema: &Semantics<RootDatabase>,
253+
ident_pat: ast::IdentPat,
254+
) -> Option<NameClass> {
255+
if let Some(def) = sema.resolve_bind_pat_to_const(&ident_pat) {
235256
return Some(NameClass::ConstReference(Definition::from(def)));
236257
}
237258

238-
let local = sema.to_def(&it)?;
239-
let pat_parent = it.syntax().parent();
259+
let local = sema.to_def(&ident_pat)?;
260+
let pat_parent = ident_pat.syntax().parent();
240261
if let Some(record_pat_field) = pat_parent.and_then(ast::RecordPatField::cast) {
241262
if record_pat_field.name_ref().is_none() {
242263
if let Some(field) = sema.resolve_record_pat_field(&record_pat_field) {
@@ -247,57 +268,23 @@ impl NameClass {
247268
}
248269
}
249270
}
271+
Some(NameClass::Definition(Definition::Local(local)))
272+
}
250273

251-
Definition::Local(local)
252-
} else if let Some(it) = ast::Rename::cast(parent.clone()) {
253-
if let Some(use_tree) = it.syntax().parent().and_then(ast::UseTree::cast) {
274+
fn classify_rename(
275+
sema: &Semantics<RootDatabase>,
276+
rename: ast::Rename,
277+
) -> Option<Definition> {
278+
if let Some(use_tree) = rename.syntax().parent().and_then(ast::UseTree::cast) {
254279
let path = use_tree.path()?;
255-
let path_segment = path.segment()?;
256-
let name_ref = path_segment.name_ref()?;
257-
let name_ref = if name_ref.self_token().is_some() {
258-
use_tree
259-
.syntax()
260-
.parent()
261-
.as_ref()
262-
// Skip over UseTreeList
263-
.and_then(|it| {
264-
let use_tree = it.parent().and_then(ast::UseTree::cast)?;
265-
let path = use_tree.path()?;
266-
let path_segment = path.segment()?;
267-
path_segment.name_ref()
268-
})
269-
.unwrap_or(name_ref)
270-
} else {
271-
name_ref
272-
};
273-
let name_ref_class = NameRefClass::classify(sema, &name_ref)?;
274-
275-
match name_ref_class {
276-
NameRefClass::Definition(def) => def,
277-
NameRefClass::FieldShorthand { local_ref: _, field_ref } => {
278-
Definition::Field(field_ref)
279-
}
280-
}
280+
sema.resolve_path(&path).map(Definition::from)
281281
} else {
282-
let extern_crate = it.syntax().parent().and_then(ast::ExternCrate::cast)?;
282+
let extern_crate = rename.syntax().parent().and_then(ast::ExternCrate::cast)?;
283283
let krate = sema.resolve_extern_crate(&extern_crate)?;
284284
let root_module = krate.root_module(sema.db);
285-
Definition::Module(root_module)
286-
}
287-
} else {
288-
match_ast! {
289-
match parent {
290-
ast::SelfParam(it) => Definition::Local(sema.to_def(&it)?),
291-
ast::RecordField(it) => Definition::Field(sema.to_def(&it)?),
292-
ast::Variant(it) => Definition::Variant(sema.to_def(&it)?),
293-
ast::TypeParam(it) => Definition::GenericParam(sema.to_def(&it)?.into()),
294-
ast::ConstParam(it) => Definition::GenericParam(sema.to_def(&it)?.into()),
295-
_ => return None,
296-
}
285+
Some(Definition::Module(root_module))
297286
}
298-
};
299-
300-
Some(NameClass::Definition(def))
287+
}
301288
}
302289

303290
pub fn classify_lifetime(
@@ -307,19 +294,14 @@ impl NameClass {
307294
let _p = profile::span("classify_lifetime").detail(|| lifetime.to_string());
308295
let parent = lifetime.syntax().parent()?;
309296

310-
match_ast! {
311-
match parent {
312-
ast::LifetimeParam(it) => {
313-
let def = sema.to_def(&it)?;
314-
Some(NameClass::Definition(Definition::GenericParam(def.into())))
315-
},
316-
ast::Label(it) => {
317-
let def = sema.to_def(&it)?;
318-
Some(NameClass::Definition(Definition::Label(def)))
319-
},
320-
_ => None,
321-
}
297+
if let Some(it) = ast::LifetimeParam::cast(parent.clone()) {
298+
sema.to_def(&it).map(Into::into).map(Definition::GenericParam)
299+
} else if let Some(it) = ast::Label::cast(parent.clone()) {
300+
sema.to_def(&it).map(Definition::Label)
301+
} else {
302+
None
322303
}
304+
.map(NameClass::Definition)
323305
}
324306
}
325307

0 commit comments

Comments
 (0)