Skip to content

Commit 6d10170

Browse files
authored
Merge pull request rust-lang#18743 from ChayimFriedman2/e0107
feat: Unify handling of path diagnostics in hir-ty
2 parents 9c55462 + 9d44ee1 commit 6d10170

File tree

15 files changed

+881
-275
lines changed

15 files changed

+881
-275
lines changed

src/tools/rust-analyzer/crates/hir-def/src/nameres.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ use crate::{
8585
FxIndexMap, LocalModuleId, Lookup, MacroExpander, MacroId, ModuleId, ProcMacroId, UseId,
8686
};
8787

88+
pub use self::path_resolution::ResolvePathResultPrefixInfo;
89+
8890
const PREDEFINED_TOOLS: &[SmolStr] = &[
8991
SmolStr::new_static("clippy"),
9092
SmolStr::new_static("rustfmt"),
@@ -615,13 +617,15 @@ impl DefMap {
615617
(res.resolved_def, res.segment_index)
616618
}
617619

620+
/// The first `Option<usize>` points at the `Enum` segment in case of `Enum::Variant`, the second
621+
/// points at the unresolved segments.
618622
pub(crate) fn resolve_path_locally(
619623
&self,
620624
db: &dyn DefDatabase,
621625
original_module: LocalModuleId,
622626
path: &ModPath,
623627
shadow: BuiltinShadowMode,
624-
) -> (PerNs, Option<usize>) {
628+
) -> (PerNs, Option<usize>, ResolvePathResultPrefixInfo) {
625629
let res = self.resolve_path_fp_with_macro_single(
626630
db,
627631
ResolveMode::Other,
@@ -630,7 +634,7 @@ impl DefMap {
630634
shadow,
631635
None, // Currently this function isn't used for macro resolution.
632636
);
633-
(res.resolved_def, res.segment_index)
637+
(res.resolved_def, res.segment_index, res.prefix_info)
634638
}
635639

636640
/// Ascends the `DefMap` hierarchy and calls `f` with every `DefMap` and containing module.

src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ use crate::{
3838
attr_resolution::{attr_macro_as_call_id, derive_macro_as_call_id},
3939
diagnostics::DefDiagnostic,
4040
mod_resolution::ModDir,
41-
path_resolution::ReachedFixedPoint,
41+
path_resolution::{ReachedFixedPoint, ResolvePathResultPrefixInfo},
4242
proc_macro::{parse_macro_name_and_helper_attrs, ProcMacroDef, ProcMacroKind},
4343
sub_namespace_match, BuiltinShadowMode, DefMap, MacroSubNs, ModuleData, ModuleOrigin,
4444
ResolveMode,
@@ -797,7 +797,7 @@ impl DefCollector<'_> {
797797
return PartialResolvedImport::Unresolved;
798798
}
799799

800-
if res.from_differing_crate {
800+
if let ResolvePathResultPrefixInfo::DifferingCrate = res.prefix_info {
801801
return PartialResolvedImport::Resolved(
802802
def.filter_visibility(|v| matches!(v, Visibility::Public)),
803803
);

src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs

Lines changed: 59 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -43,21 +43,34 @@ pub(super) struct ResolvePathResult {
4343
pub(super) resolved_def: PerNs,
4444
pub(super) segment_index: Option<usize>,
4545
pub(super) reached_fixedpoint: ReachedFixedPoint,
46-
pub(super) from_differing_crate: bool,
46+
pub(super) prefix_info: ResolvePathResultPrefixInfo,
47+
}
48+
49+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
50+
pub enum ResolvePathResultPrefixInfo {
51+
None,
52+
DifferingCrate,
53+
/// Path of the form `Enum::Variant` (and not `Variant` alone).
54+
Enum,
4755
}
4856

4957
impl ResolvePathResult {
5058
fn empty(reached_fixedpoint: ReachedFixedPoint) -> ResolvePathResult {
51-
ResolvePathResult::new(PerNs::none(), reached_fixedpoint, None, false)
59+
ResolvePathResult::new(
60+
PerNs::none(),
61+
reached_fixedpoint,
62+
None,
63+
ResolvePathResultPrefixInfo::None,
64+
)
5265
}
5366

5467
fn new(
5568
resolved_def: PerNs,
5669
reached_fixedpoint: ReachedFixedPoint,
5770
segment_index: Option<usize>,
58-
from_differing_crate: bool,
71+
prefix_info: ResolvePathResultPrefixInfo,
5972
) -> ResolvePathResult {
60-
ResolvePathResult { resolved_def, segment_index, reached_fixedpoint, from_differing_crate }
73+
ResolvePathResult { resolved_def, segment_index, reached_fixedpoint, prefix_info }
6174
}
6275
}
6376

@@ -157,7 +170,17 @@ impl DefMap {
157170
if result.reached_fixedpoint == ReachedFixedPoint::No {
158171
result.reached_fixedpoint = new.reached_fixedpoint;
159172
}
160-
result.from_differing_crate |= new.from_differing_crate;
173+
result.prefix_info = match (result.prefix_info, new.prefix_info) {
174+
(ResolvePathResultPrefixInfo::None, it) => it,
175+
(ResolvePathResultPrefixInfo::DifferingCrate, _) => {
176+
ResolvePathResultPrefixInfo::DifferingCrate
177+
}
178+
(
179+
ResolvePathResultPrefixInfo::Enum,
180+
ResolvePathResultPrefixInfo::DifferingCrate,
181+
) => ResolvePathResultPrefixInfo::DifferingCrate,
182+
(ResolvePathResultPrefixInfo::Enum, _) => ResolvePathResultPrefixInfo::Enum,
183+
};
161184
result.segment_index = match (result.segment_index, new.segment_index) {
162185
(Some(idx), None) => Some(idx),
163186
(Some(old), Some(new)) => Some(old.max(new)),
@@ -403,14 +426,14 @@ impl DefMap {
403426

404427
fn resolve_remaining_segments<'a>(
405428
&self,
406-
segments: impl Iterator<Item = (usize, &'a Name)>,
429+
mut segments: impl Iterator<Item = (usize, &'a Name)>,
407430
mut curr_per_ns: PerNs,
408431
path: &ModPath,
409432
db: &dyn DefDatabase,
410433
shadow: BuiltinShadowMode,
411434
original_module: LocalModuleId,
412435
) -> ResolvePathResult {
413-
for (i, segment) in segments {
436+
while let Some((i, segment)) = segments.next() {
414437
let curr = match curr_per_ns.take_types_full() {
415438
Some(r) => r,
416439
None => {
@@ -443,7 +466,7 @@ impl DefMap {
443466
def,
444467
ReachedFixedPoint::Yes,
445468
s.map(|s| s + i),
446-
true,
469+
ResolvePathResultPrefixInfo::DifferingCrate,
447470
);
448471
}
449472

@@ -488,17 +511,28 @@ impl DefMap {
488511
),
489512
})
490513
});
491-
match res {
492-
Some(res) => res,
493-
None => {
494-
return ResolvePathResult::new(
495-
PerNs::types(e.into(), curr.vis, curr.import),
496-
ReachedFixedPoint::Yes,
497-
Some(i),
498-
false,
499-
)
514+
// FIXME: Need to filter visibility here and below? Not sure.
515+
return match res {
516+
Some(res) => {
517+
if segments.next().is_some() {
518+
// Enum variants are in value namespace, segments left => no resolution.
519+
ResolvePathResult::empty(ReachedFixedPoint::No)
520+
} else {
521+
ResolvePathResult::new(
522+
res,
523+
ReachedFixedPoint::Yes,
524+
None,
525+
ResolvePathResultPrefixInfo::Enum,
526+
)
527+
}
500528
}
501-
}
529+
None => ResolvePathResult::new(
530+
PerNs::types(e.into(), curr.vis, curr.import),
531+
ReachedFixedPoint::Yes,
532+
Some(i),
533+
ResolvePathResultPrefixInfo::None,
534+
),
535+
};
502536
}
503537
s => {
504538
// could be an inherent method call in UFCS form
@@ -513,7 +547,7 @@ impl DefMap {
513547
PerNs::types(s, curr.vis, curr.import),
514548
ReachedFixedPoint::Yes,
515549
Some(i),
516-
false,
550+
ResolvePathResultPrefixInfo::None,
517551
);
518552
}
519553
};
@@ -522,7 +556,12 @@ impl DefMap {
522556
.filter_visibility(|vis| vis.is_visible_from_def_map(db, self, original_module));
523557
}
524558

525-
ResolvePathResult::new(curr_per_ns, ReachedFixedPoint::Yes, None, false)
559+
ResolvePathResult::new(
560+
curr_per_ns,
561+
ReachedFixedPoint::Yes,
562+
None,
563+
ResolvePathResultPrefixInfo::None,
564+
)
526565
}
527566

528567
fn resolve_name_in_module(

src/tools/rust-analyzer/crates/hir-def/src/path.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,7 @@ pub struct PathSegment<'a> {
240240
pub args_and_bindings: Option<&'a GenericArgs>,
241241
}
242242

243+
#[derive(Debug, Clone, Copy)]
243244
pub struct PathSegments<'a> {
244245
segments: &'a [Name],
245246
generic_args: Option<&'a [Option<GenericArgs>]>,
@@ -259,31 +260,45 @@ impl<'a> PathSegments<'a> {
259260
pub fn last(&self) -> Option<PathSegment<'a>> {
260261
self.get(self.len().checked_sub(1)?)
261262
}
263+
262264
pub fn get(&self, idx: usize) -> Option<PathSegment<'a>> {
263265
let res = PathSegment {
264266
name: self.segments.get(idx)?,
265267
args_and_bindings: self.generic_args.and_then(|it| it.get(idx)?.as_ref()),
266268
};
267269
Some(res)
268270
}
271+
269272
pub fn skip(&self, len: usize) -> PathSegments<'a> {
270273
PathSegments {
271274
segments: self.segments.get(len..).unwrap_or(&[]),
272275
generic_args: self.generic_args.and_then(|it| it.get(len..)),
273276
}
274277
}
278+
275279
pub fn take(&self, len: usize) -> PathSegments<'a> {
276280
PathSegments {
277281
segments: self.segments.get(..len).unwrap_or(self.segments),
278282
generic_args: self.generic_args.map(|it| it.get(..len).unwrap_or(it)),
279283
}
280284
}
285+
281286
pub fn strip_last(&self) -> PathSegments<'a> {
282287
PathSegments {
283288
segments: self.segments.split_last().map_or(&[], |it| it.1),
284289
generic_args: self.generic_args.map(|it| it.split_last().map_or(&[][..], |it| it.1)),
285290
}
286291
}
292+
293+
pub fn strip_last_two(&self) -> PathSegments<'a> {
294+
PathSegments {
295+
segments: self.segments.get(..self.segments.len().saturating_sub(2)).unwrap_or(&[]),
296+
generic_args: self
297+
.generic_args
298+
.map(|it| it.get(..it.len().saturating_sub(2)).unwrap_or(&[])),
299+
}
300+
}
301+
287302
pub fn iter(&self) -> impl Iterator<Item = PathSegment<'a>> {
288303
self.segments
289304
.iter()

0 commit comments

Comments
 (0)