Skip to content

Commit

Permalink
Merge pull request rust-lang#18976 from ChayimFriedman2/non-module-ge…
Browse files Browse the repository at this point in the history
…neric-args

fix: Fix a bug where enum variants were not considered properly in type ns resolution
  • Loading branch information
Veykril authored Jan 20, 2025
2 parents 618b913 + 31e8419 commit 64d4181
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 29 deletions.
58 changes: 39 additions & 19 deletions src/tools/rust-analyzer/crates/hir-def/src/resolver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,17 @@ impl Resolver {
db: &dyn DefDatabase,
path: &Path,
) -> Option<(TypeNs, Option<usize>, Option<ImportOrExternCrate>)> {
self.resolve_path_in_type_ns_with_prefix_info(db, path).map(
|(resolution, remaining_segments, import, _)| (resolution, remaining_segments, import),
)
}

pub fn resolve_path_in_type_ns_with_prefix_info(
&self,
db: &dyn DefDatabase,
path: &Path,
) -> Option<(TypeNs, Option<usize>, Option<ImportOrExternCrate>, ResolvePathResultPrefixInfo)>
{
let path = match path {
Path::BarePath(mod_path) => mod_path,
Path::Normal(it) => it.mod_path(),
Expand All @@ -181,7 +192,12 @@ impl Resolver {
| LangItemTarget::ImplDef(_)
| LangItemTarget::Static(_) => return None,
};
return Some((type_ns, seg.as_ref().map(|_| 1), None));
return Some((
type_ns,
seg.as_ref().map(|_| 1),
None,
ResolvePathResultPrefixInfo::default(),
));
}
};
let first_name = path.segments().first()?;
Expand All @@ -197,17 +213,32 @@ impl Resolver {
Scope::ExprScope(_) | Scope::MacroDefScope(_) => continue,
Scope::GenericParams { params, def } => {
if let Some(id) = params.find_type_by_name(first_name, *def) {
return Some((TypeNs::GenericParam(id), remaining_idx(), None));
return Some((
TypeNs::GenericParam(id),
remaining_idx(),
None,
ResolvePathResultPrefixInfo::default(),
));
}
}
&Scope::ImplDefScope(impl_) => {
if *first_name == sym::Self_.clone() {
return Some((TypeNs::SelfType(impl_), remaining_idx(), None));
return Some((
TypeNs::SelfType(impl_),
remaining_idx(),
None,
ResolvePathResultPrefixInfo::default(),
));
}
}
&Scope::AdtScope(adt) => {
if *first_name == sym::Self_.clone() {
return Some((TypeNs::AdtSelfType(adt), remaining_idx(), None));
return Some((
TypeNs::AdtSelfType(adt),
remaining_idx(),
None,
ResolvePathResultPrefixInfo::default(),
));
}
}
Scope::BlockScope(m) => {
Expand All @@ -220,18 +251,6 @@ impl Resolver {
self.module_scope.resolve_path_in_type_ns(db, path)
}

pub fn resolve_path_in_type_ns_fully_with_imports(
&self,
db: &dyn DefDatabase,
path: &Path,
) -> Option<(TypeNs, Option<ImportOrExternCrate>)> {
let (res, unresolved, imp) = self.resolve_path_in_type_ns(db, path)?;
if unresolved.is_some() {
return None;
}
Some((res, imp))
}

pub fn resolve_path_in_type_ns_fully(
&self,
db: &dyn DefDatabase,
Expand Down Expand Up @@ -986,11 +1005,12 @@ impl ModuleItemMap {
&self,
db: &dyn DefDatabase,
path: &ModPath,
) -> Option<(TypeNs, Option<usize>, Option<ImportOrExternCrate>)> {
let (module_def, idx, _) =
) -> Option<(TypeNs, Option<usize>, Option<ImportOrExternCrate>, ResolvePathResultPrefixInfo)>
{
let (module_def, idx, prefix_info) =
self.def_map.resolve_path_locally(db, self.module_id, path, BuiltinShadowMode::Other);
let (res, import) = to_type_ns(module_def)?;
Some((res, idx, import))
Some((res, idx, import, prefix_info))
}
}

Expand Down
33 changes: 23 additions & 10 deletions src/tools/rust-analyzer/crates/hir-ty/src/lower.rs
Original file line number Diff line number Diff line change
Expand Up @@ -761,8 +761,8 @@ impl<'a> TyLoweringContext<'a> {
path: &Path,
on_diagnostic: &mut dyn FnMut(&mut Self, PathLoweringDiagnostic),
) -> Option<(TypeNs, Option<usize>)> {
let (resolution, remaining_index, _) =
self.resolver.resolve_path_in_type_ns(self.db.upcast(), path)?;
let (resolution, remaining_index, _, prefix_info) =
self.resolver.resolve_path_in_type_ns_with_prefix_info(self.db.upcast(), path)?;
let segments = path.segments();

match path {
Expand All @@ -771,13 +771,12 @@ impl<'a> TyLoweringContext<'a> {
_ => return Some((resolution, remaining_index)),
};

let (module_segments, resolved_segment_idx, resolved_segment) = match remaining_index {
None => (
segments.strip_last(),
segments.len() - 1,
segments.last().expect("resolved path has at least one element"),
),
Some(i) => (segments.take(i - 1), i - 1, segments.get(i - 1).unwrap()),
let (module_segments, resolved_segment_idx, enum_segment) = match remaining_index {
None if prefix_info.enum_variant => {
(segments.strip_last_two(), segments.len() - 1, Some(segments.len() - 2))
}
None => (segments.strip_last(), segments.len() - 1, None),
Some(i) => (segments.take(i - 1), i - 1, None),
};

for (i, mod_segment) in module_segments.iter().enumerate() {
Expand All @@ -792,9 +791,23 @@ impl<'a> TyLoweringContext<'a> {
}
}

if let Some(enum_segment) = enum_segment {
if segments.get(enum_segment).is_some_and(|it| it.args_and_bindings.is_some())
&& segments.get(enum_segment + 1).is_some_and(|it| it.args_and_bindings.is_some())
{
on_diagnostic(
self,
PathLoweringDiagnostic::GenericArgsProhibited {
segment: (enum_segment + 1) as u32,
reason: GenericArgsProhibitedReason::EnumVariant,
},
);
}
}

self.handle_type_ns_resolution(
&resolution,
resolved_segment,
segments.get(resolved_segment_idx).expect("should have resolved segment"),
resolved_segment_idx,
on_diagnostic,
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -600,6 +600,25 @@ pub mod __private {
//- /bar.rs crate:bar deps:foo edition:2018
fn bar() {
_ = foo::__private::Result::<(), ()>::Ok;
}
"#,
);
}

#[test]
fn enum_variant_type_ns() {
check_diagnostics(
r#"
enum KvnDeserializerErr<I> {
UnexpectedKeyword { found: I, expected: I },
}
fn foo() {
let _x: KvnDeserializerErr<()> =
KvnDeserializerErr::<()>::UnexpectedKeyword { found: (), expected: () };
let _x: KvnDeserializerErr<()> =
KvnDeserializerErr::<()>::UnexpectedKeyword::<()> { found: (), expected: () };
// ^^^^^^ 💡 error: you can specify generic arguments on either the enum or the variant, but not both
}
"#,
);
Expand Down

0 comments on commit 64d4181

Please sign in to comment.