9674: fix: Fix pattern name resolution when name is also occupied in type namespace r=flodiebold a=jonas-schievink

Fixes https://github.com/rust-analyzer/rust-analyzer/issues/8694

Co-authored-by: Jonas Schievink <jonasschievink@gmail.com>
This commit is contained in:
bors[bot] 2021-07-22 11:49:18 +00:00 committed by GitHub
commit 444679f202
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 55 additions and 7 deletions

View file

@ -23,7 +23,7 @@ use hir_def::{
expr::{ArithOp, BinaryOp, BindingAnnotation, ExprId, PatId},
lang_item::LangItemTarget,
path::{path, Path},
resolver::{HasResolver, Resolver, TypeNs},
resolver::{HasResolver, ResolveValueResult, Resolver, TypeNs, ValueNs},
type_ref::TypeRef,
AdtId, AssocItemId, DefWithBodyId, EnumVariantId, FieldId, FunctionId, HasModule, Lookup,
TraitId, TypeAliasId, VariantId,
@ -548,7 +548,7 @@ impl<'a> InferenceContext<'a> {
self.table.normalize_associated_types_in(ty)
}
fn resolve_variant(&mut self, path: Option<&Path>) -> (Ty, Option<VariantId>) {
fn resolve_variant(&mut self, path: Option<&Path>, value_ns: bool) -> (Ty, Option<VariantId>) {
let path = match path {
Some(path) => path,
None => return (self.err_ty(), None),
@ -557,11 +557,32 @@ impl<'a> InferenceContext<'a> {
let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver);
// FIXME: this should resolve assoc items as well, see this example:
// https://play.rust-lang.org/?gist=087992e9e22495446c01c0d4e2d69521
let (resolution, unresolved) =
let (resolution, unresolved) = if value_ns {
match resolver.resolve_path_in_value_ns(self.db.upcast(), path.mod_path()) {
Some(ResolveValueResult::ValueNs(value)) => match value {
ValueNs::EnumVariantId(var) => {
let substs = ctx.substs_from_path(path, var.into(), true);
let ty = self.db.ty(var.parent.into());
let ty = self.insert_type_vars(ty.substitute(&Interner, &substs));
return (ty, Some(var.into()));
}
ValueNs::StructId(strukt) => {
let substs = ctx.substs_from_path(path, strukt.into(), true);
let ty = self.db.ty(strukt.into());
let ty = self.insert_type_vars(ty.substitute(&Interner, &substs));
return (ty, Some(strukt.into()));
}
_ => return (self.err_ty(), None),
},
Some(ResolveValueResult::Partial(typens, unresolved)) => (typens, Some(unresolved)),
None => return (self.err_ty(), None),
}
} else {
match resolver.resolve_path_in_type_ns(self.db.upcast(), path.mod_path()) {
Some(it) => it,
None => return (self.err_ty(), None),
};
}
};
return match resolution {
TypeNs::AdtId(AdtId::StructId(strukt)) => {
let substs = ctx.substs_from_path(path, strukt.into(), true);

View file

@ -437,7 +437,7 @@ impl<'a> InferenceContext<'a> {
TyKind::Never.intern(&Interner)
}
Expr::RecordLit { path, fields, spread } => {
let (ty, def_id) = self.resolve_variant(path.as_deref());
let (ty, def_id) = self.resolve_variant(path.as_deref(), false);
if let Some(variant) = def_id {
self.write_variant_resolution(tgt_expr.into(), variant);
}

View file

@ -27,7 +27,7 @@ impl<'a> InferenceContext<'a> {
id: PatId,
ellipsis: Option<usize>,
) -> Ty {
let (ty, def) = self.resolve_variant(path);
let (ty, def) = self.resolve_variant(path, true);
let var_data = def.map(|it| it.variant_data(self.db.upcast()));
if let Some(variant) = def {
self.write_variant_resolution(id.into(), variant);
@ -68,7 +68,7 @@ impl<'a> InferenceContext<'a> {
default_bm: BindingMode,
id: PatId,
) -> Ty {
let (ty, def) = self.resolve_variant(path);
let (ty, def) = self.resolve_variant(path, false);
let var_data = def.map(|it| it.variant_data(self.db.upcast()));
if let Some(variant) = def {
self.write_variant_resolution(id.into(), variant);

View file

@ -889,3 +889,30 @@ fn main() {
"#]],
);
}
#[test]
fn pattern_lookup_in_value_ns() {
check_types(
r#"
use self::Constructor::*;
struct IntRange {
range: (),
}
enum Constructor {
IntRange(IntRange),
}
fn main() {
match Constructor::IntRange(IntRange { range: () }) {
IntRange(x) => {
x;
//^ IntRange
}
Constructor::IntRange(x) => {
x;
//^ IntRange
}
}
}
"#,
);
}