From b596c32a4102643a1c45282092beafb5a31c16a4 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Thu, 22 Jul 2021 13:40:18 +0200 Subject: [PATCH] Resolve tuple variants in value namespace --- crates/hir_ty/src/infer.rs | 29 +++++++++++++++++++++++++---- crates/hir_ty/src/infer/expr.rs | 2 +- crates/hir_ty/src/infer/pat.rs | 4 ++-- crates/hir_ty/src/tests/patterns.rs | 27 +++++++++++++++++++++++++++ 4 files changed, 55 insertions(+), 7 deletions(-) diff --git a/crates/hir_ty/src/infer.rs b/crates/hir_ty/src/infer.rs index 154c44afa4..a879ca3823 100644 --- a/crates/hir_ty/src/infer.rs +++ b/crates/hir_ty/src/infer.rs @@ -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) { + fn resolve_variant(&mut self, path: Option<&Path>, value_ns: bool) -> (Ty, Option) { 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); diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs index f1bc6895c8..d667613428 100644 --- a/crates/hir_ty/src/infer/expr.rs +++ b/crates/hir_ty/src/infer/expr.rs @@ -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); } diff --git a/crates/hir_ty/src/infer/pat.rs b/crates/hir_ty/src/infer/pat.rs index 86e2d1b8df..603237f944 100644 --- a/crates/hir_ty/src/infer/pat.rs +++ b/crates/hir_ty/src/infer/pat.rs @@ -27,7 +27,7 @@ impl<'a> InferenceContext<'a> { id: PatId, ellipsis: Option, ) -> 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); diff --git a/crates/hir_ty/src/tests/patterns.rs b/crates/hir_ty/src/tests/patterns.rs index 47aa30d2e3..778d19b747 100644 --- a/crates/hir_ty/src/tests/patterns.rs +++ b/crates/hir_ty/src/tests/patterns.rs @@ -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 + } + } +} + "#, + ); +}